如何让DaemonSet节点初始化Pod仅在每个节点运行一次?
解决Kubernetes DaemonSet初始化脚本重复执行的问题
问题背景
需要在每个Kubernetes节点上执行一次初始化脚本,当前使用DaemonSet部署的Pod执行完脚本后以exit code 0退出,导致DaemonSet反复重启Pod,脚本重复执行。尝试过添加preStop钩子为节点打k8s.amazee.io/node-configured标签,以及修改command追加标签操作,但均未生效。目标是确保每个节点仅执行一次初始化,阻止Pod重复重启。
失败原因分析
- preStop钩子未生效:当容器正常执行完脚本并exit 0时,Kubernetes的preStop钩子可能不会被触发——终止流程在容器主动退出后直接完成,钩子没有执行时机,导致节点未打上标签。
- command配置存在语法错误:之前修改的command中存在多余引号(
/bin/sh")、错误的分号位置,导致kubectl标签命令未被正确执行,节点无法被标记为已配置,DaemonSet持续重启Pod。
正确解决方案
核心思路:在初始化脚本执行完成后,立即为节点打上标签,确保Pod退出前节点已被标记,DaemonSet后续不会在该节点重新调度Pod。
修正后的完整配置YAML如下:
--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: test-init-node-cr rules: - apiGroups: - "" resources: - nodes verbs: - get - patch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: test-init-node-sa roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: test-init-node-cr subjects: - kind: ServiceAccount name: test-init-node-sa namespace: default --- apiVersion: v1 kind: ServiceAccount metadata: name: test-init-node-sa namespace: default --- apiVersion: apps/v1 kind: DaemonSet metadata: name: test-init-node namespace: default spec: selector: matchLabels: app.kubernetes.io/name: test-init-node app.kubernetes.io/component: configurator template: metadata: name: test-init-node labels: app.kubernetes.io/name: test-init-node app.kubernetes.io/component: configurator spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: k8s.amazee.io/node-configured operator: DoesNotExist hostPID: true hostNetwork: true tolerations: - effect: NoSchedule key: node-role.kubernetes.io/master serviceAccount: test-init-node-sa containers: - name: init env: - name: MY_NODE_NAME valueFrom: fieldRef: fieldPath: spec.nodeName command: - nsenter - --mount=/proc/1/ns/mnt - -- - bash - -xc - | echo "starting the magic" # 执行初始化操作 echo "* hard core unlimited" >> /etc/security/limits.d/game.conf echo "* soft core unlimited" >> /etc/security/limits.d/game.conf # 初始化完成后为节点打标签(--overwrite避免重复打标签报错) kubectl label node "$MY_NODE_NAME" k8s.amazee.io/node-configured=$(date +%s) --overwrite image: alpine/k8s:1.28.0 resources: requests: cpu: 50m memory: 50M securityContext: runAsUser: 0 privileged: true
关键修改点说明
- 将标签操作整合到bash脚本的here-doc中,确保初始化脚本执行完成后才执行标签命令,保证节点在Pod退出前被标记。
- 添加
--overwrite参数,避免节点已有标签时命令报错,提升配置鲁棒性。 - 修正了之前command配置中的语法错误,确保所有命令在同一个bash环境中执行。
验证方式
- 应用配置后,查看Pod状态:
kubectl get pods -n default -l app.kubernetes.io/name=test-init-node - 查看节点标签:
kubectl get nodes --show-labels | grep k8s.amazee.io/node-configured - 确认已完成初始化的节点上不会再重启新的Pod,且每个节点仅执行一次初始化脚本。
内容的提问来源于stack exchange,提问作者Y.H.
相关产品推荐
相关产品推荐

