Sổ tay Kubernetes: Triển khai ứng dụng đa container (p3)
Loạt bài viết sổ tay Kubernetes:
- Sổ tay Kubernetes: Giới thiệu về Kubernetes.
- Sổ tay Kubernetes: Các khái niệm cơ bản trong Kubernetes.
- Sổ tay Kubernetes: Phương pháp triển khai bằng khai báo.
- Sổ tay Kubernetes: Triển khai ứng dụng đa container (p1).
- Sổ tay Kubernetes: Triển khai ứng dụng đa container (p2).
- Sổ tay Kubernetes: Triển khai ứng dụng đa container (p3) (bài viết này).
- Sổ tay Kubernetes: làm việc với Ingress Controller (p1).
- Sổ tay Kubernetes: làm việc với Ingress Controller (p2).
Ở phần 2, bạn đã học cách xem log của container trong pod để tìm hiểu nguyên nhân và khắc phục lỗi khi triển khai. Bạn cũng đã tìm hiểu về cách cấu hình volume lưu trữ dữ liệu trong cụm kubernetes sử dụng Persistent Volume và Persistent Volume Claim.
Ở phần 3 này, chúng ta sẽ tìm hiểu cách cung cấp động Persistent Volume, kết nối volume với pod và kết nối các thành phần trong cụm với nhau.
Cung cấp động Persistent Volume
Trong phần trước, bạn đã tạo một persistent volume và sau đó tạo một claim. Nhưng, điều gì sẽ xảy ra nếu không có bất kỳ persistent volume nào được cung cấp trước đó?
Trong những trường hợp như vậy, một persistent volume tương thích với claim sẽ được cung cấp tự động.
Để minh họa điều này, hãy xóa persistent volume đã tạo trước đó và yêu cầu persistent volume bằng các lệnh sau:
kubectl delete persistentvolumeclaim --all
# persistentvolumeclaim "database-persistent-volume-claim" deleted
kubectl delete persistentvolumeclaim --all
# persistentvolume "database-persistent-volume" deleted
Mở tệp database-persistent-volume-claim.yaml
và cập nhật nội dung của nó như sau:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: database-persistent-volume-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
Tôi đã xóa trường spec.storageClass
khỏi tệp. Bây giờ chạy lại tệp database-persistent-volume-claim.yaml
mà không cần chạy tệp database-persistent-volume.yaml
:
kubectl apply -f database-persistent-volume-claim.yaml
# persistentvolumeclaim/database-persistent-volume-claim created
Bây giờ sử dụng lệnh get
để xem thông tin claim:
kubectl get persistentvolumeclaim
# NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
# database-persistent-volume-claim Bound pvc-525ae8af-00d3-4cc7-ae47-866aa13dffd5 2Gi RWO standard 2s
Như bạn có thể thấy, một volume có tên pvc-525ae8af-00d3-4cc7-ae47-866aa13dffd5
và dung lượng lưu trữ 2Gi
đã được cấp và liên kết động với claim.
Bạn có thể sử dụng một persistent volume được cung cấp tĩnh hoặc động cho phần còn lại của dự án này. Tôi sẽ sử dụng một cái được cấp phép động.
Kết nối Volume với các Pod
Bây giờ bạn đã tạo một persistent volume và một claim, đã đến lúc để cho pod cơ sở dữ liệu sử dụng volume này.
Bạn thực hiện việc này bằng cách kết nối pod với persistent volume claim mà bạn đã thực hiện trong phần trước. Mở tệp postgres-deployment.yaml
và cập nhật nội dung của nó như sau:
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres-deployment
spec:
replicas: 1
selector:
matchLabels:
component: postgres
template:
metadata:
labels:
component: postgres
spec:
# volume configuration for the pod
volumes:
- name: postgres-storage
persistentVolumeClaim:
claimName: database-persistent-volume-claim
containers:
- name: postgres
image: fhsinchy/notes-postgres
ports:
- containerPort: 5432
# volume mounting configuration for the container
volumeMounts:
- name: postgres-storage
mountPath: /var/lib/postgresql/data
subPath: postgres
env:
- name: POSTGRES_PASSWORD
value: 63eaQB9wtLqmNBpg
- name: POSTGRES_DB
value: notesdb
Tôi đã thêm hai trường mới trong tệp cấu hình này.
- Trường
spec.volumes
chứa thông tin cần thiết cho pod để tìm persistent volume claim. Trườngspec.volumes.name
có thể là bất cứ điều gì bạn muốn. Trườngspec.volumes.persistentVolumeClaim.claimName
phải khớp với giá trị trườngmetadata.name
từ tệpdatabase-persistent-volume-claim.yaml
. - Trường
containers.volumeMounts
chứa thông tin cần thiết để gắn volume bên trong container. Trườngcontainers.volumeMounts.name
phải khớp với giá trị của trườngspec.volumes.name
. Trườngcontainers.volumeMounts.mountPath
cho biết thư mục nơi volume này sẽ được gắn kết./var/lib/postgresql/data
là thư mục dữ liệu mặc định cho PostgreSQL. Trườngcontainers.volumeMounts.subPath
cho biết một thư mục sẽ được tạo bên trong volume. Giả sử rằng bạn cũng đang sử dụng cùng một volume với các pod khác. Trong trường hợp đó, bạn có thể đặt dữ liệu dành riêng cho pod bên trong một thư mục khác bên trong volume đó. Tất cả dữ liệu được lưu bên trong thư mục/var/lib/postgresql/data
sẽ đi vào bên trong một thư mụcpostgres
của volume.
Bây giờ chạy lại tệp postgres-deployment.yaml
bằng cách thực hiện lệnh sau:
kubectl apply -f postgres-deployment.yaml
# deployment.apps/postgres-deployment configured
Bây giờ bạn có một triển khai cơ sở dữ liệu thích hợp với nguy cơ mất dữ liệu nhỏ hơn nhiều.
Một điều mà tôi muốn đề cập ở đây là việc triển khai cơ sở dữ liệu trong dự án này chỉ có một bản sao (replicas). Nếu có nhiều hơn một bản sao, mọi thứ sẽ khác.
Nhiều pod truy cập vào cùng một volume mà chúng không biết về sự tồn tại của nhau có thể mang lại kết quả thảm khốc. Trong những trường hợp như vậy, việc tạo các thư mục con cho các pod bên trong ổ đĩa đó có thể là một ý tưởng hay.
Kết nối mọi thứ
Bây giờ bạn đã chạy cả API và cơ sở dữ liệu, đã đến lúc hoàn thành một số công việc chưa hoàn thành và thiết lập mạng.
Bạn đã học trong các phần trước rằng để thiết lập mạng trong Kubernetes, bạn sử dụng các dịch vụ. Trước khi bạn bắt đầu viết các dịch vụ, hãy xem qua kế hoạch mạng mà tôi có cho dự án này.
- Cơ sở dữ liệu sẽ chỉ được hiển thị trong cụm bằng cách sử dụng dịch vụ
ClusterIP
. Không có truy cập bên ngoài nào được cho phép. - Tuy nhiên, việc triển khai API sẽ được tiếp xúc với thế giới bên ngoài. Người dùng sẽ giao tiếp với API và API sẽ giao tiếp với cơ sở dữ liệu.
Trước đây bạn đã làm việc với dịch vụ LoadBalancer
đưa ứng dụng ra thế giới bên ngoài. ClusterIP
hiển thị một ứng dụng trong cụm và không cho phép truy cập bên ngoài.
Vì dịch vụ cơ sở dữ liệu chỉ nên có sẵn ở bên trong cụm, dịch vụ ClusterIP
là phù hợp hoàn hảo cho tình huống này.
Tạo một tệp mới có tên postgres-cluster-ip-service.yaml
bên trong thư mục k8s
và đưa nội dung sau vào đó:
apiVersion: v1
kind: Service
metadata:
name: postgres-cluster-ip-service
spec:
type: ClusterIP
selector:
component: postgres
ports:
- port: 5432
targetPort: 5432
Như bạn có thể thấy, tệp cấu hình cho ClusterIP
giống với tệp cấu hình cho LoadBalancer
. Điều duy nhất khác biệt là giá trị của spec.type
.
Bây giờ bạn sẽ có thể hiểu tệp này mà không gặp bất kỳ rắc rối nào. 5432 là cổng mặc định mà PostgreSQL chạy trên đó. Đó là lý do tại sao cổng đó phải được tiếp xúc.
Tệp cấu hình tiếp theo dành cho dịch vụ LoadBalancer
, chịu trách nhiệm đưa API ra thế giới bên ngoài. Tạo một tệp khác có tên api-load-balancer-service.yaml
và đặt nội dung sau vào đó:
apiVersion: v1
kind: Service
metadata:
name: api-load-balancer-service
spec:
type: LoadBalancer
ports:
- port: 3000
targetPort: 3000
selector:
component: api
Cấu hình này giống với cấu hình bạn đã viết trong phần trước. API chạy trong cổng 3000 bên trong container và đó là lý do tại sao cổng đó phải được hiển thị.
Điều cuối cùng cần làm là thêm phần còn lại của các biến môi trường vào triển khai API. Vì vậy, hãy mở tệp api-deployment.yaml
và cập nhật nội dung của nó như sau:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-deployment
spec:
replicas: 3
selector:
matchLabels:
component: api
template:
metadata:
labels:
component: api
spec:
containers:
- name: api
image: fhsinchy/notes-api
ports:
- containerPort: 3000
env:
- name: DB_CONNECTION
value: pg
- name: DB_HOST
value: postgres-cluster-ip-service
- name: DB_PORT
value: '5432'
- name: DB_USER
value: postgres
- name: DB_DATABASE
value: notesdb
- name: DB_PASSWORD
value: 63eaQB9wtLqmNBpg
Trước đây chỉ có biến DB_CONNECTION
trong spec.containers.env
. Các biến mới như sau:
DB_HOST
chỉ ra địa chỉ máy chủ cho dịch vụ cơ sở dữ liệu. Trong môi trường không container, giá trị thường là127.0.0.1
. Nhưng trong môi trường Kubernetes, bạn không biết địa chỉ IP của pod cơ sở dữ liệu. Do đó, bạn chỉ cần sử dụng tên dịch vụ hiển thị cơ sở dữ liệu để thay thế.DB_PORT
là cổng được hiển thị từ dịch vụ cơ sở dữ liệu, là 5432.DB_USER
là người dùng để kết nối với cơ sở dữ liệu.postgres
là tên người dùng mặc định.DB_DATABASE
là cơ sở dữ liệu mà API sẽ kết nối tới. Điều này phải khớp với giá trịspec.containers.env.DB_DATABASE
từ tệppostgres-deployment.yaml
.DB_PASSWORD
là mật khẩu để kết nối với cơ sở dữ liệu. Điều này phải khớp với giá trịspec.containers.env.DB_PASSWORD
từ tệppostgres-deployment.yaml
.
Sau khi hoàn tất, bây giờ bạn đã sẵn sàng để kiểm tra API. Trước khi bạn làm điều đó, tôi khuyên bạn nên áp dụng tất cả các tệp cấu hình một lần nữa bằng cách thực hiện lệnh sau:
kubectl apply -f k8s
# deployment.apps/api-deployment created
# service/api-load-balancer-service created
# persistentvolumeclaim/database-persistent-volume-claim created
# service/postgres-cluster-ip-service created
# deployment.apps/postgres-deployment created
Nếu bạn gặp bất kỳ lỗi nào, chỉ cần xóa tất cả tài nguyên và áp dụng lại các tệp. Các dịch vụ, persistent volume và persistent volume claim sẽ được tạo ngay lập tức.
Sử dụng lệnh get
để đảm bảo rằng tất cả các deployment đã được cài đặt và đang chạy:
kubectl get deployment
# NAME READY UP-TO-DATE AVAILABLE AGE
# api-deployment 3/3 3 3 106s
# postgres-deployment 1/1 1 1 106s
Như bạn có thể thấy từ cột READY
, tất cả các pod đều đang hoạt động. Để truy cập API, hãy sử dụng lệnh service
cho minikube
.
minikube service api-load-balancer-service
# |-----------|---------------------------|-------------|-----------------------------|
# | NAMESPACE | NAME | TARGET PORT | URL |
# |-----------|---------------------------|-------------|-----------------------------|
# | default | api-load-balancer-service | 3000 | http://172.19.186.112:31546 |
# |-----------|---------------------------|-------------|-----------------------------|
# * Opening service default/api-load-balancer-service in default browser...
API sẽ tự động mở trong trình duyệt mặc định của bạn:
Đây là phản hồi mặc định cho API. Bạn cũng có thể sử dụng một số công cụ kiểm tra API như Insomnia hoặc Postman để kiểm tra API. API có đầy đủ chức năng CRUD.
Bạn có thể xem các bài kiểm tra đi kèm với mã nguồn API dưới dạng tài liệu. Chỉ cần mở tệp api/tests/e2e/api/routes/notes.test.js
. Bạn sẽ có thể hiểu tệp mà không gặp nhiều rắc rối nếu bạn có kinh nghiệm với JavaScript và Express.
Bài viết gốc.