Ansible变量数组过滤:优化Nginx配置Playbook循环效率问题
优化Ansible Nginx配置部署的循环效率问题
我之前也踩过类似的坑——150个站点两次全量循环,每次5分钟,确实太磨人了!核心问题就是重复遍历全量配置带来的开销,咱们可以通过合并任务逻辑或者单次循环完成多步操作来大幅提速,具体方案给你列出来:
方案1:单次全量循环+子集处理链接
先把所有配置部署到sites-available,然后只对实际有变更的配置创建符号链接,避免第二次全量遍历:
- name: 高效部署Nginx站点配置 hosts: nginx_servers vars: nginx_sites: - { nginx_template: 'site.conf.tpl', domain: 'example.com', server: 'ServerA', enabled: true, conf_name: 'example_site' } # 剩下149个配置... tasks: - name: 渲染模板到sites-available目录 template: src: "{{ item.nginx_template }}" dest: "/etc/nginx/sites-available/{{ item.conf_name }}.conf" loop: "{{ nginx_sites }}" loop_control: label: "{{ item.domain }}" # 让输出只显示域名,更清爽 when: item.enabled register: deployed_results - name: 为更新/新增的配置创建软链到sites-enabled file: src: "/etc/nginx/sites-available/{{ item.item.conf_name }}.conf" dest: "/etc/nginx/sites-enabled/{{ item.item.conf_name }}.conf" state: link loop: "{{ deployed_results.results }}" loop_control: label: "{{ item.item.domain }}" when: item.changed # 只处理有变更的项,省时间!
这个思路是:第一次遍历全量配置完成部署,同时注册执行结果;第二次只遍历成功且有变更的配置项来创建链接,相当于把第二次全量循环变成了小范围遍历,速度会快很多。
方案2:用任务封装实现单循环多操作
把“部署+链接”的逻辑封装成独立任务文件,然后用一次循环调用这个文件,每个站点只走一遍流程:
首先创建deploy_single_nginx_site.yml:
- name: 渲染当前站点的Nginx配置 template: src: "{{ site.nginx_template }}" dest: "/etc/nginx/sites-available/{{ site.conf_name }}.conf" when: site.enabled - name: 为当前站点创建启用链接 file: src: "/etc/nginx/sites-available/{{ site.conf_name }}.conf" dest: "/etc/nginx/sites-enabled/{{ site.conf_name }}.conf" state: link when: site.enabled
然后在主Playbook里调用:
- name: 批量处理Nginx站点配置 hosts: nginx_servers vars: nginx_sites: - { nginx_template: 'site.conf.tpl', domain: 'example.com', server: 'ServerA', enabled: true, conf_name: 'example_site' } # 其他配置... tasks: - name: 逐个处理每个站点 include_tasks: deploy_single_nginx_site.yml loop: "{{ nginx_sites }}" loop_control: label: "{{ item.domain }}" loop_var: site # 避免变量冲突,让逻辑更清晰
这个方案的优势是逻辑模块化,后续维护起来更方便,而且全程只遍历一次全量配置,从根源上解决两次循环的效率问题。
额外提速小技巧
- 过滤禁用站点:循环前先把
enabled: false的配置过滤掉,减少循环数量:
之后用nginx_active_sites: "{{ nginx_sites | selectattr('enabled', 'equalto', true) | list }}"nginx_active_sites作为循环源就行。 - 开启并发执行:如果你的ServerA是多台服务器,在
ansible.cfg里把forks调大(比如设为20),让Ansible同时处理多台机器的任务,总耗时会直接砍半甚至更多。 - 精准控制变更触发:在模板任务里用
changed_when自定义变更条件,避免无意义的重复操作,比如只有当模板内容和目标文件差异超过特定阈值时才标记为变更。
内容的提问来源于stack exchange,提问作者Pablo Marti Cordero
相关产品推荐
相关产品推荐

