Чи є параметр запускати цикли with_items паралельно в Ansible?


12

Я працюю Ansible 2.2, але можу оновити, якщо це допоможе.

Я бачив це і був дуже схвильований, але, схоже, це не є в цій (або будь-якій) версії документації Ansible.

Проблема, яку я намагаюся вирішити, - це те, що я отримав 1000 користувачів, якими мені потрібно керувати у вікні Centos.

Це завдання потрібно виконувати серійно. І ще більше дратує, що все відображається як змінено, тому що команда "закінчується" в модулі користувача завжди позначає річ як змінену.

це також виглядало багатообіцяюче, але для виконання кожної команди в циклі 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 є фрагмент, я думаю, це трохи допомагає для контексту. Мене більше цікавить концептуально, чи дійсно є спосіб виконання завдань (у циклі) паралельно на тому ж хості. Я знаю, що я міг би зробити багато індивідуальних речей з асинхронією, але не так багато з with_items.
Пітер Тернер

Отже, якщо потрібно створити 1000 користувачів, це слід закінчити так само швидко, як створити лише одного користувача. Цікаво, чому б не використовувати щось на зразок LDAP?
030

1
Якщо серйозно, ви рухаєтеся до больового шляху, я не думаю, що хтось обробляє більше десятка облікових записів із локальною базою облікових записів, як тільки кількість користувачів зростає, я припускаю, що всі переходять до централізованої системи обліку, як правило деякий бекенд ldap (може бути активним каталогом), а потім встановити час закінчення терміну дії та відкритий ключ як атрибути цієї центральної бази, потім використовуйте такі речі, як sss_ssh_authorizedkeys, щоб дозволити ssh-серверу отримати авторизовані ключі від цієї центральної бази.
Тенсібай

2
Я не погоджуюсь, для чого саме відповідальний (натякаючи, що це не робить масового створення / управління користувачами). Я відстоюю те, що обліковими записами не слід керувати на великих локальних рахунках (факт, що вони не є людськими рахунками, ніяк не має значення для проблеми)
Тенсібай

Відповіді:


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, проте це потребуватиме додаткового завдання 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варіант, який найкраще працює, якщо мені доведеться виконувати одне і те ж завдання в кількох хостах. Саме тут мені вдалося «заощадити» найбільше часу.

Оскільки ви розмістили посилання на документацію відповіді у запитанні, я не збираюся цього робити.


@chicks Ви можете змінити pollзначення на 0 у прикладі 3. Це дивовижне пояснення !! Thnx.
Дебанджан Басу

@DebanjanBasu Кожен може внести запропоновані зміни. Я можу бути тим, хто схвалює це в черзі на огляд, але вам слід отримати кредит за саму редагування.
пташенята

Одно редагування символів на жаль не дозволено! :(
Дебанджан Басу

2
Варіант 3 чудово працює, дякую! Хоча один коментар: принаймні відповідь 2.8 async_statusвимагає jid, ні id.
EdwardTeach

4

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

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


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 }}"

Хоча ці посилання можуть відповісти на питання, якщо вони зірвуться, у вашій відповіді майбутнім читачам нічого не залишиться, будь ласка, спробуйте показати, як це допоможе вирішити проблему своїми власними словами / прикладами, а посилання залиште лише для більш детальної інформації.
Тенсібай

так, я не можу позначити це як відповідь, поки А.) Я перевіряю це, і B.) тут розміщується відповідний код. Але дякую, що все-таки вказали мені в цьому напрямку.
Пітер Тернер

Вибачте, я поспішав :)
webKnjaZ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.