Existe uma maneira de executar loops with_items em paralelo no Ansible?


12

Estou executando o Ansible 2.2, mas pode atualizar se ajudar.

Vi isso e fiquei bastante empolgado, mas não parece estar nesta (ou em nenhuma) versão da documentação do Ansible.

O problema que estou tentando resolver é que tenho 1000 usuários que preciso gerenciar em uma caixa de Centos.

Demora um pouco para executar esta tarefa em série. E ainda mais irritante, tudo aparece como alterado porque o comando "expira" no módulo do usuário sempre marca a coisa como alterada.

isso também parecia promissor, mas levou a mesma quantidade de tempo para executar cada comando no loop with_items e não foi mais rápido (nunca me preocupei em esperar o suficiente para chegar ao fim).

Ignorar tarefas é rápido agora (muito mais rápido do que no Ansible 2.0), se eu não conseguir descobrir como fazer isso funcionar em paralelo, acho que vou voltar e descobrir como ignorar tarefas sem sentido e se todas mais falhar, eu vou escrever meu próprio módulo. Mas parece que eu deveria ser capaz de fazer tudo isso mais rapidamente no Ansible.


Isto é o que eu quero executar em paralelo, host_authorizationsé uma lista de nomes de usuários e outros dados.

  - 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

Forneça um trecho de código. Caso contrário, é difícil ajudar.
030

@ 030 há um trecho, acho que ajuda um pouco no contexto. Estou mais interessado conceitualmente se houver realmente uma maneira de executar tarefas (em loop) em paralelo no mesmo host. Eu sei que eu poderia fazer uma tonelada de coisas individuais com async, mas não tanto com with_items.
Peter Turner

Então, basicamente, se for necessário criar 1.000 usuários, ele deverá ser concluído o mais rápido possível, criando apenas um usuário. Interessante, por que não usar algo como LDAP?
030

11
Sério, você está caminhando em direção a um caminho doloroso, acho que ninguém lida com mais de uma dúzia de contas com base local, assim que o número de usuários cresce, presumo que todos se mudem para um sistema de contabilidade centralizado, normalmente algum back-end ldap (poderia ser diretório ativo) e, em seguida, defina o tempo de expiração e a chave pública como atributos dessa base central e use coisas como sss_ssh_authorizedkeys para permitir que o servidor ssh obtenha as chaves autorizadas nessa base central.
Tensibai

2
Discordo que é para isso que o ansible é (dica: ele não faz criação / gerenciamento de usuários em massa). Eu mantenho o ponto que as contas não devem ser geridos em bases de contas locais em grande volume (verdade eles não são contas humanos é irrelevante para o problema de qualquer maneira)
Tensibai

Respostas:


13

Como o @webKnja mencionou, isso é possível com o asyncmodo. Eu mesmo descobri recentemente e aprendi que você pode usá-lo de três maneiras diferentes, dependendo de suas necessidades.

  1. Execute e faça uma sondagem nos resultados, observe o poll:5: Isso fará uma sondagem nos resultados a cada 5 segundos. Você pode economizar algum tempo com esse método.

    - 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. Dispare e esqueça poll: 0 , esta é uma opção muito rápida, já que o Ansible está apenas executando essas tarefas. O lado negativo é que não sabemos qual foi o resultado da tarefa, ou seja changed: True/False. Claro que é uma desvantagem se você se importa com o feedback;).

    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. Dispare e esqueçaasync_status , a sintaxe da tarefa é a mesma do exemplo 2, sempre que exigirá tarefa adicional async_status. Este é o meu favorito, pois é relativamente rápido (mais rápido que o loop normal ou o execute and poll) e permite que você capture o feedback, embora precise lidar com o novo registerpara o seu async_task.

    retries: 20 - quantas tentativas antes de falhar.

    delay: 2 - quantos segundos esperar entre as pesquisas.

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

Uma palavra de cautela , dependendo da tarefa que você talvez não consiga usar a asyncopção. Eu tinha exemplos em que estava interagindo com o sistema que não era capaz de lidar com várias solicitações para o mesmo recurso. Eu achei a asyncopção melhor funcionando se eu tiver que executar a mesma tarefa em vários hosts. Foi onde pude "economizar" mais tempo.

Desde que você postou o link para a documentação Ansible na pergunta, não vou fazer isso.


@chicks, você pode querer alterar o pollvalor para 0 no exemplo 3. Esta é uma explicação incrível! Thnx.
Debanjan Basu

@DebanjanBasu Qualquer um pode fazer edições sugeridas. Talvez eu seja quem aprova nas filas de revisão, mas você deve obter crédito pela edição em si.
pintos

Infelizmente, edições de um personagem não são permitidas! :(
Debanjan Basu

2
Opção 3 funciona muito bem, obrigado! Porém, um comentário: a partir do Ansible 2.8, async_statusrequer jid, não id.
EdwardTeach

4

Para responder à sua pergunta: Não, a partir de agora o Ansible não pode executar loops em paralelo.

Em newusersvez disso, eu usaria , criado para a criação de usuários em massa. Crie um arquivo com todos os usuários, copie-o para o host e execute newusers /path/to/user/listuma commandtarefa.


3

É possível conseguir isso usando o asyncmodo. Por favor, encontre algumas referências sobre como fazer isso abaixo.

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

Embora esses links possam responder à pergunta se eles quebrarem, não resta mais nada na sua resposta para futuros leitores, tente mostrar como isso ajudaria a resolver o problema com suas próprias palavras / exemplo e deixe os links apenas para informações mais detalhadas.
Tensibai

sim, não posso marcar isso como a resposta até que A.) eu teste e B.) o código relevante seja colocado aqui. Mas obrigado por me apontar nessa direção, no entanto.
Peter Turner

Desculpe, eu era depressa :)
webKnjaZ
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.