如何在Ansible任务级别覆盖主机,实现K8S Worker节点Cordon、Drain与重启
解决方案:逐个重启Kubernetes Worker节点的Ansible Playbook
你的需求完全可以实现,但任务级别不能直接使用hosts关键字,需要通过delegate_to或local_action指定在localhost执行kubectl命令,同时仍能获取当前Worker节点的主机名变量。以下是修正后的完整Playbook及关键说明:
修正后的Playbook代码
- name: 逐个重启Kubernetes Worker节点 become: yes hosts: workers gather_facts: no serial: 1 # 强制逐个处理节点,确保一个节点完成全流程再处理下一个 tasks: - name: 将Worker节点标记为不可调度(cordon) delegate_to: localhost # 该任务委托到localhost执行 shell: kubectl cordon {{ inventory_hostname }} async: 300 poll: 10 - name: 驱逐Worker节点上的Pod(drain) delegate_to: localhost shell: > kubectl drain {{ inventory_hostname }} --ignore-daemonsets --delete-emptydir-data --force async: 300 poll: 10 register: drain_result failed_when: drain_result.rc not in [0, 1] # 兼容节点无Pod可驱逐的场景 - name: 重启Worker节点 reboot: reboot_timeout: 500
关键要点说明
- 任务级主机切换:用
delegate_to: localhost替代示例中的hosts: localhost,既让kubectl命令在本地执行,又保留了Play目标主机(Worker节点)的变量(比如inventory_hostname就是当前Worker的主机名),完美匹配kubectl命令的需求。 - 逐个节点执行:
serial: 1是核心配置,它会让Play按顺序处理workers组中的每个节点,只有当前节点完成cordon、drain、重启全流程后,才会开始处理下一个节点。 - kubectl drain参数优化:添加了
--ignore-daemonsets(忽略守护进程Pod,这类Pod通常无法被驱逐)、--delete-emptydir-data(清理使用emptyDir的Pod数据)、--force(强制驱逐无法优雅终止的Pod),这些是生产环境中常用的必要参数。 - 容错处理:drain任务的
failed_when规则,兼容了节点上已无可驱逐Pod的场景(此时kubectl drain可能返回非0码,但不属于执行失败)。
内容的提问来源于stack exchange,提问作者PrestonDocks
相关产品推荐
相关产品推荐

