This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Các khái niệm

Phần Khái niệm giúp bạn tìm hiểu về các bộ phận của hệ thống Kubernetes và các khái niệm mà Kubernetes sử dụng để biểu diễn cụm cluster của bạn, đồng thời giúp bạn hiểu sâu hơn về cách thức hoạt động của Kubernetes.

1 - Deployments

Deployment quản lý một tập hợp các Pod để chạy một workload ứng dụng, thường là các ứng dụng không duy trì trạng thái.

Deployment cung cấp khả năng cập nhật dạng khai báo (declarative) cho các Pod và ReplicaSet.

Bạn mô tả trạng thái mong muốn (desired state) trong một Deployment, và Vòng điều khiển (Controller) của Deployment sẽ thay đổi trạng thái thực tế sang trạng thái mong muốn với tốc độ được kiểm soát. Bạn có thể định nghĩa các Deployment để tạo ReplicaSet mới, hoặc để xóa các Deployment hiện có và tiếp nhận toàn bộ tài nguyên của chúng bằng các Deployment mới.

Lưu ý:

Không quản lý trực tiếp các ReplicaSet thuộc sở hữu của một Deployment. Hãy cân nhắc mở một issue trong repository chính của Kubernetes nếu trường hợp sử dụng của bạn không được đề cập bên dưới.

Trường hợp sử dụng

Sau đây là các trường hợp sử dụng điển hình của Deployment:

Tạo một Deployment

Dưới đây là một ví dụ về Deployment. Nó tạo một ReplicaSet để khởi chạy ba Pod nginx:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

Trong ví dụ này:

  • Một Deployment tên là nginx-deployment được tạo, được chỉ định bởi trường .metadata.name. Tên này sẽ trở thành cơ sở để đặt tên cho các ReplicaSet và Pod được tạo sau đó. Xem Viết spec cho Deployment để biết thêm chi tiết.

  • Deployment tạo một ReplicaSet, ReplicaSet này tạo ba Pod replica, được chỉ định bởi trường .spec.replicas.

  • Trường .spec.selector định nghĩa cách ReplicaSet được tạo ra tìm các Pod mà nó cần quản lý. Trong trường hợp này, bạn chọn một label được định nghĩa trong Pod template (app: nginx). Tuy nhiên, có thể sử dụng các quy tắc lựa chọn phức tạp hơn, miễn là bản thân Pod template thỏa mãn quy tắc đó.

    Lưu ý:

    Trường .spec.selector.matchLabels là một map gồm các cặp {key,value}. Một cặp {key,value} trong map matchLabels tương đương với một phần tử của matchExpressions, có trường key là "key", operator là "In", và mảng values chỉ chứa "value". Tất cả các yêu cầu, từ cả matchLabels và matchExpressions, đều phải được thỏa mãn thì mới khớp.
  • Trường .spec.template chứa các trường con sau:

    • Các Pod được gắn label app: nginx thông qua trường .metadata.labels.
    • Đặc tả của Pod template, hay trường .spec, chỉ ra rằng các Pod chạy một container, nginx, container này chạy image nginx trên Docker Hub ở phiên bản 1.14.2.
    • Tạo một container và đặt tên là nginx thông qua trường .spec.containers[0].name.

Trước khi bắt đầu, hãy đảm bảo cluster Kubernetes của bạn đang hoạt động. Làm theo các bước dưới đây để tạo Deployment ở trên:

  1. Tạo Deployment bằng cách chạy lệnh sau:

    kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
    
  2. Chạy kubectl get deployments để kiểm tra xem Deployment đã được tạo hay chưa.

    Nếu Deployment vẫn đang được tạo, kết quả sẽ tương tự như sau:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   0/3     0            0           1s
    

    Khi bạn kiểm tra các Deployment trong cluster, các trường sau được hiển thị:

    • NAME liệt kê tên của các Deployment trong namespace.
    • READY hiển thị số replica của ứng dụng đang sẵn sàng phục vụ người dùng. Giá trị có dạng ready/desired.
    • UP-TO-DATE hiển thị số replica đã được cập nhật để đạt trạng thái mong muốn.
    • AVAILABLE hiển thị số replica của ứng dụng đang khả dụng cho người dùng.
    • AGE hiển thị khoảng thời gian ứng dụng đã chạy.

    Lưu ý rằng số replica mong muốn là 3, theo trường .spec.replicas.

  3. Để xem trạng thái rollout của Deployment, chạy kubectl rollout status deployment/nginx-deployment.

    Kết quả tương tự như sau:

    Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
    deployment "nginx-deployment" successfully rolled out
    
  4. Chạy lại kubectl get deployments sau vài giây. Kết quả tương tự như sau:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           18s
    

    Lưu ý rằng Deployment đã tạo cả ba replica, và tất cả các replica đều đã được cập nhật (chứa Pod template mới nhất) và khả dụng.

  5. Để xem ReplicaSet (rs) được tạo bởi Deployment, chạy kubectl get rs. Kết quả tương tự như sau:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-75675f5897   3         3         3       18s
    

    Kết quả của ReplicaSet hiển thị các trường sau:

    • NAME liệt kê tên của các ReplicaSet trong namespace.
    • DESIRED hiển thị số replica mong muốn của ứng dụng, được bạn định nghĩa khi tạo Deployment. Đây là trạng thái mong muốn.
    • CURRENT hiển thị số replica đang chạy.
    • READY hiển thị số replica của ứng dụng đang sẵn sàng phục vụ người dùng.
    • AGE hiển thị khoảng thời gian ứng dụng đã chạy.

    Lưu ý rằng tên của ReplicaSet luôn có định dạng [DEPLOYMENT-NAME]-[HASH]. Tên này sẽ trở thành cơ sở để đặt tên cho các Pod được tạo ra.

    Chuỗi HASH giống với label pod-template-hash trên ReplicaSet.

  6. Để xem các label được tự động sinh ra cho mỗi Pod, chạy kubectl get pods --show-labels. Kết quả tương tự như sau:

    NAME                                READY     STATUS    RESTARTS   AGE       LABELS
    nginx-deployment-75675f5897-7ci7o   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
    nginx-deployment-75675f5897-kzszj   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
    nginx-deployment-75675f5897-qqcnn   1/1       Running   0          18s       app=nginx,pod-template-hash=75675f5897
    

    ReplicaSet được tạo đảm bảo rằng luôn có ba Pod nginx.

Lưu ý:

Bạn phải chỉ định một selector và label của Pod template phù hợp trong Deployment (trong trường hợp này là app: nginx).

Không để label hoặc selector trùng lặp với các controller khác (bao gồm các Deployment và StatefulSet khác). Kubernetes không ngăn bạn làm điều đó, và nếu nhiều controller có selector trùng lặp, các controller đó có thể xung đột và hoạt động không như mong đợi.

Label pod-template-hash

Chú ý:

Không được thay đổi label này.

Label pod-template-hash được Deployment controller thêm vào mỗi ReplicaSet mà một Deployment tạo ra hoặc tiếp nhận (adopt).

Label này đảm bảo rằng các ReplicaSet con của một Deployment không bị trùng lặp. Nó được sinh ra bằng cách băm PodTemplate của ReplicaSet và sử dụng giá trị băm thu được làm giá trị label, được thêm vào selector của ReplicaSet, label của Pod template, và vào mọi Pod hiện có mà ReplicaSet có thể đang quản lý.

Cập nhật một Deployment

Lưu ý:

Rollout của một Deployment được kích hoạt khi và chỉ khi Pod template của Deployment (tức là .spec.template) bị thay đổi, ví dụ khi label hoặc image container của template được cập nhật. Các cập nhật khác, chẳng hạn như scale Deployment, sẽ không kích hoạt rollout.

Làm theo các bước dưới đây để cập nhật Deployment của bạn:

  1. Hãy cập nhật các Pod nginx để sử dụng image nginx:1.16.1 thay cho image nginx:1.14.2.

    kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1
    

    hoặc sử dụng lệnh sau:

    kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
    

    trong đó deployment/nginx-deployment chỉ định Deployment, nginx chỉ định container sẽ được cập nhật và nginx:1.16.1 chỉ định image mới cùng tag của nó.

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment image updated
    

    Ngoài ra, bạn có thể edit Deployment và thay đổi .spec.template.spec.containers[0].image từ nginx:1.14.2 thành nginx:1.16.1:

    kubectl edit deployment/nginx-deployment
    

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment edited
    
  2. Để xem trạng thái rollout, chạy:

    kubectl rollout status deployment/nginx-deployment
    

    Kết quả tương tự như sau:

    Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
    

    hoặc

    deployment "nginx-deployment" successfully rolled out
    

Xem thêm chi tiết về Deployment đã được cập nhật:

  • Sau khi rollout thành công, bạn có thể xem Deployment bằng cách chạy kubectl get deployments. Kết quả tương tự như sau:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           36s
    
  • Chạy kubectl get rs để thấy rằng Deployment đã cập nhật các Pod bằng cách tạo một ReplicaSet mới và scale nó lên 3 replica, đồng thời scale ReplicaSet cũ xuống 0 replica.

    kubectl get rs
    

    Kết quả tương tự như sau:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-1564180365   3         3         3       6s
    nginx-deployment-2035384211   0         0         0       36s
    
  • Lúc này, chạy get pods sẽ chỉ hiển thị các Pod mới:

    kubectl get pods
    

    Kết quả tương tự như sau:

    NAME                                READY     STATUS    RESTARTS   AGE
    nginx-deployment-1564180365-khku8   1/1       Running   0          14s
    nginx-deployment-1564180365-nacti   1/1       Running   0          14s
    nginx-deployment-1564180365-z9gth   1/1       Running   0          14s
    

    Lần tiếp theo khi muốn cập nhật các Pod này, bạn chỉ cần cập nhật lại Pod template của Deployment.

    Deployment đảm bảo rằng chỉ một số lượng nhất định Pod bị ngừng hoạt động trong khi chúng đang được cập nhật. Theo mặc định, nó đảm bảo rằng ít nhất 75% số Pod mong muốn đang chạy (tối đa 25% không khả dụng - max unavailable).

    Deployment cũng đảm bảo rằng chỉ một số lượng nhất định Pod được tạo vượt quá số Pod mong muốn. Theo mặc định, nó đảm bảo rằng tối đa 125% số Pod mong muốn đang chạy (vượt tối đa 25% - max surge).

    Ví dụ, nếu quan sát kỹ Deployment ở trên, bạn sẽ thấy nó tạo một Pod mới trước, sau đó xóa một Pod cũ, rồi tạo thêm một Pod mới khác. Nó không dừng các Pod cũ cho đến khi có đủ số lượng Pod mới đã chạy, và không tạo Pod mới cho đến khi đủ số lượng Pod cũ đã bị dừng. Nó đảm bảo rằng ít nhất 3 Pod khả dụng và tổng cộng tối đa 4 Pod khả dụng. Với một Deployment có 4 replica, số lượng Pod sẽ nằm trong khoảng từ 3 đến 5.

  • Lấy thông tin chi tiết về Deployment của bạn:

    kubectl describe deployments
    

    Kết quả tương tự như sau:

    Name:                   nginx-deployment
    Namespace:              default
    CreationTimestamp:      Thu, 30 Nov 2017 10:56:25 +0000
    Labels:                 app=nginx
    Annotations:            deployment.kubernetes.io/revision=2
    Selector:               app=nginx
    Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=nginx
       Containers:
        nginx:
          Image:        nginx:1.16.1
          Port:         80/TCP
          Environment:  <none>
          Mounts:       <none>
        Volumes:        <none>
      Conditions:
        Type           Status  Reason
        ----           ------  ------
        Available      True    MinimumReplicasAvailable
        Progressing    True    NewReplicaSetAvailable
      OldReplicaSets:  <none>
      NewReplicaSet:   nginx-deployment-1564180365 (3/3 replicas created)
      Events:
        Type    Reason             Age   From                   Message
        ----    ------             ----  ----                   -------
        Normal  ScalingReplicaSet  2m    deployment-controller  Scaled up replica set nginx-deployment-2035384211 to 3
        Normal  ScalingReplicaSet  24s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 1
        Normal  ScalingReplicaSet  22s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 2
        Normal  ScalingReplicaSet  22s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 2
        Normal  ScalingReplicaSet  19s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 1
        Normal  ScalingReplicaSet  19s   deployment-controller  Scaled up replica set nginx-deployment-1564180365 to 3
        Normal  ScalingReplicaSet  14s   deployment-controller  Scaled down replica set nginx-deployment-2035384211 to 0
    

    Ở đây bạn thấy rằng khi tạo Deployment lần đầu, nó đã tạo một ReplicaSet (nginx-deployment-2035384211) và scale trực tiếp lên 3 replica. Khi bạn cập nhật Deployment, nó tạo một ReplicaSet mới (nginx-deployment-1564180365), scale lên 1 và chờ Pod đó chạy. Sau đó nó scale ReplicaSet cũ xuống 2 và scale ReplicaSet mới lên 2, sao cho luôn có ít nhất 3 Pod khả dụng và tối đa 4 Pod được tạo tại mọi thời điểm. Sau đó nó tiếp tục scale up ReplicaSet mới và scale down ReplicaSet cũ, với cùng chiến lược rolling update. Cuối cùng, bạn sẽ có 3 replica khả dụng trong ReplicaSet mới, và ReplicaSet cũ được scale xuống 0.

