对 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 腾出空间。
注意
如果删除的 Pod 不受任何控制器控制或者 Pod 没有副本,这将导致服务中断。这也不会遵循PodDisruptionBudget。上线故障
如果最近的 DaemonSet 模板更新已损坏,例如容器崩溃循环或者容器镜像不存在(通常是由于拼写错误),DaemonSet 上线将无法进行。
要解决此问题,请再次更新 DaemonSet 模板。新的上线将不会被之前不健康的上线所阻塞。
时钟偏差
如果在 DaemonSet 中指定了 .spec.minReadySeconds
,那么主节点和节点之间的时钟偏差将导致 DaemonSet 无法检测到正确的上线进度。
清理
从命名空间中删除 DaemonSet
kubectl delete ds fluentd-elasticsearch -n kube-system