參考:https://kubernetes.io/zh/docs/tasks/manage-daemon/update-daemon-set/
DaemonSet 更新策略
DaemonSet 有兩種更新策略:
- OnDelete: 使用 OnDelete 更新策略時,在更新 DaemonSet 模板后,只有當你手動刪除老的 DaemonSet pods 之后,新的 DaemonSet Pod 才會被自動創建。跟 Kubernetes 1.6 以前的版本類似。
- RollingUpdate: 這是默認的更新策略。使用 RollingUpdate 更新策略時,在更新 DaemonSet 模板后, 老的 DaemonSet pods 將被終止,並且將以受控方式自動創建新的 DaemonSet pods。 更新期間,最多只能有 DaemonSet 的一個 Pod 運行於每個節點上。
執行滾動更新
要啟用 DaemonSet 的滾動更新功能,必須設置 .spec.updateStrategy.type 為 RollingUpdate。
你可能想設置 .spec.updateStrategy.rollingUpdate.maxUnavailable (默認為 1) 和 .spec.minReadySeconds (默認為 0)。
創建帶有 RollingUpdate 更新策略的 DaemonSet
下面的 YAML 包含一個 DaemonSet,其更新策略為 'RollingUpdate':
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:
# this toleration is to have the daemonset runnable on master nodes
# remove it if your masters can't run pods
- key: node-role.kubernetes.io/master
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 的滾動更新策略
首先,檢查 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 的任何更新都將觸發滾動更新。 這可以通過幾個不同的 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:
# this toleration is to have the daemonset runnable on master nodes
# remove it if your masters can't run pods
- key: node-role.kubernetes.io/master
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
指令式命令
如果你使用 指令式命令 來更新 DaemonSets,請使用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 最新滾動更新的進度:
kubectl rollout status ds/fluentd-elasticsearch -n kube-system
當滾動更新完成時,輸出結果如下:
daemonset "fluentd-elasticsearch" successfully rolled out
故障排查
DaemonSet 滾動更新卡住
有時,DaemonSet 滾動更新可能卡住,以下是一些可能的原因:
一些節點可用資源耗盡
DaemonSet 滾動更新可能會卡住,其 Pod 至少在某個節點上無法調度運行。 當節點上可用資源耗盡時, 這是可能的。
發生這種情況時,通過對 kubectl get nodes 和下面命令行的輸出作比較, 找出沒有調度部署 DaemonSet Pods 的節點:
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 無法檢測到正確的滾動更新進度。