Lưu ý:

Kubernetes không tính các Pod đang dừng khi tính số lượng availableReplicas, giá trị này phải nằm trong khoảng replicas - maxUnavailable đến replicas + maxSurge. Do đó, bạn có thể thấy có nhiều Pod hơn dự kiến trong quá trình rollout, và tổng tài nguyên mà Deployment tiêu thụ lớn hơn replicas + maxSurge cho đến khi terminationGracePeriodSeconds của các Pod đang dừng hết hạn.

Rollover (hay còn gọi là nhiều cập nhật diễn ra đồng thời)

Mỗi khi Deployment controller phát hiện một Deployment mới, một ReplicaSet sẽ được tạo để khởi chạy các Pod mong muốn. Nếu Deployment được cập nhật, ReplicaSet hiện có đang kiểm soát các Pod có label khớp với .spec.selector nhưng có template không khớp với .spec.template sẽ bị scale down. Cuối cùng, ReplicaSet mới được scale lên .spec.replicas và tất cả các ReplicaSet cũ được scale xuống 0.

Nếu bạn cập nhật một Deployment trong khi một rollout đang diễn ra, Deployment sẽ tạo một ReplicaSet mới theo bản cập nhật và bắt đầu scale up ReplicaSet đó, đồng thời rollover ReplicaSet mà nó đang scale up trước đó -- nó sẽ thêm ReplicaSet đó vào danh sách các ReplicaSet cũ và bắt đầu scale down nó.

Ví dụ, giả sử bạn tạo một Deployment để tạo 5 replica của nginx:1.14.2, nhưng sau đó cập nhật Deployment để tạo 5 replica của nginx:1.16.1, khi mới chỉ có 3 replica của nginx:1.14.2 được tạo. Trong trường hợp đó, Deployment ngay lập tức bắt đầu dừng 3 Pod nginx:1.14.2 mà nó đã tạo, và bắt đầu tạo các Pod nginx:1.16.1. Nó không đợi 5 replica của nginx:1.14.2 được tạo xong rồi mới chuyển hướng.

Cập nhật label selector

Nhìn chung, việc cập nhật label selector không được khuyến khích, và bạn nên lên kế hoạch cho các selector từ trước. Label selector của một Deployment là bất biến sau khi được tạo; không thể cập nhật nó bằng kubectl patch, kubectl edit, kubectl apply, hay các công cụ như helm upgrade.

Nếu buộc phải thay đổi selector, bạn cần xóa Deployment rồi tạo lại. Theo mặc định, việc xóa Deployment cũng xóa các Pod đang chạy của nó, gây ra downtime; hãy dùng --cascade=orphan nếu bạn cần các Pod đó tiếp tục chạy trong khi tạo lại Deployment (xem các hệ quả bên dưới). Hãy hết sức thận trọng và đảm bảo bạn hiểu rõ các hệ quả sau:

  • Thêm: Khi bạn tạo một Deployment mới với selector hẹp hơn, Deployment mới bắt buộc phải có Pod template phù hợp. Nếu bạn có một manifest sẵn có và sửa manifest đó để thu hẹp selector, bạn cần sửa metadata của Pod template bên trong Deployment đó, thêm các label mới cho khớp, nếu không API server sẽ trả về lỗi xác thực (validation error). Đây là một thay đổi không chồng lấn (non-overlapping): Deployment mới sẽ không "thấy" các Pod cũ (vốn không có label mới), khiến ReplicaSet cũ bị mồ côi (orphaned) và một ReplicaSet hoàn toàn mới được tạo ra.
  • Thay đổi giá trị: Thay đổi giá trị hiện có của một key trong selector (ví dụ, từ v1 thành v2) dẫn đến hành vi giống như khi thêm (ReplicaSet cũ bị mồ côi và được tạo lại).
  • Xóa: Xóa một key hiện có khỏi selector của Deployment không yêu cầu bất kỳ thay đổi nào đối với label của Pod template. Đây là một thay đổi chồng lấn (overlapping): selector mới, rộng hơn sẽ khớp với các Pod cũ. Các ReplicaSet hiện có không bị mồ côi, và không có ReplicaSet mới nào được tạo, nhưng lưu ý rằng label đã xóa vẫn tồn tại trong các Pod và ReplicaSet hiện có. Bạn có thể dọn dẹp điều đó bằng cách kích hoạt một rollout cho Deployment.

Rollback một Deployment

Đôi khi, bạn có thể muốn rollback một Deployment; ví dụ, khi Deployment không ổn định, chẳng hạn như bị crash liên tục (crash looping). Theo mặc định, toàn bộ lịch sử rollout của Deployment được lưu giữ trong hệ thống để bạn có thể rollback bất cứ lúc nào (bạn có thể thay đổi điều này bằng cách sửa giới hạn lịch sử revision - revision history limit).

Lưu ý:

Revision của một Deployment được tạo khi rollout của Deployment được kích hoạt. Điều này có nghĩa là revision mới được tạo khi và chỉ khi Pod template (.spec.template) của Deployment bị thay đổi, ví dụ khi bạn cập nhật label hoặc image container của template. Các cập nhật khác, chẳng hạn như scale Deployment, không tạo ra revision mới của Deployment, nhờ đó bạn có thể thực hiện đồng thời việc scale thủ công hoặc tự động. Điều này có nghĩa là khi bạn rollback về một revision trước đó, chỉ phần Pod template của Deployment được rollback.
  • Giả sử bạn gõ nhầm khi cập nhật Deployment, đặt tên image là nginx:1.161 thay vì nginx:1.16.1:

    kubectl set image deployment/nginx-deployment nginx=nginx:1.161
    

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment image updated
    
  • Rollout bị kẹt. Bạn có thể xác minh điều này bằng cách kiểm tra trạng thái rollout:

    kubectl rollout status deployment/nginx-deployment
    

    Kết quả tương tự như sau:

    Waiting for rollout to finish: 1 out of 3 new replicas have been updated...
    
  • Nhấn Ctrl-C để dừng theo dõi trạng thái rollout ở trên. Để biết thêm thông tin về các rollout bị kẹt, đọc thêm tại đây.

  • Bạn thấy rằng số replica cũ (cộng số replica từ nginx-deployment-1564180365 và nginx-deployment-2035384211) là 3, và số replica mới (từ nginx-deployment-3066724191) là 1.

    kubectl get rs
    

    Kết quả tương tự như sau:

    NAME                          DESIRED   CURRENT   READY   AGE
    nginx-deployment-1564180365   3         3         3       25s
    nginx-deployment-2035384211   0         0         0       36s
    nginx-deployment-3066724191   1         1         0       6s
    
  • Xem các Pod đã được tạo, bạn sẽ thấy 1 Pod được tạo bởi ReplicaSet mới bị kẹt trong vòng lặp kéo image (image pull loop).

    kubectl get pods
    

    Kết quả tương tự như sau:

    NAME                                READY     STATUS             RESTARTS   AGE
    nginx-deployment-1564180365-70iae   1/1       Running            0          25s
    nginx-deployment-1564180365-jbqqo   1/1       Running            0          25s
    nginx-deployment-1564180365-hysrc   1/1       Running            0          25s
    nginx-deployment-3066724191-08mng   0/1       ImagePullBackOff   0          6s
    

    Lưu ý:

    Deployment controller tự động dừng rollout lỗi và ngừng scale up ReplicaSet mới. Điều này phụ thuộc vào các tham số rollingUpdate (cụ thể là maxUnavailable) mà bạn đã chỉ định. Theo mặc định, Kubernetes đặt giá trị này là 25%.
  • Lấy mô tả của Deployment:

    kubectl describe deployment
    

    Kết quả tương tự như sau:

    Name:           nginx-deployment
    Namespace:      default
    CreationTimestamp:  Tue, 15 Mar 2016 14:48:04 -0700
    Labels:         app=nginx
    Selector:       app=nginx
    Replicas:       3 desired | 1 updated | 4 total | 3 available | 1 unavailable
    StrategyType:       RollingUpdate
    MinReadySeconds:    0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=nginx
      Containers:
       nginx:
        Image:        nginx:1.161
        Port:         80/TCP
        Host Port:    0/TCP
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    ReplicaSetUpdated
    OldReplicaSets:     nginx-deployment-1564180365 (3/3 replicas created)
    NewReplicaSet:      nginx-deployment-3066724191 (1/1 replicas created)
    Events:
      FirstSeen LastSeen    Count   From                    SubObjectPath   Type        Reason              Message
      --------- --------    -----   ----                    -------------   --------    ------              -------
      1m        1m          1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-2035384211 to 3
      22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 1
      22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 2
      22s       22s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 2
      21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 1
      21s       21s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-1564180365 to 3
      13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled down replica set nginx-deployment-2035384211 to 0
      13s       13s         1       {deployment-controller }                Normal      ScalingReplicaSet   Scaled up replica set nginx-deployment-3066724191 to 1
    

    Để khắc phục điều này, bạn cần rollback về một revision ổn định trước đó của Deployment.

Kiểm tra lịch sử rollout của một Deployment

Làm theo các bước dưới đây để kiểm tra lịch sử rollout:

  1. Đầu tiên, kiểm tra các revision của Deployment này:

    kubectl rollout history deployment/nginx-deployment
    

    Kết quả tương tự như sau:

    deployments "nginx-deployment"
    REVISION    CHANGE-CAUSE
    1           <none>
    2           <none>
    3           <none>
    

    CHANGE-CAUSE được sao chép từ annotation kubernetes.io/change-cause của Deployment sang các revision của nó khi chúng được tạo. Bạn có thể chỉ định thông điệp CHANGE-CAUSE bằng cách:

    • Gắn annotation cho Deployment bằng kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.16.1"
    • Sửa manifest của tài nguyên một cách thủ công.
    • Sử dụng công cụ tự động đặt annotation.

    Lưu ý:

    Trong các phiên bản Kubernetes cũ hơn, bạn có thể dùng cờ --record với các lệnh kubectl để tự động điền trường CHANGE-CAUSE. Cờ này không còn được hỗ trợ (deprecated) và sẽ bị loại bỏ trong một bản phát hành tương lai.
  2. Để xem chi tiết của từng revision, chạy:

    kubectl rollout history deployment/nginx-deployment --revision=2
    

    Kết quả tương tự như sau:

    deployments "nginx-deployment" revision 2
      Labels:       app=nginx
              pod-template-hash=1159050644
      Containers:
       nginx:
        Image:      nginx:1.16.1
        Port:       80/TCP
         QoS Tier:
            cpu:      BestEffort
            memory:   BestEffort
        Environment Variables:      <none>
      No volumes.
    

Rollback về revision trước đó

Làm theo các bước dưới đây để rollback Deployment từ phiên bản hiện tại về phiên bản trước đó, tức là phiên bản 2.

  1. Giả sử bây giờ bạn quyết định hoàn tác rollout hiện tại và rollback về revision trước đó:

    kubectl rollout undo deployment/nginx-deployment
    

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment rolled back
    

    Ngoài ra, bạn có thể rollback về một revision cụ thể bằng cách chỉ định nó với --to-revision:

    kubectl rollout undo deployment/nginx-deployment --to-revision=2
    

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment rolled back
    

    Để biết thêm chi tiết về các lệnh liên quan đến rollout, đọc kubectl rollout.

    Deployment giờ đã được rollback về một revision ổn định trước đó. Như bạn thấy, một sự kiện DeploymentRollback cho việc rollback về revision 2 được tạo ra từ Deployment controller.

  2. Để kiểm tra xem việc rollback đã thành công và Deployment đang chạy như mong đợi hay chưa, chạy:

    kubectl get deployment nginx-deployment
    

    Kết quả tương tự như sau:

    NAME               READY   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment   3/3     3            3           30m
    
  3. Lấy mô tả của Deployment:

    kubectl describe deployment nginx-deployment
    

    Kết quả tương tự như sau:

    Name:                   nginx-deployment
    Namespace:              default
    CreationTimestamp:      Sun, 02 Sep 2018 18:17:55 -0500
    Labels:                 app=nginx
    Annotations:            deployment.kubernetes.io/revision=4
    Selector:               app=nginx
    Replicas:               3 desired | 3 updated | 3 total | 3 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=nginx
      Containers:
       nginx:
        Image:        nginx:1.16.1
        Port:         80/TCP
        Host Port:    0/TCP
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    NewReplicaSetAvailable
    OldReplicaSets:  <none>
    NewReplicaSet:   nginx-deployment-c4747d96c (3/3 replicas created)
    Events:
      Type    Reason              Age   From                   Message
      ----    ------              ----  ----                   -------
      Normal  ScalingReplicaSet   12m   deployment-controller  Scaled up replica set nginx-deployment-75675f5897 to 3
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 1
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 2
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 2
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 1
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-c4747d96c to 3
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled down replica set nginx-deployment-75675f5897 to 0
      Normal  ScalingReplicaSet   11m   deployment-controller  Scaled up replica set nginx-deployment-595696685f to 1
      Normal  DeploymentRollback  15s   deployment-controller  Rolled back deployment "nginx-deployment" to revision 2
      Normal  ScalingReplicaSet   15s   deployment-controller  Scaled down replica set nginx-deployment-595696685f to 0
    

