有没有办法在Ansible中并行运行with_items循环?


12

我正在运行Ansible 2.2,但可以帮助升级。

我看到了这个消息,并感到非常兴奋,但是在这个(或任何版本)的Ansible文档中似乎都没有。

我要解决的问题是我需要在Centos机器上管理1000个用户。

串行运行此任务需要花费相当长的时间。更令人讨厌的是,所有内容都显示为已更改,因为用户模块上的“ expires”命令始终将其标记为已更改。

看起来也很有希望,但是在with_items循环中运行每个命令花费的时间相同,并且运行速度没有更快(我从不费心等待足够长的时间才能到达结尾)。

现在,跳过任务的速度很快(比Ansible 2.0快很多),如果我不知道如何并行进行这项工作,我想我会回过头来弄清楚如何跳过毫无意义的任务,如果有的话否则失败,我将编写自己的模块。但是似乎我应该可以在Ansible中更快地完成所有这些工作。


这是我要并行运行的, host_authorizations是用户名和其他数据的列表。

  - name: Create/modify OS user accounts
    user: name={{ item.username }} group=sshusers shell=/bin/bash home="/home/selinux-modules/{{ item.username }}" state=present expires={{item.expiredate|default(omit)}}
    with_items: "{{ host_authorizations }}"
    tags: full_maintenance

请提供代码段。否则很难提供帮助。
030

@ 030有一个摘要,我想它对上下文有帮助。从概念上讲,我更感兴趣的是是否真的有一种方法可以在同一主机上并行运行任务(循环)。我知道我可以用async来做很多单独的事情,但是用with_items不能做很多。
彼得·特纳

因此,基本上,如果必须创建1000个用户,则完成它的速度应与仅创建一个用户一样快。有趣的是,为什么不使用LDAP之类的东西呢?
030

1
认真地说,您正在走上一条痛苦的道路,我认为没有人会使用本地帐户来处理十几个帐户,而随着用户数量的增加,我认为每个人通常都会使用集中式会计系统一些ldap后端(可能是活动目录),然后将到期时间和公钥设置为该中央库的属性,然后使用sss_ssh_authorizedkeys之类的东西让ssh服务器从该中央库获取授权密钥。
Tensibai '18 -4-12

2
我不同意这是ansible的用途(提示它并不执行批量用户创建/管理)。我的观点是,不应以本地帐户为基础对帐户进行大量管理(事实上它们不是人工帐户,无论如何都与问题无关)
Tensibai

Answers:


13

正如@webKnja提到的,这可以通过async模式实现。我最近亲自发现了它,并了解到可以根据需要以3种不同的方式使用它。

  1. 执行并轮询结果,注意poll:5,这将每5秒轮询一次结果。使用此方法可以节省一些时间。

    - name: My long runing task
      some_module_name:
        ip: "{{item.fabric}}"
        username: "{{user}}"
        password: "{{password}}"
        secret: "{{secret}}"
      loop: "{{zoning_list}}"
      register: _alias_vc_0
      async: 60
      poll: 5
    
  2. poll: 0随手可,这是非常快速的选择,因为Ansible只是在执行这些任务。不利的一面是我们不知道任务的结果是什么changed: True/False。当然,如果您关心反馈的话,这是一个缺点。

    name: My long runing task
    some_module_name:
      ip: "{{item.fabric}}"
      username: "{{user}}"
      password: "{{password}}"
      secret: "{{secret}}"
    loop: "{{zoning_list}}"
    register: _alias_vc_0
    async: 60
    poll: 0
    
  3. 消防与忘记async_status,语法的任务是一样的例子2 whowever这将需要额外的任务async_status。这是我最喜欢的,因为它是比较快(快于正常循环或execute and poll),并允许您捕捉反馈,尽管需要应对新register的你async_task

    retries: 20 -失败前要进行多少次尝试。

    delay: 2 -两次轮询之间要等待多少秒。

    - name: My long runing task
      some_module_name:
        ip: "{{item.fabric}}"
        username: "{{user}}"
        password: "{{password}}"
        secret: "{{secret}}"
      loop: "{{zoning_list}}"
      register: _alias_vc_0
      async: 60
      poll: 0
    
    
    - name: Wait for My long running task to finish
      async_status:
        id: "{{ item.ansible_job_id }}"
      register: _jobs_alias_vc_0
      retries: 20
      delay: 2
      until: _jobs_alias_vc_0.finished
      loop: "{{_alias_vc_0.results}}"
    

请注意,根据您的任务,您可能无法使用该async选件。我有一些示例,其中我与无法处理同一资源的多个请求的系统进行交互。async如果必须在多个主机上执行同一任务,我发现选项最有效。那是我能够“节省”最多时间的地方。

自从您在问题中发布了Ansible文档的链接以来,我就不会这样做。


@chicks您可能想poll在示例3 中将值更改为0。这是一个了不起的解释!谢谢
Debanjan Basu,

@DebanjanBasu任何人都可以进行建议的编辑。我可能是在审核队列中批准它的人,但是您应该为编辑本身而功劳。
小鸡

遗憾地不允许编辑一个字符!:(
Debanjan Basu

2
选项3效果很好,谢谢!但有一条评论:至少从Ansible 2.8开始,async_status要求为jid,而不是id
EdwardTeach '19

4

要回答您的问题:否,到目前为止,Ansible无法并行运行循环。

我会newusers改为使用它来创建大量用户。创建一个包含所有用户的文件,将其复制到主机,然后newusers /path/to/user/listcommand任务中运行。


3

可以实现这种使用async模式。请在下面找到一些有关如何执行此操作的参考。

参考:

---

- name: Run tasks in parallel
  hosts: localhost
  connection: local
  gather_facts: no
  tasks:
    - name: Pretend to create instances
      command: "sleep {{ item }}"  # Instead of calling a long running operation at a cloud provider, we just sleep.
      with_items:
        - 6
        - 8
        - 7
      register: _create_instances
      async: 600  # Maximum runtime in seconds. Adjust as needed.
      poll: 0  # Fire and continue (never poll)

    - name: Wait for creation to finish
      async_status:
        jid: "{{ item.ansible_job_id }}"
      register: _jobs
      until: _jobs.finished
      delay: 5  # Check every 5 seconds. Adjust as you like.
      retries: 10  # Retry up to 10 times. Adjust as needed.
      with_items: "{{ _create_instances.results }}"

虽然这些链接可能会回答这个问题,但是它们对未来的读者没有任何帮助,但请尝试用自己的语言/示例来展示这将如何帮助解决问题,并仅保留链接以获取更详细的信息。
Tensibai

是的,我不能将其标记为答案,直到A.)我对其进行测试并且B.)相关代码放置在此处。但是仍然感谢您指出我的方向。
彼得·特纳

抱歉,我很着急:)
webKnjaZ 18/09/19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.