Есть ли способ запустить циклы with_items параллельно в Ansible?

12

Я использую Ansible 2.2, но могу обновить, если это поможет.

Я видел это и был довольно взволнован, но этого, похоже, нет в этой (или любой другой) версии документации Ansible.

Проблема, которую я пытаюсь решить, состоит в том, что у меня есть 1000 пользователей, которыми я должен управлять на коробке Centos.

Это занимает много времени, чтобы запустить эту задачу поочередно. И что еще более раздражает, все выглядит как измененное, потому что команда «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 мог получить авторизованные ключи из этой центральной базы.
Тенсибай
2
Я не согласен с тем, для чего нужен ansible (намек на то, что он не выполняет массовое создание / управление пользователями). Я настаиваю на том, что учетными записями нельзя управлять на локальных базах учетных записей в больших объемах (факт, что они не являются учетными записями людей, так или иначе, не имеет отношения к проблеме)
Tensibai

Ответы:

13

Как упомянул @webKnja, это возможно в asyncрежиме. Я недавно обнаружил это сам и узнал, что вы можете использовать его тремя различными способами в зависимости от ваших потребностей.

  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, для кого это потребует дополнительной задачи 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 в вопросе, я не собираюсь этого делать.

MMT
источник
@ chicks, вы можете изменить pollзначение на 0 в примере 3. Это удивительное объяснение !! Thnx.
Дебанжан Басу
@DebanjanBasu Любой может внести предложенные изменения. Я могу быть тем, кто одобряет его в очередях просмотра, но вы должны получить кредит на само редактирование.
птенцы
К сожалению, редактирование одного персонажа запрещено! :(
Дебанжан Басу
2
Вариант 3 отлично работает, спасибо! Один комментарий: по крайней мере, в Ansible 2.8, async_statusтребуется jid, а не id.
EdwardTeach
4

Чтобы ответить на ваш вопрос: Нет, на данный момент Ansible не может выполнять циклы параллельно.

Я бы использовал newusersвместо этого, что сделано для массового создания пользователей. Создайте файл со всеми пользователями в нем, скопируйте его к хозяину, и запустить newusers /path/to/user/listв commandзадаче.

simonz
источник
3

Этого можно добиться, используя asyncрежим. Пожалуйста, найдите некоторые ссылки для того, как сделать это ниже.

Refs:

---

- 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 }}"
webKnjaZ
источник
Хотя эти ссылки могут ответить на вопрос, если они потерпят крах, в вашем ответе для будущих читателей ничего не останется, пожалуйста, попробуйте продемонстрировать, как это поможет решить проблему с вашими собственными словами / примером, и оставьте ссылки только для более подробной информации.
Тенсибай
да, я не могу пометить это как ответ, пока A.) я не проверю это и B.) соответствующий код размещен здесь. Но, тем не менее, спасибо, что указали мне в этом направлении.
Питер Тернер
Извините, я был спешит :)
webKnjaZ