Scale một Deployment

Bạn có thể scale một Deployment bằng lệnh sau:

kubectl scale deployment/nginx-deployment --replicas=10

Kết quả tương tự như sau:

deployment.apps/nginx-deployment scaled

Giả sử horizontal Pod autoscaling đã được bật trong cluster của bạn, bạn có thể thiết lập một autoscaler cho Deployment và chọn số lượng Pod tối thiểu và tối đa mà bạn muốn chạy dựa trên mức sử dụng CPU của các Pod hiện có.

kubectl autoscale deployment/nginx-deployment --min=10 --max=15 --cpu-percent=80%

Kết quả tương tự như sau:

deployment.apps/nginx-deployment scaled

Scale theo tỷ lệ

Các Deployment kiểu RollingUpdate hỗ trợ chạy nhiều phiên bản của một ứng dụng cùng một lúc. Khi bạn hoặc một autoscaler scale một Deployment RollingUpdate đang ở giữa quá trình rollout (đang diễn ra hoặc đang tạm dừng), Deployment controller sẽ phân bổ cân đối các replica bổ sung vào các ReplicaSet đang hoạt động (các ReplicaSet có Pod) để giảm thiểu rủi ro. Điều này được gọi là scale theo tỷ lệ (proportional scaling).

Ví dụ, bạn đang chạy một Deployment với 10 replica, maxSurge=3, và maxUnavailable=2.

  • Đảm bảo rằng 10 replica trong Deployment của bạn đang chạy.

    kubectl get deploy
    

    Kết quả tương tự như sau:

    NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    nginx-deployment     10        10        10           10          50s
    
  • Bạn cập nhật sang một image mới mà không thể phân giải được từ bên trong cluster.

    kubectl set image deployment/nginx-deployment nginx=nginx:sometag
    

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment image updated
    
  • Việc cập nhật image khởi động một rollout mới với ReplicaSet nginx-deployment-1989198191, nhưng rollout này bị chặn do yêu cầu maxUnavailable mà bạn đã đề cập ở trên. Kiểm tra trạng thái rollout:

    kubectl get rs
    

    Kết quả tương tự như sau:

    NAME                          DESIRED   CURRENT   READY     AGE
    nginx-deployment-1989198191   5         5         0         9s
    nginx-deployment-618515232    8         8         8         1m
    
  • Sau đó, một yêu cầu scale mới cho Deployment xuất hiện. Autoscaler tăng số replica của Deployment lên 15. Deployment controller cần quyết định nơi để thêm 5 replica mới này. Nếu bạn không sử dụng scale theo tỷ lệ, cả 5 replica sẽ được thêm vào ReplicaSet mới. Với scale theo tỷ lệ, bạn phân bổ các replica bổ sung cho tất cả các ReplicaSet. Phần lớn hơn được chia cho các ReplicaSet có nhiều replica nhất và phần nhỏ hơn được chia cho các ReplicaSet có ít replica hơn. Phần dư sẽ được thêm vào ReplicaSet có nhiều replica nhất. Các ReplicaSet có 0 replica sẽ không được scale up.

Trong ví dụ trên, 3 replica được thêm vào ReplicaSet cũ và 2 replica được thêm vào ReplicaSet mới. Quá trình rollout cuối cùng sẽ chuyển tất cả các replica sang ReplicaSet mới, với giả định các replica mới hoạt động bình thường (healthy). Để xác nhận điều này, chạy:

kubectl get deploy

Kết quả tương tự như sau:

NAME                 DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment     15        18        7            8           7m

Trạng thái rollout xác nhận cách các replica được thêm vào mỗi ReplicaSet.

kubectl get rs

Kết quả tương tự như sau:

NAME                          DESIRED   CURRENT   READY     AGE
nginx-deployment-1989198191   7         7         0         7m
nginx-deployment-618515232    11        11        11        7m

Tạm dừng và tiếp tục rollout của một Deployment

Khi bạn cập nhật một Deployment, hoặc dự định cập nhật, bạn có thể tạm dừng các rollout của Deployment đó trước khi kích hoạt một hoặc nhiều cập nhật. Khi bạn đã sẵn sàng áp dụng các thay đổi đó, bạn tiếp tục các rollout cho Deployment. Cách làm này cho phép bạn áp dụng nhiều bản sửa lỗi trong khoảng thời gian giữa lúc tạm dừng và tiếp tục mà không kích hoạt các rollout không cần thiết.

  • Ví dụ, với một Deployment vừa được tạo:

    Lấy thông tin chi tiết của Deployment:

    kubectl get deploy
    

    Kết quả tương tự như sau:

    NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
    nginx     3         3         3            3           1m
    

    Lấy trạng thái rollout:

    kubectl get rs
    

    Kết quả tương tự như sau:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   3         3         3         1m
    
  • Tạm dừng bằng cách chạy lệnh sau:

    kubectl rollout pause deployment/nginx-deployment
    

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment paused
    
  • Sau đó cập nhật image của Deployment:

    kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
    

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment image updated
    
  • Lưu ý rằng không có rollout mới nào được bắt đầu:

    kubectl rollout history deployment/nginx-deployment
    

    Kết quả tương tự như sau:

    deployments "nginx"
    REVISION  CHANGE-CAUSE
    1   <none>
    
  • Lấy trạng thái rollout để xác minh rằng ReplicaSet hiện có không thay đổi:

    kubectl get rs
    

    Kết quả tương tự như sau:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   3         3         3         2m
    
  • Bạn có thể thực hiện bao nhiêu cập nhật tùy thích, ví dụ, cập nhật các tài nguyên sẽ được sử dụng:

    kubectl set resources deployment/nginx-deployment -c=nginx --limits=cpu=200m,memory=512Mi
    

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment resource requirements updated
    

    Trạng thái ban đầu của Deployment trước khi tạm dừng rollout vẫn tiếp tục hoạt động, nhưng các cập nhật mới cho Deployment sẽ không có tác dụng chừng nào rollout của Deployment còn đang bị tạm dừng.

  • Cuối cùng, tiếp tục rollout của Deployment và quan sát một ReplicaSet mới được tạo ra với tất cả các cập nhật mới:

    kubectl rollout resume deployment/nginx-deployment
    

    Kết quả tương tự như sau:

    deployment.apps/nginx-deployment resumed
    
  • Theo dõi (watch) trạng thái của rollout cho đến khi hoàn tất.

    kubectl get rs --watch
    

    Kết quả tương tự như sau:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   2         2         2         2m
    nginx-3926361531   2         2         0         6s
    nginx-3926361531   2         2         1         18s
    nginx-2142116321   1         2         2         2m
    nginx-2142116321   1         2         2         2m
    nginx-3926361531   3         2         1         18s
    nginx-3926361531   3         2         1         18s
    nginx-2142116321   1         1         1         2m
    nginx-3926361531   3         3         1         18s
    nginx-3926361531   3         3         2         19s
    nginx-2142116321   0         1         1         2m
    nginx-2142116321   0         1         1         2m
    nginx-2142116321   0         0         0         2m
    nginx-3926361531   3         3         3         20s
    
  • Lấy trạng thái của rollout mới nhất:

    kubectl get rs
    

    Kết quả tương tự như sau:

    NAME               DESIRED   CURRENT   READY     AGE
    nginx-2142116321   0         0         0         2m
    nginx-3926361531   3         3         3         28s
    

Lưu ý:

Bạn không thể rollback một Deployment đang bị tạm dừng cho đến khi bạn tiếp tục (resume) nó.

Trạng thái của Deployment

Một Deployment trải qua nhiều trạng thái khác nhau trong vòng đời của nó. Nó có thể đang tiến triển trong khi rollout một ReplicaSet mới, có thể hoàn tất, hoặc có thể không tiến triển được.

Deployment đang tiến triển

Kubernetes đánh dấu một Deployment là đang tiến triển (progressing) khi một trong các tác vụ sau được thực hiện:

  • Deployment tạo một ReplicaSet mới.
  • Deployment đang scale up ReplicaSet mới nhất của nó.
  • Deployment đang scale down (các) ReplicaSet cũ hơn của nó.
  • Các Pod mới trở nên ready hoặc available (ready trong ít nhất MinReadySeconds).

Khi rollout chuyển sang trạng thái “progressing”, Deployment controller thêm một condition với các thuộc tính sau vào .status.conditions của Deployment:

  • type: Progressing
  • status: "True"
  • reason: NewReplicaSetCreated | reason: FoundNewReplicaSet | reason: ReplicaSetUpdated

Bạn có thể theo dõi tiến trình của một Deployment bằng cách sử dụng kubectl rollout status.

Deployment hoàn tất

Kubernetes đánh dấu một Deployment là hoàn tất (complete) khi nó có các đặc điểm sau:

  • Tất cả các replica liên kết với Deployment đã được cập nhật lên phiên bản mới nhất mà bạn chỉ định, nghĩa là mọi cập nhật bạn yêu cầu đều đã được hoàn thành.
  • Tất cả các replica liên kết với Deployment đều sẵn sàng (available).
  • Không có replica cũ nào của Deployment đang chạy.

Khi rollout chuyển sang trạng thái “complete”, Deployment controller đặt một condition với các thuộc tính sau vào .status.conditions của Deployment:

  • type: Progressing
  • status: "True"
  • reason: NewReplicaSetAvailable

Condition Progressing này sẽ giữ giá trị trạng thái "True" cho đến khi một rollout mới được khởi tạo. Condition này vẫn giữ nguyên ngay cả khi tính khả dụng của các replica thay đổi (điều này thay vào đó sẽ ảnh hưởng đến condition Available).

Bạn có thể kiểm tra xem một Deployment đã hoàn tất hay chưa bằng cách sử dụng kubectl rollout status. Nếu rollout hoàn tất thành công, kubectl rollout status trả về exit code bằng 0.

kubectl rollout status deployment/nginx-deployment

Kết quả tương tự như sau:

Waiting for rollout to finish: 2 of 3 updated replicas are available...
deployment "nginx-deployment" successfully rolled out

và exit status của kubectl rollout là 0 (thành công):

echo $?
0

Deployment thất bại

Deployment của bạn có thể bị kẹt khi cố gắng triển khai ReplicaSet mới nhất mà không bao giờ hoàn tất. Điều này có thể xảy ra do một số yếu tố sau:

  • Không đủ quota
  • Readiness probe thất bại
  • Lỗi khi kéo image (image pull)
  • Không đủ quyền
  • Limit range
  • Cấu hình runtime của ứng dụng bị sai

Một cách để phát hiện tình trạng này là chỉ định một tham số thời hạn (deadline) trong spec của Deployment: (.spec.progressDeadlineSeconds). .spec.progressDeadlineSeconds biểu thị số giây mà Deployment controller chờ trước khi báo hiệu (trong trạng thái của Deployment) rằng tiến trình của Deployment đã bị đình trệ.

Lệnh kubectl sau đây thiết lập spec với progressDeadlineSeconds để khiến controller báo cáo việc rollout của Deployment không có tiến triển sau 10 phút:

kubectl patch deployment/nginx-deployment -p '{"spec":{"progressDeadlineSeconds":600}}'

Kết quả tương tự như sau:

deployment.apps/nginx-deployment patched

Khi vượt quá thời hạn, Deployment controller sẽ thêm một DeploymentCondition với các thuộc tính sau vào .status.conditions của Deployment:

  • type: Progressing
  • status: "False"
  • reason: ProgressDeadlineExceeded

Condition này cũng có thể thất bại sớm và khi đó được đặt giá trị trạng thái "False" vì các lý do như ReplicaSetCreateError. Ngoài ra, thời hạn sẽ không còn được tính đến khi rollout của Deployment đã hoàn tất.

Xem Kubernetes API conventions để biết thêm thông tin về các status condition.

Lưu ý:

