我有一个剧本,应该下载并解压多个 zip 文件。这些存档大小为数百 MB 到数 GB,因此这两个步骤都需要一些时间。我想通过异步操作提高性能:
- name: Downloading cnx 6.5 files from flexnet
become: yes
flexnet_download:
user: "{{ flexnet_download.user }}"
password: "{{ flexnet_download.password }}"
target: "{{ flexnet_download.target }}/cnx"
package_id: HCL_Connections_6.5_CRx
files:
- HCL_Connections_6.5_lin.tar
- name: Downloading db2 files from flexnet
become: yes
async: 3600 #1h
poll: 0
flexnet_download:
user: "{{ flexnet_download.user }}"
password: "{{ flexnet_download.password }}"
target: "{{ flexnet_download.target }}/db2"
package_id: HCL_Connections_6.5
files:
- CNB75ML.tar
- CNB23ML.zip
- name: "Unpack cnx installer archive {{ cnx.install_archive_core }} to {{ cnx.install_dir_core }}"
become: yes
async: 3600 #1h
poll: 0
unarchive:
src: "{{ cnx.install_archive_core }}"
dest: "{{ cnx.install_dir_core }}"
creates: "{{ cnx.install_dir_core }}/launchpad.sh"
extra_opts:
- --strip=1
第一个任务下载第一个 zip。然后,我尝试在提取第一个 zip 的同时并行下载其他 zip(
cnx.install_archive_core
是 HC6.5_CR1.zip
的完整路径)。不幸的是,unarchive
任务失败了:
TASK [Unpack cnx installer archive /opt/cnx-install/cnx/HCL_Connections_6.5_lin.tar to /opt/cnx-install/cnx/core] **********************************************************************************
Saturday 06 February 2021 12:45:19 +0000 (0:02:39.856) 0:02:40.551 *****
fatal: [127.0.0.1]: FAILED! => changed=false
msg: async is not supported for this task.
我猜
unarchive
模块不支持。但我想知道 unarchive
模块中似乎没有关于它的文档。由于 Ansible 幸运的是开源的,我发现了这个检查,似乎模块需要设置一个属性
_supports_async = True
以允许异步使用。当搜索异步插件时,我只找到了8个插件 - 它们都不能用于提取。 有没有其他方法可以异步解压档案?
unarchive
模块添加异步支持?我猜异步是通过在后台运行任务然后在指定的时间间隔内轮询stdout/stderr来实现的。 以这种方式使用
unzip
CLI 工具提取时需要考虑什么?
Ansible 做事方式。但我看到的唯一方法是在 shell 上手动运行 unzip
,
command
插件支持异步。
unarchive
模块仍然不支持异步模式。
但是仍然有一些方法可以欺骗 Ansible。使用库存并行运行戏剧
我们应该调整我们的库存 - 定义两个主机,它们的下载和目标目录参数具有不同的值:
---
downloads:
vars:
ansible_connection: local # it could be any type
ansible_host: localhost # also any - the idea is that it's the same machine for both host names in inventory
install_archive_core: "./archive/Archive-{{ inventory_hostname }}.zip"
install_dir_core: "unarchived/{{ inventory_hostname }}" # `cox` or `db2` is used to separate the paths
hosts:
cnx:
package_id: HCL_Connections_6.5_CRx
files:
- HCL_Connections_6.5_lin.tar
db2:
package_id: HCL_Connections_6.5
files:
- CNB75ML.tar
- CNB23ML.zip
示例剧本(肯定是为了测试而简化的):
- name: Test async unpacking
hosts: downloads
gather_facts: false
tasks:
- name: Create the target directories
file:
path: "{{ install_dir_core }}"
state: directory
- name: Unpack the archive
unarchive:
src: "{{ install_archive_core }}"
dest: "{{ install_dir_core }}"
when: not ansible_check_mode
我们来测试一下。我有两个相同的档案:
Archive-cnx.zip
和
Archive-db2.zip
(均为 207,4 MB)。
解压一个 db2
存档大约需要 13.5 秒,而 cnx
则需要相同的时间:ansible-playbook playbook.yml --inventory inventory.yml --limit db2
PLAY RECAP ******************************************************************************************************************************************************************************************
cnx : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Friday 29 December 2023 04:08:47 +0100 (0:00:13.492) 0:00:14.092 *******
===============================================================================
Unpack the archive ----------------------------------------------------- 13.49s
Create the target directories ------------------------------------------- 0.58s
并行解压两个档案仅需 20 秒:
ansible-playbook playbook.yml --inventory inventory.yml
PLAY RECAP ******************************************************************************************************************************************************************************************
cnx : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
db2 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Friday 29 December 2023 04:12:06 +0100 (0:00:19.866) 0:00:20.532 *******
===============================================================================
Unpack the archive ----------------------------------------------------- 19.87s
Create the target directories ------------------------------------------- 0.65s
策略
可以提供帮助的地方:它不会阻止播放中当前批次的其他主机执行后续任务:
- name: Test async downloading and unpacking
hosts: downloads
gather_facts: false
strategy: free
tasks:
- name: Downloading files from flexnet
become: yes
flexnet_download:
user: "{{ flexnet_download.user }}"
password: "{{ flexnet_download.password }}"
target: "{{ install_archive_core }}"
package_id: "{{ package_id }}"
files: "{{ files }}"
- name: Create the target directories
file:
path: "{{ install_dir_core }}"
state: directory
- name: Unpack the archive
unarchive:
src: "{{ install_archive_core }}"
dest: "{{ install_dir_core }}"
when: not ansible_check_mode
在此示例中,即使
Downloading files from flexnet
任务需要更长的时间来处理其中一个文件,Ansible 也不会等待其完成,而是会尽快继续执行
Create the target directories
和 Unpack the archive
任务。我们仍然可以使用 Test async downloading and unpacking
并在以后的游戏中定义我们自己的同步点。我解释了这种方法,并在此处稍微不同的上下文中提到了一些其他细节:Ansible Playbook 运行一些主机并行和一些串行。