對 DaemonSet 執行滾動更新

本頁面展示瞭如何對 DaemonSet 執行滾動更新。

準備工作

你需要一個 Kubernetes 叢集,並且 kubectl 命令列工具已配置為與你的叢集通訊。建議在至少有兩個節點不作為控制平面主機的叢集上執行本教程。如果你還沒有叢集,可以使用 minikube 建立一個,或者使用這些 Kubernetes 演練場中的一個。

DaemonSet 更新策略

DaemonSet 有兩種更新策略型別

  • OnDelete:使用 OnDelete 更新策略,在你更新 DaemonSet 模板後,新的 DaemonSet Pod 只有在你手動刪除舊的 DaemonSet Pod 時才會被建立。這與 Kubernetes 1.5 及之前版本中 DaemonSet 的行為相同。
  • RollingUpdate:這是預設的更新策略。
    使用 RollingUpdate 更新策略,在你更新 DaemonSet 模板後,舊的 DaemonSet Pod 將被殺死,新的 DaemonSet Pod 將以受控方式自動建立。在整個更新過程中,每個節點上最多隻執行一個 DaemonSet Pod。

執行滾動更新

要啟用 DaemonSet 的滾動更新功能,你必須將其 .spec.updateStrategy.type 設定為 RollingUpdate

你可能還需要設定 .spec.updateStrategy.rollingUpdate.maxUnavailable (預設為 1)、.spec.minReadySeconds (預設為 0) 和 .spec.updateStrategy.rollingUpdate.maxSurge (預設為 0)。

建立具有 RollingUpdate 更新策略的 DaemonSet

此 YAML 檔案指定了一個更新策略為 'RollingUpdate' 的 DaemonSet

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # these tolerations are to have the daemonset runnable on control plane nodes
      # remove them if your control plane nodes should not run pods
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v5.0.1
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

驗證 DaemonSet 清單的更新策略後,建立 DaemonSet

kubectl create -f https://k8s.io/examples/controllers/fluentd-daemonset.yaml

或者,如果你打算使用 kubectl apply 更新 DaemonSet,則使用 kubectl apply 建立相同的 DaemonSet。

kubectl apply -f https://k8s.io/examples/controllers/fluentd-daemonset.yaml

檢查 DaemonSet RollingUpdate 更新策略

檢查 DaemonSet 的更新策略,並確保其設定為 RollingUpdate

kubectl get ds/fluentd-elasticsearch -o go-template='{{.spec.updateStrategy.type}}{{"\n"}}' -n kube-system

如果你尚未在系統中建立 DaemonSet,請使用以下命令檢查你的 DaemonSet 清單

kubectl apply -f https://k8s.io/examples/controllers/fluentd-daemonset.yaml --dry-run=client -o go-template='{{.spec.updateStrategy.type}}{{"\n"}}'

兩個命令的輸出都應為

RollingUpdate

如果輸出不是 RollingUpdate,請返回並相應地修改 DaemonSet 物件或清單。

更新 DaemonSet 模板

RollingUpdate DaemonSet 的 .spec.template 的任何更新都將觸發滾動更新。讓我們透過應用新的 YAML 檔案來更新 DaemonSet。這可以通過幾個不同的 kubectl 命令來完成。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd-elasticsearch
  namespace: kube-system
  labels:
    k8s-app: fluentd-logging
spec:
  selector:
    matchLabels:
      name: fluentd-elasticsearch
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
  template:
    metadata:
      labels:
        name: fluentd-elasticsearch
    spec:
      tolerations:
      # these tolerations are to have the daemonset runnable on control plane nodes
      # remove them if your control plane nodes should not run pods
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        operator: Exists
        effect: NoSchedule
      containers:
      - name: fluentd-elasticsearch
        image: quay.io/fluentd_elasticsearch/fluentd:v5.0.1
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

宣告式命令

如果你使用配置檔案更新 DaemonSet,請使用 kubectl apply

kubectl apply -f https://k8s.io/examples/controllers/fluentd-daemonset-update.yaml

命令式命令

如果你使用命令式命令更新 DaemonSet,請使用 kubectl edit

kubectl edit ds/fluentd-elasticsearch -n kube-system
只更新容器映象

如果你只需要更新 DaemonSet 模板中的容器映象,即 .spec.template.spec.containers[*].image,請使用 kubectl set image

kubectl set image ds/fluentd-elasticsearch fluentd-elasticsearch=quay.io/fluentd_elasticsearch/fluentd:v2.6.0 -n kube-system

檢視滾動更新狀態

最後,檢視最新 DaemonSet 滾動更新的 rollout 狀態

kubectl rollout status ds/fluentd-elasticsearch -n kube-system

當 rollout 完成時,輸出類似於此

daemonset "fluentd-elasticsearch" successfully rolled out

故障排除

DaemonSet 滾動更新停滯

有時,DaemonSet 滾動更新可能會停滯。以下是一些可能的原因

某些節點資源不足

由於新的 DaemonSet Pod 無法在至少一個節點上排程,rollout 停滯。這可能是因為節點 資源不足

發生這種情況時,透過比較 kubectl get nodes 的輸出和以下命令的輸出來查詢沒有 DaemonSet Pod 排程的節點

kubectl get pods -l name=fluentd-elasticsearch -o wide -n kube-system

找到這些節點後,從節點中刪除一些非 DaemonSet Pod 以騰出空間給新的 DaemonSet Pod。

損壞的 rollout

如果最近的 DaemonSet 模板更新已損壞,例如,容器崩潰迴圈,或者容器映象不存在(通常是由於打字錯誤),DaemonSet rollout 將無法進行。

要解決此問題,請再次更新 DaemonSet 模板。新的 rollout 不會被以前不健康的 rollout 阻塞。

時鐘偏差

如果 DaemonSet 中指定了 .spec.minReadySeconds,則主節點和節點之間的時鐘偏差將導致 DaemonSet 無法檢測到正確的 rollout 進度。

清理

從名稱空間中刪除 DaemonSet

kubectl delete ds fluentd-elasticsearch -n kube-system

下一步

最後修改於 2023 年 8 月 24 日下午 6:38 PST:使用 code_sample 簡碼代替 code 簡碼 (e8b136c3b3)