如何循环执行带有不同delivery变量的多主机Ansible Playbook
我完全懂你的困扰——你手里有个包含多主机任务的main.yaml,想循环用不同的delivery值跑这个playbook,但之前用include_tasks的时候栽了跟头:因为include_tasks是在当前play的主机上下文里执行任务,根本没法兼容main.yaml里独立定义的hosts块。
别慌,咱们换个思路,用play级别的导入/包含来实现循环,而不是任务级的。下面是具体的解决方案:
第一步:先把你的main.yaml调整成标准语法
先把原文件的语法补全修正,确保它能正确接收delivery变量:
# main.yaml - hosts: host1 tasks: - name: "在host1执行解压任务" unarchive: src: "{{ deliveryI }}{{ delivery }}.zip" dest: "{{ dir_app }}livraisons/" mode: "0755" - hosts: host2 tasks: - name: "在host2执行shell任务" shell: xxxxxxxxx - hosts: host3 tasks: - name: "在host3执行自定义任务" # 这里可以补充你需要的任务内容
第二步:创建循环启动的playbook
新建一个启动用的playbook(比如叫run_main_loop.yaml),用import_playbook来循环调用整个main.yaml,每次传递不同的delivery值:
# run_main_loop.yaml - name: 循环遍历delivery列表,执行main playbook import_playbook: main.yaml loop: - delivery1 - delivery2 - delivery3 loop_control: loop_var: delivery
为什么这个方案能解决问题?
import_playbook是play级别的导入,它会把main.yaml里的所有plays(每个hosts块就是一个独立play)完整执行一遍,每次循环都会把delivery变量设置为当前列表项的值,这样main.yaml里的每个任务都能拿到对应的变量值。
而你之前用include_tasks的问题在于:它是任务级的包含,只能在当前play的主机范围内执行任务,根本识别不了main.yaml里的hosts定义,自然就会出问题。
进阶玩法:动态传递delivery列表
如果不想把delivery列表写死在启动playbook里,也可以从外部读取:
比如先定义一个变量文件vars/deliveries.yaml:
# vars/deliveries.yaml delivery_list: - delivery1 - delivery2 - delivery3
然后修改启动playbook:
# run_main_loop.yaml - name: 从变量文件读取delivery列表并循环执行 import_playbook: main.yaml loop: "{{ delivery_list }}" loop_control: loop_var: delivery vars_files: - vars/deliveries.yaml
或者直接从命令行传递列表:
# run_main_loop.yaml - name: 动态接收命令行传递的delivery列表 include_playbook: main.yaml loop: "{{ delivery_list }}" loop_control: loop_var: delivery
运行时用这条命令:
ansible-playbook run_main_loop.yaml --extra-vars "delivery_list=['delivery1','delivery2','delivery3']"
最后执行启动playbook
直接运行启动playbook即可,不需要额外传delivery变量:
ansible-playbook run_main_loop.yaml
备注:内容来源于stack exchange,提问作者Abdou

