如何在Ansible单Play中让pre_tasks全主机执行,roles遵循serial规则
实现Ansible Playbook中pre_tasks全主机执行、roles按serial分批运行的方案
问题背景
当前使用的是两个分离的Play:
- name: Kubernetes Tasks hosts: cluster become: true gather_facts: true tags: - kubernetes - never tasks: - name: Import facts ansible.builtin.import_role: name: k3s tasks_from: facts - name: Kubernetes Provisioning hosts: cluster become: true gather_facts: true roles: - role: helm - role: k3s serial: - 1 - 2 - 5 tags: kubernetes
希望合并为单个Play,同时满足两个需求:
pre_tasks在所有集群主机上一次性执行roles部分遵循serial定义的分批规则(先1台,再2台,最后5台)运行
实现建议
Ansible默认会让serial作用于整个Play的所有阶段(包括pre_tasks),直接写单个Play无法满足需求,可通过以下两种方式实现:
方式1:用循环+委派强制pre_tasks全量执行
修改pre_tasks中的任务,通过遍历所有主机并委派执行,确保前置任务在所有机器上运行:
- name: Kubernetes Provisioning hosts: cluster become: true gather_facts: true pre_tasks: - name: Import facts on all hosts ansible.builtin.import_role: name: k3s tasks_from: facts delegate_to: "{{ item }}" delegate_facts: true run_once: true loop: "{{ ansible_play_hosts_all }}" roles: - role: helm - role: k3s serial: - 1 - 2 - 5 tags: kubernetes
loop: "{{ ansible_play_hosts_all }}"遍历所有目标主机delegate_to: "{{ item }}"将任务委派到每台主机执行delegate_facts: true确保收集到的事实同步到对应主机的变量中run_once: true保证循环只执行一次,避免重复触发
方式2:拆分Play并同步事实
如果pre_tasks涉及主机配置变更或清单更新,可保留两个Play但优化逻辑:
- name: Collect global facts hosts: cluster become: true gather_facts: true tags: kubernetes tasks: - name: Import facts ansible.builtin.import_role: name: k3s tasks_from: facts - name: Refresh inventory to sync facts ansible.builtin.meta: refresh_inventory - name: Kubernetes Provisioning hosts: cluster become: true gather_facts: false # 前置Play已收集,关闭节省时间 roles: - role: helm - role: k3s serial: - 1 - 2 - 5 tags: kubernetes
- 第一个Play全量执行事实收集,完成所有前置操作
meta: refresh_inventory确保后续Play能获取最新的主机事实- 第二个Play按
serial规则分批运行roles
注意事项
- 方式1适合轻量的事实收集任务,避免循环执行过重操作
- 方式2逻辑更清晰,适合涉及主机配置变更或清单更新的场景
- 测试时可通过
--list-hosts参数验证serial的分批效果,确保roles按预期运行
内容的提问来源于stack exchange,提问作者Floren
相关产品推荐
相关产品推荐

