Ansible Playbook 执行调优

Ansible Playbook 执行调优

优化执行速度

优化执行速度有以下几个方式:

  • 优化基础架构,保证控制节点和主机之间网络延迟足够低,带宽足够高
  • 禁用事实变量收集
  • 利用事实变量缓存重复利用事实变量
  • 限制事实变量收集
  • 增加并行
  • 部分模块避免使用循环
  • 使用回调插件分析 Playbook 执行性能
  • 使用 ansible.posix.synchronize 复制大量文件
  • 使用模板复制文件
  • 启用流水线

优化基础架构

这个比较简单就是提升硬件配置。

禁用事实变量收集

---
- name: Playbook
  hosts: all
  gather_facts: false

Ansible 的配置文件里也可以设置禁用。

利用事实变量缓存重复利用事实变量

可以让 Ansible 在执行 Playbook 时先收集事实变量并缓存起来,后续的 Playbook 则设置 gather_facts: false 以禁用事实变量收集,让后续的 Playbook 使用已缓存的事实变量。

---
- name: Cache
  hosts: all
  gather_facts: true
  tasks: []

- name: Playbook
  hosts: all
  gather_facts: false
  tasks:
    - name: Debug
      ansible.builtin.debug:
        var: ansible_facts

Ansible 在配置文件中设置 gathering=smart 的话就可以保证在上述 Playbook 删除两行 gather_facts 也有同样的效果。

[defaults]
gathering=smart

Ansible 默认将变量缓存到内存中,执行完成后丢弃,将事实变量缓存到本地文件或其他可以存储缓存数据的数据库(如 redis)中也是可以提高效率的办法。

限制事实变量收集

ansible.builtin.setup 默认收集所有变量,通过 gather_subset 设置只收集部分变量。

关于 ansible.builtin.setup 子集,参考 ansible-doc ansible.builtin.setup

- name: Playbook
  hosts: all
  gather_facts: false
  tasks:
    - name: Setup
      ansible.builtin.setup:
        gather_subset:
          - '!all'
          - '!min'
          - network

增加并行

通过 forks 增加同时执行任务的主机数量。

[defaults]
forks=100

forks 也可以在其它地方设置,如 PlaybookAd Hoc

部分模块避免使用循环

这里以 ansible.builtin.dnf 模块为例,先列出两种写法:

---
- name: Install packages
  hosts: all
  become: true
  gather_facts: false
  tasks:
    - name: Install packages
      ansible.builtin.dnf:
        name:
          - httpd
          - mod_ssl
          - httpd-tools
          - mariadb-server
          - mariadb
          - php
          - php-mysqlnd
        state: present

---
- name: Install packages
  hosts: all
  become: true
  gather_facts: false
  tasks:
    - name: Install packages
      ansible.builtin.dnf:
        name: "{{ item }}"
        state: present
      loop:
        - httpd
        - mod_ssl
        - httpd-tools
        - mariadb-server
        - mariadb
        - php
        - php-mysqlnd

上边两种写法都能实现软件包的安装,但是两种写法所消耗的时间不一样。

第一种写法等效于:

[root@remote-host ~]# dnf install httpd mod_ssl httpd-tools \
    mariadb-server mariadb php php-mysqlnd

第二种写法等效于:

[root@remote-host ~]# dnf install httpd
[root@remote-host ~]# dnf install mod_ssl
[root@remote-host ~]# dnf install httpd-tools
[root@remote-host ~]# dnf install mariadb-server
[root@remote-host ~]# dnf install mariadb
[root@remote-host ~]# dnf install php
[root@remote-host ~]# dnf install php-mysqlnd

所以对于 ansible.builtin.dnf 模块,循环并不高效,应直接通过数组的方式列出所有要安装的软件包。

使用回调插件分析 Playbook 执行性能

Ansible 自带一些回调插件,也可以安装一些回调插件,下边是 quay.io/ansible/awx-ee:latest 执行环境自带的回调插件。

[root@remote-host ansible]# ansible-navigator doc -t callback -l
[WARNING]: Collection azure.azcollection does not support Ansible version 2.15.13
[WARNING]: Collection google.cloud does not support Ansible version 2.15.13
[WARNING]: Collection community.vmware does not support Ansible version 2.15.13
amazon.aws.aws_resource_actions summarizes all "resource:actions" completed
ansible.builtin.default         default Ansible screen output
ansible.builtin.junit           write playbook output to a JUnit file
ansible.builtin.minimal         minimal Ansible screen output
ansible.builtin.oneline         oneline Ansible screen output
ansible.builtin.tree            Save host events to files
ansible.legacy.awx_display      Playbook event dispatcher for ansible-runner
ansible.posix.cgroup_perf_recap Profiles system activity of tasks and full execution using cgroups
ansible.posix.debug             formatted stdout/stderr display
ansible.posix.json              Ansible screen output as JSON
ansible.posix.jsonl             Ansible screen output as JSONL (lines in json format)
ansible.posix.profile_roles     adds timing information to roles
ansible.posix.profile_tasks     adds time information to tasks
ansible.posix.timer             Adds time to play stats
ovirt.ovirt.stdout              Output the log of ansible
theforeman.foreman.foreman      Sends events to Foreman

