Czy istnieje sposób równoległego uruchamiania pętli with_items w Ansible?

12

Korzystam z Ansible 2.2, ale mogę zaktualizować, jeśli to pomoże.

Widziałem to i byłem bardzo podekscytowany, ale wydaje się, że nie ma go w tej (lub żadnej) wersji dokumentacji Ansible.

Problem, który próbuję rozwiązać, to 1000 użytkowników, którymi muszę zarządzać na urządzeniu Centos.

Wykonanie tego zadania zajmuje dużo czasu. A nawet bardziej irytujące, wszystko pokazuje się jako zmienione, ponieważ polecenie „wygasa” w module użytkownika zawsze oznacza to jako zmienione.

wyglądało to również obiecująco, ale uruchomienie każdej komendy w pętli with_items zajęło tyle samo czasu i nie przyspieszyło (nigdy nie zadałem sobie trudu, by czekać wystarczająco długo, aby dojść do końca).

Pomijanie zadań jest teraz szybkie (dużo szybsze niż w Ansible 2.0), jeśli nie będę w stanie wymyślić, jak to zrobić równolegle, myślę, że wrócę i wymyślę, jak pomijać niepotrzebne zadania, a jeśli wszystko inaczej zawiedzie, napiszę własny moduł. Ale wydaje się, że powinienem być w stanie zrobić to wszystko szybciej w Ansible.


To, co chcę uruchomić równolegle, host_authorizationsto lista nazw użytkowników i innych danych.

  - 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
Peter Turner
źródło
Podaj fragment kodu. W przeciwnym razie trudno jest pomóc.
030
@ 030 jest fragment, myślę, że to trochę pomaga w kontekście. Interesuje mnie bardziej koncepcyjnie, czy naprawdę istnieje sposób na równoległe uruchamianie zadań na tym samym hoście. Wiem, że mogłem zrobić mnóstwo pojedynczych rzeczy za pomocą asynchronizacji, ale nie tyle z with_items.
Peter Turner,
Zasadniczo, jeśli trzeba utworzyć 1000 użytkowników, należy to zakończyć tak szybko, jak utworzenie tylko jednego użytkownika. Ciekawe, dlaczego nie skorzystać z czegoś takiego jak LDAP?
030
1
Poważnie, zmierzasz w kierunku bólu, nie sądzę, aby ktokolwiek obsługiwał więcej niż tuzin kont z lokalną bazą kont, jak tylko liczba użytkowników wzrośnie, zakładam, że wszyscy przechodzą do scentralizowanego systemu księgowego, zwykle niektóre backend ldap (może być active directory), a następnie ustaw czas wygaśnięcia i klucz publiczny jako atrybuty tej centralnej bazy, a następnie użyj rzeczy takich jak sss_ssh_authorizedkeys, aby pozwolić serwerowi ssh uzyskać autoryzowane klucze z tej centralnej bazy.
Tensibai
2
Nie zgadzam się z tym, po co jest odpowiedzialny (wskazówka, że ​​nie robi to masowego tworzenia / zarządzania użytkownikami). Stoję na stanowisku, że kontami nie należy zarządzać na dużych kontach lokalnych (fakt, że nie są to konta ludzkie, nie ma znaczenia dla problemu)
Tensibai

Odpowiedzi:

13

Jak wspomniano @webKnja, jest to możliwe w asynctrybie. Niedawno go odkryłem i nauczyłem się, że możesz go używać na 3 różne sposoby, w zależności od potrzeb.

  1. Wykonaj i odpytaj wyniki, zwróć uwagę poll:5, Spowoduje to odpytanie wyników co 5 sekund. Dzięki tej metodzie możesz zaoszczędzić trochę czasu.

    - 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. Strzelaj i zapominaj poll: 0 , jest to bardzo szybka opcja, ponieważ Ansible to po prostu strzelanie do tych zadań. Minusem jest to, że nie wiemy, jaki był wynik zadania, tj changed: True/False. Oczywiście jest to minus, jeśli zależy ci na opiniach;).

    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. Odpal i zapomnijasync_status , składnia zadania jest taka sama jak w przykładzie 2, jednak będzie wymagała dodatkowego zadania async_status. To jest mój ulubiony, ponieważ jest to stosunkowo szybko (szybciej niż normalny lub pętli execute and poll) i pozwala uchwycić zwrotne chociaż będzie musiał radzić sobie z nową registerdla twojego async_task.

    retries: 20 - ile prób przed niepowodzeniem.

    delay: 2 - ile sekund trzeba czekać między ankietami.

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

Uwaga , w zależności od zadania, możesz nie móc skorzystać z tej asyncopcji. Miałem przykłady interakcji z systemem, który nie był w stanie obsłużyć wielu żądań dotyczących tego samego zasobu. Znalazłem asyncopcję najlepiej działającą, jeśli muszę wykonać to samo zadanie na wielu hostach. Właśnie tam mogłem „zaoszczędzić” najwięcej czasu.

Ponieważ w pytaniu zamieściłeś link do dokumentacji Ansible, nie zamierzam tego robić.

MMT
źródło
@ kurczęta, możesz chcieć zmienić pollwartość na 0 w przykładzie 3. To niesamowite wyjaśnienie !! Dziękuję
Debanjan Basu
@DebanjanBasu Każdy może dokonywać sugerowanych zmian. Być może to ja zatwierdzam go w kolejkach recenzji, ale powinieneś uzyskać uznanie za samą edycję.
pisklęta
Niestety modyfikacje jednej postaci są niedozwolone! :(
Debanjan Basu
2
Opcja 3 działa świetnie, dzięki! Jedna uwaga jednak: jak co najmniej ansibl 2,8, async_statuswymaga jid, nie id.
EdwardTeach
4

Aby odpowiedzieć na twoje pytanie: Nie, na razie Ansible nie może równolegle uruchamiać pętli.

Użyłbym newuserszamiast tego, który jest przeznaczony do masowego tworzenia użytkowników. Utwórz plik ze wszystkimi użytkownikami w nim, skopiuj go nad do hosta i uruchomić newusers /path/to/user/listw commandzadaniu.

simonz
źródło
3

Można to osiągnąć za pomocą asynctrybu. Poniżej znajdują się odniesienia do tego, jak to zrobić.

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
źródło
Chociaż linki te mogą odpowiedzieć na pytanie, jeśli dojdą do zerwania, nie ma już nic w odpowiedzi dla przyszłych czytelników, spróbuj pokazać, w jaki sposób pomogłoby to rozwiązać problem z własnymi słowami / przykładami i pozostawić linki tylko dla bardziej szczegółowych informacji.
Tensibai
tak, nie mogę zaznaczyć tego jako odpowiedzi, dopóki A.) nie przetestuję tego i B.) tutaj zostanie wstawiony odpowiedni kod. Ale dziękuję za skierowanie mnie w tym kierunku.
Peter Turner,
Przepraszam, spieszyłem się :)
webKnjaZ