对 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)