Kubernetes không thực hiện bất kỳ hành động nào đối với một Deployment bị đình trệ ngoài việc báo cáo một status condition với reason: ProgressDeadlineExceeded. Các orchestrator cấp cao hơn có thể tận dụng điều này và hành động tương ứng, ví dụ như rollback Deployment về phiên bản trước đó.

Lưu ý:

Nếu bạn tạm dừng rollout của một Deployment, Kubernetes không kiểm tra tiến trình so với thời hạn bạn đã chỉ định. Bạn có thể an toàn tạm dừng rollout của một Deployment giữa chừng rồi tiếp tục mà không kích hoạt condition vượt quá thời hạn.

Bạn có thể gặp phải các lỗi tạm thời với Deployment, do bạn đặt timeout quá thấp hoặc do bất kỳ loại lỗi nào khác có thể được coi là tạm thời. Ví dụ, giả sử bạn không đủ quota. Nếu bạn describe Deployment, bạn sẽ thấy phần sau:

kubectl describe deployment nginx-deployment

Kết quả tương tự như sau:

<...>
Conditions:
  Type            Status  Reason
  ----            ------  ------
  Available       True    MinimumReplicasAvailable
  Progressing     True    ReplicaSetUpdated
  ReplicaFailure  True    FailedCreate
<...>

Nếu bạn chạy kubectl get deployment nginx-deployment -o yaml, trạng thái của Deployment tương tự như sau:

status:
  availableReplicas: 2
  conditions:
  - lastTransitionTime: 2016-10-04T12:25:39Z
    lastUpdateTime: 2016-10-04T12:25:39Z
    message: Replica set "nginx-deployment-4262182780" is progressing.
    reason: ReplicaSetUpdated
    status: "True"
    type: Progressing
  - lastTransitionTime: 2016-10-04T12:25:42Z
    lastUpdateTime: 2016-10-04T12:25:42Z
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: 2016-10-04T12:25:39Z
    lastUpdateTime: 2016-10-04T12:25:39Z
    message: 'Error creating: pods "nginx-deployment-4262182780-" is forbidden: exceeded quota:
      object-counts, requested: pods=1, used: pods=3, limited: pods=2'
    reason: FailedCreate
    status: "True"
    type: ReplicaFailure
  observedGeneration: 3
  replicas: 2
  unavailableReplicas: 2

Cuối cùng, khi vượt quá thời hạn tiến trình của Deployment, Kubernetes sẽ cập nhật trạng thái và lý do (reason) của condition Progressing:

Conditions:
  Type            Status  Reason
  ----            ------  ------
  Available       True    MinimumReplicasAvailable
  Progressing     False   ProgressDeadlineExceeded
  ReplicaFailure  True    FailedCreate

Bạn có thể giải quyết vấn đề thiếu quota bằng cách scale down Deployment, scale down các controller khác mà bạn đang chạy, hoặc tăng quota trong namespace của bạn. Nếu bạn đáp ứng các điều kiện về quota và sau đó Deployment controller hoàn tất rollout của Deployment, bạn sẽ thấy trạng thái của Deployment được cập nhật với một condition thành công (status: "True" và reason: NewReplicaSetAvailable).

Conditions:
  Type          Status  Reason
  ----          ------  ------
  Available     True    MinimumReplicasAvailable
  Progressing   True    NewReplicaSetAvailable

type: Available với status: "True" nghĩa là Deployment của bạn đạt mức khả dụng tối thiểu (minimum availability). Mức khả dụng tối thiểu được quyết định bởi các tham số được chỉ định trong chiến lược triển khai (deployment strategy). type: Progressing với status: "True" nghĩa là Deployment của bạn hoặc đang ở giữa quá trình rollout và đang tiến triển, hoặc đã hoàn tất tiến trình thành công và số lượng replica mới tối thiểu cần thiết đã sẵn sàng (xem Reason của condition để biết chi tiết - trong trường hợp của chúng ta, reason: NewReplicaSetAvailable nghĩa là Deployment đã hoàn tất).

Bạn có thể kiểm tra xem một Deployment có bị thất bại trong việc tiến triển hay không bằng cách sử dụng kubectl rollout status. kubectl rollout status trả về exit code khác 0 nếu Deployment đã vượt quá thời hạn tiến trình.

kubectl rollout status deployment/nginx-deployment

Kết quả tương tự như sau:

Waiting for rollout to finish: 2 out of 3 new replicas have been updated...
error: deployment "nginx" exceeded its progress deadline

và exit status của kubectl rollout là 1 (cho biết có lỗi):

echo $?
1

Thao tác trên một Deployment thất bại

Tất cả các thao tác áp dụng cho một Deployment hoàn tất cũng áp dụng cho một Deployment thất bại. Bạn có thể scale up/down, rollback về một revision trước đó, hoặc thậm chí tạm dừng nó nếu bạn cần áp dụng nhiều điều chỉnh cho Pod template của Deployment.

Chính sách dọn dẹp

Bạn có thể đặt trường .spec.revisionHistoryLimit trong một Deployment để chỉ định số lượng ReplicaSet cũ của Deployment này mà bạn muốn giữ lại. Phần còn lại sẽ được thu gom rác (garbage-collected) ở chế độ nền. Theo mặc định, giá trị này là 10.

Lưu ý:

Việc đặt tường minh trường này bằng 0 sẽ dẫn đến việc dọn sạch toàn bộ lịch sử của Deployment, do đó Deployment đó sẽ không thể rollback.

Việc dọn dẹp chỉ bắt đầu sau khi Deployment đạt trạng thái hoàn tất. Nếu bạn đặt .spec.revisionHistoryLimit bằng 0, mọi rollout vẫn kích hoạt việc tạo một ReplicaSet mới trước khi Kubernetes xóa ReplicaSet cũ.

Ngay cả khi giới hạn lịch sử revision khác 0, bạn vẫn có thể có nhiều ReplicaSet hơn giới hạn mà bạn cấu hình. Ví dụ, nếu các Pod bị crash liên tục (crash looping) và có nhiều sự kiện rolling update được kích hoạt theo thời gian, bạn có thể có nhiều ReplicaSet hơn .spec.revisionHistoryLimit vì Deployment không bao giờ đạt trạng thái hoàn tất.

Canary deployment

Nếu bạn muốn rollout các bản phát hành (release) cho một nhóm nhỏ người dùng hoặc máy chủ bằng Deployment, bạn có thể tạo nhiều Deployment, mỗi Deployment tương ứng với một bản phát hành, theo mô hình canary được mô tả trong quản lý tài nguyên.

Để tìm hiểu chi tiết, hãy làm theo hướng dẫn Triển khai một bản phát hành bằng Canary Deployment.

Viết spec cho Deployment

Giống như mọi cấu hình Kubernetes khác, một Deployment cần các trường .apiVersion, .kind và .metadata. Để biết thông tin chung về cách làm việc với các file cấu hình, xem triển khai ứng dụng, cấu hình container, và sử dụng kubectl để quản lý tài nguyên.

Khi control plane tạo các Pod mới cho một Deployment, .metadata.name của Deployment là một phần cơ sở để đặt tên cho các Pod đó. Tên của Deployment phải là một giá trị DNS subdomain hợp lệ, nhưng điều này có thể gây ra kết quả không mong muốn cho hostname của Pod. Để tương thích tốt nhất, tên nên tuân theo các quy tắc chặt chẽ hơn của một DNS label.

Một Deployment cũng cần có phần .spec.

Pod Template

.spec.template và .spec.selector là các trường bắt buộc duy nhất của .spec.

.spec.template là một Pod template. Nó có schema giống hệt một Pod, ngoại trừ việc nó được lồng bên trong và không có apiVersion hay kind.

Ngoài các trường bắt buộc của một Pod, Pod template trong một Deployment phải chỉ định các label và một restart policy phù hợp. Với label, hãy đảm bảo không trùng lặp với các controller khác. Xem selector.

Chỉ cho phép .spec.template.spec.restartPolicy bằng Always, đây cũng là giá trị mặc định nếu không được chỉ định.

Replicas

.spec.replicas là một trường tùy chọn, chỉ định số lượng Pod mong muốn. Giá trị mặc định là 1.

Nếu bạn scale một Deployment thủ công, ví dụ qua kubectl scale deployment deployment --replicas=X, rồi sau đó cập nhật Deployment đó dựa trên một manifest (ví dụ: bằng cách chạy kubectl apply -f deployment.yaml), thì việc áp dụng manifest đó sẽ ghi đè lên việc scale thủ công mà bạn đã thực hiện trước đó.

Nếu một HorizontalPodAutoscaler (hoặc bất kỳ API tương tự nào cho horizontal scaling) đang quản lý việc scale cho một Deployment, đừng đặt .spec.replicas.

Thay vào đó, hãy để control plane của Kubernetes tự động quản lý trường .spec.replicas.

Selector

.spec.selector là một trường bắt buộc, chỉ định một label selector cho các Pod mà Deployment này nhắm tới.

.spec.selector phải khớp với .spec.template.metadata.labels, nếu không sẽ bị API từ chối.

Trong phiên bản API apps/v1, .spec.selector và .metadata.labels không mặc định lấy giá trị của .spec.template.metadata.labels nếu không được đặt. Vì vậy chúng phải được đặt một cách tường minh. Cũng lưu ý rằng trong apps/v1, .spec.selector là bất biến sau khi Deployment được tạo.

Một Deployment có thể dừng (terminate) các Pod có label khớp với selector nếu template của chúng khác với .spec.template hoặc nếu tổng số lượng các Pod như vậy vượt quá .spec.replicas. Nó sẽ khởi chạy các Pod mới với .spec.template nếu số lượng Pod ít hơn số lượng mong muốn.

Lưu ý:

Bạn không nên tạo các Pod khác có label khớp với selector này, dù là trực tiếp, bằng cách tạo một Deployment khác, hay bằng cách tạo một controller khác như ReplicaSet hoặc ReplicationController. Nếu bạn làm vậy, Deployment đầu tiên sẽ cho rằng chính nó đã tạo ra các Pod khác này. Kubernetes không ngăn bạn làm điều này.

Nếu bạn có nhiều controller có selector trùng lặp nhau, các controller đó sẽ tranh chấp với nhau và sẽ không hoạt động đúng.

Strategy

.spec.strategy chỉ định chiến lược được sử dụng để thay thế các Pod cũ bằng các Pod mới. .spec.strategy.type có thể là "Recreate" hoặc "RollingUpdate". "RollingUpdate" là giá trị mặc định.

Recreate Deployment

Khi .spec.strategy.type==Recreate, tất cả các Pod hiện có sẽ bị dừng trước khi các Pod mới được tạo.

Lưu ý:

Điều này chỉ đảm bảo các Pod bị dừng trước khi tạo Pod mới đối với các lần nâng cấp. Nếu bạn nâng cấp một Deployment, tất cả các Pod của revision cũ sẽ bị dừng ngay lập tức. Hệ thống chờ việc xóa thành công rồi mới tạo bất kỳ Pod nào của revision mới. Nếu bạn xóa thủ công một Pod, vòng đời của nó do ReplicaSet kiểm soát và Pod thay thế sẽ được tạo ngay lập tức (ngay cả khi Pod cũ vẫn đang ở trạng thái Terminating). Nếu bạn cần đảm bảo "tối đa" (at most) cho các Pod của mình, bạn nên cân nhắc sử dụng một StatefulSet.

Rolling Update Deployment

Deployment cập nhật các Pod theo kiểu rolling update (scale down dần các ReplicaSet cũ và scale up ReplicaSet mới) khi .spec.strategy.type==RollingUpdate. Bạn có thể chỉ định maxUnavailable và maxSurge để kiểm soát quá trình rolling update.

Max Unavailable

.spec.strategy.rollingUpdate.maxUnavailable là một trường tùy chọn, chỉ định số lượng Pod tối đa có thể không khả dụng (unavailable) trong quá trình cập nhật. Giá trị có thể là một số tuyệt đối (ví dụ: 5) hoặc tỷ lệ phần trăm của số Pod mong muốn (ví dụ: 10%). Số tuyệt đối được tính từ tỷ lệ phần trăm bằng cách làm tròn xuống. Giá trị này không thể bằng 0 nếu .spec.strategy.rollingUpdate.maxSurge bằng 0. Giá trị mặc định là 25%.

Ví dụ, khi giá trị này được đặt là 30%, ReplicaSet cũ có thể được scale down xuống còn 70% số Pod mong muốn ngay khi rolling update bắt đầu. Khi các Pod mới đã sẵn sàng, ReplicaSet cũ có thể được scale down thêm, tiếp theo là scale up ReplicaSet mới, đảm bảo rằng tổng số Pod khả dụng tại mọi thời điểm trong quá trình cập nhật luôn ít nhất bằng 70% số Pod mong muốn.