可以通过以下方式启用插件:

[defaults]
callbacks_enabled=ansible.posix.timer, ansible.posix.profile_tasks, ansible.posix.profile_roles

再来个示例:

[root@remote-host ansible]# grep callbacks_enabled ansible.cfg
callbacks_enabled=ansible.posix.timer, ansible.posix.profile_tasks, ansible.posix.profile_roles

[root@remote-host ansible]# ansible-navigator run setup.yml

PLAY [setup] *******************************************************************

TASK [upgrade system] **********************************************************
Sunday 14 December 2025  17:38:23 +0000 (0:00:00.052)       0:00:00.052 *******
Sunday 14 December 2025  17:38:23 +0000 (0:00:00.050)       0:00:00.050 *******
changed: [base-k8s-master-1]
changed: [base-k8s-worker-2]
changed: [base-k8s-worker-1]

PLAY RECAP *********************************************************************
base-k8s-master-1          : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
base-k8s-worker-1          : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
base-k8s-worker-2          : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

PLAYBOOK RECAP *****************************************************************
Playbook run took 0 days, 0 hours, 24 minutes, 48 seconds

TASKS RECAP ********************************************************************
Sunday 14 December 2025  18:03:12 +0000 (0:24:48.951)       0:24:49.004 *******
===============================================================================
upgrade system ------------------------------------------------------- 1488.95s

ROLES RECAP ********************************************************************
Sunday 14 December 2025  18:03:12 +0000 (0:24:48.953)       0:24:49.003 *******
===============================================================================
ansible.builtin.dnf -------------------------------------------------- 1488.95s
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
total ---------------------------------------------------------------- 1488.95s

使用 ansible.posix.synchronize 复制大量文件

ansible.builtin.copy 模块可将文件和目录递归复制到被控主机。 当目录内含有许多文件时,复制可能需很长时间。如果是多次执行的话,后续只会复制不同的文件,使用时间会比第一次短。

如果要复制大量文件到被控主机时,使用 ansible.posix.synchronize 模块效率会更高。ansible.posix.synchronize 模块会在后台使用 rsync,速度比 ansible.builtin.copy 更快。将 delete 选项设置为 true 时,模块还可以从目标删除源主机上不再存在的文件。

ansible.posix.synchronize 模块在 ansible.posix 集合中,Ansible-Core 默认不带这个集合,需要手动添加集合。

ansible.posix.synchronize 模块要求被控节点安装 rsync 工具。

最后来个示例:

  1. 查看主机清单、Ansible 回调配置并创建 50 个文件:
   [root@ansible-controller ansible]# cat inventory
   base-k8s-master-1
   base-k8s-worker-1
   base-k8s-worker-2

   [root@ansible-controller ansible]# grep -e '^callback' ansible.cfg
   callbacks_enabled=ansible.posix.timer, ansible.posix.profile_tasks, ansible.posix.profile_roles

   [root@ansible-controller ansible]# touch files/testfile{0..49}
  1. 使用 ansible.builtin.copy 模块复制文件:
   [root@ansible-controller ansible]# cat test.yml
   ---
   - name: test
     hosts: all
     gather_facts: false
     tasks:
     - name: copy file
       ansible.builtin.copy:
         src: "./files/"
         dest: "/tmp"

   [root@ansible-controller ansible]# ansible-navigator run test.yml

   PLAY [test] ********************************************************************

   TASK [copy file] ***************************************************************
   Sunday 11 January 2026  15:45:06 +0000 (0:00:00.011)       0:00:00.011 ********
   Sunday 11 January 2026  15:45:06 +0000 (0:00:00.010)       0:00:00.010 ********
   changed: [base-k8s-worker-2]
   changed: [base-k8s-worker-1]
   changed: [base-k8s-master-1]

   PLAY RECAP *********************************************************************
   base-k8s-master-1          : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
   base-k8s-worker-1          : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
   base-k8s-worker-2          : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

   PLAYBOOK RECAP *****************************************************************
   Playbook run took 0 days, 0 hours, 0 minutes, 19 seconds

   TASKS RECAP ********************************************************************
   Sunday 11 January 2026  15:45:26 +0000 (0:00:19.801)       0:00:19.813 ********
   ===============================================================================
   copy file -------------------------------------------------------------- 19.80s

   ROLES RECAP ********************************************************************
   Sunday 11 January 2026  15:45:26 +0000 (0:00:19.802)       0:00:19.813 ********
   ===============================================================================
   ansible.builtin.copy --------------------------------------------------- 19.80s
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   total ------------------------------------------------------------------ 19.80s

