Existe-t-il un moyen d'exécuter des boucles with_items en parallèle dans Ansible?

12

J'utilise Ansible 2.2, mais je peux mettre à niveau si cela aide.

J'ai vu cela et j'étais assez excité, mais cela ne semble pas être dans cette version (ou n'importe quelle autre) de la documentation Ansible.

Le problème que j'essaie de résoudre est que j'ai 1000 utilisateurs que je dois gérer sur une box Centos.

Il faut un certain temps pour exécuter cette tâche en série. Et encore plus ennuyeux, tout apparaît comme modifié car la commande "expires" sur le module utilisateur marque toujours la chose comme modifiée.

cela semblait également prometteur, mais cela prenait le même temps pour exécuter chaque commande dans la boucle with_items et n'allait pas plus vite (je n'ai jamais pris la peine d'attendre assez longtemps pour arriver à la fin).

Sauter des tâches est rapide maintenant (beaucoup plus rapide que dans Ansible 2.0), si je ne peux pas comprendre comment faire fonctionner cela en parallèle, je pense que je vais revenir en arrière et comprendre comment sauter des tâches inutiles et si tout sinon échoue, je vais écrire mon propre module. Mais il semble que je devrais pouvoir faire tout cela plus rapidement dans Ansible.


C'est ce que je veux exécuter en parallèle, host_authorizationsc'est une liste de noms d'utilisateurs et d'autres données.

  - 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
la source
Veuillez fournir un extrait de code. Sinon, il est difficile d'aider.
030
@ 030 il y a un extrait, je suppose que ça aide un peu pour le contexte. Je suis plus intéressé conceptuellement s'il existe vraiment un moyen d'exécuter des tâches (en boucle) en parallèle sur le même hôte. Je sais que je pourrais faire une tonne de choses individuelles avec async, mais pas tellement avec with_items.
Peter Turner
Donc, fondamentalement, si 1000 utilisateurs doivent être créés, cela devrait être terminé aussi rapidement que la création d'un seul utilisateur. Intéressant, pourquoi ne pas utiliser quelque chose comme LDAP?
030
1
Sérieusement, vous vous dirigez vers un chemin de douleur, je ne pense pas que quiconque gère plus d'une douzaine de comptes avec une base de comptes locale, dès que le nombre d'utilisateurs augmente, je suppose que tout le monde passe à un système comptable centralisé, habituellement un backend ldap (pourrait être un répertoire actif), puis définissez l'heure d'expiration et la clé publique comme attributs de cette base centrale, puis utilisez des choses comme sss_ssh_authorizedkeys pour permettre au serveur ssh d'obtenir les clés autorisées de cette base centrale.
Tensibai
2
Je ne suis pas d'accord pour dire à quoi sert ansible (un indice étant qu'il ne fait pas de création / gestion en masse d'utilisateurs). Je maintiens le point que les comptes ne doivent pas être gérés sur des bases de comptes locales à grand volume (le fait qu'ils ne soient pas des comptes humains n'est pas pertinent pour le problème de toute façon)
Tensibai

Réponses:

13

Comme @webKnja l'a mentionné, cela est possible avec le asyncmode. Je l'ai moi-même découvert récemment et j'ai appris que vous pouvez l'utiliser de 3 manières différentes selon vos besoins.

  1. Exécutez et interrogez les résultats, notez le poll:5, cela interrogera les résultats toutes les 5 secondes. Vous pouvez gagner du temps avec cette méthode.

    - 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. Tirez et oubliez poll: 0 , c'est une option très rapide car Ansible ne fait que tirer sur ces tâches. L'inconvénient est que nous ne savons pas quel a été le résultat de la tâche, c'est-à-dire changed: True/False. Bien sûr, c'est un inconvénient si vous vous souciez des commentaires;).

    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. Déclenchez et oubliez avecasync_status , la syntaxe de la tâche est la même que dans l'exemple 2, chaque fois qu'elle nécessitera une tâche supplémentaire async_status. C'est mon préféré car il est relativement rapide (plus rapide que le bouclage normal ou le execute and poll) et vous permet de capturer les commentaires, mais il faudra en traiter de nouveaux registerpour votre async_task.

    retries: 20 - combien de tentatives avant d'échouer.

    delay: 2 - combien de secondes attendre entre les sondages.

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

Un mot d'avertissement , selon la tâche, vous ne pourrez peut-être pas utiliser l' asyncoption. J'ai eu des exemples où j'interagissais avec un système qui n'était pas en mesure de gérer plusieurs demandes pour la même ressource. J'ai trouvé que l' asyncoption fonctionnait mieux si je devais effectuer la même tâche sur plusieurs hôtes. C'est là que j'ai pu "économiser" le plus de temps.

Depuis que vous avez publié le lien vers la documentation Ansible dans la question, je ne vais pas le faire.

MMT
la source
@chicks vous voudrez peut-être changer la pollvaleur à 0 dans l'exemple 3. C'est une explication incroyable !! Thnx.
Debanjan Basu
@DebanjanBasu Tout le monde peut apporter des modifications suggérées. Je suis peut-être celui qui l'approuve dans les files d'attente de révision, mais vous devriez obtenir le crédit pour l'édition elle-même.
poussins
Les modifications d'un caractère ne sont malheureusement pas autorisées! :(
Debanjan Basu
2
L'option 3 fonctionne très bien, merci! Un commentaire cependant: depuis au moins Ansible 2.8, async_statusnécessite jid, non id.
EdwardTeach
4

Pour répondre à votre question: Non, pour l'instant Ansible ne peut pas exécuter de boucles en parallèle.

J'utiliserais à la newusersplace, ce qui est fait pour la création d'utilisateurs en masse. Créez un fichier avec tous les utilisateurs, copiez-le sur l'hôte et exécutez newusers /path/to/user/listune commandtâche.

simonz
la source
3

Il est possible d'y parvenir en utilisant le asyncmode. Veuillez trouver ci-dessous quelques références sur la façon de procéder.

Réfs:

---

- 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
la source
Bien que ces liens puissent répondre à la question s'ils se cassent, il n'y a plus rien dans votre réponse pour les futurs lecteurs, veuillez essayer de montrer comment cela pourrait aider à résoudre le problème avec vos propres mots / exemple et laisser les liens pour des informations plus détaillées uniquement.
Tensibai
oui, je ne peux pas marquer cela comme réponse jusqu'à ce que A.) Je le teste et B.) le code pertinent est placé ici. Mais merci de m'avoir quand même orienté dans cette direction.
Peter Turner
Désolé, j'étais pressé :)
webKnjaZ