Max Surge

.spec.strategy.rollingUpdate.maxSurge là một trường tùy chọn, chỉ định số lượng Pod tối đa có thể được tạo vượt quá số lượng Pod mong muốn. Giá trị có thể là một số tuyệt đối (ví dụ: 5) hoặc tỷ lệ phần trăm của số Pod mong muốn (ví dụ: 10%). Giá trị này không thể bằng 0 nếu maxUnavailable bằng 0. Số tuyệt đối được tính từ tỷ lệ phần trăm bằng cách làm tròn lên. Giá trị mặc định là 25%.

Ví dụ, khi giá trị này được đặt là 30%, ReplicaSet mới có thể được scale up ngay khi rolling update bắt đầu, sao cho tổng số Pod cũ và mới không vượt quá 130% số Pod mong muốn. Khi các Pod cũ đã bị dừng, ReplicaSet mới có thể được scale up thêm, đảm bảo rằng tổng số Pod đang chạy tại mọi thời điểm trong quá trình cập nhật tối đa là 130% số Pod mong muốn.

Dưới đây là một số ví dụ về Rolling Update Deployment sử dụng maxUnavailable và maxSurge:

apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
   app: nginx
spec:
 replicas: 3
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx:1.14.2
       ports:
       - containerPort: 80
 strategy:
   type: RollingUpdate
   rollingUpdate:
     maxUnavailable: 1
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
   app: nginx
spec:
 replicas: 3
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx:1.14.2
       ports:
       - containerPort: 80
 strategy:
   type: RollingUpdate
   rollingUpdate:
     maxSurge: 1
apiVersion: apps/v1
kind: Deployment
metadata:
 name: nginx-deployment
 labels:
   app: nginx
spec:
 replicas: 3
 selector:
   matchLabels:
     app: nginx
 template:
   metadata:
     labels:
       app: nginx
   spec:
     containers:
     - name: nginx
       image: nginx:1.14.2
       ports:
       - containerPort: 80
 strategy:
   type: RollingUpdate
   rollingUpdate:
     maxSurge: 1
     maxUnavailable: 1

Progress Deadline Seconds

.spec.progressDeadlineSeconds là một trường tùy chọn, chỉ định số giây bạn muốn chờ Deployment tiến triển trước khi hệ thống báo cáo rằng Deployment đã không tiến triển được - được thể hiện dưới dạng một condition với type: Progressing, status: "False". và reason: ProgressDeadlineExceeded trong trạng thái của tài nguyên. Deployment controller sẽ tiếp tục thử lại Deployment. Giá trị mặc định là 600.

Nếu được chỉ định, trường này cần lớn hơn .spec.minReadySeconds.

Min Ready Seconds

.spec.minReadySeconds là một trường tùy chọn, chỉ định số giây tối thiểu mà một Pod mới được tạo phải ở trạng thái ready mà không có container nào bị crash, để được coi là available (khả dụng). Giá trị mặc định là 0 (Pod sẽ được coi là available ngay khi nó ready). Để tìm hiểu thêm về thời điểm một Pod được coi là ready, xem Container Probes.

Các Pod đang dừng (terminating)

TRẠNG THÁI TÍNH NĂNG: Beta since Kubernetes v1.35; enabled by default

Bạn chỉ có thể thấy các Pod đang dừng nếu DeploymentReplicaSetTerminatingReplicas feature gate được bật trên API server và trên kube-controller-manager

Các Pod chuyển sang trạng thái đang dừng do bị xóa hoặc do scale down có thể mất nhiều thời gian để dừng hẳn, và có thể tiêu tốn thêm tài nguyên trong khoảng thời gian đó. Do đó, tổng số Pod có thể tạm thời vượt quá .spec.replicas. Bạn có thể theo dõi các Pod đang dừng bằng trường .status.terminatingReplicas của Deployment.

Revision History Limit

Lịch sử revision của một Deployment được lưu trữ trong các ReplicaSet mà nó kiểm soát.

.spec.revisionHistoryLimit là một trường tùy chọn, chỉ định số lượng ReplicaSet cũ được giữ lại để cho phép rollback. Các ReplicaSet cũ này tiêu tốn tài nguyên trong etcd và làm rối kết quả của kubectl get rs. Cấu hình của mỗi revision Deployment được lưu trữ trong các ReplicaSet của nó; do đó, một khi ReplicaSet cũ bị xóa, bạn sẽ mất khả năng rollback về revision đó của Deployment. Theo mặc định, 10 ReplicaSet cũ sẽ được giữ lại, tuy nhiên giá trị lý tưởng của trường này phụ thuộc vào tần suất và độ ổn định của các Deployment mới.

Cụ thể hơn, việc đặt trường này bằng 0 có nghĩa là tất cả các ReplicaSet cũ có 0 replica sẽ bị dọn dẹp. Trong trường hợp này, không thể hoàn tác (undo) một rollout mới của Deployment, vì lịch sử revision của nó đã bị dọn dẹp.

Paused

.spec.paused là một trường boolean tùy chọn dùng để tạm dừng và tiếp tục một Deployment. Điểm khác biệt duy nhất giữa một Deployment đang tạm dừng và một Deployment không bị tạm dừng là mọi thay đổi đối với PodTemplateSpec của Deployment đang tạm dừng sẽ không kích hoạt rollout mới chừng nào nó còn đang bị tạm dừng. Theo mặc định, một Deployment không bị tạm dừng khi được tạo.

Tiếp theo là gì

2 - Service

Hiển thị một ứng dụng đang chạy trong cluster của bạn dưới cùng một endpoint hướng ra bên ngoài, ngay cả khi workload được chia thành nhiều backend.

Trang này đang được dịch. Vui lòng xem phiên bản tiếng Anh để biết thông tin mới nhất.

3 - Persistent Volumes

Trang này đang được dịch. Vui lòng xem phiên bản tiếng Anh để biết thông tin mới nhất.

4 - Tổng quan

4.1 - Kubernetes là gì

Trang tổng quan của Kubernetes.

Kubernetes là một nền tảng nguồn mở, khả chuyển, có thể mở rộng để quản lý các ứng dụng được đóng gói và các service, giúp thuận lợi trong việc cấu hình và tự động hoá việc triển khai ứng dụng. Kubernetes là một hệ sinh thái lớn và phát triển nhanh chóng. Các dịch vụ, sự hỗ trợ và công cụ có sẵn rộng rãi.

Tên gọi Kubernetes có nguồn gốc từ tiếng Hy Lạp, có ý nghĩa là người lái tàu hoặc hoa tiêu. Google mở mã nguồn Kubernetes từ năm 2014. Kubernetes xây dựng dựa trên một thập kỷ rưỡi kinh nghiệm mà Google có được với việc vận hành một khối lượng lớn workload trong thực tế, kết hợp với các ý tưởng và thực tiễn tốt nhất từ cộng đồng.

Quay ngược thời gian

Chúng ta hãy xem tại sao Kubernetes rất hữu ích bằng cách quay ngược thời gian.

Deployment evolution

Thời đại triển khai theo cách truyền thống: Ban đầu, các ứng dụng được chạy trên các máy chủ vật lý. Không có cách nào để xác định ranh giới tài nguyên cho các ứng dụng trong máy chủ vật lý và điều này gây ra sự cố phân bổ tài nguyên. Ví dụ, nếu nhiều ứng dụng cùng chạy trên một máy chủ vật lý, có thể có những trường hợp một ứng dụng sẽ chiếm phần lớn tài nguyên hơn và kết quả là các ứng dụng khác sẽ hoạt động kém đi. Một giải pháp cho điều này sẽ là chạy từng ứng dụng trên một máy chủ vật lý khác nhau. Nhưng giải pháp này không tối ưu vì tài nguyên không được sử dụng đúng mức và rất tốn kém cho các tổ chức để có thể duy trì nhiều máy chủ vật lý như vậy.

Thời đại triển khai ảo hóa: Như một giải pháp, ảo hóa đã được giới thiệu. Nó cho phép bạn chạy nhiều Máy ảo (VM) trên CPU của một máy chủ vật lý. Ảo hóa cho phép các ứng dụng được cô lập giữa các VM và cung cấp mức độ bảo mật vì thông tin của một ứng dụng không thể được truy cập tự do bởi một ứng dụng khác.

Ảo hóa cho phép sử dụng tốt hơn các tài nguyên trong một máy chủ vật lý và cho phép khả năng mở rộng tốt hơn vì một ứng dụng có thể được thêm hoặc cập nhật dễ dàng, giảm chi phí phần cứng và hơn thế nữa. Với ảo hóa, bạn có thể có một tập hợp các tài nguyên vật lý dưới dạng một cụm các máy ảo sẵn dùng.

Mỗi VM là một máy tính chạy tất cả các thành phần, bao gồm cả hệ điều hành riêng của nó, bên trên phần cứng được ảo hóa.

Thời đại triển khai Container: Các container tương tự như VM, nhưng chúng có tính cô lập để chia sẻ Hệ điều hành (HĐH) giữa các ứng dụng. Do đó, container được coi là nhẹ (lightweight). Tương tự như VM, một container có hệ thống tệp (filesystem), CPU, bộ nhớ, process space, v.v. Khi chúng được tách rời khỏi cơ sở hạ tầng bên dưới, chúng có thể khả chuyển (portable) trên cloud hoặc các bản phân phối Hệ điều hành.

Các container đã trở nên phổ biến vì chúng có thêm nhiều lợi ích, chẳng hạn như:

  • Tạo mới và triển khai ứng dụng Agile: gia tăng tính dễ dàng và hiệu quả của việc tạo các container image so với việc sử dụng VM image.
  • Phát triển, tích hợp và triển khai liên tục: cung cấp khả năng build và triển khai container image thường xuyên và đáng tin cậy với việc rollbacks dễ dàng, nhanh chóng.
  • Phân biệt giữa Dev và Ops: tạo các images của các application container tại thời điểm build/release thay vì thời gian triển khai, do đó phân tách các ứng dụng khỏi hạ tầng.
  • Khả năng quan sát không chỉ hiển thị thông tin và các metric ở mức Hệ điều hành, mà còn cả application health và các tín hiệu khác.
  • Tính nhất quán về môi trường trong suốt quá trình phát triển, testing và trong production: Chạy tương tự trên laptop như trên cloud.
  • Tính khả chuyển trên cloud và các bản phân phối HĐH: Chạy trên Ubuntu, RHEL, CoreOS, on-premises, Google Kubernetes Engine và bất kì nơi nào khác.
  • Quản lý tập trung ứng dụng: Tăng mức độ trừu tượng từ việc chạy một Hệ điều hành trên phần cứng ảo hóa sang chạy một ứng dụng trên một HĐH bằng logical resources.
  • Các micro-services phân tán, elastic: ứng dụng được phân tách thành các phần nhỏ hơn, độc lập và thể được triển khai và quản lý một cách linh hoạt - chứ không phải một app nguyên khối (monolithic).
  • Cô lập các tài nguyên: dự đoán hiệu năng ứng dụng
  • Sử dụng tài nguyên: hiệu quả

Tại sao bạn cần Kubernetes và nó có thể làm những gì?

Các container là một cách tốt để đóng gói và chạy các ứng dụng của bạn. Trong môi trường production, bạn cần quản lý các container chạy các ứng dụng và đảm bảo rằng không có khoảng thời gian downtime. Ví dụ, nếu một container bị tắt đi, một container khác cần phải khởi động lên. Điều này sẽ dễ dàng hơn nếu được xử lý bởi một hệ thống.

Đó là cách Kubernetes đến với chúng ta. Kubernetes cung cấp cho bạn một framework để chạy các hệ phân tán một cách mạnh mẽ. Nó đảm nhiệm việc nhân rộng và chuyển đổi dự phòng cho ứng dụng của bạn, cung cấp các mẫu deployment và hơn thế nữa. Ví dụ, Kubernetes có thể dễ dàng quản lý một triển khai canary cho hệ thống của bạn.

