对 DaemonSet 执行滚动更新

本文介绍了如何对 DaemonSet 执行滚动更新。

Before you begin

你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 建议在至少有两个节点的集群上运行本教程,且这些节点不作为控制平面主机。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

DaemonSet 更新策略

DaemonSet 有两种更新策略:

  • OnDelete: 使用 OnDelete 更新策略时,在更新 DaemonSet 模板后,只有当你手动删除老的 DaemonSet pods 之后,新的 DaemonSet Pod 才会被自动创建。跟 Kubernetes 1.6 以前的版本类似。
  • RollingUpdate: 这是默认的更新策略。使用 RollingUpdate 更新策略时,在更新 DaemonSet 模板后, 老的 DaemonSet pods 将被终止,并且将以受控方式自动创建新的 DaemonSet pods。 更新期间,最多只能有 DaemonSet 的一个 Pod 运行于每个节点上。

执行滚动更新

要启用 DaemonSet 的滚动更新功能,必须设置 .spec.updateStrategy.typeRollingUpdate

你可能想设置 .spec.updateStrategy.rollingUpdate.maxUnavailable (默认为 1), .spec.minReadySeconds (默认为 0) 和 .spec.updateStrategy.rollingUpdate.maxSurge (一种 Beta 阶段的特性,默认为 0)。

创建带有 RollingUpdate 更新策略的 DaemonSet

下面的 YAML 包含一个 DaemonSet,其更新策略为 ‘RollingUpdate’:

controllers/fluentd-daemonset.yaml

  1. apiVersion: apps/v1
  2. kind: DaemonSet
  3. metadata:
  4. name: fluentd-elasticsearch
  5. namespace: kube-system
  6. labels:
  7. k8s-app: fluentd-logging
  8. spec:
  9. selector:
  10. matchLabels:
  11. name: fluentd-elasticsearch
  12. updateStrategy:
  13. type: RollingUpdate
  14. rollingUpdate:
  15. maxUnavailable: 1
  16. template:
  17. metadata:
  18. labels:
  19. name: fluentd-elasticsearch
  20. spec:
  21. tolerations:
  22. # this toleration is to have the daemonset runnable on master nodes
  23. # remove it if your masters can't run pods
  24. - key: node-role.kubernetes.io/master
  25. effect: NoSchedule
  26. containers:
  27. - name: fluentd-elasticsearch
  28. image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
  29. volumeMounts:
  30. - name: varlog
  31. mountPath: /var/log
  32. - name: varlibdockercontainers
  33. mountPath: /var/lib/docker/containers
  34. readOnly: true
  35. terminationGracePeriodSeconds: 30
  36. volumes:
  37. - name: varlog
  38. hostPath:
  39. path: /var/log
  40. - name: varlibdockercontainers
  41. hostPath:
  42. path: /var/lib/docker/containers

检查了 DaemonSet 清单中更新策略的设置之后,创建 DaemonSet:

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

另一种方式是如果你希望使用 kubectl apply 来更新 DaemonSet 的话,也可以 使用 kubectl apply 来创建 DaemonSet:

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

检查 DaemonSet 的滚动更新策略

首先,检查 DaemonSet 的更新策略,确保已经将其设置为 RollingUpdate:

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

如果还没在系统中创建 DaemonSet,请使用以下命令检查 DaemonSet 的清单:

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

两个命令的输出都应该为:

  1. RollingUpdate

如果输出不是 RollingUpdate,请返回并相应地修改 DaemonSet 对象或者清单。

更新 DaemonSet 模板

RollingUpdate DaemonSet 的 .spec.template 的任何更新都将触发滚动更新。 这可以通过几个不同的 kubectl 命令来完成。

controllers/fluentd-daemonset-update.yaml

  1. apiVersion: apps/v1
  2. kind: DaemonSet
  3. metadata:
  4. name: fluentd-elasticsearch
  5. namespace: kube-system
  6. labels:
  7. k8s-app: fluentd-logging
  8. spec:
  9. selector:
  10. matchLabels:
  11. name: fluentd-elasticsearch
  12. updateStrategy:
  13. type: RollingUpdate
  14. rollingUpdate:
  15. maxUnavailable: 1
  16. template:
  17. metadata:
  18. labels:
  19. name: fluentd-elasticsearch
  20. spec:
  21. tolerations:
  22. # this toleration is to have the daemonset runnable on master nodes
  23. # remove it if your masters can't run pods
  24. - key: node-role.kubernetes.io/master
  25. effect: NoSchedule
  26. containers:
  27. - name: fluentd-elasticsearch
  28. image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2
  29. resources:
  30. limits:
  31. memory: 200Mi
  32. requests:
  33. cpu: 100m
  34. memory: 200Mi
  35. volumeMounts:
  36. - name: varlog
  37. mountPath: /var/log
  38. - name: varlibdockercontainers
  39. mountPath: /var/lib/docker/containers
  40. readOnly: true
  41. terminationGracePeriodSeconds: 30
  42. volumes:
  43. - name: varlog
  44. hostPath:
  45. path: /var/log
  46. - name: varlibdockercontainers
  47. hostPath:
  48. path: /var/lib/docker/containers

声明式命令

如果你使用 配置文件 来更新 DaemonSet,请使用 kubectl apply:

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

指令式命令

如果你使用 指令式命令 来更新 DaemonSets,请使用kubectl edit

  1. kubectl edit ds/fluentd-elasticsearch -n kube-system
只更新容器镜像

如果你只需要更新 DaemonSet 模板里的容器镜像,比如,.spec.template.spec.containers[*].image, 请使用 kubectl set image:

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

监视滚动更新状态

最后,观察 DaemonSet 最新滚动更新的进度:

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

当滚动更新完成时,输出结果如下:

  1. daemonset "fluentd-elasticsearch" successfully rolled out

故障排查

DaemonSet 滚动更新卡住

有时,DaemonSet 滚动更新可能卡住,以下是一些可能的原因:

一些节点可用资源耗尽

DaemonSet 滚动更新可能会卡住,其 Pod 至少在某个节点上无法调度运行。 当节点上可用资源耗尽时, 这是可能的。

发生这种情况时,通过对 kubectl get nodes 和下面命令行的输出作比较, 找出没有调度部署 DaemonSet Pods 的节点:

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

一旦找到这些节点,从节点上删除一些非 DaemonSet Pod,为新的 DaemonSet Pod 腾出空间。

Note: 当所删除的 Pod 不受任何控制器管理,也不是多副本的 Pod时,上述操作将导致服务中断。 同时,上述操作也不会考虑 PodDisruptionBudget 所施加的约束。

不完整的滚动更新

如果最近的 DaemonSet 模板更新被破坏了,比如,容器处于崩溃循环状态或者容器镜像不存在 (通常由于拼写错误),就会发生 DaemonSet 滚动更新中断。

要解决此问题,需再次更新 DaemonSet 模板。新的滚动更新不会被以前的不健康的滚动更新阻止。

时钟偏差

如果在 DaemonSet 中指定了 .spec.minReadySeconds,主控节点和工作节点之间的时钟偏差会使 DaemonSet 无法检测到正确的滚动更新进度。

清理

从名字空间中删除 DaemonSet:

  1. kubectl delete ds fluentd-elasticsearch -n kube-system

What’s next

最后修改 March 27, 2022 at 8:58 PM PST: [zh] Update update-daemon-set.md (27ba7df7b)