Sổ tay Kubernetes: Triển khai ứng dụng đa container (p3)

Loạt bài viết sổ tay Kubernetes:

Ở 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ường spec.volumes.name có thể là bất cứ điều gì bạn muốn. Trường spec.volumes.persistentVolumeClaim.claimName phải khớp với giá trị trường metadata.name từ tệp database-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ường containers.volumeMounts.name phải khớp với giá trị của trường spec.volumes.name. Trường containers.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ường containers.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ục postgres 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.

Mô hình triển khai ứng dụng trong Kubernetes
  • 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ệp postgres-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ệp postgres-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:

Kết quả triển khai ứng dụng trên nhiều container trong kubernetes

Đâ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.

Sổ tay Kubernetes: làm việc với Ingress Controller (p1)
Trong hướng dẫn này, bạn sẽ tìm hiểu về Ingress Controller và cách sử dụng NGINX Ingress Controller để cấu hình định tuyến trong Kubernetes.

Bài viết gốc.

KubernetesDevOps
Bài Viết Liên Quan:
Sổ tay Kubernetes: làm việc với Ingress Controller (p2)
Trung Nguyen 30/05/2021
Sổ tay Kubernetes: làm việc với Ingress Controller (p2)

Trong phần này, bạn sẽ tìm hiểu cách sử dụng Secret, ConfigMap để lưu trữ thông tin cấu hình, phát hành các bản cập nhật và xử lý sự cố trong Kubernetes.

Sổ tay Kubernetes: làm việc với Ingress Controller (p1)
Trung Nguyen 30/05/2021
Sổ tay Kubernetes: làm việc với Ingress Controller (p1)

Trong hướng dẫn này, bạn sẽ tìm hiểu về Ingress Controller và cách sử dụng NGINX Ingress Controller để cấu hình định tuyến trong Kubernetes.

Sổ tay Kubernetes: Triển khai ứng dụng đa container (p2)
Trung Nguyen 30/05/2021
Sổ tay Kubernetes: Triển khai ứng dụng đa container (p2)

Ở phần 2 này, chúng ta sẽ tìm cách khắc phục những lỗi xảy ra khi triển khai. Chúng ta cũng tìm hiểu thêm về Persistent Volume, Persistent Volume Claim.

Sổ tay Kubernetes: Triển khai ứng dụng đa container (p1)
Trung Nguyen 29/05/2021
Sổ tay Kubernetes: Triển khai ứng dụng đa container (p1)

Trong phần này, bạn sẽ tìm hiểu về Deployment, ClusterIP, PersistentVolume, PersistentVolumeClaim để triển khai một ứng dụng bao gồm hai container.