可以看到复制总用时 19.80 秒。

  1. 使用 ansible.posix.synchronize 模块复制文件:
   [root@ansible-controller ansible]# cat test.yml
   ---
   - name: test
     hosts: all
     gather_facts: false
     tasks:
     - name: copy file
       ansible.posix.synchronize:
         src: "./files/"
         dest: "/tmp/"

   [root@ansible-controller ansible]# ansible-navigator run test.yml

   PLAY [test] ********************************************************************

   TASK [copy file] ***************************************************************
   Sunday 11 January 2026  15:56:42 +0000 (0:00:00.030)       0:00:00.030 ********
   Sunday 11 January 2026  15:56:42 +0000 (0:00:00.029)       0:00:00.029 ********
   changed: [base-k8s-worker-1]
   changed: [base-k8s-worker-2]
   changed: [base-k8s-master-1]

   PLAY RECAP *********************************************************************
   base-k8s-master-1          : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
   base-k8s-worker-1          : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
   base-k8s-worker-2          : ok=1    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

   PLAYBOOK RECAP *****************************************************************
   Playbook run took 0 days, 0 hours, 0 minutes, 0 seconds

   TASKS RECAP ********************************************************************
   Sunday 11 January 2026  15:56:43 +0000 (0:00:00.422)       0:00:00.453 ********
   ===============================================================================
   copy file --------------------------------------------------------------- 0.42s

   ROLES RECAP ********************************************************************
   Sunday 11 January 2026  15:56:43 +0000 (0:00:00.423)       0:00:00.452 ********
   ===============================================================================
   ansible.posix.synchronize ----------------------------------------------- 0.42s
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   total ------------------------------------------------------------------- 0.42s

可以看到总执行时间为 0.42 秒。

使用模板复制文件

如果只是修改一行文件,ansible.builtin.lineinfile 会比较方便,但是如果要修改多行文件 ansible.builtin.template 会比 ansible.builtin.lineinfile 更高效。

启用流水线

Ansible 默认禁用流水线,禁用流水线的 Task 执行流程如下:

控制端
  |
  | ssh
  v
远端主机
  |
  | scp 模块代码 -> /tmp/ansible_xxx.py
  |
  | ssh sudo python /tmp/ansible_xxx.py
  |
  | 执行
  • 模块先拷贝到远端磁盘
  • 再 sudo 执行
  • 至少 2~3 次 SSH 往返

通过在 ansible.cfg 设置 pipelining=True 可以开启流水线,开启后的 Task 执行流程如下:

控制端
  |
  | ssh(打开一次连接)
  |   ├── stdin:模块代码
  |   └── stdout/stderr:执行结果
  v
远端主机
  |
  | sudo python  (从 stdin 读模块)
  |
  | 执行

等效于:

ssh host "sudo python3 -" < ansible_module.py
  • python3 -: 👉 表示 从 stdin 读取代码
  • < ansible_module.py
    👉 把模块内容通过 stdin 送过去
  • 为什么流水线方式会快
  • 默认模式
    • ssh ×2
    • scp ×1
    • 磁盘 IO
    • sudo fork
  • pipelining
    • ssh ×1
    • 0 次 scp
    • 0 次磁盘 IO
    • sudo 直接读 stdin

这一段问的 AI,不知道解释的有没有问题。

开启流水线要求 sudo 禁用 requiretty 选项。

Defaults:ansible !requiretty
ansible ALL=(ALL) NOPASSWD: ALL

可以通过 visudo 命令修改

[root@host ~]# visudo
...output omitted...
Defaults !requiretty

在红帽企业 Linux 8 上(应该也算及以上),这个 sudo 选项默认为禁用,但在其他系统中可能为启用状态。