Kubernetes cung cấp cho bạn:

  • Service discovery và cân bằng tải
    Kubernetes có thể expose một container sử dụng DNS hoặc địa chỉ IP của riêng nó. Nếu lượng traffic truy cập đến một container cao, Kubernetes có thể cân bằng tải và phân phối lưu lượng mạng (network traffic) để việc triển khai được ổn định.
  • Điều phối bộ nhớ
    Kubernetes cho phép bạn tự động mount một hệ thống lưu trữ mà bạn chọn, như local storages, public cloud providers, v.v.
  • Tự động rollouts và rollbacks
    Bạn có thể mô tả trạng thái mong muốn cho các container được triển khai dùng Kubernetes và nó có thể thay đổi trạng thái thực tế sang trạng thái mong muốn với tần suất được kiểm soát. Ví dụ, bạn có thể tự động hoá Kubernetes để tạo mới các container cho việc triển khai của bạn, xoá các container hiện có và áp dụng tất cả các resource của chúng vào container mới.
  • Đóng gói tự động
    Bạn cung cấp cho Kubernetes một cluster gồm các node mà nó có thể sử dụng để chạy các tác vụ được đóng gói (containerized task). Bạn cho Kubernetes biết mỗi container cần bao nhiêu CPU và bộ nhớ (RAM). Kubernetes có thể điều phối các container đến các node để tận dụng tốt nhất các resource của bạn.
  • Tự phục hồi
    Kubernetes khởi động lại các containers bị lỗi, thay thế các container, xoá các container không phản hồi lại cấu hình health check do người dùng xác định và không cho các client biết đến chúng cho đến khi chúng sẵn sàng hoạt động.
  • Quản lý cấu hình và bảo mật
    Kubernetes cho phép bạn lưu trữ và quản lý các thông tin nhạy cảm như: password, OAuth token và SSH key. Bạn có thể triển khai và cập nhật lại secret và cấu hình ứng dụng mà không cần build lại các container image và không để lộ secret trong cấu hình stack của bạn.

Kubernetes không phải là gì?

Kubernetes không phải là một hệ thống PaaS (Nền tảng như một Dịch vụ) truyền thống, toàn diện. Do Kubernetes hoạt động ở tầng container chứ không phải ở tầng phần cứng, nó cung cấp một số tính năng thường áp dụng chung cho các dịch vụ PaaS, như triển khai, nhân rộng, cân bằng tải, ghi nhật ký và giám sát. Tuy nhiên, Kubernetes không phải là cấu trúc nguyên khối và các giải pháp mặc định này là tùy chọn và có thể cắm được (pluggable).

Kubernetes:

  • Không giới hạn các loại ứng dụng được hỗ trợ. Kubernetes nhằm mục đích hỗ trợ một khối lượng công việc cực kỳ đa dạng, bao gồm cả stateless, stateful và xử lý dữ liệu. Nếu một ứng dụng có thể chạy trong một container, nó sẽ chạy rất tốt trên Kubernetes.
  • Không triển khai mã nguồn và không build ứng dụng của bạn. Quy trình CI/CD được xác định bởi tổ chức cũng như các yêu cầu kỹ thuật.
  • Không cung cấp các service ở mức ứng dụng, như middleware (ví dụ, các message buses), các framework xử lý dữ liệu (ví dụ, Spark), cơ sở dữ liệu (ví dụ, MySQL), bộ nhớ cache, cũng như hệ thống lưu trữ của cluster (ví dụ, Ceph). Các thành phần như vậy có thể chạy trên Kubernetes và/hoặc có thể được truy cập bởi các ứng dụng chạy trên Kubernetes thông qua các cơ chế di động, chẳng hạn như Open Service Broker.
  • Không bắt buộc các giải pháp ghi lại nhật ký (logging), giám sát (monitoring) hoặc cảnh báo (alerting). Nó cung cấp một số sự tích hợp như proof-of-concept, và cơ chế để thu thập và xuất các số liệu.
  • Không cung cấp, không bắt buộc một cấu hình ngôn ngữ/hệ thống (ví dụ: Jsonnet). Nó cung cấp một API khai báo có thể được targeted bởi các hình thức khai báo tùy ý.
  • Không cung cấp cũng như áp dụng bất kỳ cấu hình toàn diện, bảo trì, quản lý hoặc hệ thống tự phục hồi.
  • Ngoài ra, Kubernetes không phải là một hệ thống điều phối đơn thuần. Trong thực tế, nó loại bỏ sự cần thiết của việc điều phối. Định nghĩa kỹ thuật của điều phối là việc thực thi một quy trình công việc được xác định: đầu tiên làm việc A, sau đó là B rồi sau chót là C. Ngược lại, Kubernetes bao gồm một tập các quy trình kiểm soát độc lập, có thể kết hợp, liên tục điều khiển trạng thái hiện tại theo trạng thái mong muốn đã cho. Nó không phải là vấn đề làm thế nào bạn có thể đi được từ A đến C. Kiểm soát tập trung cũng không bắt buộc. Điều này dẫn đến một hệ thống dễ sử dụng hơn, mạnh mẽ hơn, linh hoạt hơn và có thể mở rộng.

Tiếp theo là gì

5 - Kiến Trúc Cluster

5.1 - Leases

Trong các hệ thống phân tán, Kubernetes sử dụng cơ chế leases (giữ quyền tạm thời) để khóa tài nguyên dùng chung và điều phối hoạt động giữa các thành phần trong cụm. Trong Kubernetes, lease được biểu diễn bằng các đối tượng Lease thuộc API group coordination.k8s.io API Group, Những đối tượng này đóng vai trò quan trọng trong hệ thống, ví dụ như theo dõi trạng thái node (heartbeat) và cơ chế bầu chọn leader giữa các thành phần nội bộ.

Node heartbeats

Kubernetes sử dụng Lease API để truyền tín hiệu heartbeat từ kubelet về Kubernetes API server. Với mỗi đối tượng Node, sẽ có một đối tượng Lease tương ứng (có cùng tên) nằm trong namespace kube-node-lease. Ở tầng bên dưới, mỗi lần kubelet gửi heartbeat thực chất là một lệnh update lên đối tượng Lease, cập nhật trường spec.renewTime. Control plane của Kubernetes sẽ dựa vào dấu thời gian trong trường này để xác định node đó còn hoạt động hay không.

Xem Node Lease objects để biết thêm chi tiết.

Leader election

Kubernetes cũng sử dụng Lease để đảm bảo rằng chỉ một phiên bản duy nhất của một thành phần có thể hoạt động tại một thời điểm. Cơ chế này được áp dụng cho các thành phần của control plane như kube-controller-manager và kube-scheduler trong các cấu hình HA (High Availability) — nơi chỉ một phiên bản của thành phần đó được phép hoạt động chính, còn các phiên bản còn lại sẽ ở chế độ chờ.

Đọc thêm tại coordinated leader election để tìm hiểu cách Kubernetes sử dụng Lease API để chọn phiên bản nào sẽ đóng vai trò leader.

API server identity

TRẠNG THÁI TÍNH NĂNG: Beta since Kubernetes v1.26; enabled by default

Từ phiên bản Kubernetes v1.26, mỗi kube-apiserver sẽ sử dụng Lease API để công bố danh tính của mình với phần còn lại của hệ thống.Mặc dù việc này chưa mang lại lợi ích trực tiếp, nhưng nó cung cấp một cơ chế để các thành phần khác có thể phát hiện được có bao nhiêu phiên bản kube-apiserver đang hoạt động trong control plane. Việc tồn tại các Lease của kube-apiserver giúp chuẩn bị cho các tính năng trong tương lai, nơi các kube-apiserver có thể cần phối hợp hoạt động với nhau.

Bạn có thể kiểm tra các Lease này trong namespace kube-system, với tên theo dạng apiserver-<sha256-hash>. Hoặc sử dụng label để lọc apiserver.kubernetes.io/identity=kube-apiserver:

kubectl -n kube-system get lease -l apiserver.kubernetes.io/identity=kube-apiserver
NAME                                        HOLDER                                                                           AGE
apiserver-07a5ea9b9b072c4a5f3d1c3702        apiserver-07a5ea9b9b072c4a5f3d1c3702_0c8914f7-0f35-440e-8676-7844977d3a05        5m33s
apiserver-7be9e061c59d368b3ddaf1376e        apiserver-7be9e061c59d368b3ddaf1376e_84f2a85d-37c1-4b14-b6b9-603e62e4896f        4m23s
apiserver-1dfef752bcb36637d2763d1868        apiserver-1dfef752bcb36637d2763d1868_c5ffa286-8a9a-45d4-91e7-61118ed58d2e        4m43s

Chuỗi SHA256 hash được sử dụng trong tên của đối tượng Lease được tính dựa trên hostname của hệ điều hành mà kube-apiserver nhìn thấy. Do đó, mỗi kube-apiserver cần được cấu hình với một hostname duy nhất trong cụm Kubernetes để tránh xung đột. Khi có một instance mới của kube-apiserver được khởi động và sử dụng cùng hostname với một instance trước đó, nó sẽ tiếp quản Lease đã có sẵn bằng cách ghi đè holder identity, thay vì tạo một Lease mới.Bạn có thể kiểm tra hostname mà kube-apiserver đang sử dụng bằng cách tra nhãn kubernetes.io/hostname trên node hoặc pod tương ứng:

kubectl -n kube-system get lease apiserver-07a5ea9b9b072c4a5f3d1c3702 -o yaml
apiVersion: coordination.k8s.io/v1
kind: Lease
metadata:
  creationTimestamp: "2023-07-02T13:16:48Z"
  labels:
    apiserver.kubernetes.io/identity: kube-apiserver
    kubernetes.io/hostname: master-1
  name: apiserver-07a5ea9b9b072c4a5f3d1c3702
  namespace: kube-system
  resourceVersion: "334899"
  uid: 90870ab5-1ba9-4523-b215-e4d4e662acb1
spec:
  holderIdentity: apiserver-07a5ea9b9b072c4a5f3d1c3702_0c8914f7-0f35-440e-8676-7844977d3a05
  leaseDurationSeconds: 3600
  renewTime: "2023-07-04T21:58:48.065888Z"

Các Lease đã hết hạn từ những kube-apiserver không còn tồn tại sẽ được thu gom tự động (garbage collect) bởi các kube-apiserver mới sau 1 giờ.

Bạn có thể tắt cơ chế Lease định danh của API server bằng cách vô hiệu hóa feature gate APIServerIdentity. Xem thêm tại feature gate.

Workloads

Bạn có thể tự định nghĩa và sử dụng Lease cho chính workload của mình. Ví dụ: bạn có thể chạy một controller tùy chỉnh, trong đó một bản sao chính (primary hoặc leader) sẽ thực hiện các thao tác mà các bản sao còn lại không thực hiện. Bạn định nghĩa một đối tượng Lease để các bản sao của controller có thể chọn hoặc bầu chọn ra leader, sử dụng Kubernetes API để phối hợp hoạt động. Nếu bạn sử dụng Lease, cách thực hiện tốt là đặt tên Lease sao cho dễ liên kết với sản phẩm hoặc thành phần sử dụng nó. Ví dụ: nếu bạn có một thành phần tên là Example Foo, thì nên đặt Lease là example-foo.

Nếu người vận hành cluster hoặc người dùng cuối có thể triển khai nhiều phiên bản của cùng một thành phần, hãy chọn một tiền tố tên riêng biệt và áp dụng một cơ chế (chẳng hạn như hash của tên Deployment) để tránh trùng tên Lease.

Bạn cũng có thể sử dụng một cách tiếp cận khác, miễn là đạt được mục tiêu chung: các phần mềm khác nhau không gây xung đột với nhau khi sử dụng Lease.

5.2 - Các khái niệm nền tảng của Cloud Controller Manager

Khái niệm Cloud Controller Manager (CCM) (để tránh nhầm lẫn với bản binary build cùng tên) được định nghĩa riêng biệt để cho phép các bên cung cấp dịch vụ cloud và thành phần chính của Kubernetes phát triển độc lập với nhau. CCM chạy đồng thời với những thành phần khác thuộc máy chủ của một cluster như Controller Manager của Kubernetes, API server, và Scheduler. Nó cũng có thể đóng vai trò như một addon cho Kubernetes.

Cloud Controller Manager này được thiết kế dựa trên cơ chế plugin nhằm cho phép các bên Cloud Provider có thể tích hợp với Kubernetes một cách dễ dàng thông qua các plugin này. Đã có những bản kế hoạch được thiết kế sẵn nhằm mục đích hỗ trợ những cloud provider thay đổi từ mô hình cũ sang mô hình mới đi chung với CCM.

Tài liệu này thảo luận về những khái niệm đằng sau một CCM và đưa ra những chi tiết về chức năng liên quan của nó.

Dưới đây là kiến trúc của một Kubernetes cluster khi không đi cùng với Cloud Controller Manager:

Kiến trúc CCM Kube trước đây

Thiết kế

Trong sơ đồ trên, Kubernetes và nhà cung cấp dịch vụ cloud được tích hợp thông qua một số thành phần sau:

  • Kubelet
  • Kubernetes Controller Manager
  • Kubernetes API server

CCM hợp nhất tất cả các logic phụ thuộc trên một nền tàng Cloud từ 3 thành phần trên để tạo thành một điểm tích hợp duy nhất với hệ thống Cloud. Sơ đồ kiến trúc khi đi kèm với CCM sẽ trở thành:

Kiến trúc CCM Kube hiện tại

Các thành phần của CCM

