对 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:v2.5.2
        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:v2.5.2
        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

上线完成后,输出类似于:

daemonset "fluentd-elasticsearch" successfully rolled out

故障排除

DaemonSet 滚动更新停滞

有时,DaemonSet 滚动更新可能会卡住。这里有一些可能的原因:

某些节点资源不足

上线卡住是因为新的 DaemonSet Pod 无法调度到至少一个节点上。 当节点资源不足时,可能会发生这种情况。

发生这种情况时,通过比较 kubectl get nodes 的输出和以下命令的输出,找到没有调度 DaemonSet Pod 的节点:

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

找到这些节点后,从节点中删除一些非 DaemonSet 的 Pod,以便为新的 DaemonSet Pod 腾出空间。

上线故障

如果最近的 DaemonSet 模板更新已损坏,例如容器崩溃循环或者容器镜像不存在(通常是由于拼写错误),DaemonSet 上线将无法进行。

要解决此问题,请再次更新 DaemonSet 模板。新的上线将不会被之前不健康的上线所阻塞。

时钟偏差

如果在 DaemonSet 中指定了 .spec.minReadySeconds,那么主节点和节点之间的时钟偏差将导致 DaemonSet 无法检测到正确的上线进度。

清理

从命名空间中删除 DaemonSet

kubectl delete ds fluentd-elasticsearch -n kube-system

接下来

上次修改时间:2023 年 8 月 24 日下午 6:38 PST:Use code_sample shortcode instead of code shortcode (e8b136c3b3)