最后再来个示例:

  1. 查看主机清单、Ansible 回调配置和 Playbook:
   # 3 个被控主机
   [root@ansible-controller ansible]# cat inventory
   base-k8s-master-1
   base-k8s-worker-1
   base-k8s-worker-2

   [root@ansible-controller ansible]# grep '^callback' ansible.cfg
   callbacks_enabled=ansible.posix.timer, ansible.posix.profile_tasks, ansible.posix.profile_roles

   # 在所有被控主机的 /tmp 目录创建 50 个文件并对每个文件添加一行内容
   [root@ansible-controller ansible]# cat test.yml
   ---
   - name: test
     hosts: all
     gather_facts: false
     tasks:
     - name: create file
       ansible.builtin.file:
         path: "/tmp/testilfile-{{ item }}"
         state: touch
       loop: "{{ range(0,50) | list }}"
     - name: lineinfile
       ansible.builtin.lineinfile:
         line: "line {{ item }}"
         path: "/tmp/testilfile-{{ item }}"
       loop: "{{ range(0,50) | list }}"
  1. 未开启流水线的情况:
   [root@ansible-controller ansible]# grep 'pipelining=' ansible.cfg
   pipelining=False

   [root@ansible-controller ansible]# ansible-navigator run test.yml

   PLAY [test] ********************************************************************

   TASK [create file] *************************************************************
   Sunday 11 January 2026  15:32:31 +0000 (0:00:00.008)       0:00:00.008 ********
   Sunday 11 January 2026  15:32:31 +0000 (0:00:00.007)       0:00:00.007 ********
   changed: [base-k8s-worker-1] => (item=0)
   changed: [base-k8s-worker-2] => (item=0)
   changed: [base-k8s-master-1] => (item=0)
   ...output omitted...
   ok: [base-k8s-worker-2] => (item=49)
   ok: [base-k8s-master-1] => (item=48)
   ok: [base-k8s-master-1] => (item=49)

   PLAY RECAP *********************************************************************
   base-k8s-master-1          : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
   base-k8s-worker-1          : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
   base-k8s-worker-2          : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

   PLAYBOOK RECAP *****************************************************************
   Playbook run took 0 days, 0 hours, 0 minutes, 31 seconds

   TASKS RECAP ********************************************************************
   Sunday 11 January 2026  15:33:03 +0000 (0:00:15.644)       0:00:31.637 ********
   ===============================================================================
   create file ------------------------------------------------------------ 15.98s
   lineinfile ------------------------------------------------------------- 15.64s

   ROLES RECAP ********************************************************************
   Sunday 11 January 2026  15:33:03 +0000 (0:00:15.645)       0:00:31.636 ********
   ===============================================================================
   ansible.builtin.file --------------------------------------------------- 15.98s
   ansible.builtin.lineinfile --------------------------------------------- 15.65s
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   total ------------------------------------------------------------------ 31.63s

可以看到两个任务都是 15 秒多,总时间 31.63 秒。

  1. 开启流水线的情况:
   [root@ansible-controller ansible]# grep 'pipelining=' ansible.cfg
   pipelining=True

   [root@ansible-controller ansible]# ansible-navigator run test.yml

   PLAY [test] ********************************************************************

   TASK [create file] *************************************************************
   Sunday 11 January 2026  15:38:58 +0000 (0:00:00.007)       0:00:00.007 ********
   Sunday 11 January 2026  15:38:58 +0000 (0:00:00.006)       0:00:00.006 ********
   changed: [base-k8s-worker-2] => (item=0)
   changed: [base-k8s-master-1] => (item=0)
   changed: [base-k8s-worker-1] => (item=0)
   ...output omitted...
   ok: [base-k8s-worker-2] => (item=49)
   ok: [base-k8s-master-1] => (item=48)
   ok: [base-k8s-master-1] => (item=49)

   PLAY RECAP *********************************************************************
   base-k8s-master-1          : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
   base-k8s-worker-1          : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
   base-k8s-worker-2          : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

   PLAYBOOK RECAP *****************************************************************
   Playbook run took 0 days, 0 hours, 0 minutes, 18 seconds

   TASKS RECAP ********************************************************************
   Sunday 11 January 2026  15:39:16 +0000 (0:00:08.838)       0:00:18.504 ********
   ===============================================================================
   create file ------------------------------------------------------------- 9.66s
   lineinfile -------------------------------------------------------------- 8.84s

   ROLES RECAP ********************************************************************
   Sunday 11 January 2026  15:39:16 +0000 (0:00:08.838)       0:00:18.504 ********
   ===============================================================================
   ansible.builtin.file ---------------------------------------------------- 9.66s
   ansible.builtin.lineinfile ---------------------------------------------- 8.84s
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   total ------------------------------------------------------------------ 18.50s

可以看到两个任务都是 9 秒左右,总时间 18.50 秒。

Ansible Playbook 执行调优
https://www.linuxstudynotes.com/2026/01/12/ansible/ansible-playbook-%e6%89%a7%e8%a1%8c%e8%b0%83%e4%bc%98/
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