Cloud Controller Manager phân nhỏ một số chức năng của Kubernetes controller manager (KCM) và chạy nó như một tiến trình tách biệt. Cụ thể hơn, nó phân nhỏ những controller trong Kubernetes Controller Manager phụ thuộc vào Cloud. Kubernetes Controller Manager sẽ có những controller nhỏ hơn:

  • Node controller
  • Volume controller
  • Route controller
  • Service controller

Tại phiên bản 1.9, CCM thực hiện chạy những controller sau từ trong danh sách trên:

  • Node controller
  • Route controller
  • Service controller

Lưu ý:

Volume controller được bỏ ra khỏi Cloud Controller Manager. Do độ phức tạp lớn ảnh hướng và sẽ tốn nhiều thời gian cũng như nhân lực không đáp ứng đủ cho việc tách hẳn tầng logic liên quan tới Volume từ những bên cung cấp dịch vụ, và quyết định cuối cùng là sẽ không triển khai quản lý Volume như một phần của CCM.

Kết hoạch ban đầu của dự án là hỗ trợ Volume sử dụng Cloud Controller Manager để áp dụng những Flex Volume linh hoạt nhằm dễ dàng tích hợp bổ sung thêm. Tuy nhiên, một giải pháp khác cũng đang được lên kế hoạch để thay thế Flex Volume được biết là CSI.

Sau khi xem xét về khía cạnh này, chúng tôi quyết định sẽ có một khoảng thời gian nghỉ trước khi CSI trở nên sẵn sàng cho việc sử dụng.

Chức năng của Cloud Controller Manager

CCM thừa hưởng những tính năng của nó từ các thành phần trong Kubernetes phụ thuộc vào các Cloud Provider. Phần kế tiếp sẽ giới thiệu những thành phần này.

1. Kubernetes Conntroller Manager

Phần lớn các tính năng của CCM bắt nguồn từ Kubernetes controller manager. Như đã đề cập ở phần trước, CCM bao gồm:

  • Node controller
  • Route controller
  • Service controller

Node controller

Node controller có vai trò khởi tạo một Node bằng cách thu thập thông tin về những Node đang chạy trong cluster từ các cloud provider.

Node controller sẽ thực hiện những chức năng sau:

  1. Khởi tạo một Node với các nhãn region/zone.
  2. Khởi tạo một Node với những thông tin được cung cấp từ cloud, ví dụ như loại máy và kích cỡ.
  3. Thu thập địa chỉ mạng của Node và hostname.
  4. Trong trường hợp một Node không có tín hiệu phản hồi, Node controller sẽ kiểm tra xem Node này có thực sự xóa khỏi hệ thống cloud hay chưa. Nếu Node đó không còn tồn tại trên cloud, controller sẽ xóa Node đó khỏi Kubernetes cluster.

Route controller

Route controller đóng vai trò cấu hình định tuyến trong nằm trong hệ thống cloud để các container trên các Node khác nhau trong Kubernetes cluster có thể giao tiếp với nhau. Route controller hiện chỉ đáp ứng được cho các Google Compute Engine cluster.

Service controller

Service controller lắng nghe các sự kiện tạo mới, cập nhật và xoá bỏ một service. Dựa trên trạng thái hiện tại của các vụ trên Kubernetes, nó cấu hình các dịch vụ cân bằng tải trên cloud (như ELB của AWS, Google Load Balancer, hay Oracle Cloud Infrastructure LB) nhằm phản ánh trạng thái của các Service trên Kubernetes. Ngoài ra, nó đảm bảo những service backends cho các dịch vụ cần bằng tải trên cloud được cập nhật

2. Kubelet

Node controller bao gồm một số tính năng phụ thuộc vào tầng cloud của Kubelet. Trước khi có CCM, Kubelet đảm nhận vai trò khởi tạo một Node với thông tin chi tiết từ cloud như địa chỉ IP, region hay instance type. Với CCM, vai trò này được CCM đảm nhận thay cho Kubelet.

Với mô hình mới này, Kubelet sẽ khởi tạo một Node nhưng không đi kèm với những thông tin từ cloud. Tuy nhiên, nó sẽ thêm vào một dấu Taint để đánh dấu Node sẽ không được lập lịch cho tới khi CCM khởi tạo xong Node này với những thông tin cụ thể cung cấp từ Cloud, sau đó nó sẽ xóa những dấu chờ này.

Cơ chế Plugin

CCM sử dụng interface trong ngôn ngữ Go cho phép triển khai trên bất kì hệ thống cloud nào cũng có thể plugged in. Cụ thể hơn, nó sử dụng CloudProvider Interface được định nghĩa ở đây.

Cách triển khai của bốn controller được nêu ở trên, và một số được thực hiện như giao diện chung cho các bên cung cấp dịch vụ cloud, sẽ ở trong lõi (core) của Kubernetes. Việc triển khai dành riêng cho từng cloud provider sẽ được xây dựng bên ngoài lõi (core) và triển khai các giao diện được xác định bên trong lõi.

Để biết thêm chỉ tiết, xem Cloud Controller Manager.

Phân quyền

Phần này sẽ phân nhỏ quyền truy cập cần có cho các API object cung cấp bởi CCM để thực hiện những hành động của nó.

Node controller

Node controller chỉ hoạt động với các Node. Nó yêu cầu đầy đủ quyền truy cập bao gồm get, list, create, update, patch, watch, và delete một Node.

v1/Node:

  • Get
  • List
  • Create
  • Update
  • Patch
  • Watch
  • Delete

Route controller

Route controller lắng nghe sự kiện tạo ra các Node và cấu hình các Route tương ứng. Nó yêu cầu có quyền truy cập get tới các đối Node.

v1/Node:

  • Get

Service controller

Service controller lắng nghe các sự kiện khởi tạo, cập nhật và xóa bỏ một Service và cấu hình những endpoint phù hợp.

Để truy cập các Service, nó cần quyền list, và watch. Để cập nhật Service, nó sẽ cần patch và update.

Để thiết lập các endpoint cho các Service, nó cần quyền create, list, get, watch, và update.

v1/Service:

  • List
  • Get
  • Watch
  • Patch
  • Update

Các vấn đề khác

Việc triển khai lõi của CCM yêu cầu cần có quyền tạo mới sự kiện và đảm bảo quyền thực thi một số hành động, nó cần có quyền tạo các Service Accounts

v1/Event:

  • Create
  • Patch
  • Update

v1/ServiceAccount:

  • Create

Với RBAC ClusterRole, CCM cần có ClusterRole tối thiểu:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cloud-controller-manager
rules:
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
      - update
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - "*"
  - apiGroups:
      - ""
    resources:
      - nodes/status
    verbs:
      - patch
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - list
      - patch
      - update
      - watch
  - apiGroups:
      - ""
    resources:
      - serviceaccounts
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - persistentvolumes
    verbs:
      - get
      - list
      - update
      - watch
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - create
      - get
      - list
      - watch
      - update

Các nhà cung cấp đã triển khai

Sau đây là danh sách các nhà cung cấp dịch vụ cloud đã triển khai CCM:

Quản lý Cluster

Hướng dẫn chi tiết cho việc cấu hình và chạy CCM được cung cấp tại đây.

5.3 - Kubernetes - Khả năng tự phục hồi (Self-Healing)

Kubernetes được thiết kế với khả năng tự phục hồi giúp duy trì tình trạng khỏe mạnh và tính khả dụng của các workload. Nó tự động thay thế các container bị lỗi, lập lịch lại các workload khi node trở nên không khả dụng, và đảm bảo rằng trạng thái mong muốn của hệ thống được duy trì.

Khả năng tự phục hồi

  • Khởi động lại ở cấp độ container: Nếu một container bên trong Pod bị lỗi, Kubernetes sẽ khởi động lại nó dựa trên restartPolicy.

  • Thay thế replica: Nếu một Pod trong Deployment hoặc StatefulSet bị lỗi, Kubernetes sẽ tạo một Pod thay thế để duy trì số lượng replica được chỉ định. Nếu một Pod thuộc DaemonSet bị lỗi, control plane sẽ tạo một Pod thay thế để chạy trên cùng node đó.

  • Phục hồi persistent storage: Nếu một node đang chạy Pod với PersistentVolume (PV) được gắn kết, và node đó bị lỗi, Kubernetes có thể gắn lại volume vào Pod mới trên node khác.

  • Cân bằng tải cho Service: Nếu một Pod đằng sau Service bị lỗi, Kubernetes sẽ tự động loại bỏ nó khỏi endpoint của Service để chỉ định tuyến traffic đến các Pod khỏe mạnh.

Dưới đây là một số thành phần chính cung cấp khả năng tự phục hồi của Kubernetes:

  • kubelet: Đảm bảo rằng các container đang chạy, và khởi động lại những container bị lỗi.

  • ReplicaSet, StatefulSet và DaemonSet controller: Duy trì số lượng replica Pod mong muốn.

  • PersistentVolume controller: Quản lý việc gắn kết và tháo gỡ volume cho các stateful workload.

Những điều cần cân nhắc

  • Lỗi Storage: Nếu một persistent volume trở nên không khả dụng, có thể cần các bước phục hồi thủ công.

  • Lỗi Ứng dụng: Kubernetes có thể khởi động lại container, nhưng các vấn đề ứng dụng cơ bản phải được giải quyết riêng biệt.

Tiếp theo là gì

5.4 - Proxy Đa Phiên Bản (Mixed Version Proxy)

TRẠNG THÁI TÍNH NĂNG: Beta since Kubernetes v1.36; enabled by default

Kubernetes 1.37 giới thiệu một tính năng alpha cho phép API Server proxy các yêu cầu tài nguyên đến các API server ngang hàng khác. Tính năng này đặc biệt hữu ích khi trong một cụm có nhiều API server đang chạy các phiên bản Kubernetes khác nhau (ví dụ: trong quá trình nâng cấp cụm kéo dài sang phiên bản mới).

Điều này giúp quản trị viên của cluster cấu hình các cluster có độ sẵn sàng cao (high availability) có thể được nâng cấp một cách an toàn hơn, bằng cách chuyển hướng các yêu cầu tài nguyên (trong thời gian nâng cấp) đến đúng kube-api server. Cơ chế proxy này giúp người dùng tránh gặp lỗi 404 (Not Found) không mong muốn do quá trình nâng cấp gây ra.

Cơ chế này được gọi là Proxy Đa Phiên Bản.

Bật tính năng Proxy Đa Phiên Bản

Đảm bảo rằng cờ feature gate UnknownVersionInteroperabilityProxy đã được bật khi khởi động API Server:

kube-apiserver \
--feature-gates=UnknownVersionInteroperabilityProxy=true \
# các tham số dòng lệnh bắt buộc cho tính năng này
--peer-ca-file=<đường dẫn đến CA cert của kube-apiserver>
--proxy-client-cert-file=<đường dẫn đến chứng chỉ proxy của aggregator>,
--proxy-client-key-file=<đường dẫn đến khóa proxy của aggregator>,
--requestheader-client-ca-file=<đường dẫn đến CA cert của aggregator>,
# requestheader-allowed-names có thể để trống để chấp nhận mọi Common Name
--requestheader-allowed-names=<các Common Name hợp lệ để xác minh chứng chỉ proxy client>,

# các cờ tuỳ chọn cho tính năng này
--peer-advertise-ip=<Địa chỉ IP của kube-apiserver này để peer sử dụng khi proxy> --peer-advertise-port=<Cổng mà kube-apiserver này mở để peer sử dụng khi proxy>

# …và các cờ khác như thường lệ

Kết nối và xác thực giữa các API server

  • API server nguồn tái sử dụng các cờ xác thực client cho API server hiện có là --proxy-client-cert-file và --proxy-client-key-file để trình bày danh tính của nó, danh tính này sẽ được kube-apiserver đích (destination kube-apiserver) xác minh. API server đích sẽ xác thực kết nối từ phía đối tác dựa trên cấu hình được chỉ định thông qua tham số dòng lệnh --requestheader-client-ca-file.

  • Để xác thực chứng chỉ phục vụ (serving cert) của API server đích, bạn cần cấu hình một gói chứng chỉ CA bằng cách cung cấp tham số dòng lệnh --peer-ca-file cho API server nguồn.

Cấu hình kết nối tới peer API server

Để khai báo địa chỉ mạng của một API server mà các peer sẽ sử dụng để proxy yêu cầu, sử dụng các tham số --peer-advertise-ip và --peer-advertise-port, hoặc khai báo trong tệp cấu hình của API server.

Nếu không khai báo các cờ này, kube-apiserver sẽ mặc định sử dụng giá trị từ --advertise-address hoặc --bind-address. Nếu các tham số này cũng không được cấu hình, địa chỉ giao diện mạng mặc định của máy chủ sẽ được dùng.

Cơ chế proxy giữa các phiên bản khác nhau

Khi proxy đa phiên bản được bật, aggregation layer sẽ tải một bộ lọc đặc biệt với các hành vi sau:

  • Khi một API server nhận được yêu cầu tài nguyên mà nó không thể xử lý (do chưa hỗ trợ API đó hoặc API bị tắt), nó sẽ tìm cách proxy yêu cầu đến một API server ngang hàng có thể xử lý yêu cầu đó.

Việc này được thực hiện bằng cách xác định các nhóm / phiên bản / tài nguyên API mà server hiện tại không nhận biết, rồi chuyển tiếp yêu cầu tới một peer có thể xử lý được.

  • Nếu API server peer gặp lỗi khi phản hồi, API server nguồn sẽ trả về lỗi 503 ("Service Unavailable").

Cách hoạt động bên trong

Khi một API server nhận yêu cầu tài nguyên, nó kiểm tra xem API server nào có thể xử lý yêu cầu đó. Việc kiểm tra này dựa trên API StorageVersion nội bộ.

  • Nếu tài nguyên đã được API server nhận biết (ví dụ: GET /api/v1/pods/some-pod), yêu cầu sẽ được xử lý tại chỗ.

  • Nếu không có đối tượng StorageVersion nào tương ứng với tài nguyên yêu cầu (ví dụ: GET /my-api/v1/my-resource) nhưng APIService tương ứng được cấu hình để proxy đến một API server mở rộng, thì yêu cầu sẽ được xử lý theo luồng proxy mở rộng.

  • Nếu có một đối tượng StorageVersion hợp lệ cho tài nguyên được yêu cầu (ví dụ: GET /batch/v1/jobs) và API server đang cố xử lý yêu cầu đó (gọi là handling API server) đã tắt nhóm API batch, thì handling API server sẽ truy xuất danh sách các API server ngang hàng (peer API servers) có phục vụ nhóm API / phiên bản / tài nguyên tương ứng (trong trường hợp này là api/batch/v1) dựa trên thông tin từ đối tượng StorageVersion đã truy xuất. Sau đó, handling API server sẽ chuyển tiếp (proxy) yêu cầu đến một trong những kube-apiserver ngang hàng phù hợp, vốn có khả năng xử lý tài nguyên được yêu cầu.

    • Nếu không có peer nào khả dụng cho nhóm / phiên bản / tài nguyên đó, API server sẽ trả lại lỗi 404 ("Not Found").

    • Nếu có peer phù hợp nhưng không phản hồi (do lỗi mạng, hoặc thông tin về peer chưa được đăng ký đúng lúc), thì API server sẽ trả về lỗi 503 ("Service Unavailable").

6 - Secrets

Trang này đang được dịch. Vui lòng xem phiên bản tiếng Anh để biết thông tin mới nhất.

7 - Containers

Containers Kubernetes

7.1 - Các biến môi trường của Container

Trang này mô tả các tài nguyên có sẵn cho các Containers trong môi trường Container.

Môi trường container

Môi trường Container trong Kubernetes cung cấp một số tài nguyên quan trọng cho Container:

  • Một hệ thống tệp tin (filesystem), là sự kết hợp của một image và một hoặc nhiều volumes.
  • Thông tin về chính container đó.
  • Thông tin về các đối tượng (object) khác trong cluster.

Thông tin container

Hostname của một Container là tên của Pod mà Container đang chạy trong đó. Có thể lấy thông tin qua lệnh hostname hoặc lệnh gọi hàm gethostname trong libc.

Tên của Pod và namespace có thể lấy ở các biến môi trường thông qua downward API.

Các biến môi trường do người dùng định nghĩa từ định nghĩa của Pod cũng có trong thông tin của Container, như là mọi biến môi trường khác được xác định tĩnh trong Docker image.

Thông tin cluster

Một danh sách tất cả các services đang chạy khi một Container được tạo đều có trong Container dưới dạng các biến môi trường. Các biến môi trường này đều khớp với cú pháp của các Docker links.

Đối với một service có tên là foo ánh xạ với Container có tên là bar, các biến sau được xác định:

FOO_SERVICE_HOST=<host mà service đang chạy>
FOO_SERVICE_PORT=<port mà service đang chạy>

Các services có địa chỉ IP và có sẵn cho Container thông qua DNS nếu DNS addon được enable. 

Tiếp theo là gì

7.2 - Container Lifecycle Hooks

Trang này mô tả cách mà kubelet quản lý các Container có thể sử dụng framework Container lifecycle hook để chạy mã nguồn được kích hoạt bởi các sự kiện trong lifecycle của nó.

Tổng quan

Tương tự như nhiều framework ngôn ngữ lập trình có thành phần các lifecycle hooks, như là Angular, Kubernetes cung cấp các Container cùng với các lifecycle hook. Các hooks cho phép các Container nhận thức được các sự kiện trong lifecycle của chúng và chạy mã nguồn được triển khai trong một trình xử lý khi lifecycle hook tương ứng được thực thi.

Container hooks

Có 2 hooks được cung cấp cho các Containers:

PostStart

Hook này thực thi ngay sau khi một container được tạo mới. Tuy nhiên, không có gì đảm bảo rằng hook này sẽ thực thi trước container ENTRYPOINT. Không có tham số nào được truyền cho trình xử lý (handler).

PreStop

Hook này được gọi tức thì ngay trước khi một container bị chấm dứt bởi một API request hoặc sự kiện quản lý như liveness/startup probe failure, preemption, tranh chấp tài nguyên và các vấn đề khác. Một lời gọi tới PreStop hook thất bại nếu container ở trạng thái đã chấm dứt (terminated) hoặc đã hoàn thành (completed) và hook phải hoàn thành trước khi tín hiệu TERM được gửi tới để dừng container. Thời gian gia hạn chấm dứt của Pod bắt đầu trước khi hook PreStop được chạy, nên Container cuối cùng sẽ chấm dứt trong thời gian gia hạn chấm dứt của Pod bất kể kết quả của handler là gì. Không có tham số nào được truyền cho trình xử lý (handler).

Xem thêm chi tiết về hành vi chấm dứt (termination behavior) tại Termination of Pods.

Các cách thực hiện Hook handler (Hook handler implementations)

Các Containers có thể truy cập một hook bằng cách thực hiện và đăng ký một handler cho hook đó. Có 3 loại hook handler có thể được triển khai cho các Containers:

  • Exec - Thực thi một lệnh cụ thể, như là pre-stop.sh trong cgroups và namespaces của Container. Tài nguyên được sử dụng bởi lệnh được tính vào Container.
  • HTTP - Thực thi một HTTP request với một endpoint cụ thể trên Container.
  • Sleep - Dừng container trong một khoảng thời gian. Đây là tính năng đang ở beta-level, được tự động bật bởi PodLifecycleSleepAction feature gate.

Lưu ý:

Tính năng beta PodLifecycleSleepActionAllowZero được bật mặc định từ bản v1.33. Tính năng này cho phép bạn thiết lập thời gian sleep là 0 giây (hay không thực hiện hành động nào) cho các hooks Sleep lifecycle của bạn.

Thực thi hook handler (Hook handler execution)

Khi một hook quản lý Container lifecycle được gọi, hệ thống quản lý Kubernetes thực thi trình xử lý (handler) dựa trên hành động của hook. httpGet, tcpSocket (deprecated) và sleep được thực thi bởi tiến trình kubelet, còn exec được thực thi trong container.

Lời gọi hook PostStart handler được khởi tạo khi một container được tạo, nghĩa là container ENTRYPOINT và hook PostStart được kích hoạt đồng thời. Tuy nhiên, nếu hook PostStart mất quá nhiều thời gian để chạy hoặc bị treo, container không thể chuyển sang trạng thái running.

Các hooks PreStop không được thực thi bất đồng bộ với tín hiệu dừng Container; hook phải được hoàn thành thực thi trước khi tín hiệu TERM được gửi. Nếu hook PreStop bị treo khi thực thi, Pod phase ở trạng thái Terminating và tiếp tục cho tới khi bị chấm dứt sau terminationGracePeriodSeconds hết hạn. Khoảng thời gian gia hạn này bằng tổng thời gian mà cả hook PreStop thực thi và Container dừng lại một cách bình thường. Ví dụ, nếu terminationGracePeriodSeconds là 60, và hook mất 55 giây để hoàn thành, và Container mất thêm 10 giây để dừng lại sau khi nhận được tín hiệu, thì Container sẽ bị chấm dứt trước khi nó kịp dừng bình thường, vì terminationGracePeriodSeconds nhỏ hơn tổng thời gian cần thiết để thực hiện hai việc này (55+10).

Nếu hook PostStart hoặc PreStop thất bại, nó sẽ xóa Container.

Người dùng nên làm cho hook handlers nhẹ nhất có thể. Tuy nhiên, có những trường hợp khi những lệnh chạy dài có ý nghĩa, chẳng hạn như khi lưu trạng thái trước khi dừng một container.

Hook delivery guarantees

Hook delivery được trù định ít nhất một lần, điều đó có nghĩa là hook có thể được gọi nhiều lần cho bất kỳ sự kiện cho trước nào, chẳng hạn như PostStart hoặc PreStop. Tùy thuộc vào việc thực hiện hook để xử lý việc này một cách chính xác.

Nhìn chung, chỉ có các deliveries đơn được thực hiện. Ví dụ, nếu một HTTP hook receiver bị down và không thể nhận các traffic, sẽ không được gửi lại. Tuy nhiên, trong một số trường hợp hiếm hoi, delivery kép có thể xảy ra. Chẳng hạn, nếu một kubelet khởi động lại ở giữa quá trình gửi một hook, hook có thể được gửi lại sau khi kubelet quay trở lại.

Debugging Hook handlers

Log cho một Hook handler không được hiển thị trong các Pod events. Nếu một handler thất bại vì lí do nào đó, nó sẽ broadcast một event. Đối với PostStart, đây là event FailedPostStartHook, và đối với PreStop, đây là event FailedPreStopHook. Để tự tạo ra một event lỗi FailedPostStartHook, bạn có thể điều chỉnh file lifecycle-events.yaml để thay đổi lệnh postStart thành "badcommand" và áp dụng nó. Dưới đây là một số ví dụ output của events từ việc chạy lệnh kubectl describe pod lifecycle-demo:

Events:
  Type     Reason               Age              From               Message
  ----     ------               ----             ----               -------
  Normal   Scheduled            7s               default-scheduler  Successfully assigned default/lifecycle-demo to ip-XXX-XXX-XX-XX.us-east-2...
  Normal   Pulled               6s               kubelet            Successfully pulled image "nginx" in 229.604315ms
  Normal   Pulling              4s (x2 over 6s)  kubelet            Pulling image "nginx"
  Normal   Created              4s (x2 over 5s)  kubelet            Created container lifecycle-demo-container
  Normal   Started              4s (x2 over 5s)  kubelet            Started container lifecycle-demo-container
  Warning  FailedPostStartHook  4s (x2 over 5s)  kubelet            Exec lifecycle hook ([badcommand]) for Container "lifecycle-demo-container" in Pod "lifecycle-demo_default(30229739-9651-4e5a-9a32-a8f1688862db)" failed - error: command 'badcommand' exited with 126: , message: "OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: \"badcommand\": executable file not found in $PATH: unknown\r\n"
  Normal   Killing              4s (x2 over 5s)  kubelet            FailedPostStartHook
  Normal   Pulled               4s               kubelet            Successfully pulled image "nginx" in 215.66395ms
  Warning  BackOff              2s (x2 over 3s)  kubelet            Back-off restarting failed container

Tiếp theo là gì

8 - Jobs

Trang này đang được dịch. Vui lòng xem phiên bản tiếng Anh để biết thông tin mới nhất.

9 - Quản lý tài nguyên cho Containers

Trang này đang được dịch. Vui lòng xem phiên bản tiếng Anh để biết thông tin mới nhất.

10 - IPv4/IPv6 dual-stack

Kubernetes cho phép bạn cấu hình mạng IPv4 đơn, mạng IPv6 đơn, hoặc mạng kép với cả hai họ mạng hoạt động. Trang này giải thích cách thức hoạt động.

Trang này đang được dịch. Vui lòng xem phiên bản tiếng Anh để biết thông tin mới nhất.

11 - Mở rộng Kubernetes

Các cách khác nhau để thay đổi hành vi của cluster Kubernetes của bạn.

Trang này đang được dịch. Vui lòng xem phiên bản tiếng Anh để biết thông tin mới nhất.

12 - ReplicaSet

Mục đích của ReplicaSet là duy trì một tập hợp ổn định các Pod bản sao đang chạy tại bất kỳ thời điểm nào. Thông thường, bạn định nghĩa một Deployment và để Deployment đó quản lý các ReplicaSet tự động.

Trang này đang được dịch. Vui lòng xem phiên bản tiếng Anh để biết thông tin mới nhất.