britho / Ansible-HedHat

0 stars 0 forks source link

Aula-7-8 #5

Open britho opened 3 years ago

britho commented 3 years ago

Meta | Escrever playbooks otimizados para projetos maiores e mais complexos. -- | -- Objetivos | Escrever padrões de host sofisticados a fim de selecionar hosts com eficiência para uma ação ou um comando ad hoc. Descrever a natureza e a finalidade dos inventários dinâmicos, além de instalar e usar um script existente como uma fonte de inventário dinâmico do Ansible. Ajustar o número de conexões simultâneas abertas pelo Ansible para hosts gerenciados e como o Ansible processa grupos de hosts gerenciados por meio das tarefas da ação. Gerenciar playbooks grandes importando ou incluindo playbooks e tarefas de arquivos externos, seja incondicionalmente ou com base em um teste condicional. Seções | Seleção de hosts com padrões de host (e exercício orientado) Gerenciamento de inventários dinâmicos (e exercício orientado) Configuração de paralelismo (e exercício orientado) Inclusão e importação de arquivos (e exercício orientado) Laboratório | Gerenciamento de projetos grandes

Objetivos

Depois de concluir esta seção, você deverá ser capaz de escrever padrões de host sofisticados a fim de selecionar hosts com eficiência para uma ação ou um comando ad hoc.

Referências a hosts de inventário

Os padrões de host são usados para especificar os hosts que devem ser o alvo de uma ação ou comando ad hoc. Na sua forma mais simples, o nome de um host gerenciado ou de um grupo de hosts no inventário é um padrão de host que especifica o host ou grupo de hosts.

Você já usou padrões de host neste curso. Em uma ação, a diretiva de hosts especifica os hosts gerenciados nos quais executar a ação. Para um comando ad hoc, forneça o padrão de host como um argumento de linha de comando do comando ansible.

Normalmente, é mais fácil controlar quais são os hosts de destino de uma ação usando padrões de host com cuidado e tendo grupos de inventário apropriados, em vez de configurar condicionais complexas nas tarefas da ação. Portanto, é importante ter uma compreensão robusta dos padrões de host.

O exemplo a seguir é usado em toda esta seção para ilustrar os padrões de host.

[student@controlnode ~]$ cat myinventory
web.example.com
data.example.com
[lab]
labhost1.example.com
labhost2.example.com
[test]
test1.example.com
test2.example.com
[datacenter1]
labhost1.example.com
test1.example.com
[datacenter2]
labhost2.example.com
test2.example.com
[datacenter:children]
datacenter1
datacenter2
[new]
192.168.2.1
192.168.2.2

Para demonstrar como os padrões de host são resolvidos, você executará um playbook do Ansible, playbook.yml, usando diferentes padrões de host para segmentar diferentes subconjuntos de hosts gerenciados neste exemplo de inventário.

Hosts gerenciados

O padrão de host mais básico é o nome de apenas um host gerenciado listado no inventário. Isso especifica que o host será o único destino de ação do comando ansible no inventário.

Quando o playbook é executado, a primeira tarefa Gathering Facts deve ser executada em todos os hosts gerenciados que correspondam ao padrão de host. Uma falha durante essa tarefa pode fazer com que o host gerenciado seja removido da ação.

Se um endereço IP estiver listado explicitamente no inventário, em vez de um nome de host, ele poderá ser usado como um padrão de host. Se o endereço IP não estiver listado no inventário, você não poderá usá-lo para especificar o host, mesmo se o endereço IP for resolvido no nome de host no DNS.

O exemplo a seguir mostra como um padrão de host pode ser usado para referenciar um endereço IP contido em um inventário.

[student@controlnode ~]$ cat playbook.yml
---
- hosts: 192.168.2.1
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [192.168.2.1]
...output omitted...

Um problema relacionado a hosts gerenciados por endereço IP no inventário é que pode ser difícil lembrar qual endereço IP corresponde a qual host para suas ações e comandos ad hoc. No entanto, pode ser necessário especificar o host por endereço IP, para fins de conexão, se o host não tiver um nome de host que possa ser resolvido.

É possível apontar um alias para um endereço IP específico no seu inventário, definindo a variável de host ansible_host. Por exemplo, você poderia ter um host no inventário chamado dummy.example e direcionar conexões usando esse nome para o endereço IP 192.168.2.1, criando um arquivo host_vars/dummy.example contendo a seguinte variável de host:

ansible_host: 192.168.2.1

Especificação de hosts usando um grupo

Você já usou grupos de hosts de inventário como padrões de host. Quando um nome de grupo é utilizado como padrão de host, ele especifica que o Ansible atuará sobre os hosts que são membros do grupo.

[student@controlnode ~]$ cat playbook.yml
---
- hosts: lab
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost1.example.com]
ok: [labhost2.example.com]
...output omitted...

Há um grupo especial chamado all que corresponde a todos os hosts gerenciados no inventário.

[student@controlnode ~]$ cat playbook.yml
---
- hosts: all
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost2.example.com]
ok: [test2.example.com]
ok: [web.example.com]
ok: [data.example.com]
ok: [labhost1.example.com]
ok: [192.168.2.1]
ok: [test1.example.com]
ok: [192.168.2.2]

Há também um grupo especial chamado ungrouped que inclui todos os hosts gerenciados no inventário que não são membros de nenhum outro grupo:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: ungrouped
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [web.example.com]
ok: [data.example.com]

Correspondência de vários hosts com curingas

Outro método para obter o mesmo resultado que o do padrão de host all é usar o asterisco (*), que corresponde a qualquer string. Se o padrão de host for apenas um asterisco entre aspas, todos os hosts no inventário corresponderão.

[student@controlnode ~]$ cat playbook.yml
---
- hosts: '*'
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost2.example.com]
ok: [test2.example.com]
ok: [web.example.com]
ok: [data.example.com]
ok: [labhost1.example.com]
ok: [192.168.2.1]
ok: [test1.example.com]
ok: [192.168.2.2]

Alguns caracteres usados nos padrões de host também são relevantes para o shell. Isso pode ser um problema ao usar padrões de host para executar comandos ad hoc da linha de comando com ansible. A prática recomendada é colocar entre aspas simples os padrões de host usados na linha de comando para protegê-los de expansão de shell indesejada.

Da mesma forma, se você estiver usando algum curinga especial ou caracteres de lista em um playbook do Ansible, deverá colocar seu padrão de host entre aspas simples para garantir que seja analisado corretamente.

---
  hosts: '!test1.example.com,development'

O caractere de asterisco também pode ser usado para corresponder hosts ou grupos gerenciados que contenham uma substring específica.

Por exemplo, o padrão de host de curinga a seguir corresponde a todos os nomes de inventário que terminam em .example.com:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: '*.example.com'
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost1.example.com]
ok: [test1.example.com]
ok: [labhost2.example.com]
ok: [test2.example.com]
ok: [web.example.com]
ok: [data.example.com]

O exemplo a seguir usa um padrão de host de curinga que corresponde a nomes de hosts ou grupos de hosts que iniciam com 192.168.2.:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: '192.168.2.*'
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [192.168.2.1]
ok: [192.168.2.2]

O próximo exemplo usa um padrão de host de curinga que corresponde a nomes de hosts ou grupos de hosts que iniciam com datacenter:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: 'datacenter*'
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost1.example.com]
ok: [test1.example.com]
ok: [labhost2.example.com]
ok: [test2.example.com]

Os padrões de host de curinga correspondem a todos os nomes de inventário, hosts e grupos de hosts. Eles não diferenciam entre nomes que são nomes DNS, endereços IP ou grupos, o que pode provocar algumas correspondências inesperadas.

Por exemplo, compare os resultados da especificação do padrão de host datacenter* do exemplo anterior com os resultados do padrão de host data* com base no inventário de exemplo:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: 'data*'
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost1.example.com]
ok: [test1.example.com]
ok: [labhost2.example.com]
ok: [test2.example.com]
ok: [data.example.com]

Listas

Várias entradas em um inventário podem ser referenciadas usando listas lógicas. Uma lista separada por vírgulas de padrões de host corresponde a todos os hosts que correspondem a qualquer um dos padrões de host.

Se você fornecer uma lista separada por vírgulas de hosts gerenciados, todos esses hosts gerenciados serão o alvo:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: labhost1.example.com,test2.example.com,192.168.2.2
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost1.example.com]
ok: [test2.example.com]
ok: [192.168.2.2]

Se você fornecer uma lista separada por vírgulas de grupos, todos os hosts nesses grupos serão o alvo:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: lab,datacenter1
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost1.example.com]
ok: [labhost2.example.com]
ok: [test1.example.com]

Você também pode misturar hosts, grupos de hosts e curingas, conforme mostrado abaixo:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: lab,data*,192.168.2.2
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost1.example.com]
ok: [labhost2.example.com]
ok: [test1.example.com]
ok: [test2.example.com]
ok: [data.example.com]
ok: [192.168.2.2]

O caractere de dois-pontos (:) pode ser usado no lugar de uma vírgula. Porém, a vírgula é o separador de preferência, especialmente ao se trabalhar com endereços IPv6 como nomes de hosts gerenciados. Você pode ver a sintaxe de dois-pontos em exemplos anteriores.

Se um item em uma lista inicia com um caractere de "e" comercial (&), os hosts deverão corresponder a esse item para corresponder ao padrão de host. Funciona de modo semelhante a um AND lógico.

Por exemplo, com base no nosso inventário de exemplo, o padrão de host a seguir corresponde a máquinas no grupo lab apenas se elas também estiverem no grupo datacenter1:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: lab,&datacenter1
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost1.example.com]

Você também pode especificar que as máquinas no grupo datacenter1 correspondem apenas se estiverem no grupo lab com os padrões de host &lab,datacenter1 ou datacenter1,&lab.

Você pode excluir hosts que correspondam a um padrão de uma lista, usando o caractere de ponto de exclamação (!) na frente do padrão de host. Isso funciona como um NOT lógico.

Este exemplo corresponde a todos os hosts definidos no grupo datacenter, exceto test2.example.com, com base no inventário de exemplo:

[student@controlnode ~]$ cat playbook.yml
---
- hosts: datacenter,!test2.example.com
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [labhost1.example.com]
ok: [test1.example.com]
ok: [labhost2.example.com]

O padrão '!test2.example.com,datacenter' poderia ser usado no exemplo anterior para obter o mesmo resultado.

O exemplo final mostra o uso de um padrão de host que corresponde a todos os hosts no inventário de teste, exceto os hosts gerenciados do grupo datacenter1.

[student@controlnode ~]$ cat playbook.yml
---
- hosts: all,!datacenter1
...output omitted...
[student@controlnode ~]$ ansible-playbook playbook.yml
PLAY [Test Host Patterns] **************************************************
TASK [Gathering Facts] *****************************************************
ok: [web.example.com]
ok: [data.example.com]
ok: [labhost2.example.com]
ok: [test2.example.com]
ok: [192.168.2.1]
ok: [192.168.2.2]
britho commented 3 years ago

Neste exercício, você explorará como usar padrões de host para especificar hosts do inventário para ações ou comandos ad hoc. Você receberá diversos inventários de exemplo para explorar os padrões de host.

Resultados

Você deverá ser capaz de usar diferentes padrões de host para acessar vários hosts em um inventário.

Faça login na workstation como student usando a senha student.

Na workstation, execute o comando lab projects-host start. O script cria o diretório do projeto projects-host e, em seguida, faz o download dos arquivos de configuração e inventário de host do Ansible necessários para este exercício.

[student@workstation ~]$ lab projects-host start

Na workstation, mude para o diretório de trabalho deste exercício, /home/student/projects-host, e revise o conteúdo do diretório.

[student@workstation ~]$ cd ~/projects-host
[student@workstation projects-host]$

    Liste os conteúdos do diretório.

    [student@workstation projects-host]$ ls
    ansible.cfg inventory1 inventory2 playbook.yml

    Inspecione o arquivo de inventário de exemplo, inventory1. Veja como o inventário é organizado. Explore quais hosts e grupos estão no inventário, além de quais domínios são usados.

    srv1.example.com
    srv2.example.com
    s1.lab.example.com
    s2.lab.example.com

    [web]
    jupiter.lab.example.com
    saturn.example.com

    [db]
    db1.example.com
    db2.example.com
    db3.example.com

    [lb]
    lb1.lab.example.com
    lb2.lab.example.com

    [boston]
    db1.example.com
    jupiter.lab.example.com
    lb2.lab.example.com

    [london]
    db2.example.com
    db3.example.com
    file1.lab.example.com
    lb1.lab.example.com

    [dev]
    web1.lab.example.com
    db3.example.com

    [stage]
    file2.example.com
    db2.example.com

    [prod]
    lb2.lab.example.com
    db1.example.com
    jupiter.lab.example.com

    [function:children]
    web
    db
    lb
    city

    [city:children]
    boston
    london
    environments

    [environments:children]
    dev
    stage
    prod
    new

    [new]
    172.25.252.23
    172.25.252.44
    172.25.252.32

    Inspecione o arquivo de inventário de exemplo, inventory2. Veja como o inventário é organizado. Explore quais hosts e grupos estão no inventário, além de quais domínios são usados.

    workstation.lab.example.com

    [london]
    servera.lab.example.com

    [berlin]
    serverb.lab.example.com

    [tokyo]
    serverc.lab.example.com

    [atlanta]
    serverd.lab.example.com

    [europe:children]
    london
    berlin

    Por fim, inspecione o conteúdo do playbook, playbook.yml. Observe como o manual usa o módulo debug para exibir o nome de cada host gerenciado.

    ---
    - name: Resolve host patterns
      hosts:
      tasks:
        - name: Display managed host name
          debug:
            msg: "{{ inventory_hostname }}"

Usando um comando ad hoc, determine se o servidor db1.example.com está presente no arquivo de inventário inventory1.

[student@workstation projects-host]$ ansible db1.example.com -i inventory1 \
> --list-hosts
  hosts (1):
    db1.example.com

Usando um comando ad hoc, faça referencia a um endereço IP contido no inventário inventory1 com um padrão de host.

[student@workstation projects-host]$ ansible 172.25.252.44 -i inventory1 \
> --list-hosts
 hosts (1):
    172.25.252.44

Com um comando ad hoc, use o grupo all para listar todos os hosts gerenciados no arquivo de inventário inventory1.

[student@workstation projects-host]$ ansible all -i inventory1 --list-hosts
  hosts (17):
    srv1.example.com
    srv2.example.com
    s1.lab.example.com
    s2.lab.example.com
    jupiter.lab.example.com
    saturn.example.com
    db1.example.com
    db2.example.com
    db3.example.com
    lb1.lab.example.com
    lb2.lab.example.com
    file1.lab.example.com
    web1.lab.example.com
    file2.example.com
    172.25.252.23
    172.25.252.44
    172.25.252.32

Com um comando ad hoc, use o caractere de asterisco (*) para listar todos os hosts que terminam em .example.com no arquivo de inventário inventory1.

[student@workstation projects-host]$ ansible '*.example.com' -i inventory1 \
> --list-hosts
  hosts (14):
    jupiter.lab.example.com
    saturn.example.com
    db1.example.com
    db2.example.com
    db3.example.com
    lb1.lab.example.com
    lb2.lab.example.com
    file1.lab.example.com
    web1.lab.example.com
    file2.example.com
    srv1.example.com
    srv2.example.com
    s1.lab.example.com
    s2.lab.example.com

Como você pode ver na saída do comando anterior, há 14 hosts no domínio *.example.com. Modifique o padrão de host no comando ad hoc anterior para que os hosts no domínio *.lab.example.com sejam ignorados.

[student@workstation projects-host]$ ansible '*.example.com, !*.lab.example.com' \
> -i inventory1 --list-hosts
  hosts (7):
    saturn.example.com
    db1.example.com
    db2.example.com
    db3.example.com
    file2.example.com
    srv1.example.com
    srv2.example.com

Sem acessar os grupos no arquivo de inventário inventory1, use um comando ad hoc para listar estes três hosts: lb1.lab.example.com, s1.lab.example.com e db1.example.com.

[student@workstation projects-host]$ ansible \
> lb1.lab.example.com,s1.lab.example.com,db1.example.com -i inventory1 \
> --list-hosts
  hosts (3):
    lb1.lab.example.com
    s1.lab.example.com
    db1.example.com

Use um padrão de host de curinga em um comando ad hoc para listar os hosts que começam com 172.25. Endereço IP no arquivo de inventário inventory1.

[student@workstation projects-host]$ ansible '172.25.*' -i inventory1 --list-hosts
  hosts (3):
    172.25.252.23
    172.25.252.44
    172.25.252.32

Use um padrão de host em um comando ad hoc para listar todos os hosts no arquivo de inventário inventory1 que começam com a letra "s".

[student@workstation projects-host]$ ansible 's*' -i inventory1 --list-hosts
  hosts (7):
    saturn.example.com
    srv1.example.com
    srv2.example.com
    s1.lab.example.com
    s2.lab.example.com
    file2.example.com
    db2.example.com

Observe os hosts file2.example.com e db2.example.com na saída no comando anterior. Eles aparecem na lista porque são membros de um grupo chamado stage, que também começa com a letra "s".

Usando uma lista e padrões de host de curinga em um comando ad hoc, liste todos os hosts no inventário inventory1 no grupo prod, os hosts com um endereço IP que comece com 172 e os hosts que contenham lab no nome.

[student@workstation projects-host]$ ansible 'prod,172*,*lab*' -i inventory1 \
> --list-hosts
  hosts (11):
    lb2.lab.example.com
    db1.example.com
    jupiter.lab.example.com
    172.25.252.23
    172.25.252.44
    172.25.252.32
    lb1.lab.example.com
    file1.lab.example.com
    web1.lab.example.com
    s1.lab.example.com
    s2.lab.example.com

Use um comando ad hoc para listar todos os hosts que pertencem aos grupos db e london.

[student@workstation projects-host]$ ansible 'db,&london' -i inventory1 \
> --list-hosts
  hosts (2):
    db2.example.com
    db3.example.com

Modifique o valor de hosts no arquivo playbook.yml para que todos os servidores no grupo London sejam usados como destino. Execute o playbook usando o arquivo de inventário inventory2.

...output omitted...
  hosts: london
...output omitted...

[student@workstation projects-host]$ ansible-playbook -i inventory2 playbook.yml
...output omitted...
TASK [Gathering Facts] ************************************************
ok: [servera.lab.example.com]
...output omitted...

Modifique o valor de hosts no arquivo playbook.yml para que todos os servidores no grupo aninhado europe sejam definidos como destino. Execute o playbook usando o arquivo de inventário inventory2.

...output omitted...
  hosts: europe
...output omitted...

[student@workstation projects-host]$ ansible-playbook -i inventory2 playbook.yml
...output omitted...
TASK [Gathering Facts] ************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]
...output omitted...

Modifique o valor de hosts no arquivo playbook.yml para que todos os servidores que não pertençam a algum grupo sejam definidos como destino. Execute o playbook usando o arquivo de inventário inventory2.

...output omitted...
  hosts: ungrouped
...output omitted...

[student@workstation projects-hosts]$ ansible-playbook -i inventory2 playbook.yml
...output omitted...
TASK [Gathering Facts] ************************************************
ok: [workstation.lab.example.com]
...output omitted...

Encerramento

Na workstation, execute o script lab projects-host finish para limpar este exercício.

[student@workstation ~]$ lab projects-host finish

Isso conclui o exercício orientado.

britho commented 3 years ago

Objetivos

Depois de concluir esta seção, você deverá ser capaz de descrever o que são inventários dinâmicos, bem como instalar e usar um script existente como uma fonte de inventário dinâmico do Ansible. Geração de inventários de modo dinâmico

Os arquivos de inventário estático com os quais você trabalhou até agora são fáceis de escrever e são convenientes para gerenciar infraestruturas pequenas. Contudo, ao trabalhar com várias máquinas ou em um ambiente em que haja alta rotatividade de máquinas, pode ser difícil manter os arquivos de inventário estático atualizados.

A maioria dos grandes ambientes de TI tem sistemas que controlam quais hosts estão disponíveis e como eles são organizados. Por exemplo, pode haver um serviço de diretório externo mantido por um sistema de monitoramento, como o Zabbix ou em servidores FreeIPA ou Active Directory. Servidores de instalação como o Cobbler ou serviços de gerenciamento como o RedHat Satellite podem monitorar sistemas bare-metal implantados. Do modo semelhante, serviços em nuvem como o Amazon Web Services EC2 ou uma implantação do OpenStack ou infraestruturas de máquina virtual baseada em VMware ou RedHat Virtualization podem ser fontes de informação sobre as instâncias e máquinas virtuais temporárias.

O Ansible é compatível com scripts dynamic inventory que recuperam as informações atuais desses tipos de fontes sempre que o Ansible for executado, permitindo que o inventário seja atualizado em tempo real. Esses scripts são programas executáveis que coletam informações de algumas fontes externas e geram o inventário em formato JSON.

Os scripts de inventário dinâmico são usados exatamente como arquivos de texto de inventário estático. A localização do inventário é especificada diretamente no arquivo ansible.cfg atual ou por meio da opção -i. Se o arquivo do inventário for executável, ele será tratado como um programa de inventário dinâmico e o Ansible tentará executá-lo para gerar o inventário. Se o arquivo não for executável, ele será tratado como um inventário estático.

A localização do inventário pode ser configurada no arquivo de configuração ansible.cfg com o parâmetro inventory. Por padrão, ela está configurada como /etc/ansible/hosts. Disponibilização de scripts

A comunidade de open source contribuiu com vários scripts de inventário dinâmico existentes para o projeto do Ansible. Eles não estão incluídos no pacote ansible nem têm suporte oficial da RedHat. Esses scripts estão disponíveis na página do GitHub do Ansible em https://github.com/ansible/ansible/tree/devel/contrib/inventory.

Algumas fontes de dados ou plataformas que são destino de scripts de inventário dinâmico disponibilizados incluem:

Plataformas de nuvem privada, como RedHat OpenStack Platform.

Plataformas de nuvem pública, como Rackspace Cloud, Amazon Web Services EC2 e Google Compute Engine.

Plataformas de virtualização, como RedHat Virtualization (oVirt) e VMware vSphere.

Soluções de plataforma como serviço, como a OpenShift Container Platform.

Ferramentas de gerenciamento de ciclo de vida, como a Foreman (com RedHat Satellite6 ou independente) e a Spacewalk (upstream do RedHat Satellite5).

Provedores de hospedagem, como Digital Ocean e Linode. 

Cada script pode ter suas próprias dependências e requisitos de funcionamento. Os scripts disponibilizados são, em sua maioria, escritos em Python, mas isso não é um requisito de scripts de inventário dinâmico. Escrever programas de inventário dinâmico

Se não existir um script de inventário dinâmico no sistema de diretórios ou na infraestrutura em uso, você poderá escrever um programa de inventário dinâmico personalizado. O programa personalizado pode ser escrito em qualquer linguagem de programação, mas deve retornar informações de inventário no formato JSON ao receber as opções apropriadas.

O comando ansible-inventory pode ser uma ferramenta útil para aprender como criar inventários do Ansible no formato JSON. Você pode usar o comando ansible-inventory, disponível desde o Ansible2.4, para visualizar um arquivo de inventário no formato JSON.

Para exibir o conteúdo do arquivo de inventário no formato JSON, execute o comando ansible-inventory --list. Você pode usar a opção -i para especificar o local do arquivo de inventário a ser processado ou usar o inventário padrão definido pela configuração atual do Ansible.

O exemplo a seguir demonstra o uso do comando ansible-inventory para processar um arquivo de inventário em estilo INI e gerá-lo no formato JSON.

[student@workstation projects-host]$ cat inventory workstation1.lab.example.com

[webservers] web1.lab.example.com web2.lab.example.com

[databases] db1.lab.example.com db2.lab.example.com

[student@workstation projects-host]$ ansible-inventory -i inventory --list { "_meta": { "hostvars": { "db1.lab.example.com": {}, "db2.lab.example.com": {}, "web1.lab.example.com": {}, "web2.lab.example.com": {}, "workstation1.lab.example.com": {} } }, "all": { "children": [ "databases", "ungrouped", "webservers" ] }, "databases": { "hosts": [ "db1.lab.example.com", "db2.lab.example.com" ] }, "ungrouped": { "hosts": [ "workstation1.lab.example.com" ] }, "webservers": { "hosts": [ "web1.lab.example.com", "web2.lab.example.com" ] } }

Se desejar escrever seu próprio script de inventário dinâmico, você encontrará informações mais detalhadas na seção Desenvolvimento de fontes de inventário dinâmico do Ansible Developer Guide. Veja a seguir uma breve visão geral.

Inicie o script com uma linha de interpretador adequada (por exemplo, #!/usr/bin/python). Além disso, ele deve ser executável para funcionar com o Ansible.

Quando a opção --list for passada, o script deve imprimir um hash/dicionário em código JSON de todos os hosts e grupos no inventário.

Em sua forma mais simples, um grupo pode ser uma lista de hosts gerenciados. Neste exemplo de saída em código JSON de um script de inventário, webservers é um grupo de hosts que tem web1.lab.example.com e web2.lab.example.com como hosts gerenciados no grupo. O grupo de hosts databases inclui os hosts db1.lab.example.com e db2.lab.example.com como membros.

[student@workstation ~]$ ./inventoryscript --list { "webservers" : [ "web1.lab.example.com", "web2.lab.example.com" ], "databases" : [ "db1.lab.example.com", "db2.lab.example.com" ] }

Como alternativa, o valor de cada grupo pode ser um hash/dicionário JSON contendo uma lista de cada host gerenciado, grupos filho e qualquer variável de grupo que possa estar definida. O próximo exemplo mostra a saída em código JSON de um inventário dinâmico mais complexo. O grupo boston tem dois grupos filho (backup e ipa), três hosts gerenciados próprios e uma variável de grupo definida (example_host: false).

{ "webservers" : [ "web1.demo.example.com", "web2.demo.example.com" ], "boston" : { "children" : [ "backup", "ipa" ], "vars" : { "example_host" : false }, "hosts" : [ "server1.demo.example.com", "server2.demo.example.com", "server3.demo.example.com" ] }, "backup" : [ "server4.demo.example.com" ], "ipa" : [ "server5.demo.example.com" ], "_meta" : { "hostvars" : { "server5.demo.example.com": { "ntpserver": "ntp.demo.example.com", "dnsserver": "dns.demo.example.com" } } } }

O script também deverá ser compatível com a opção --host managed-host. Essa opção deve imprimir um hash/dicionário JSON que consista em variáveis associadas a esse host, ou um hash/dicionário JSON vazio.

[student@workstation ~]$ ./inventoryscript --host server5.demo.example.com { "ntpserver" : "ntp.demo.example.com", "dnsserver" : "dns.demo.example.com" }

Quando chamado com a opção --host hostname, o script deve imprimir um hash/dicionário JSON das variáveis do host especificado. Um hash ou dicionário JSON vazio pode ser impresso se nenhuma variável for fornecida.

Opcionalmente, se a primeira opção --list retornar um elemento de nível superior denominado _meta, será possível retornar todas as variáveis de host em uma chamada de script, o que melhora o desempenho do script. Nesse caso, chamadas --host não são feitas.

Consulte Desenvolvimento de fontes de inventário dinâmico para obter mais informações. Gerenciamento de múltiplos inventários

O Ansible aceita o uso de vários inventários na mesma execução. Se o local do inventário for um diretório (seja ele definido pela opção -i, pelo valor do parâmetro inventory ou de alguma outra maneira), todos os arquivos de inventário incluídos no diretório, estáticos ou dinâmicos, serão combinados para determinar o inventário. Os arquivos executáveis dentro de cada diretório são usados para recuperar inventários dinâmicos, e os outros arquivos são usados como inventários estáticos.

Os arquivos de inventário não devem depender de outros arquivos ou scripts de inventário para serem resolvidos. Por exemplo, se um arquivo de inventário estático especificar que um grupo específico deve ser secundário de outro grupo, ele também precisará ter uma entrada de espaço reservado para esse grupo, mesmo se todos os membros desse grupo venham do inventário dinâmico. Considere o grupo cloud-east no seguinte exemplo:

[cloud-east]

[servers] test.demo.example.com

[servers:children] cloud-east

Isso garante que todos os arquivos de inventário sejam internamente consistentes, independentemente da ordem na qual forem analisados.

A ordem na qual os arquivos de inventário são analisados não é especificada pela documentação. Atualmente, quando existem vários arquivos de inventário, eles são analisados em ordem alfabética. Se uma fonte de inventário depender de informações de outra fonte de inventário, a ordem na qual elas são carregadas poderá determinar se o arquivo de inventário funciona como esperado ou se gera um erro. Portanto, é importante garantir que todos os arquivos sejam consistentes para evitar erros inesperados.

O Ansible ignora arquivos em um diretório de inventários se eles terminarem com determinados sufixos. Isso pode ser controlado com a diretiva inventory_ignore_extensions no arquivo de configuração do Ansible. Mais informações estão disponíveis na documentação do Ansible.

Working With Dynamic Inventory: Ansible Documentation

Developing Dynamic Inventory: Ansible Documentation

britho commented 3 years ago

Neste exercício, você instalará scripts personalizados que geram de modo dinâmico uma lista de hosts de inventário.

Resultados

Você será capaz de instalar e usar scripts de inventário dinâmico existentes.

Faça login na workstation como student usando a senha student.

Na workstation, execute o comando lab projects-inventory start. Ele garante que o Ansible esteja instalado na workstation e também cria o diretório de trabalho /home/student/projects-inventory para este exercício.

[student@workstation ~]$ lab projects-inventory start

Na workstation, mude para o diretório de trabalho do exercício, /home/student/projects-inventory. Veja o conteúdo do arquivo de configuração do Ansible ansible.cfg. O arquivo de configuração define o local do inventário como inventory.

[defaults]
inventory = inventory

Crie o diretório /home/student/projects-inventory/inventory.

[student@workstation projects-inventory]$ mkdir inventory

Em http://materials.example.com/labs/projects-inventory/, faça download dos arquivos inventorya.py, inventoryw.py e hosts para o diretório /home/student/projects-inventory/inventory. Ambos os arquivos que terminam com .py são scripts que geram inventários dinâmicos, e o terceiro arquivo é um inventário estático.

    O script inventorya.py fornece o grupo webservers, que inclui o host servera.lab.example.com.

    O script inventoryw.py fornece o host workstation.lab.example.com.

    O arquivo de inventário estático hosts define o grupo servers, que é um grupo pai do grupo webservers. 

[student@workstation projects-inventory]$ wget \
> http://materials.example.com/labs/projects-inventory/inventorya.py \
> -O inventory/inventorya.py
[student@workstation projects-inventory]$ wget \
> http://materials.example.com/labs/projects-inventory/inventoryw.py \
> -O inventory/inventoryw.py
[student@workstation projects-inventory]$ wget \
> http://materials.example.com/labs/projects-inventory/hosts \
> -O inventory/hosts

Usando o comando ansible com o script inventorya.py como inventário, liste os hosts gerenciados associados ao grupo webservers. Um erro relacionado às permissões de inventorya.py é gerado.

[student@workstation projects-inventory]$ ansible -i inventory/inventorya.py \
> webservers --list-hosts
 [WARNING]:  * Failed to parse /home/student/projects-inventory/inventory/inventorya.py with script plugin: problem running /home/student/projects-inventory/inventory/inventorya.py --list ([Errno 13] Permission denied)

 [WARNING]:  * Failed to parse /home/student/projects-inventory/inventory/inventorya.py with ini plugin: /home/student/projects-inventory/inventory/inventorya.py:3: Expected key=value host variable assignment, got: subprocess

 [WARNING]: Unable to parse /home/student/projects-inventory/inventory/inventorya.py as an inventory source

 [WARNING]: No inventory was parsed, only implicit localhost is available

 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

 [WARNING]: Could not match supplied host pattern, ignoring: webservers

  hosts (0):

Verifique as permissões atuais do script inventorya.py e altere-as para 755.

[student@workstation projects-inventory]$ ls -la inventory/inventorya.py
-rw-rw-r--. 1 student student 639 Apr 29 14:20 inventory/inventorya.py
[student@workstation projects-inventory]$ chmod 755 inventory/inventorya.py

Altere as permissões do script inventoryw.py para 755.

[student@workstation projects-inventory]$ chmod 755 inventory/inventoryw.py

Verifique a saída atual do script inventorya.py usando o parâmetro --list. Os hosts associados ao grupo webservers serão exibidos.

[student@workstation projects-inventory]$ inventory/inventorya.py --list
{"webservers": {"hosts": ["servera.lab.example.com"], "vars": { }}}

Verifique a saída atual do script inventoryw.py usando o parâmetro --list. O host workstation.lab.example.com será exibido.

[student@workstation projects-inventory]$ inventory/inventoryw.py --list
{"all": {"hosts": ["workstation.lab.example.com"], "vars": { }}}

Verifique a definição do grupo servers no arquivo /home/student/projects-inventory/inventory/hosts. O grupo webservers definido no inventário dinâmico é configurado como secundário do grupo servers.

[student@workstation projects-inventory]$ cat inventory/hosts
[servers:children]
webservers

Execute o comando a seguir para verificar a lista de hosts do grupo webservers. É exibido um erro informando que o grupo webservers não está definido.

[student@workstation projects-inventory]$ ansible webservers --list-hosts
 [WARNING]:  * Failed to parse /home/student/projects-inventory/inventory/hosts with yaml plugin: Syntax Error while loading YAML.   found unexpected ':'  The error appears to have been in '/home/student/projects-inventory/inventory/hosts': line 1, column 9, but may be elsewhere in the file depending on the exact syntax problem.  The offending line appears to be:   [servers:children]         ^ here

 [WARNING]:  * Failed to parse /home/student/projects-inventory/inventory/hosts with ini plugin: /home/student/projects-inventory/inventory/hosts:2: Section [servers:children] includes undefined group: webservers

 [WARNING]: Unable to parse /home/student/projects-inventory/inventory/hosts as an inventory source

  hosts (1):
    servera.lab.example.com

Para evitar esse problema, o inventário estático deve ter uma entrada de espaço reservado definindo um grupo de hosts webservers vazio. É importante que o inventário estático defina todos os grupos de hosts referenciados por ele, já que ele pode desaparecer de modo dinâmico da fonte externa, provocando esse erro.

Edite o arquivo /home/student/projects-inventory/inventory/hosts para que contenha o seguinte conteúdo:

[webservers]

[servers:children]
webservers

Se o script de inventário dinâmico que fornece o grupo de hosts for nomeado de forma que seja classificado antes de o inventário estático referenciá-lo, você não verá esse erro. Entretanto, se o grupo de hosts desaparecer do inventário dinâmico e você não tiver um espaço reservado, o inventário estático fará referência a um grupo de hosts ausente e o erro interromperá a análise do inventário.

Execute novamente o comando a seguir para verificar a lista de hosts do grupo webservers. Deverá funcionar sem erros.

[student@workstation projects-inventory]$ ansible webservers --list-hosts
  hosts (1):
    servera.lab.example.com

Encerramento

Na workstation, execute o comando lab projects-inventory finish para limpar este exercício.

[student@workstation ~]$ lab projects-inventory finish

Isso conclui o exercício orientado.

britho commented 3 years ago

Objetivos

Depois de concluir esta seção, você deverá ser capaz de ajustar o número de conexões simultâneas abertas pelo Ansible para hosts gerenciados e como o Ansible processa grupos de hosts gerenciados por meio das tarefas da ação. Configuração de paralelismo no Ansible usando forks

Quando o Ansible processa um playbook, ele executa cada ação em ordem. Depois de determinar a lista de hosts da ação, o Ansible executa cada tarefa em ordem. Normalmente, todos os hosts devem concluir com êxito uma tarefa antes que qualquer host inicie a próxima tarefa da ação.

Em teoria, o Ansible poderia se conectar simultaneamente a todos os hosts da ação para cada tarefa. Isso funciona bem para listas de hosts pequenas. Mas se a ação tiver como destino centenas de hosts, isso pode sobrecarregar o nó de controle.

O número máximo de conexões simultâneas que o Ansible faz é controlado pelo parâmetro forks no arquivo de configuração do Ansible. Por padrão, ele está definido como 5, o que pode ser verificado usando uma das opções a seguir.

[student@demo ~]$ grep forks ansible.cfg forks = 5

[student@demo ~]$ ansible-config dump |grep -i forks DEFAULT_FORKS(default) = 5

[student@demo ~]$ ansible-config list |grep -i forks DEFAULT_FORKS: description: Maximum number of forks Ansible will use to execute tasks on target

Por exemplo, suponha que um nó de controle do Ansible esteja configurado com o valor padrão de cinco forks e a ação tenha dez hosts gerenciados. O Ansible executará a primeira tarefa da ação nos primeiros cinco hosts gerenciados. Em seguida, realizará uma segunda rodada de execução da primeira tarefa nos outros cinco hosts gerenciados. Depois que a primeira tarefa tiver sido executada em todos os hosts gerenciados, o Ansible prosseguirá com a execução da próxima tarefa em todos os hosts gerenciados, em grupos de cinco hosts por vez. O Ansible fará isso com cada tarefa até que a ação termine.

O padrão para forks está definido de modo muito conservador. Se o nó de controle estiver gerenciando hosts Linux, a maioria das tarefas será executada nos hosts gerenciados e o nó de controle terá menos carga. Nesse caso, você geralmente pode definir forks com um valor muito mais alto, possivelmente mais próximo de 100, e observar melhorias no desempenho.

Se os playbooks executarem muitos códigos no nó de controle, você deve aumentar o limite de forks de maneira moderada. Se você usar o Ansible para gerenciar roteadores e switches de rede, a maioria desses módulos é executada no nó de controle e não no dispositivo de rede. Devido à carga mais alta que isso coloca no nó de controle, sua capacidade de suporte a aumentos no número de forks será significativamente menor do que em um nó de controle que gerencia somente hosts Linux.

Você pode substituir a configuração padrão de forks na linha de comando do arquivo de configuração do Ansible. Ambos os comandos ansible e ansible-playbook oferecem as opções -f ou --forks para especificar o número de forks a serem usados. Gerenciamento de atualizações em cascata

Normalmente, quando o Ansible executa uma ação, ele garante que todos os hosts gerenciados tenham concluído cada tarefa antes de iniciar a próxima tarefa. Depois que todos os hosts gerenciados tiverem concluído todas as tarefas, os manipuladores notificados são executados.

No entanto, executar todas as tarefas em todos os hosts pode levar a um comportamento indesejável. Por exemplo, se uma ação atualiza um cluster de servidores web com carga balanceada, talvez seja necessário desativar cada servidor web durante a atualização. Se todos os servidores forem atualizados na mesma ação, é possível que todos eles fiquem fora de serviço ao mesmo tempo.

Uma maneira de evitar esse problema é usar a palavra-chave serial para executar a ação nos hosts em lotes. A ação completa será executada em cada lote de hosts antes que o próximo lote seja iniciado.

No exemplo abaixo, o Ansible executa a ação em dois hosts gerenciados por vez, até que todos os hosts gerenciados tenham sido atualizados. O Ansible começa executando as tarefas da ação nos dois primeiros hosts gerenciados. Se um ou ambos os hosts notificarem o manipulador, o Ansible executará o manipulador conforme necessário para esses dois hosts. Quando a execução da ação é concluída nesses dois hosts gerenciados, o Ansible repete o processo nos próximos dois hosts gerenciados. O Ansible continua executando a ação dessa maneira até que todos os hosts gerenciados tenham sido atualizados.


Suponha que o grupo webservers no exemplo anterior contenha cinco servidores web que residem atrás de um balanceador de carga. Com o parâmetro serial definido como 2, a ação executará até dois servidores web por vez. Assim, a maioria dos cinco servidores web estará sempre disponível.

Em contrapartida, na ausência da palavra-chave serial, a execução da ação e a execução resultante do manipulador ocorreriam em todos os cinco servidores web ao mesmo tempo. Isso provavelmente levaria a uma interrupção do serviço, pois os serviços web em todos os servidores web seriam reiniciados ao mesmo tempo.

Para determinadas finalidades, cada lote de hosts conta como se fosse uma ação completa em execução em um subconjunto de hosts. Isso significa que, se um lote inteiro falhar, a ação falha, o que faz com que todo o playbook falhe.

No cenário anterior com a definição serial: 2, se algo estiver errado e a ação falhar para os dois primeiros hosts processados, o playbook será anulado e a ação não será executada nos três hosts restantes. Esse é um recurso útil porque apenas um subconjunto dos servidores estaria indisponível, deixando o serviço degradado em vez de inativo.

A palavra-chave serial também pode ser especificada como uma porcentagem. Essa porcentagem é aplicada ao número total de hosts na ação para determinar o tamanho do lote de atualização em cascata. Independentemente da porcentagem, o número de hosts por aprovação sempre será 1 ou mais.

Rolling Update Batch Size — Delegation, Rolling Updates, and Local Actions — Ansible Documentation

Ansible Performance Tuning (For Fun and Profit)

britho commented 3 years ago

Neste exercício, você explorará os efeitos de diferentes diretivas de forks e em série na maneira com que uma ação é processada pelo Ansible.

Resultados

Você será capaz de ajustar execuções paralelas e seriais de um playbook em vários hosts gerenciados.

Faça login na workstation como student usando a senha student.

Na workstation, execute o comando lab projects-parallelism start. O script verifica se o Ansible está instalado na workstation e cria uma estrutura de diretório e arquivos associados para o ambiente de laboratório.

[student@workstation ~]$ lab projects-parallelism start

Mude para o diretório /home/student/projects-parallelism. Examine o conteúdo do diretório do projeto para se familiarizar com os arquivos do projeto.

    Examine o conteúdo do arquivo ansible.cfg. Observe que o arquivo de inventário está definido como inventory. Observe também que o parâmetro forks está definido como 4.

    [defaults]
    inventory=inventory
    remote_user=devops
    forks=4
    ...output omitted...

    Examine o conteúdo do arquivo inventory. Observe que ele contém um grupo de hosts, webservers, que contém quatro hosts.

    [webservers]
    servera.lab.example.com
    serverb.lab.example.com
    serverc.lab.example.com
    serverd.lab.example.com

    Examine o conteúdo do arquivo playbook.yml. O playbook é executado no grupo de hosts webservers e garante que o pacote httpd mais recente esteja instalado e que o serviço httpd esteja ativado e iniciado.

    ---
        - name: Update web server
          hosts: webservers

          tasks:
            - name: Lastest httpd package installed
                yum:
                  name: httpd
                  state: latest
                notify:
                  - Restart httpd

          handlers:
            - name: Restart httpd
              service:
                name: httpd
                enabled: yes
                state: restarted

    Por fim, examine o conteúdo do arquivo remove_apache.yml. O playbook é executado no grupo de hosts webservers, garante que o serviço httpd esteja desativado e interrompido e, em seguida, garante que o pacote httpd não esteja instalado.

    ---
    - hosts: webservers
      tasks:
        - service:
            name: httpd
            enabled: no
            state: stopped
        - yum:
            name: httpd
            state: absent

Execute o playbook playbook.yml, usando o comando time para determinar quanto tempo leva para o playbook ser executado. Observe o manual enquanto ele é executado. Observe como o Ansible realiza cada tarefa em todos os quatro hosts ao mesmo tempo.

[student@workstation projects-parallelism]$ time ansible-playbook playbook.yml
PLAY [Update apache] *******************************************************

TASK [Gathering Facts] *****************************************************
ok: [servera.lab.example.com]
ok: [serverd.lab.example.com]
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

...output omitted...

real    0m22.701s
user    0m23.275s
sys     0m2.637s

Execute o playbook remove_apache.yml para interromper e desativar o serviço httpd, além de remover o pacote httpd.

[student@workstation projects-parallelism]$ ansible-playbook remove_apache.yml

Altere o valor do parâmetro forks para 1 em ansible.cfg.

[defaults]
inventory=inventory
remote_user=devops
forks=1
...output omitted...

Execute novamente o playbook playbook.yml, usando o comando time para determinar quanto tempo leva para o playbook ser executado. Observe o playbook enquanto ele é executado. Observe que, desta vez, o Ansible realiza cada tarefa em um host de cada vez. Observe também como a redução do número de forks causou uma demora na execução do playbook.

[student@workstation projects-parallelism]$ time ansible-playbook playbook.yml

PLAY [Update apache] *******************************************************

TASK [Gathering Facts] *****************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]
ok: [serverc.lab.example.com]
ok: [serverd.lab.example.com]

...output omitted...

real    0m37.853s
user    0m22.414s
sys     0m4.749s

Execute o playbook remove_apache.yml para interromper e desativar o serviço httpd, além de remover o pacote httpd.

[student@workstation projects-parallelism]$ ansible-playbook remove_apache.yml

Defina o valor do parâmetro forks como 2 em ansible.cfg.

[defaults]
inventory=inventory
remote_user=devops
forks=2
...output omitted...

Adicione o parâmetro serial a seguir à ação no playbook playbook.yml para que a ação só seja executada em dois hosts por vez. O início do playbook deve ser exibido da seguinte maneira:

---
- name: Update web server
  hosts: webservers
  serial: 2

Execute o playbook playbook.yml novamente. Observe o manual enquanto ele é executado. Observe como o Ansible executa toda a ação em apenas dois hosts antes executá-la novamente nos dois hosts restantes.

[student@workstation projects-parallelism]$ ansible-playbook playbook.yml

PLAY [Update apache] *******************************************************

TASK [Gathering Facts] *****************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]

TASK [Latest version of apache installed] **********************************
changed: [servera.lab.example.com]
changed: [serverb.lab.example.com]

...output omitted...

PLAY [Update apache] *******************************************************

TASK [Gathering Facts] *****************************************************
ok: [serverc.lab.example.com]
ok: [serverd.lab.example.com]

TASK [Latest version of apache installed] **********************************
changed: [serverd.lab.example.com]
changed: [serverc.lab.example.com]

...output omitted...

Execute o playbook remove_apache.yml para interromper e desativar o serviço httpd, além de remover o pacote httpd.

[student@workstation projects-parallelism]$ ansible-playbook remove_apache.yml

Defina o valor do parâmetro forks como 4 novamente em ansible.cfg.

[defaults]
inventory=inventory
remote_user=devops
forks=4
...output omitted...

Defina o parâmetro serial no playbook playbook.yml como 3. O início do playbook deve ser exibido da seguinte maneira:

---
- name: Update web server
  hosts: webservers
  serial: 3

Execute o playbook playbook.yml novamente. Observe o manual enquanto ele é executado. Observe como o Ansible executa toda a ação em apenas três hosts e, depois, a executa novamente no host restante.

[student@workstation projects-parallelism]$ ansible-playbook playbook.yml

PLAY [Update apache] *******************************************************

TASK [Gathering Facts] *****************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

TASK [Latest version of apache installed] **********************************
changed: [servera.lab.example.com]
changed: [serverb.lab.example.com]
changed: [serverc.lab.example.com]

...output omitted...

PLAY [Update apache] *******************************************************

TASK [Gathering Facts] *****************************************************
ok: [serverd.lab.example.com]

TASK [Latest version of apache installed] **********************************
changed: [serverd.lab.example.com]

...output omitted...

Encerramento

Na workstation, execute o comando lab projects-parallelism finish para limpar este exercício.

[student@workstation ~]$ lab projects-parallelism finish

Isso conclui o exercício orientado.

britho commented 3 years ago

Objetivos

Depois de concluir esta seção, você deverá ser capaz de gerenciar playbooks grandes importando ou incluindo outros playbooks ou tarefas de arquivos externos, seja incondicionalmente ou com base em um teste condicional. Gerenciamento de playbooks grandes

Quando um playbook fica longo ou complexo, você pode dividi-lo em arquivos menores para facilitar o gerenciamento. Você pode combinar vários playbooks em um playbook principal de maneira modular ou inserir listas de tarefas de um arquivo em uma ação. Isso pode facilitar a reutilização de ações ou sequências de tarefas em projetos diferentes. Inclusão ou importação de arquivos

Há duas operações que o Ansible pode usar para trazer conteúdo para um playbook. Você pode incluir conteúdo, ou você pode importar conteúdo.

Quando você inclui conteúdo, isso é uma operação dinâmica. Os processos com problemas incluíram conteúdo durante a execução do playbook, conforme o conteúdo é acessado.

Quando você importa conteúdo, isso é uma operação estática. O Ansible realiza o pré-processamento do conteúdo importado quando o playbook é inicialmente analisado, antes de a execução ser iniciada. Importação de playbooks

A diretiva import_playbook permite importar arquivos externos contendo listas de ações em um playbook. Em outras palavras, você pode ter um playbook mestre que importe um ou mais playbooks adicionais.

Como o conteúdo que está sendo importado é um playbook completo, o recurso import_playbook só pode ser usado no nível superior de um playbook e não pode ser usado dentro de uma ação. Se você importar vários playbooks, eles serão importados e executados em ordem.

Um exemplo simples de um playbook mestre que importa dois playbooks adicionais é mostrado abaixo:

Você também pode intercalar ações no seu playbook mestre com playbooks importados.

No exemplo anterior, a ação Play 1 é executada primeiro, seguida pelas ações importadas do playbook play2.yml. Importação e inclusão de tarefas

Você pode importar ou incluir uma lista de tarefas de um arquivo de tarefas em uma ação. Um arquivo de tarefas é um arquivo que contém uma lista simples de tarefas:

[admin@node ~]$ cat webserver_tasks.yml

Importação de arquivos de tarefas

Você pode importar estaticamente um arquivo de tarefas para uma ação dentro de um playbook usando o recurso import_tasks. Quando você importa um arquivo de tarefas, as tarefas desse arquivo são inseridas diretamente quando o playbook é analisado. A localização de import_tasks no playbook controla onde as tarefas são inseridas e a ordem na qual várias importações são executadas.


Quando você importa um arquivo de tarefas, as tarefas desse arquivo são inseridas diretamente quando o playbook é analisado. Como import_tasks importa estaticamente as tarefas quando o playbook é analisado, são observados alguns efeitos na maneira como ele funciona.

Ao usar o recurso import_tasks, instruções condicionais definidas na importação, como when, são aplicadas a cada uma das tarefas que são importadas.

Não é possível usar loops com o recurso import_tasks.

Se você usar uma variável para especificar o nome do arquivo a ser importado, não poderá usar uma variável de inventário de grupo ou host. 

Inclusão de arquivos de tarefas

Você também pode incluir dinamicamente um arquivo de tarefas para uma ação dentro de um playbook usando o recurso include_tasks.


O recurso include_tasks não processa conteúdo no playbook até que a ação esteja em execução e que parte dela seja realizada. A ordem em que o conteúdo do playbook é processado afeta o funcionamento do recurso de inclusão de tarefas.

Ao usar o recurso include_tasks, instruções condicionais como when definidas na inclusão determinam se as tarefas estão ou não incluídas na ação.

Se você executar ansible-playbook --list-tasks para listar as tarefas no playbook, as tarefas nos arquivos de tarefas incluídos não serão exibidas. As tarefas que incluem os arquivos de tarefas são exibidas. Em comparação, o recurso import_tasks não listaria tarefas que importam arquivos de tarefas, mas sim tarefas individuais dos arquivos de tarefas importados.

Você não pode usar ansible-playbook --start-at-task para iniciar a execução de playbook a partir de uma tarefa que esteja em um arquivo de tarefas incluído.

Você não pode usar uma instrução notify para acionar um nome de manipulador que está em um arquivo de tarefas incluído. Você pode acionar um manipulador no playbook principal que inclui um arquivo de tarefas inteiro, caso em que todas as tarefas no arquivo incluído serão executadas. 

Você encontra uma discussão mais detalhada sobre as diferenças de comportamento entre import_tasks e include_tasks quando condicionais são usados em "Condicionais" no Ansible User Guide.

Casos de uso para arquivos de tarefas

Considere os seguintes exemplos em que pode ser útil gerenciar conjuntos de tarefas como arquivos externos separados do playbook:

Se servidores novos exigirem configuração completa, os administradores poderão criar vários conjuntos de tarefas para criar usuários, instalar pacotes, configurar serviços, configurar privilégios, configurar acesso a um sistema de arquivos compartilhado, fortalecer os servidores, instalar atualizações de segurança e instalar um agente de monitoramento. Cada um desses conjuntos de tarefas poderia ser gerenciado por meio de um arquivo de tarefa separado e autocontido.

Se os servidores forem gerenciados coletivamente pelos desenvolvedores, os administradores de sistema e os administradores de banco de dados, então cada organização poderá gravar seu próprio arquivo de tarefas que poderá ser revisado e integrado pelo gerente do sistema.

Se um servidor exigir uma configuração específica, ele poderá ser integrado como um conjunto de tarefas que são executadas com base em uma condicional. Em outras palavras, as tarefas só serão incluídas se critérios específicos forem atendidos.

Se um grupo de servidores precisar executar uma tarefa ou conjunto de tarefas específico, as tarefas poderão ser executadas em um servidor somente se ele fizer parte de um grupo de hosts específico. 

Gerenciamento de arquivos de tarefas

Você pode criar um diretório dedicado para arquivos de tarefa e salvar todos os arquivos de tarefa nesse diretório. Depois, seu playbook pode simplesmente incluir ou importar arquivos de tarefas desse diretório. Isso permite a construção de um playbook complexo e facilita o gerenciamento de sua estrutura e componentes. Definição de variáveis para ações e tarefas externas

A incorporação de ações ou tarefas de arquivos externos em playbooks usando a importação do Ansible e incluindo recursos aumenta muito a capacidade de reutilizar tarefas e playbooks em um ambiente do Ansible. Para maximizar a possibilidade de reutilização, esses arquivos de tarefa e ação devem ser o mais genéricos possível. Variáveis podem ser usadas para parametrizar elementos de ação e tarefa a fim de expandir a aplicação de tarefas e ações.

Por exemplo, o arquivo de tarefas a seguir instala o pacote necessário para um serviço web e, depois, ativa e inicia o serviço necessário.


Se você parametrizar o pacote e os elementos de serviço conforme mostrado no exemplo a seguir, o arquivo de tarefas também poderá ser usado para instalação e administração de outro software e de seus serviços, em vez de ser útil somente para serviços web.


Posteriormente, ao incorporar o arquivo de tarefas em um playbook, defina as variáveis a serem usadas para a execução da tarefa da seguinte maneira:

...output omitted... tasks:

O Ansible disponibiliza as variáveis transmitidas para as tarefas importadas do arquivo externo.

Você pode usar a mesma técnica para tornar os arquivos de ação mais reutilizáveis. Ao incorporar um arquivo de ação em um playbook, transmita as variáveis a serem usadas para a execução da ação da seguinte maneira:

...output omitted...

Versões anteriores do Ansible usavam o recurso include para incluir playbooks e arquivos de tarefas, dependendo do contexto. Essa funcionalidade está se tornando obsoleta por vários motivos.

Antes do Ansible2.0, o recurso include operava como uma importação estática. No Ansible2.0, ela foi alterada para operar dinamicamente, mas isso causou algumas limitações. No Ansible2.1, tornou-se possível que o recurso include fosse dinâmico ou estático, dependendo das configurações da tarefa, o que era confuso e sujeito a erros. Houve também problemas em garantir que o recurso include funcionasse corretamente em todos os contextos.

Assim, include foi substituído no Ansible2.4 por novas diretivas, como include_tasks, import_tasks e import_playbook. Você pode encontrar exemplos de include em playbooks mais antigos, mas você deve evitar usá-lo em playbooks novos.

Including and Importing — Ansible Documentation

Creating Reusable Playbooks — Ansible Documentation

Conditionals — Ansible Documentation

britho commented 3 years ago

Neste exercício, você incluirá e importará playbooks e tarefas em um playbook do Ansible de nível superior.

Resultados

Você será capaz de incluir playbooks e arquivos de tarefas em playbooks.

Faça login na workstation como student usando a senha student.

Na workstation, execute o comando lab projects-file start. O script cria o diretório de trabalho, /home/student/projects-file, e arquivos de projeto associados.

[student@workstation ~]$ lab projects-file start

Na workstation, com o usuário student, acesse o diretório /home/student/projects-file.

[student@workstation ~]$ cd ~/projects-file
[student@workstation projects-file]$ 

Revise o conteúdo dos três arquivos no subdiretório tasks.

    Revise o conteúdo do arquivo tasks/environment.yml. O arquivo contém tarefas para instalação de pacotes e administração de serviços.

    [student@workstation projects-file]$ cat tasks/environment.yml
    ---
      - name: Install the {{ package }} package
        yum:
          name: "{{ package }}"
          state: latest
      - name: Start the {{ service }} service
        service:
          name: "{{ service }}"
          enabled: true
          state: started

    Revise o conteúdo do arquivo tasks/firewall.yml. O arquivo contém tarefas para instalação, administração e configuração de software de firewall.

    [student@workstation projects-file]$ cat tasks/firewall.yml
    ---
      - name: Install the firewall
        yum:
          name: "{{ firewall_pkg }}"
          state: latest

      - name: Start the firewall
        service:
          name: "{{ firewall_svc }}"
          enabled: true
          state: started

      - name: Open the port for {{ rule }}
        firewalld:
          service: "{{ item }}"
          immediate: true
          permanent: true
          state: enabled
        loop: "{{ rule }}"

    Revise o conteúdo do arquivo tasks/placeholder.yml. Esse arquivo contém uma tarefa para preencher um arquivo de conteúdo da web de espaço reservado.

    [student@workstation projects-file]$ cat tasks/placeholder.yml
    ---
      - name: Create placeholder file
        copy:
          content: "{{ ansible_facts['fqdn'] }} has been customized using Ansible.\n"
          dest: "{{ file }}"

Revise o conteúdo do arquivo test.yml no subdiretório plays. Esse arquivo contém uma ação que testa conexões com um serviço web.

---
- name: Test web service
  hosts: localhost
  become: no
  tasks:
    - name: connect to internet web server
      uri:
        url: "{{ url }}"
        status_code: 200

Crie um playbook chamado playbook.yml. Defina a primeira ação com o nome Configure web server. A ação deve ser executada no host gerenciado servera.lab.example.com definido no arquivo inventory. O início do arquivo deve se parecer com o seguinte:

---
- name: Configure web server
  hosts: servera.lab.example.com

No playbook playbook.yml, defina a seção de tarefas com três conjuntos de tarefas. Inclua o primeiro conjunto de tarefas do arquivo de tarefas tasks/environment.yml. Defina as variáveis necessárias para instalar o pacote httpd e para ativar e iniciar o serviço httpd. Importe o segundo conjunto de tarefas do arquivo de tarefas tasks/firewall.yml. Defina as variáveis necessárias para instalar o pacote firewalld para ativar e iniciar o serviço firewalld e permitir conexões http. Importe o terceiro conjunto de tarefas do arquivo de tarefas tasks/placeholder.yml.

    Crie a seção de tarefas na primeira ação adicionando a seguinte entrada ao playbook playbook.yml.

      tasks:

    Inclua o primeiro conjunto de tarefas de tasks/environment.yml usando o recurso include_tasks. Defina as variáveis package e service como httpd . Defina a variável svc_state como started.

        - name: Include the environment task file and set the variables
          include_tasks: tasks/environment.yml
          vars:
            package: httpd
            service: httpd
          when: ansible_facts['os_family'] == 'RedHat'

    Importe o segundo conjunto de tarefas de tasks/firewall.yml usando o recurso import_tasks. Defina as variáveis firewall_pkg e firewall_svc como firewalld. Defina a variável rule como http.

        - name: Import the firewall task file and set the variables
          import_tasks: tasks/firewall.yml
          vars:
            firewall_pkg: firewalld
            firewall_svc: firewalld
            rule:
              - http
              - https

    Importe o último conjunto de tarefas de tasks/placeholder.yml usando o recurso import_tasks. Defina a variável file como /var/www/html/index.html .

        - name: Import the placeholder task file and set the variable
          import_tasks: tasks/placeholder.yml
          vars:
            file: /var/www/html/index.html

Adicione uma segunda e última ação ao playbook playbook.yml usando o conteúdo do playbook plays/test.yml.

    Adicione uma segunda ação ao playbook playbook.yml para validar a instalação do servidor web. Importe a ação de plays/test.yml. Defina a variável url como http://servera.lab.example.com.

    - name: Import test play file and set the variable
      import_playbook: plays/test.yml
      vars:
        url: 'http://servera.lab.example.com'

    Após a conclusão das alterações, seu playbook deve se parecer com o seguinte:

    ---
    - name: Configure web server
      hosts: servera.lab.example.com

      tasks:
        - name: Include the environment task file and set the variables
          include_tasks: tasks/environment.yml
          vars:
            package: httpd
            service: httpd
          when: ansible_facts['os_family'] == 'RedHat'

        - name: Import the firewall task file and set the variables
          import_tasks: tasks/firewall.yml
          vars:
            firewall_pkg: firewalld
            firewall_svc: firewalld
            rule:
              - http
              - https

        - name: Import the placeholder task file and set the variable
          import_tasks: tasks/placeholder.yml
          vars:
            file: /var/www/html/index.html

    - name: Import test play file and set the variable
      import_playbook: plays/test.yml
      vars:
        url: 'http://servera.lab.example.com'

    Salve as alterações no playbook playbook.yml. 

Antes de executar o playbook, verifique se a sintaxe está correta executando ansible-playbook --syntax-check. Se forem relatados erros, corrija-os antes de ir para a próxima etapa.

[student@workstation projects-file]$ ansible-playbook playbook.yml --syntax-check

playbook: playbook.yml

Execute o playbook playbook.yml. A saída do playbook mostra a importação da tarefa e os arquivos de ação.

[student@workstation projects-file]$ ansible-playbook playbook.yml

PLAY [Configure web server] ***********************************************

TASK [Gathering Facts] ****************************************************
ok: [servera.lab.example.com]

TASK [Install the httpd package] ******************************************
changed: [servera.lab.example.com]

TASK [Start the httpd service] ********************************************
changed: [servera.lab.example.com]

TASK [Install the firewall] ***********************************************
ok: [servera.lab.example.com]

TASK [Start the firewall] *************************************************
ok: [servera.lab.example.com]

TASK [Open the port for http] *********************************************
changed: [servera.lab.example.com]

TASK [Create placeholder file] ********************************************
changed: [servera.lab.example.com]

PLAY [Test web service] ***************************************************

TASK [Gathering Facts] ****************************************************
ok: [localhost]

TASK [connect to internet web server] *************************************
ok: [localhost]

PLAY RECAP ****************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0
servera.lab.example.com    : ok=8    changed=4    unreachable=0    failed=0

Encerramento

Na workstation, execute o script lab projects-file finish para limpar este exercício.

[student@workstation ~]$ lab projects-file finish

Isso conclui o exercício orientado.

britho commented 3 years ago

Lista de verificação de desempenho

Neste laboratório, você modificará um playbook grande para que seja mais fácil de gerenciar usando padrões de host, inclusões, importações e um inventário dinâmico. Além disso, você ajustará a maneira com que o playbook é processado pelo Ansible.

Resultados

Você pode simplificar as referências de host gerenciados em um playbook especificando padrões de host em um inventário dinâmico. Você também deve ser capaz de reestruturar um playbook para que as tarefas sejam importadas de arquivos de tarefas externos e ajustar o playbook para atualizações em cascata.

Instruções

Você herdou um playbook do administrador anterior. O playbook é usado para configurar um serviço web em servera.lab.example.com, serverb.lab.example.com, serverc.lab.example.com e serverd.lab.example.com. O playbook também configura o firewall nos quatro hosts gerenciados para que o tráfego da web seja permitido.

Faça login na workstation como student usando a senha student.

Na workstation, execute o comando lab projects-review start. Este script de configuração garante que os hosts gerenciados sejam acessíveis na rede. Ele também garante que o arquivo de configuração, o arquivo de inventário e o playbook corretos do Ansible estejam instalados no nó de controle.

[student@workstation ~]$ lab projects-review start

Faça as alterações a seguir no arquivo do playbook playbook.yml para que seja mais fácil gerenciá-lo e ajustá-lo para que futuras execuções utilizem atualizações em cascata, a fim de impedir que todos os quatro servidores web fiquem indisponíveis ao mesmo tempo.

Simplifique a lista de hosts gerenciados no playbook usando um padrão de host curinga. Use o script de inventário dinâmico inventory/inventory.py para verificar o padrão de host curinga.

    Altere o diretório para o diretório de trabalho /home/student/projects-review. Revise o arquivo de configuração ansible.cfg para determinar o local do arquivo de inventário. O inventário é definido como o subdiretório inventory, e esse subdiretório contém um script de inventário dinâmico inventory.py.

    [student@workstation ~]$ cd ~/projects-review
    [student@workstation projects-review]$ cat ansible.cfg
    [defaults]
    inventory = inventory
    ...output omitted...
    [student@workstation projects-review]$ ll
    total 16
    -rw-rw-r--. 1 student student   33 Dec 19 00:48 ansible.cfg
    drwxrwxr-x. 2 student student 4096 Dec 18 22:35 files
    drwxrwxr-x. 2 student student 4096 Dec 19 01:18 inventory
    -rw-rw-r--. 1 student student  959 Dec 18 23:48 playbook.yml
    [student@workstation projects-review]$ ll inventory/
    total 4
    -rwxrwxr-x. 1 student student 612 Dec 19 01:18 inventory.py

    Torne o script de inventário dinâmico inventory/inventory.py executável e, em seguida, execute o script de inventário dinâmico com a opção --list para exibir uma lista completa de hosts no inventário.

    [student@workstation projects-review]$ chmod 755 inventory/inventory.py
    [student@workstation projects-review]$ inventory/inventory.py --list
    {"all": {"hosts": ["servera.lab.example.com", "serverb.lab.example.com", "serverc.lab.example.com", "serverd.lab.example.com", "workstation.lab.example.com"], "vars": { }}}

    Verifique se o padrão de host server*.lab.example.com identifica corretamente os quatro hosts gerenciados que são direcionados pelo playbook playbook.yml.

    [student@workstation projects-review]$ ansible server*.lab.example.com \
    > --list-hosts
      hosts (4):
        serverb.lab.example.com
        serverd.lab.example.com
        servera.lab.example.com
        serverc.lab.example.com

    Substitua a lista de hosts no playbook playbook.yml com o padrão de host server*.lab.example.com.

    ---
    - name: Install and configure web service
      hosts: server*.lab.example.com
    ...output omitted...

Reestruture o playbook de modo que as três primeiras tarefas dele sejam mantidas em um arquivo de tarefas externo localizado em tasks/web_tasks.yml. Use o recurso import_tasks para incorporar esse arquivo de tarefas no playbook.

Crie o subdiretório tasks.

[student@workstation projects-review]$ mkdir tasks

Coloque o conteúdo das três primeiras tarefas do playbook playbook.yml no arquivo tasks/web_tasks.yml. O arquivo de tarefas deve ter o seguinte conteúdo:

---
- name: Install httpd
  yum:
    name: httpd
    state: latest

- name: Enable and start httpd
  service:
    name: httpd
    enabled: true
    state: started

- name: Tuning configuration installed
  copy:
    src: files/tune.conf
    dest: /etc/httpd/conf.d/tune.conf
    owner: root
    group: root
    mode: 0644
  notify:
    - restart httpd

Remova as três primeiras tarefas do playbook playbook.yml e insira as linhas a seguir no lugar delas, a fim de importar o arquivo de tarefas tasks/web_tasks.yml.

    - name: Import the web_tasks.yml task file
      import_tasks: tasks/web_tasks.yml

Reestruture o playbook de modo que a quarta, quinta e sexta tarefas dele sejam mantidas em um arquivo de tarefas externo localizado em tasks/firewall_tasks.yml. Use o recurso import_tasks para incorporar esse arquivo de tarefas no playbook.

Coloque o conteúdo das três tarefas restantes no playbook playbook.yml para o arquivo tasks/firewall_tasks.yml. O arquivo de tarefas deve conter o conteúdo a seguir.

---
- name: Install firewalld
  yum:
    name: firewalld
    state: latest

- name: Enable and start the firewall
  service:
    name: firewalld
    enabled: true
    state: started

- name: Open the port for http
  firewalld:
    service: http
    immediate: true
    permanent: true
    state: enabled

Remova as três tarefas restantes do playbook playbook.yml e insira as linhas a seguir no lugar delas, a fim de importar o arquivo de tarefas tasks/firewall_tasks.yml.

    - name: Import the firewall_tasks.yml task file
      import_tasks: tasks/firewall_tasks.yml

Há duplicação de tarefas entre os arquivos tasks/web_tasks.yml e tasks/firewall_tasks.yml. Mova as tarefas que instalam pacotes e ativam serviços para um novo arquivo chamado tasks/install_and_enable.yml e atualize-as para que usem variáveis. Substitua as tarefas originais por instruções import_tasks, passando valores de variáveis adequados.

Copie as tarefas do yum e de serviço de tasks/web_tasks.yml para um novo arquivo chamado tasks/install_and_enable.yml.

---
- name: Install httpd
  yum:
    name: httpd
    state: latest

- name: Enable and start httpd
  service:
    name: httpd
    enabled: true
    state: started

Substitua os nomes do pacote e do serviço em tasks/install_and_enable.yml pelas variáveis package e service.

---
- name: Install {{ package }}
  yum:
    name: "{{ package }}"
    state: latest

- name: Enable and start {{ service }}
  service:
    name: "{{ service }}"
    enabled: true
    state: started

Substitua as tarefas do yum e de serviço em tasks/web_tasks.yml e tasks/firewall_tasks.yml por instruções import_tasks.

---
- name: Install and start httpd
  import_tasks: install_and_enable.yml
  vars:
    package: httpd
    service: httpd

---
- name: Install and start firewalld
  import_tasks: install_and_enable.yml
  vars:
    package: firewalld
    service: firewalld

Como o manipulador para reiniciar o serviço httpd pode ser acionado se houver mudanças futuras no arquivo files/tune.conf, implemente o recurso de atualização em cascata no playbook playbook.yml e defina o tamanho do lote da atualização em cascata para dois hosts.

Adicione o parâmetro serial ao playbook playbook.yml.

---
- name: Install and configure web service
  hosts: server*.lab.example.com
  serial: 2
...output omitted...

Verifique se as alterações no playbook playbook.yml foram feitas corretamente e, em seguida, execute o playbook.

Verifique se o playbook playbook.yml contém o conteúdo a seguir.

---
- name: Install and configure web service
  hosts: server*.lab.example.com
  serial: 2

  tasks:
    - name: Import the web_tasks.yml task file
      import_tasks: tasks/web_tasks.yml

    - name: Import the firewall_tasks.yml task file
      import_tasks: tasks/firewall_tasks.yml

  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted

Execute o playbook com ansible-playbook --syntax-check para verificar se ele não contém erros de sintaxe. Se houver erros, corrija-os antes de continuar.

[student@workstation projects-review]$ ansible-playbook playbook.yml \
> --syntax-check
playbook: playbook.yml

Execute o playbook. O playbook deve executar o host como uma atualização em cascata com um tamanho de lote de dois hosts gerenciados.

[student@workstation projects-review]$ ansible-playbook playbook.yml

PLAY [Install and configure web service] ***********************************

TASK [Gathering Facts] *****************************************************
ok: [serverd.lab.example.com]
ok: [serverb.lab.example.com]

TASK [Install httpd] *******************************************************
changed: [serverd.lab.example.com]
changed: [serverb.lab.example.com]

TASK [Enable and start httpd] **********************************************
changed: [serverd.lab.example.com]
changed: [serverb.lab.example.com]

TASK [Tuning configuration installed] **************************************
changed: [serverb.lab.example.com]
changed: [serverd.lab.example.com]

TASK [Install firewalld] ***************************************************
ok: [serverb.lab.example.com]
ok: [serverd.lab.example.com]

TASK [Enable and start firewalld] ******************************************
ok: [serverd.lab.example.com]
ok: [serverb.lab.example.com]

TASK [Open the port for http] **********************************************
changed: [serverd.lab.example.com]
changed: [serverb.lab.example.com]

RUNNING HANDLER [restart httpd] ********************************************
changed: [serverb.lab.example.com]
changed: [serverd.lab.example.com]

PLAY [Install and configure web service] ***********************************

TASK [Gathering Facts] *****************************************************
ok: [serverc.lab.example.com]
ok: [servera.lab.example.com]

TASK [Install httpd] *******************************************************
changed: [serverc.lab.example.com]
changed: [servera.lab.example.com]

TASK [Enable and start httpd] **********************************************
changed: [serverc.lab.example.com]
changed: [servera.lab.example.com]

TASK [Tuning configuration installed] **************************************
changed: [servera.lab.example.com]
changed: [serverc.lab.example.com]

TASK [Install firewalld] ***************************************************
ok: [servera.lab.example.com]
ok: [serverc.lab.example.com]

TASK [Enable and start firewalld] ******************************************
ok: [servera.lab.example.com]
ok: [serverc.lab.example.com]

TASK [Open the port for http] **********************************************
changed: [servera.lab.example.com]
changed: [serverc.lab.example.com]

RUNNING HANDLER [restart httpd] ********************************************
changed: [serverc.lab.example.com]
changed: [servera.lab.example.com]

PLAY RECAP *****************************************************************
servera.lab.example.com    : ok=8    changed=2    unreachable=0    failed=0
serverb.lab.example.com    : ok=8    changed=5    unreachable=0    failed=0
serverc.lab.example.com    : ok=8    changed=5    unreachable=0    failed=0
serverd.lab.example.com    : ok=8    changed=5    unreachable=0    failed=0

Avaliação

Execute o comando lab projects-review grade em workstation para confirmar o êxito deste exercício. Corrija todas as falhas relatadas e execute novamente o script até que ele seja concluído com êxito.

[student@workstation ~]$ lab projects-review grade

Encerramento

Na workstation, execute o script lab projects-review finish para limpar os recursos criados neste laboratório.

[student@workstation ~]$ lab projects-review finish

Isso conclui o laboratório.

britho commented 3 years ago

Neste capítulo, você aprendeu que:

Os padrões de host são usados para especificar os hosts gerenciados que devem ser o alvo das ações ou comandos ad hoc.

Scripts dinâmicos de inventário podem ser usados para gerar listas dinâmicas de hosts gerenciados a partir de serviços de diretório ou outras fontes externas ao Ansible.

O parâmetro forks no arquivo de configuração do Ansible define o número máximo de conexões paralelas a hosts gerenciados.

O parâmetro serial pode ser usado para implementar atualizações em cascata em hosts gerenciados definindo o número de hosts gerenciados em cada lote de atualização em cascata

Você pode usar o recurso import_playbook para incorporar arquivos de ação externos em playbooks.

Você pode usar os recursos include_tasks ou import_tasks para incorporar arquivos de tarefas externos em playbooks. 
britho commented 3 years ago

Meta | Usar funções do Ansible para desenvolver playbooks com mais rapidez e reutilizar o código do Ansible. -- | -- Objetivos | Descrever o que é uma função, como ela está estruturada e como usá-la em um playbook. Criar uma função no diretório do projeto de um playbook e executá-la como parte de uma das ações no playbook. Selecionar e recuperar funções do Ansible Galaxy ou de outras fontes, como um repositório Git, e usá-las em seus playbooks. Escrever playbooks que aproveitem as funções do sistema do RedHat EnterpriseLinux para executar operações padrão. Seções | Descrição da estrutura de funções (e teste) Reutilização do conteúdo em funções do sistema (e exercício orientado) Criação de funções (e exercício orientado) Implantação de funções com o Ansible Galaxy (e exercício orientado) Laboratório | Simplificação de playbooks com funções

Objetivos

Depois de concluir esta seção, você deverá ser capaz de descrever o que é uma função, como ela é estruturada e como usá-la em um playbook.

Estruturação de playbooks do Ansible com funções

À medida que você desenvolve mais playbooks, provavelmente descobrirá que tem muitas oportunidades de reutilizar códigos de playbooks já escritos. Talvez uma ação para configurar um banco de dados MySQL para um aplicativo possa ser reutilizada, com diferentes nomes de host, senhas e usuários, para configurar um banco de dados MySQL para outro aplicativo.

Porém, no mundo real, essa ação pode ser longa e complexa, com muitos arquivos incluídos ou importados, e com tarefas e manipuladores para gerenciar várias situações. Copiar todo esse código para outro playbook pode ser uma tarefa demorada.

As funções do Ansible são uma maneira de facilitar a reutilização do código do Ansible de maneira genérica. Você pode empacotar, em uma estrutura de diretório padronizada, todas as tarefas, variáveis, arquivos, templates e outros recursos necessários para provisionar a infraestrutura ou implantar aplicativos. Copie essa função de projeto para projeto simplesmente copiando o diretório. Você pode simplesmente chamar essa função a partir de uma ação para executá-la.

Uma função bem escrita permitirá que você transmita variáveis para a função do playbook que se ajusta ao seu comportamento, definindo todos os nomes de host específicos do site, endereços IP, nomes de usuário, segredos ou outros detalhes específicos do local que você precisa. Por exemplo, uma função para implementar um servidor de banco de dados pode ter sido escrita para suportar variáveis que configuram o nome do host, o usuário administrador e a senha do banco de dados e outros parâmetros que precisam de personalização para sua instalação. O autor da função também pode garantir que valores padrão razoáveis sejam definidos para essas variáveis se você optar por não configurá-los na ação.

As funções do Ansible têm os seguintes benefícios:

  • As funções agrupam o conteúdo, permitindo fácil compartilhamento de código entre os usuários

  • As funções podem ser gravadas para definirem os elementos essenciais de um tipo de sistema: servidor web, servidor de banco de dados, repositório Git ou outro propósito

  • As funções tornam os projetos grandes mais gerenciáveis

  • As funções podem ser desenvolvidas em paralelo por diferentes administradores

Além de escrever, usar, reutilizar e compartilhar suas próprias funções, você pode obter funções de outras fontes. Algumas funções são incluídas como parte do RedHat EnterpriseLinux, no pacote rhel-system-roles. Você também pode obter diversas funções com suporte da comunidade no site do Ansible Galaxy. Mais adiante neste capítulo, você aprenderá mais sobre essas funções.

Análise da estrutura de funções do Ansible

Uma função do Ansible é definida por uma estrutura padronizada de subdiretórios e arquivos. O diretório do nível superior define o nome da função em si. Os arquivos são organizados em subdiretórios que são nomeados de acordo com a finalidade de cada arquivo na função, como tasks e handlers. Os subdiretórios files e templates contêm arquivos referenciados por tarefas em outros arquivos YAML.

O comando tree a seguir exibe a estrutura de diretórios da função user.example.

[user@host roles]$ tree user.example
user.example/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
    └── main.yml

Subdiretório | Função -- | -- defaults | O arquivo main.yml nesse diretório contém os valores padrão das variáveis de função que podem ser substituídas quando a função é usada. Essas variáveis têm baixa precedência e destinam-se a ser alteradas e personalizadas nas ações. files | Esse diretório contém arquivos estáticos que são referenciados pelas tarefas de função. handlers | O arquivo main.yml nesse diretório contém as definições de manipulador da função. meta | O arquivo main.yml nesse diretório contém informações sobre a função, incluindo autor, licença, plataformas e dependências opcionais de função. tasks | O arquivo main.yml nesse diretório contém as definições de tarefa da função. templates | Esse diretório contém modelos Jinja2 que são referenciados pelas tarefas de função. tests | Esse diretório contém um inventário e um playbook test.yml que podem ser usados para testar a função. vars | O arquivo main.yml nesse diretório define os valores de variável da função. Frequentemente, essas variáveis são usadas para propósitos internos dentro da função. Essas variáveis têm alta precedência e não devem ser alteradas quando usadas em um playbook.


Nem toda função terá todos esses diretórios.

Definição de variáveis e padrões

As variáveis de função são definidas criando um arquivo vars/main.yml com pareschave-valor na hierarquia de diretórios da função. Elas são referenciadas no arquivo YAML da função como qualquer outra variável: {{VAR_NAME}}. Essas variáveis têm alta precedência e não podem ser substituídas por variáveis de inventário. Essas variáveis destinam-se a serem usadas pelo funcionamento interno da função.

As variáveis padrão permitem que os valores padrão sejam definidos para variáveis que podem ser usadas em uma ação para configurar a função ou personalizar seu comportamento. Elas são definidas ao criar um arquivo defaults/main.yml com pares key:value na hierarquia de diretórios de função. As variáveis padrão têm a precedência mais baixa entre as variáveis disponíveis. Elas podem ser facilmente substituídas por outra variável, incluindo variáveis de inventário. Essas variáveis destinam-se a fornecer à pessoa que está escrevendo uma ação que usa a função uma maneira de personalizar ou controlar exatamente o que vai fazer. Elas podem ser usadas para fornecer informações para a função necessária para configurar ou implantar algo adequadamente.

Defina uma variável específica em vars/main.yml ou defaults/main.yml, mas não em ambos. As variáveis padrão deverão ser usadas quando a intenção for que seus valores sejam substituídos.

As funções não devem conter dados específicos de site. Elas definitivamente não devem conter nenhum segredo, como senhas ou chaves privadas.

Isso porque as funções devem ser genéricas, reutilizáveis e livremente compartilháveis. Detalhes específicos de sites não devem ser codificados para eles.

Segredos devem ser fornecidos para a função através de outros meios. Esse é um dos motivos pelos quais talvez você queira definir variáveis de função ao chamar uma função. As variáveis de função definidas na ação podem fornecer o segredo ou apontar para um arquivo criptografado no Ansible Vault que contém o segredo.

Uso de funções do Ansible em um playbook

O uso de funções em um playbook é simples. O exemplo a seguir mostra uma maneira de chamar as funções do Ansible.

---
- hosts: remote.example.com
  roles:
    - role1
    - role2

Para cada função específica, as tarefas, os manipuladores, as variáveis e as dependências da função serão importados no playbook nessa ordem. As tarefas copy, script, template ou include_tasks/import_tasks na função podem fazer referência aos arquivos, modelos ou arquivos de tarefas relevantes na função sem nomes de caminhos absolutos ou relativos. O Ansible as procura nos subdiretórios files, templates ou tasks da função, respectivamente.

Quando você usa uma seção roles para importar as funções para uma ação, as funções serão executadas primeiro, antes de quaisquer tarefas que você definir para essa ação.

O exemplo a seguir define valores para duas variáveis de função de role2, var1 e var2. Os valores das variáveis defaults e vars são substituídos quando role2 é usada.

---
- hosts: remote.example.com
  roles:
    - role: role1
    - role: role2
      var1: val1
      var2: val2

Outra sintaxe YAML equivalente que você pode ver nesse caso é:

---
- hosts: remote.example.com
  roles:
    - role: role1
    - { role: role2, var1: val1, var2: val2 }

Há situações em que isso pode ser mais difícil de ler, mesmo sendo mais compacto.

As variáveis de função definidas em linha (parâmetros de função), como nos exemplos anteriores, tem precedência muito alta. Elas substituirão a maioria das outras variáveis.

Tenha muito cuidado para não reutilizar os nomes de variáveis de função que você definir em linha em qualquer outro lugar da sua ação, já que os valores das variáveis de função substituirão as variáveis de inventário e qualquer vars de ação.

Controle da ordem de execução

Para cada ação em um playbook, as tarefas são executadas conforme ordenadas na lista de tarefas. Depois que todas as tarefas são executadas, os manipuladores notificados são executados.

Quando uma função é adicionada a uma ação, as tarefas da função são adicionadas ao início da lista de tarefas. Se uma segunda função for incluída em uma ação, sua lista de tarefas é adicionada após a primeira função.

Os manipuladores de função são adicionados às execuções da mesma maneira que as tarefas de função são adicionadas às ações. Cada ação define uma lista de manipuladores. Os manipuladores de função são adicionados à lista de manipuladores primeiro, seguidos de todos os manipuladores definidos na seção handlers da ação.

Em determinados cenários, pode ser necessário executar algumas tarefas de ação antes das funções. Para suportar esses cenários, as ações podem ser configuradas com uma seção pre_tasks. Qualquer tarefa listada nessa seção é executada antes que quaisquer funções sejam executadas. Se qualquer uma dessas tarefas notificar um manipulador, essas tarefas do manipulador serão executadas antes das funções ou tarefas normais.

As ações também suportam uma palavra-chave post_tasks. Essas tarefas são executadas após as tarefas normais da ação e todos os manipuladores que elas notificam são executados.

A ação a seguir mostra um exemplo com pre_tasks, roles, tasks, post_tasks e handlers. É incomum que uma ação contenha todas essas seções.

- name: Play to illustrate order of execution
  hosts: remote.example.com
  pre_tasks:
    - debug:
        msg: 'pre-task'
      notify: my handler
  roles:
    - role1
  tasks:
    - debug:
        msg: 'first task'
      notify: my handler
  post_tasks:
    - debug:
        msg: 'post-task'
      notify: my handler
  handlers:
    - name: my handler
      debug:
        msg: Running my handler

No exemplo acima, uma tarefa debug é executada em cada seção para notificar o manipulador handler. A tarefa my handler é executada três vezes:

  • depois que todas as tarefas pre_tasks são executadas

  • depois que todas as tarefas de função e tarefas da seção tasks forem executadas

  • depois que todas as post_tasks são executadas

As funções podem ser adicionadas a uma ação usando uma tarefa comum, não apenas incluindo-as na seção roles de uma ação. Use o módulo include_role para incluir dinamicamente uma função e use o módulo import_role para importar estaticamente uma função.

O manual a seguir demonstra como uma função pode ser incluída usando uma tarefa com o módulo include_role.

- name: Execute a role as a task
  hosts: remote.example.com
  tasks:
    - name: A normal task
      debug:
        msg: 'first task'
    - name: A task to include role2 here
      include_role: role2

O módulo include_role foi adicionado ao Ansible 2.3, e o módulo import_role ao Ansible 2.4.

britho commented 3 years ago

Escolha a resposta correta para as seguintes perguntas:

Quando concluir o teste, clique em check. Se quiser tentar novamente, clique em reset. Clique em show solution para ver todas as respostas corretas.

  1. 1.   --   | Qual das afirmações a seguir melhor descreve as funções? A |   | Definições de configuração que permitem que usuários específicos executem playbooks do Ansible. B |   | Playbooks para um data center. C |   | Coleção de arquivos de tarefas YAML e itens de suporte organizados em uma estrutura específica para fácil compartilhamento, portabilidade e reutilização.
2.   --   | Qual das opções a seguir pode ser especificada nas funções? A |   | Manipuladores B |   | Tarefas C |   | Templates D |   | Variáveis E |   | Todas as respostas acima
3.   --   | Qual arquivo declara dependências de função? A |   | O playbook do Ansible que usa a função. B |   | O arquivo meta/main.yml na hierarquia da função. C |   | O arquivo meta/main.yml no diretório do projeto. D |   | As dependências de função não podem ser definidas no Ansible.
4.   --   | Qual arquivo em uma hierarquia de diretório da função deve conter os valores iniciais de variáveis que podem ser usados como parâmetros da função? A |   | defaults/main.yml B |   | meta/main.yml C |   | vars/main.yml D |   | O arquivo de inventário de host.
britho commented 3 years ago

Objetivos

Depois de concluir esta seção, você deverá ser capaz de escrever playbooks que aproveitem as funções do sistema do RedHat EnterpriseLinux para realizar operações padrão.

Funções do sistema do RedHat Enterprise Linux

A partir do RedHat EnterpriseLinux 7.4, várias funções do Ansible foram fornecidas com o sistema operacional como parte do pacote rhel-system-roles. No RedHat Enterprise Linux8, o pacote está disponível no canal AppStream. Uma breve descrição de cada função:

Nome | Estado | Descrição da função -- | -- | -- rhel-system-roles.kdump | Totalmente compatível | Configura o serviço de recuperação de falhas kdump. rhel-system-roles.network | Totalmente compatível | Configura interfaces de rede. rhel-system-roles.selinux | Totalmente compatível | Configura e gerencia a personalização do SELinux, incluindo o modo SELinux, contextos de arquivo e porta, configurações booleanas e usuários do SELinux. rhel-system-roles.timesync | Totalmente compatível | Configura a sincronização de horário usando o Network Time Protocol ou o Precision Time Protocol. rhel-system-roles.postfix | Prévia de tecnologia | Configura cada host como um agente de transferência de e-mail usando o serviço Postfix. rhel-system-roles.firewall | Em desenvolvimento | Configura o firewall de um host. rhel-system-roles.tuned | Em desenvolvimento | Configura o serviço tuned para ajustar o desempenho do sistema.

As funções do sistema têm a finalidade de padronizar a configuração dos subsistemas do RedHat Enterprise Linux em várias versões. Use as funções do sistema para configurar qualquer RedHat Enterprise Linux, na versão 6.10 e posteriores.

Gerenciamento de configuração simplificado

Como exemplo, o serviço de sincronização de horário recomendado para o RedHat Enterprise Linux7 é o serviço chronyd. No entanto, no Red Hat Enterprise Linux 6, o serviço recomendado é o ntpd. Em um ambiente com uma mistura de hosts Red Hat Enterprise Linux 6 e 7, um administrador deve gerenciar os arquivos de configuração para ambos os serviços.

Com as funções do sistema do RHEL, os administradores não precisam mais manter os arquivos de configuração para ambos os serviços. Os administradores podem usar a função rhel-system-roles.timesync para configurar a sincronização de horário para ambos os hosts Red Hat Enterprise Linux 6 e 7. Um arquivo YAML simplificado contendo variáveis de função define a configuração da sincronização de horário para os dois tipos de hosts.

Suporte para funções do sistema RHEL

As funções do sistema do RHEL são derivadas do projeto de funções do sistema do Linux open source, encontrado no Ansible Galaxy. Diferentemente das funções do sistema do Linux, as funções do sistema do RHEL têm suporte da Red Hat como parte de uma subscrição padrão do Red Hat Enterprise Linux. As funções do sistema do RHEL têm os mesmos benefícios de suporte do ciclo de vida que vêm com uma subscrição do RedHat Enterprise Linux.

Todas as funções do sistema são testadas e estáveis. As funções Fully Supported do sistema também têm interfaces estáveis. Para qualquer função de sistema Fully Supported, a Red Hat fará o possível para garantir que as variáveis de função não sejam alteradas em versões futuras. A refatoração do playbook devido a mudanças de função do sistema deve ser mínima.

As funções de prévia de tecnologia do sistema podem utilizar diferentes variáveis de função em versões futuras. O teste de integração é recomendado para playbooks que incorporam qualquer função de prévia de tecnologia. Os playbooks podem exigir refatoração se as variáveis de função forem alteradas em uma versão futura da função.

Outras funções estão em desenvolvimento no projeto de funções de sistema do Linux upstream, mas ainda não estão disponíveis por meio de uma subscrição do RHEL. Essas funções estão disponíveis no Ansible Galaxy.

Instalação das funções do sistema do RHEL

As funções do sistema do RHEL são fornecidas pelo pacote rhel-system-roles, que está disponível no canal AppStream. Instale esse pacote no nó de controle do Ansible.

Use o procedimento a seguir para instalar o pacote rhel-system-roles. O procedimento pressupõe que o nó de controle está registrado em uma subscrição do RedHat Enterprise Linux e que o Ansible Engine está instalado. Consulte a seção em Instalação do Ansible para obter mais informações.

  1. Instale as funções do sistema do RHEL.

    [root@host ~]# yum install rhel-system-roles

Após a instalação, as funções do sistema RHEL estão localizadas no diretório /usr/share/ansible/roles:

[root@host ~]# ls -l /usr/share/ansible/roles/
total 20
...output omitted... linux-system-roles.kdump -> rhel-system-roles.kdump
...output omitted... linux-system-roles.network -> rhel-system-roles.network
...output omitted... linux-system-roles.postfix -> rhel-system-roles.postfix
...output omitted... linux-system-roles.selinux -> rhel-system-roles.selinux
...output omitted... linux-system-roles.timesync -> rhel-system-roles.timesync
...output omitted... rhel-system-roles.kdump
...output omitted... rhel-system-roles.network
...output omitted... rhel-system-roles.postfix
...output omitted... rhel-system-roles.selinux
...output omitted... rhel-system-roles.timesync

O nome upstream correspondente de cada função é vinculado à função do sistema RHEL. Isso permite que uma função seja referenciada em um playbook por qualquer nome.

O padrão roles_path no RedHat Enterprise Linux inclui /usr/share/ansible/roles no caminho; portanto, o Ansible deve encontrar automaticamente essas funções quando referenciadas por um playbook.

O Ansible pode não encontrar as funções do sistema se roles_path tiver sido substituído no arquivo de configuração atual do Ansible, se a variável de ambiente ANSIBLE_ROLES_PATH estiver definida ou se houver outra função de mesmo nome em um diretório listado anteriormente em roles_path.

Acesso à documentação para funções do sistema RHEL

Após a instalação, a documentação das funções do sistema RHEL é encontrada no diretório /usr/share/doc/rhel-system-roles-<version>/. A documentação é organizada em subdiretórios por subsistema:

[root@host ~]# ls -l /usr/share/doc/rhel-system-roles/
total 4
drwxr-xr-x. ...output omitted... kdump
drwxr-xr-x. ...output omitted... network
drwxr-xr-x. ...output omitted... postfix
drwxr-xr-x. ...output omitted... selinux
drwxr-xr-x. ...output omitted... timesync

O diretório de documentação de cada função contém um arquivo README.md. O arquivo README.md contém uma descrição da função, juntamente com informações de uso da função.

O arquivo README.md também descreve variáveis de função que afetam o comportamento da função. Muitas vezes, o arquivo README.md contém um trecho de playbook que demonstra as configurações da variável para um cenário de configuração comum.

Alguns diretórios de documentação de função contêm exemplos de playbooks. Ao usar uma função pela primeira vez, revise os playbooks de exemplo adicionais no diretório da documentação.

A documentação das funções do sistema RHEL corresponde à documentação das funções do sistema Linux. Use um navegador da web para acessar a documentação das funções upstream no site do Ansible Galaxy, https://galaxy.ansible.com.

Exemplo de sincronização de tempo

Suponhamos que você precise configurar a sincronização de horário NTP nos seus servidores. Você poderia gravar a automação para executar cada uma das tarefas necessárias. Mas as funções do sistema RHEL incluem uma função que faz isso, rhel-system-roles.timesync.

A função é documentada em README.md no diretório /usr/share/doc/rhel-system-roles/timesync. O arquivo descreve todas as variáveis que afetam o comportamento da função e contém três trechos de playbook que ilustram diferentes configurações de sincronização de horário.

Para configurar manualmente os servidores NTP, a função tem uma variável chamada timesync_ntp_servers. Ela recebe uma lista de servidores NTP. Cada item na lista é composto por um ou mais atributos. Os dois atributos principais são:

Atributo | Finalidade -- | -- hostname | O nome do host de um servidor NTP com o qual sincronizar. iburst | Um booleano que ativa ou desativa a sincronização inicial rápida. O padrão na função é não; normalmente, você deve defini-lo como sim.

Dada essa informação, o exemplo a seguir é uma ação que usa a função rhel-system-roles.timesync para configurar hosts gerenciados a fim de obter o horário de três servidores NTP usando a sincronização inicial rápida. Além disso, foi adicionada uma tarefa que usa o módulo fuso horário para definir o fuso horário dos hosts para UTC.

- name: Time Synchronization Play
  hosts: servers
  vars:
    timesync_ntp_servers:
      - hostname: 0.rhel.pool.ntp.org
        iburst: yes
      - hostname: 1.rhel.pool.ntp.org
        iburst: yes
      - hostname: 2.rhel.pool.ntp.org
        iburst: yes
    timezone: UTC
  roles:
    - rhel-system-roles.timesync
  tasks:
    - name: Set timezone
      timezone:
        name: "{{ timezone }}"

Se você quiser definir um fuso horário diferente, poderá usar o comando tzselect para procurar outros valores válidos. Você também pode usar o comando timedatectl para verificar as configurações atuais do relógio.

Este exemplo define as variáveis de função em uma seção vars da ação, mas uma prática mais recomendada pode ser configurá-los como variáveis de inventário para hosts ou grupos de hosts.

Considere um projeto de playbook com a seguinte estrutura:

[root@host playbook-project]# tree
.
├── ansible.cfg
├── group_vars
│   └── servers
│       └── timesync.yml1
├── inventory
└── timesync_playbook.yml2
  | Define as variáveis de sincronização de hora que substituem os padrões de função dos hosts no grupo servidores no inventário. Esse arquivo seria algo como: timesync_ntp_servers: - hostname: 0.rhel.pool.ntp.org iburst: yes - hostname: 1.rhel.pool.ntp.org iburst: yes - hostname: 2.rhel.pool.ntp.org iburst: yes timezone: UTC -- | --   | O conteúdo do playbook simplifica para: - name: Time Synchronization Play hosts: servers roles: - rhel-system-roles.timesync tasks: - name: Set timezone timezone: name: "{{ timezone }}"

Essa estrutura separa corretamente a função, o código do playbook e as configurações. O código do playbook é simples, fácil de ler e não deve exigir refatoração complexa. O conteúdo da função é mantido e suportado pela RedHat. Todas as configurações são tratadas como variáveis de inventário.

Essa estrutura também é compatível com um ambiente dinâmico e heterogêneo. Hosts com novos requisitos de sincronização de horário podem ser colocados em um novo grupo de hosts. Variáveis apropriadas são definidas em um arquivo YAML e colocadas no subdiretório group_vars (ou host_vars) apropriado.

Exemplo de função do SELinux

Como outro exemplo, a função rhel-system-roles.selinux simplifica o gerenciamento das configurações do SELinux. Ela é implementada usando os módulos do Ansible relacionados ao SELinux. A vantagem de usar essa função é que em vez de gravar suas próprias tarefas, você fica livre da responsabilidade de gravá-las. Em vez disso, você fornece variáveis para a função a fim de configurá-la, e o código mantido na função garantirá que sua configuração desejada do SELinux seja aplicada.

Entre as tarefas que essa função pode executar estão:

  • Definir o modo de imposição ou permissivo

  • Executar restorecon em partes da hierarquia do sistema de arquivos

  • Definir valores booleanos SELinux

  • Definir contextos de arquivos SELinux persistentemente

  • Definir mapeamentos de usuários do SELinux

Chamado da função do SELinux

Às vezes, a função do SELinux deve garantir que os hosts gerenciados sejam reinicializados para aplicar completamente suas alterações. No entanto, ele não reinicia os hosts. Isso é feito para que você possa controlar como a reinicialização é tratada. Porém, isso significa que é um pouco mais complicado do que o normal usar corretamente essa função em uma ação.

A maneira como isso funciona é que a função definirá uma variável booleana, selinux_reboot_required, como verdadeira e apresentará falha se for necessário reiniciar. Você pode usar uma estrutura block/rescue para se recuperar da falha por meio da geração de uma falha na ação se essa variável não estiver configurada como verdadeira ou reinicializando o host gerenciado e executando novamente a função se ela for verdadeira. O bloco em sua ação deve se parecer com isto:

    - name: Apply SELinux role
      block:
        - include_role:
            name: rhel-system-roles.selinux
      rescue:
        - name: Check for failure for other reasons than required reboot
          fail:
          when: not selinux_reboot_required
        - name: Restart managed host
          reboot:
        - name: Reapply SELinux role to complete changes
          include_role:
            name: rhel-system-roles.selinux

Configuração da função do SELinux

As variáveis usadas para configurar a função rhel-system-roles.selinux são documentadas em seu arquivo README.md. Os exemplos a seguir mostram algumas maneiras de usar essa função.

A variável selinux_state define o modo no qual o SELinux é executado. Ela pode ser definida para os modos de imposição, permissivo ou desativado. Se não estiver definida, o modo não é alterado.

selinux_state: enforcing

A variável selinux_booleans recebe uma lista de valores booleanos do SELinux para ajustar. Cada item na lista é um hash/dicionário de variáveis: o name do booleano, o state (se deveria ser on ou off), e se a configuração deve ser persistent nas reinicializações.

Este exemplo define httpd_enable_homedirs como on persistentemente:

selinux_booleans:
  - name: 'httpd_enable_homedirs'
    state: 'on'
    persistent: 'yes'

A variável selinux_fcontext recebe uma lista de contextos de arquivos para definir (ou remover) persistentemente. Ele funciona de forma muito semelhante ao comando selinux fcontext.

O exemplo a seguir garante que a política tenha uma regra para definir o tipo padrão do SELinux para todos os arquivos em /srv/www para httpd_sys_content_t.

selinux_fcontexts:
  - target: '/srv/www(/.*)?'
    setype: 'httpd_sys_content_t'
    state: 'present'

A variável selinux_restore_dirs especifica uma lista de diretórios nos quais executar restorecon:

selinux_restore_dirs:
  - /srv/www

A variável selinux_ports recebe uma lista de portas que devem ter um tipo de SELinux específico.

selinux_ports:
  - ports: '82'
    setype: 'http_port_t'
    proto: 'tcp'
    state: 'present'

Há outras variáveis e opções para essa função. Consulte seu arquivo README.md para obter mais informações.

britho commented 3 years ago

Neste exercício, você usará uma das funções do RedHat Enterprise Linux em conjunto com uma tarefa normal para configurar a sincronização de horário e o fuso horário em seus hosts gerenciados.

Resultados

Você deverá ser capaz de:

Instalar as funções do sistema RedHat Enterprise Linux.

Encontrar e usar a documentação das funções do sistema RHEL.

Usar a função rhel-system-roles.timesync em um playbook para configurar a sincronização de horário em hosts remotos. 

Visão geral do cenário

Sua organização mantém dois data centers: um nos Estados Unidos (Chicago) e um na Finlândia (Helsinki). Para ajudar na análise de log de servidores de banco de dados em data centers, certifique-se de que o relógio do sistema de cada host esteja sincronizado usando o Network Time Protocol. Para ajudar na análise da atividade de hora do dia nos data centers, certifique-se de que cada servidor de banco de dados tenha uma definição de fuso horário que corresponda ao local do data center do host.

A sincronização de horário tem os seguintes requisitos:

Usar o servidor NTP localizado em classroom.example.com. Ative a opção iburst para acelerar a sincronização de horário inicial.

Use o pacote chrony para a sincronização de horário. 

Faça login na workstation como student usando a senha student.

Na workstation, execute o comando lab role-system start. Isso cria o diretório de trabalho, /home/student/role-system, e o preenche com um arquivo de configuração e um inventário de host do Ansible.

[student@workstation ~]$ lab role-system start

Mude para o diretório de trabalho /home/student/role-system.

[student@workstation ~]$ cd ~/role-system
[student@workstation role-system]$ 

Instale as funções do sistema RedHat EnterpriseLinux no nó de controle, workstation.lab.example.com. Verifique o local da instalação das funções no nó de controle.

    Use o comando ansible-galaxy para verificar se nenhuma função está inicialmente disponível para uso no projeto do playbook.

    [student@workstation role-system]$ ansible-galaxy list
    # /home/student/role-system/roles
    # /usr/share/ansible/roles
    # /etc/ansible/roles
    [student@workstation role-system]$ 

    O comando ansible-galaxy procura três diretórios para funções, conforme indicado pela entrada roles_path no arquivo ansible.cfg:

        ./roles

        /usr/share/ansible/roles

        /etc/ansible/roles 

    A saída acima indica que não há funções em nenhum desses diretórios.

    Instale o pacote rhel-system-roles.

    [student@workstation role-system]$ sudo yum install rhel-system-roles

    Digite y quando solicitado para instalar o pacote.

    Use o comando ansible-galaxy para verificar se as funções do sistema estão disponíveis agora.

    [student@workstation role-system]$ ansible-galaxy list
    # /home/student/role-system/roles
    # /usr/share/ansible/roles
    - linux-system-roles.kdump, (unknown version)
    - linux-system-roles.network, (unknown version)
    - linux-system-roles.postfix, (unknown version)
    - linux-system-roles.selinux, (unknown version)
    - linux-system-roles.timesync, (unknown version)
    - rhel-system-roles.kdump, (unknown version)
    - rhel-system-roles.network, (unknown version)
    - rhel-system-roles.postfix, (unknown version)
    - rhel-system-roles.selinux, (unknown version)
    - rhel-system-roles.timesync, (unknown version)
    # /etc/ansible/roles

    As funções estão localizadas no diretório /usr/share/ansible/roles. Qualquer função que comece com linux-system-roles é, na verdade, um symlink para a função rhel-system-roles correspondente. 

Crie um playbook, configure_time.yml, com uma ação que tenha como destino o grupo de hosts database_servers. Inclua a função rhel-system-roles.timesync na seção roles da ação.

---
- name: Time Synchronization
  hosts: database_servers

  roles:
    - rhel-system-roles.timesync

A documentação de funções contém uma descrição de cada variável de função, incluindo o valor padrão da variável. Determine as variáveis de função a serem substituídas para atender aos requisitos de sincronização de horário.

Coloque os valores das variáveis de função em um arquivo chamado timesync.yml. Como esses valores de variáveis se aplicam a todos os hosts no inventário, coloque o arquivo timesync.yml no subdiretório group_vars/all.

    Revise a seção Variáveis de função do arquivo README.md para a função rhel-system-roles.timesync.

    [student@workstation role-system]$ cat \
    > /usr/share/doc/rhel-system-roles/timesync/README.md
    ...output omitted...
    Role Variables
    --------------

    ...output omitted...
    # List of NTP servers
    timesync_ntp_servers:
      - hostname: foo.example.com   # Hostname or address of the server
        minpoll: 4                  # Minimum polling interval (default 6)
        maxpoll: 8                  # Maximum polling interval (default 10)
        iburst: yes                 # Flag enabling fast initial synchronization
                                    # (default no)
        pool: no                    # Flag indicating that each resolved address
                                    # of the hostname is a separate NTP server
                                    # (default no)
    ...output omitted...
    # Name of the package which should be installed and configured for NTP.
    # Possible values are "chrony" and "ntp". If not defined, the currently active
    # or enabled service will be configured. If no service is active or enabled, a
    # package specific to the system and its version will be selected.
    timesync_ntp_provider: chrony
    ...output omitted...

    Crie o subdiretório group_vars/all.

    [student@workstation role-system]$ mkdir -pv group_vars/all
    mkdir: created directory 'group_vars'
    mkdir: created directory 'group_vars/all'

    Crie um novo arquivo group_vars/all/timesync.yml usando um editor de texto. Adicione definições de variáveis para satisfazer os requisitos de sincronização de horário. O arquivo agora contém:

    ---
    #rhel-system-roles.timesync variables for all hosts

    timesync_ntp_provider: chrony

    timesync_ntp_servers:
      - hostname: classroom.example.com
        iburst: yes

Adicione uma tarefa a configure_time.yml para definir o fuso horário de cada host. Certifique-se de que a tarefa usa o módulo timezone e é executada após a função rhel-system-roles.timesync.

Como os hosts não pertencem ao mesmo fuso horário, use uma variável (host_timezone) para o nome do fuso horário.

    Revise a seção Exemplos da documentação do módulo timezone.

    [student@workstation role-system]$ ansible-doc timezone | grep -A 4 "EXAMPLES"
    EXAMPLES:
    - name: set timezone to Asia/Tokyo
      timezone:
        name: Asia/Tokyo

    Adicione uma tarefa à seção post_tasks da ação no playbook configure_time.yml. Configure a tarefa com base no exemplo da documentação, mas use a variável host_timezone para o nome do fuso horário.

    A documentação em ansible-doc timezone recomenda a reinicialização do serviço Cron se o módulo alterar o fuso horário, a fim de garantir que as tarefas do Cron sejam executadas nos horários certos. Adicione uma palavra-chave notify à tarefa, com o valor restart crond associado. A seção post_tasks da ação deve ser:

      post_tasks:
        - name: Set timezone
          timezone:
            name: "{{ host_timezone }}"
          notify: restart crond

    Adicione o manipulador restart crond à ação Time Synchronization. O playbook completo agora contém:

    ---
    - name: Time Synchronization
      hosts: database_servers

      roles:
        - rhel-system-roles.timesync

      post_tasks:
        - name: Set timezone
          timezone:
            name: "{{ host_timezone }}"
          notify: restart crond

      handlers:
        - name: restart crond
          service:
            name: crond
            state: restarted

Para cada data center, crie um arquivo chamado timezone.yml que contenha um valor apropriado para a variável host_timezone. Use o comando timedatectl list-timezones para encontrar a string de fuso horário válida para cada data center.

    Crie os subdiretórios group_vars para os grupos de hosts na_datacenter e europe_datacenter.

    [student@workstation role-system]$ mkdir -pv \
    > group_vars/{na_datacenter,europe_datacenter}
    mkdir: created directory 'group_vars/na_datacenter'
    mkdir: created directory 'group_vars/europe_datacenter'

    Use o comando timedatectl list-timezones para determinar o fuso horário para os data centers dos EUA e da Europa:

    [student@workstation role-system]$ timedatectl list-timezones | grep Chicago
    America/Chicago
    [student@workstation role-system]$ timedatectl list-timezones | grep Helsinki
    Europe/Helsinki

    Crie timezone.yml para ambos os data centers:

    [student@workstation role-system]$ echo "host_timezone: America/Chicago" > \
    > group_vars/na_datacenter/timezone.yml
    [student@workstation role-system]$ echo "host_timezone: Europe/Helsinki" > \
    > group_vars/europe_datacenter/timezone.yml

Execute o playbook.

[student@workstation role-system]$ ansible-playbook configure_time.yml

PLAY [Time Synchronization] **************************************************

TASK [Gathering Facts] *******************************************************
ok: [serverb.lab.example.com]
ok: [servera.lab.example.com]

TASK [rhel-system-roles.timesync : Check if only NTP is needed] **************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]

...output omitted...

TASK [rhel-system-roles.timesync : Enable timemaster] ************************
skipping: [servera.lab.example.com]
skipping: [serverb.lab.example.com]

RUNNING HANDLER [rhel-system-roles.timesync : restart chronyd] ***************
changed: [servera.lab.example.com]
changed: [serverb.lab.example.com]

TASK [Set timezone] **********************************************************
changed: [serverb.lab.example.com]
changed: [servera.lab.example.com]

RUNNING HANDLER [restart crond] **********************************************
changed: [serverb.lab.example.com]
changed: [servera.lab.example.com]

PLAY RECAP *******************************************************************
servera.lab.example.com    : ok=17   changed=6    unreachable=0    failed=0    
skipped=20   rescued=0    ignored=6   
serverb.lab.example.com    : ok=17   changed=6    unreachable=0    failed=0    
skipped=20   rescued=0    ignored=6

Verifique as configurações de fuso horário de cada servidor. Use um comando ad hoc do Ansible para ver a saída do comando date em todos os servidores de bancos de dados.

Os fusos horários reais listados variarão dependendo da época do ano e se o horário de verão estiver ativo.

[student@workstation role-system]$ ansible database_servers -m shell -a date
serverb.lab.example.com | CHANGED | rc=0 >>
Wed Apr  3 06:27:01 EEST 2019

servera.lab.example.com | CHANGED | rc=0 >>
Tue Apr  2 22:27:01 CDT 2019

Cada servidor tem uma configuração de fuso horário com base em sua localização geográfica. 

Encerramento

Execute o comando lab role-system finish para limpar o host gerenciado.

[student@workstation ~]$ lab role-system finish

Isso conclui o exercício orientado

britho commented 3 years ago

Objetivos

Depois de concluir esta seção, você deverá ser capaz de criar uma função no diretório de projeto de um playbook e executá-la como parte de uma das ações do playbook. O processo de criação de função

A criação de funções no Ansible não requer ferramentas especiais de desenvolvimento. A criação e o uso de uma função é um processo em três etapas:

Crie a estrutura de diretórios de funções.

Defina o conteúdo da função.

Use a função em um playbook. 

Criação da estrutura de diretório de função

Por padrão, o Ansible procura funções em um subdiretório chamado roles no diretório que contém seu playbook do Ansible. Isso permite que você armazene funções com o playbook e outros arquivos de suporte.

Se o Ansible não puder encontrar a função lá, ele busca nos diretórios especificados pelos roles_path de configuração do Ansible, em ordem. Essa variável contém uma lista separada por vírgulas de diretórios para pesquisa. O valor padrão dessa variável é:

~/.ansible/roles:/usr/share/ansible/roles:/etc/ansible/roles

Isso permite que você instale funções em seu sistema que sejam compartilhadas por vários projetos. Por exemplo, você pode ter suas próprias funções instaladas em seu diretório pessoal no subdiretório ~/.ansible/roles e o sistema pode ter funções instaladas para todos os usuários no diretório /usr/share/ansible/roles.

Cada função tem seu próprio diretório com uma estrutura de diretórios padronizada. Por exemplo, a estrutura de diretório a seguir contém os arquivos que definem a função motd.

[user@host ~]$ tree roles/ roles/ └── motd ├── defaults │ └── main.yml ├── files ├── handlers ├── meta │ └── main.yml ├── README.md ├── tasks │ └── main.yml └── templates └── motd.j2

O README.md fornece uma descrição básica legível da função, documentação e exemplos de como usá-la, e todos os possíveis requisitos não relacionados ao Ansible que ela precisa para funcionar. O subdiretório meta contém um arquivo main.yml que especifica informações sobre o autor, licença, compatibilidade e dependências do módulo. O subdiretório files contém arquivos com conteúdo fixo; já o subdiretório templates contém modelos que poderão ser implantados pela função quando esta for usada. Os outros subdiretórios podem conter arquivos main.yml que definem valores de variáveis, manipuladores, tarefas, metadados de função ou variáveis padrão, dependendo do subdiretório em que estiverem.

Se um subdiretório existir mas estiver vazio, como handlers neste exemplo, ele é ignorado. Se uma função não usar um recurso, o subdiretório pode ser omitido por completo. Por exemplo, o subdiretório vars foi omitido deste exemplo.

Criação de um esqueleto de função

Você pode criar todos os subdiretórios e arquivos necessários para uma nova função usando os comandos padrão do Linux. Como alternativa, há utilitários de linha de comando para automatizar o processo de criação de novas funções.

A ferramenta de linha de comando ansible-galaxy (abordada com mais detalhes posteriormente neste curso) é usada para gerenciar funções do Ansible, incluindo a criação de novas funções. Você pode executar ansible-galaxy init para criar a estrutura de diretórios para uma nova função. Especifique o nome da função como um argumento para o comando, que cria um subdiretório para a nova função no diretório de trabalho atual.

[user@host playbook-project]$ cd roles [user@host roles]$ ansible-galaxy init my_new_role

Definição do conteúdo da função

Depois de criar a estrutura de diretório, você deve escrever o conteúdo da função. Um bom lugar para começar é o arquivo de tarefas ROLENAME/tasks/main.yml, a lista principal de tarefas executadas pela função.

O arquivo tasks/main.yml a seguir gerencia o arquivo /etc/motd em hosts gerenciados. Ele usa o módulo template para implantar o nome do modelo chamado motd.j2 para o host gerenciado. Como o módulo template é configurado em uma tarefa de função, em vez de uma tarefa de playbook, o modelo motd.j2 é recuperado do subdiretório templates da função.

[user@host ~]$ cat roles/motd/tasks/main.yml

tasks file for motd

O comando a seguir exibe os conteúdos do modelo motd.j2 da função motd. Ele referencia fatos do Ansible e uma variável system_owner.

[user@host ~]$ cat roles/motd/templates/motd.j2 This is the system {{ ansible_facts['hostname'] }}.

Today's date is: {{ ansible_facts['date_time']['date'] }}.

Only use this system with permission. You can ask {{ system_owner }} for access.

A função define um valor padrão para a variável system_owner. O arquivo defaults/main.yml na estrutura do diretório da função é onde o valor está definido.

O arquivo defaults/main.yml a seguir define a variável system_owner para user@host.example.com. Esse será o endereço de e-mail escrito no arquivo /etc/motd dos hosts gerenciados ao qual essa função é aplicada.

[user@host ~]$ cat roles/motd/defaults/main.yml

system_owner: user@host.example.com

Práticas recomendadas para o desenvolvimento de conteúdo de função

As funções permitem que os playbooks sejam escritos de forma modular. Para maximizar a eficácia das funções recentemente desenvolvidas, considere implementar as seguintes práticas recomendadas no desenvolvimento da função:

Mantenha cada função em seu próprio repositório de controle da versão. O Ansible funciona bem com repositórios baseados em git.

Informações confidenciais, como senhas ou chaves SSH, não devem ser armazenadas no repositório de funções. Valores confidenciais devem ser parametrizados como variáveis com valores padrão que não são confidenciais. Playbooks que usam a função são responsáveis por definir variáveis confidenciais através de arquivos de variáveis do Ansible Vault, variáveis de ambiente ou outras opções ansible-playbook.

Use ansible-galaxy init para iniciar sua função e, em seguida, remova todos os diretórios e arquivos desnecessários.

Crie e mantenha os arquivos README.md e meta/main.yml para documentar para que serve sua função, quem a escreveu e como usá-la.

Mantenha sua função focada em um propósito ou função específicos. Em vez de fazer com que uma função sirva para muitas coisas, você pode escrever mais de uma função.

Reutilize e realize a refatoração das funções com frequência. Resista à criação de novas funções para configurações de borda. Se uma função existente realizar a maioria das configurações necessárias, refatore a função existente para que integre o novo cenário de configuração. Use técnicas de integração e teste de regressão para garantir que a função forneça a nova funcionalidade necessária e também não cause problemas para os playbooks existentes. 

Definição das dependências da função

As dependências da função permitem que uma função inclua outras como dependências. Por exemplo, uma função que define um servidor de documentação pode depender de outra função que instala e configura um servidor web. As dependências são definidas no arquivo meta/main.yml na hierarquia de diretórios da função.

Veja a seguir um arquivo meta/main.yml de amostra.


dependencies:

Por padrão, as funções são adicionadas apenas uma vez como uma dependência para um playbook. Se outra função listar a mesma dependência, ela não será executada novamente. Esse comportamento pode ser substituído pela definição da variável allow_duplicates como yes no arquivo meta/main.yml.

Limite as dependências da sua função em outras funções. As dependências dificultam a manutenção da sua função, especialmente se ela tiver muitas dependências complexas. Uso da função em um playbook

Para acessar uma função, referencie-a na seção roles: de uma ação. O playbook a seguir refere-se à função motd. Como nenhuma variável é especificada, a função é aplicada com seus valores de variáveis padrão.

[user@host ~]$ cat use-motd-role.yml

Quando o playbook é executado, as tarefas realizadas por causa de uma função podem ser identificadas pelo prefixo do nome da função. O exemplo de saída a seguir ilustra isso com o prefixo motd : no nome da tarefa:

[user@host ~]$ ansible-playbook -i inventory use-motd-role.yml

PLAY [use motd role playbook] **

TASK [setup] *** ok: [remote.example.com]

TASK [motd : deliver motd file] **** changed: [remote.example.com]

PLAY RECAP ***** remote.example.com : ok=2 changed=1 unreachable=0 failed=0

O cenário acima pressupõe que a função motd está localizada no diretório roles. Posteriormente no curso, você verá como usar uma função que está localizada remotamente em um repositório de controle de versão.

Alteração do comportamento de uma função com variáveis

Uma função bem escrita usa variáveis padrão para alterar o comportamento da função a fim de corresponder a um cenário de configuração relacionado. Isso ajuda a tornar a função mais genérica e reutilizável em vários contextos.

O valor de qualquer variável definida no diretório defaults de uma função será substituído se essa mesma variável for definida:

em um arquivo de inventário, como uma variável de host ou uma variável de grupo.

em um arquivo YAML nos diretórios group_vars ou host_vars de um projeto de playbook

como uma variável aninhada na palavra-chave vars de uma ação

como uma variável ao incluir a função na palavra-chave roles de uma ação 

O exemplo a seguir mostra como usar a função motd com um valor diferente para a variável da função system_owner. O valor especificado, someone@host.example.com, substituirá a referência da variável quando a função for aplicada a um host gerenciado.

[user@host ~]$ cat use-motd-role.yml

Quando definido dessa forma, a variável system_owner substitui o valor da variável padrão de mesmo nome. Nenhuma definição de variável aninhada na palavra-chave vars substituirá o valor da mesma variável, se definido no diretório vars de uma função.

O exemplo a seguir também mostra como usar a função motd com um valor diferente para a variável da função system_owner. O valor especificado, someone@host.example.com, substituirá a referência da variável, independentemente de estar definido no diretório vars ou defaults da função.

[user@host ~]$ cat use-motd-role.yml

A precedência da variável pode ser confusa ao trabalhar com variáveis de função em uma ação.

Quase qualquer outra variável substituirá as variáveis padrão de uma função: variáveis de inventário, ação vars, role parameters em linha, e assim por diante.

Menos variáveis podem substituir variáveis definidas no diretório vars de uma função. Fatos, variáveis carregadas com include_vars, variáveis registradas e parâmetros de função são algumas variáveis que podem fazer isso. As variáveis de inventário e vars de ação não podem. Isso é importante porque ajuda a evitar que sua ação altere acidentalmente o funcionamento interno da função.

No entanto, as variáveis declaradas em linha como parâmetros de função, como o último dos exemplos anteriores, tem precedência muito alta. Elas podem substituir variáveis definidas no diretório vars de uma função. Se um parâmetro de função tiver o mesmo nome que uma variável definida em vars de ação, vars de uma função ou uma variável de inventário ou de playbook, o parâmetro de função substituirá a outra variável. 

Using Roles — Ansible Documentation

Using Variables — Ansible Documentation

britho commented 3 years ago

Neste exercício, você criará uma função do Ansible que usa variáveis, arquivos, templates, tarefas e manipuladores para implantar um serviço de rede.

Resultados

Você deverá ser capaz de criar uma função que usa variáveis e parâmetros.

A função myvhost instala e configura o serviço Apache em um host. É fornecido um template chamado vhost.conf.j2 que será usado para gerar /etc/httpd/conf.d/vhost.conf.

Faça login na workstation como student usando a senha student.

Na workstation, execute o comando lab role-create start. Isso cria o diretório de trabalho, /home/student/role-create, e o preenche com um arquivo de configuração e um inventário de host do Ansible.

[student@workstation ~]$ lab role-create start

Mude para o diretório de trabalho /home/student/role-create.

[student@workstation ~]$ cd ~/role-create
[student@workstation role-create]$ 

Crie a estrutura de diretórios para uma função chamada myvhost. A função inclui arquivos, modelos, tarefas e manipuladores fixos.

[student@workstation role-create]$ mkdir -v roles; cd roles
mkdir: created directory 'roles'
[student@workstation roles]$ ansible-galaxy init myvhost
- myvhost was created successfully
[student@workstation roles]$ rm -rvf myvhost/{defaults,vars,tests}
removed 'myvhost/defaults/main.yml'
removed directory: 'myvhost/defaults'
removed 'myvhost/vars/main.yml'
removed directory: 'myvhost/vars'
removed 'myvhost/tests/inventory'
removed 'myvhost/tests/test.yml'
removed directory: 'myvhost/tests'
[student@workstation roles]$ cd ..
[student@workstation role-create]$ 

Edite o arquivo main.yml no subdiretório tasks da função. A função deverá realizar as seguintes tarefas:

    O pacote httpd é instalado

    O serviço httpd foi iniciado e está habilitado.

    O arquivo de configuração do servidor web é instalado, usando um template fornecido pela função 

    Edite o arquivo roles/myvhost/tasks/main.yml. Inclua código para usar o módulo yum a fim de instalar o pacote httpd. O conteúdo do arquivo deve parecer-se com o seguinte:

    ---
    # tasks file for myvhost

    - name: Ensure httpd is installed
      yum:
        name: httpd
        state: latest

    Inclua um código adicional ao arquivo roles/myvhost/tasks/main.yml para usar o módulo service a fim de iniciar e habilitar o serviço httpd.

    - name: Ensure httpd is started and enabled
      service:
        name: httpd
        state: started
        enabled: true

    Adicione outra estrofe para usar o módulo template a fim criar /etc/httpd/conf.d/vhost.conf no host gerenciado. Ela deverá chamar um manipulador para reiniciar o daemon httpd quando o arquivo estiver atualizado.

    - name: vhost file is installed
      template:
        src: vhost.conf.j2
        dest: /etc/httpd/conf.d/vhost.conf
        owner: root
        group: root
        mode: 0644
      notify:
        - restart httpd

    Salve suas alterações e saia do arquivo roles/myvhost/tasks/main.yml. 

Crie o manipulador para reiniciar o serviço httpd. Edite o arquivo roles/myvhost/handlers/main.yml e inclua o código a para usar o módulo service. Salve e saia. O conteúdo do arquivo deve ter a seguinte aparência:

---
# handlers file for myvhost

- name: restart httpd
  service:
    name: httpd
    state: restarted

Mova o template vhost.conf.j2 do diretório do projeto para o subdiretório templates da função.

[student@workstation role-create]$ mv -v vhost.conf.j2 roles/myvhost/templates/
renamed 'vhost.conf.j2' -> 'roles/myvhost/templates/vhost.conf.j2'

Crie o conteúdo HTML a ser fornecido pelo servidor web.

    Crie o diretório files/html/ para armazenar o conteúdo.

    [student@workstation role-create]$ mkdir -pv files/html
    mkdir: created directory 'files/html'

    Crie um arquivo index.html abaixo desse diretório com o conteúdo: simple index.

    [student@workstation role-create]$ echo \
    > 'simple index' > files/html/index.html

Teste a função myvhost para verificar se ela funciona corretamente.

    Escreva um playbook que use a função use-vhost-role.yml. Inclua uma tarefa para copiar o conteúdo HTML de files/html/ . Use o módulo copy e inclua uma barra à direita após o nome do diretório de origem. Ele deverá ter o seguinte conteúdo:

    ---
    - name: Use myvhost role playbook
      hosts: webservers
      pre_tasks:
        - name: pre_tasks message
          debug:
            msg: 'Ensure web server configuration.'

      roles:
        - myvhost

      post_tasks:
        - name: HTML content is installed
          copy:
            src: files/html/
            dest: "/var/www/vhosts/{{ ansible_hostname }}"

        - name: post_tasks message
          debug:
            msg: 'Web server is configured.'

    Antes de executar o playbook, verifique se a sintaxe está correta executando ansible-playbook com --syntax-check. Se ela relatar algum erro, corrija-o antes de ir para a próxima etapa. Você verá uma saída semelhante à seguinte:

    [student@workstation role-create]$ ansible-playbook use-vhost-role.yml \
    > --syntax-check

    playbook: use-vhost-role.yml

    Execute o playbook. Revise a saída para confirmar que o Ansible realizou as ações no servidor web, servera.

    [student@workstation role-create]$ ansible-playbook use-vhost-role.yml

    PLAY [Use myvhost role playbook] *********************************************

    TASK [Gathering Facts] *******************************************************
    ok: [servera.lab.example.com]

    TASK [pre_tasks message] *****************************************************
    ok: [servera.lab.example.com] => {
        "msg": "Ensure web server configuration."
    }

    TASK [myvhost : Ensure httpd is installed] ***********************************
    changed: [servera.lab.example.com]

    TASK [myvhost : Ensure httpd is started and enabled] *************************
    changed: [servera.lab.example.com]

    TASK [myvhost : vhost file is installed] *************************************
    changed: [servera.lab.example.com]

    RUNNING HANDLER [myvhost : restart httpd] ************************************
    changed: [servera.lab.example.com]

    TASK [HTML content is installed] ***********************************
    changed: [servera.lab.example.com]

    TASK [post_tasks message] ****************************************************
    ok: [servera.lab.example.com] => {
        "msg": "Web server is configured."
    }

    PLAY RECAP *******************************************************************
    servera.lab.example.com    : ok=8    changed=5    unreachable=0    failed=0

    Execute comandos ad hoc para confirmar que a função teve o desempenho esperado. O pacote httpd deve estar instalado, e o serviço httpd deve estar em execução.

    [student@workstation role-create]$ ansible webservers -a \
    > 'systemctl is-active httpd'
    servera.lab.example.com | CHANGED | rc=0 >>
    active

    [student@workstation role-create]$ ansible webservers -a \
    > 'systemctl is-enabled httpd'
    servera.lab.example.com | CHANGED | rc=0 >>
    enabled

    A configuração do Apache deve estar instalada com as variáveis do modelo expandidas.

    [student@workstation role-create]$ ansible webservers -a \
    > 'cat /etc/httpd/conf.d/vhost.conf'
    servera.lab.example.com | CHANGED | rc=0 >>
    # Ansible managed:

    <VirtualHost *:80>
        ServerAdmin webmaster@servera.lab.example.com
        ServerName servera.lab.example.com
        ErrorLog logs/servera-error.log
        CustomLog logs/servera-common.log common
        DocumentRoot /var/www/vhosts/servera/

        <Directory /var/www/vhosts/servera/>
            Options +Indexes +FollowSymlinks +Includes
            Order allow,deny
            Allow from all
        </Directory>
    </VirtualHost>

    O conteúdo em HTML deve ser encontrado em um diretório chamado /var/www/vhosts/servera. O arquivo index.html deve conter a string simple index.

    [student@workstation role-create]$ ansible webservers -a \
    > 'cat /var/www/vhosts/servera/index.html'
    servera.lab.example.com | CHANGED | rc=0 >>
    simple index

    Use o módulo uri em um comando ad hoc para verificar se o conteúdo da web está disponível localmente. Defina o parâmetro return_content como true para que o conteúdo da resposta do servidor seja adicionado à saída. O conteúdo do servidor deve ser a string "simple index\n".

    [student@workstation role-create]$ ansible webservers -m uri \
    > -a 'url=http://localhost return_content=true'
    servera.lab.example.com | SUCCESS => {
        "accept_ranges": "bytes",
        "changed": false,
        "connection": "close",
        "content": "simple index\n",
    ...output omitted...
        "status": 200,
        "url": "http://localhost"
    }

    Confirme se o conteúdo do servidor web está disponível para clientes remotos.

    [student@workstation role-create]$ curl http://servera.lab.example.com
    simple index

Encerramento

Execute o comando lab role-create finish para limpar o host gerenciado.

[student@workstation ~]$ lab role-create finish

Isso conclui o exercício orientado.

britho commented 3 years ago

Objetivos

Depois de concluir esta seção, você deverá ser capaz de selecionar e recuperar funções do Ansible Galaxy ou de outras fontes, como um repositório Git, e usá-las em playbooks.

Introdução ao Ansible Galaxy

O Ansible Galaxy é uma biblioteca pública de conteúdo do Ansible escrito por diversos administradores e usuários do Ansible. Contém milhares de funções do Ansible e um banco de dados pesquisável que ajuda os usuários do Ansible a identificar funções que podem ajudá-los a realizar uma tarefa administrativa. O Ansible Galaxy inclui links para documentos e vídeos de novos usuários e desenvolvedores de funções do Ansible.

  --
8.1: Página inicial do Ansible Galaxy

Além disso, o comando ansible-galaxy que você usa para obter e gerenciar funções do Ansible Galaxy também pode ser usado para obter e gerenciar funções que seus projetos precisam a partir dos seus próprios repositórios Git.

Ajuda com o Ansible Galaxy

A guia Documentation na página inicial do site do Ansible Galaxy leva a uma página que descreve como se usa o Ansible Galaxy. Há conteúdo sobre como baixar as funções do Ansible Galaxy e como usá-las. As instruções de como desenvolver funções e fazer upload delas para o Ansible Galaxy também estão nessa página.

Navegação de funções no Ansible Galaxy

A guia Search na lateral esquerda do site do Ansible Galaxy dá aos usuários acesso às informações sobre as funções publicadas no Ansible Galaxy. Você pode pesquisar por uma função do Ansible pelo nome, usando tags ou por outros atributos. Os resultados são apresentados em ordem decrescente de Melhor correspondência, que é uma pontuação calculada com base na qualidade da função, na popularidade da função e nos critérios de pesquisa.

Content Scoring na documentação tem mais informações sobre como funcionam as pontuações das funções de acordo com o Ansible Galaxy.

  --
8.2: Tela de pesquisa do Ansible Galaxy

O Ansible Galaxy reporta o número de vezes que cada função foi baixada do Ansible Galaxy. Além disso, o Ansible Galaxy também relata o número de observadores, forks e estrelas que o repositório GitHub da função tem. Os usuários podem usar essas informações para ajudar a determinar como o desenvolvimento ativo é para uma função e o quão popular ela é na comunidade.

A figura a seguir mostra os resultados de pesquisa que o Ansible Galaxy exibe após uma pesquisa pela palavra-chave redis foi realizada. Observe que o primeiro resultado tem uma Melhor correspondência de 0.9009.

  --
8.3: Exemplo de resultados de pesquisa do Ansible Galaxy

O menu suspenso Filters à direita da caixa de pesquisa permite que sejam realizadas pesquisas em palavras-chave, IDs de autores, plataforma e tags. Os possíveis valores da plataforma incluem EL para RedHat EnterpriseLinux (e distribuições estreitamente relacionadas, como o CentOS) e Fedora, entre outros.

As tags são strings arbitrárias de uma única palavra definidas pelo autor da função que descrevem e categorizam a função. Os usuários podem usar tags para encontrar funções relevantes. Os possíveis valores de tag incluem system, development, web, monitoring e outros. Uma função pode ter até 20 tags no Ansible Galaxy.

Na interface de pesquisa do Ansible Galaxy, as pesquisas por palavra-chave combinam palavras ou frases no arquivo README, no nome do conteúdo ou na descrição do conteúdo. As pesquisas por tags, por outro lado, correspondem especificamente aos valores da tag definidos pelo autor para a função.

A ferramenta de linha de comando do Ansible Galaxy

A ferramenta de linha de comando ansible-galaxy pode ser usada para pesquisar, instalar, listar, remover, inicializar ou exibir informações sobre funções.

Busca por funções da linha de comando

O subcomando ansible-galaxy search pesquisa funções no Ansible Galaxy. Se você especificar uma string como um argumento, ela será usada para pesquisar funções por palavra-chave no Ansible Galaxy. Você pode usar as opções --author, --platforms e --galaxy-tags para refinar os resultados de pesquisa. Você também pode usar essas opções como chave de pesquisa principal. Por exemplo, o comando ansible-galaxy search --author geerlingguy exibirá todas as funções enviadas pelo usuário geerlingguy.

Os resultados são exibidos em ordem alfabética, não por pontuação decrescente de Melhor correspondência. O exemplo a seguir exibe os nomes das funções que incluem redis e estão disponíveis para a plataforma Enterprise Linux (EL).

[user@host ~]$ ansible-galaxy search 'redis' --platforms EL
Found 124 roles matching your search:
 Name                                  Description
 ----                                  -----------
 1it.sudo                              Ansible role for managing sudoers
 AerisCloud.librato                    Install and configure the Librato Agent
 AerisCloud.redis                      Installs redis on a server
 AlbanAndrieu.java                     Manage Java installation
 andrewrothstein.redis                 builds Redis from src and installs
...output omitted...
 geerlingguy.php-redis                 PhpRedis support for Linux
 geerlingguy.redis                     Redis for Linux
 gikoluo.filebeat                      Filebeat for Linux.
...output omitted...

O subcomando ansible-galaxy info exibe informações mais detalhadas sobre uma função. O Ansible Galaxy obtém essa informação a partir de vários lugares, incluindo a função do arquivo meta/main.yml e seu repositório GitHub. O comando a seguir exibe informações sobre a função geerlingguy.redis, disponível no Ansible Galaxy.

[user@host ~]$ ansible-galaxy info geerlingguy.redis
Role: geerlingguy.redis
        description: Redis for Linux
        active: True
...output omitted...
        download_count: 146209
        forks_count: 82
        github_branch: master
        github_repo: ansible-role-redis
        github_user: geerlingguy
...output omitted...
        license: license (BSD, MIT)
        min_ansible_version: 2.4
        modified: 2018-11-19T14:53:29.722718Z
        open_issues_count: 11
        path: [u'/etc/ansible/roles', u'/usr/share/ansible/roles']
        role_type: ANS
        stargazers_count: 98
...output omitted...

Instalação de funções do Ansible Galaxy

O subcomando ansible-galaxy install faz download de uma função do Ansible Galaxy e faz sua instalação localmente no nó de controle.

Por padrão, as funções são instaladas no primeiro diretório que é gravável no roles_path do usuário. Baseado no padrão roles_path definido para o Ansible, normalmente a função será instalada no diretório ~/.ansible/roles. O padrão roles_path pode ser substituído por seu arquivo de configuração atual do Ansible ou pela variável de ambiente ANSIBLE_ROLES_PATH, que afeta o comportamento de ansible-galaxy.

Você também pode especificar um diretório específico no qual instalar a função usando a opção -p DIRECTORY.

No exemplo a seguir, ansible-galaxy instala a função geerlingguy.redis no diretório roles de um projeto de playbook. O diretório de trabalho atual do comando é /opt/project.

[user@host project]$ ansible-galaxy install geerlingguy.redis -p roles/
- downloading role 'redis', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/...output omitted...
- extracting geerlingguy.redis to /opt/project/roles/geerlingguy.redis
- geerlingguy.redis (1.6.0) was installed successfully
[user@host project]$ ls roles/
geerlingguy.redis

Instalação de funções usando um arquivo de requisitos

Você também pode usar ansible-galaxy para instalar uma lista de funções com base em definições em um arquivo de texto. Por exemplo, se você tiver um playbook que precisa ter funções específicas instaladas, poderá criar um arquivoroles/requirements.yml no diretório do projeto que especifica quais funções são necessárias. Esse arquivo funciona como um manifesto de dependência para o projeto do playbook, que permite que os playbooks sejam desenvolvidos e testados separadamente de qualquer função de suporte.

Por exemplo, um simples requirements.yml para instalar geerlingguy.redis pode ser assim:

- src: geerlingguy.redis
  version: "1.5.0"

O atributo src especifica a origem da função, nesse caso, a função geerlingguy.redis do Ansible Galaxy. O atributo version é opcional e especifica a versão da função a ser instalada, nesse caso, a 1.5.0.

Você deve especificar a versão da função em seu arquivo requirements.yml, especialmente para playbooks em produção.

Se você não especificar uma versão, receberá a versão mais recente da função. Se o autor do upstream fizer alterações na função que são sejam incompatíveis com seu playbook, isso pode causar uma falha de automação ou outros problemas.

Para instalar as funções usando um arquivo de função, use a opção -r REQUIREMENTS-FILE:

[user@host project]$ ansible-galaxy install -r roles/requirements.yml \
> -p roles 
- downloading role 'redis', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-redis/archive/1.6.0.tar.gz
- extracting geerlingguy.redis to /opt/project/roles/geerlingguy.redis
- geerlingguy.redis (1.6.0) was installed successfully

Você pode usar ansible-galaxy para instalar funções que não estão no Ansible Galaxy. Você pode hospedar suas próprias funções proprietárias ou internas em um repositório Git privado ou em um servidor web. O exemplo a seguir mostra como configurar um arquivo de requisitos usando várias fontes remotas.

[user@host project]$ cat roles/requirements.yml
# from Ansible Galaxy, using the latest version
- src: geerlingguy.redis
# from Ansible Galaxy, overriding the name and using a specific version
- src: geerlingguy.redis
  version: "1.5.0"
  name: redis_prod
# from any Git-based repository, using HTTPS
- src: https://gitlab.com/guardianproject-ops/ansible-nginx-acme.git
  scm: git
  version: 56e00a54
  name: nginx-acme
# from any Git-based repository, using SSH
- src: git@gitlab.com:guardianproject-ops/ansible-nginx-acme.git
  scm: git
  version: master
  name: nginx-acme-ssh
# from a role tar ball, given a URL;
#   supports 'http', 'https', or 'file' protocols
- src: file:///opt/local/roles/myrole.tar
  name: myrole

A palavra-chave src especifica o nome da função do Ansible Galaxy. Se a função não estiver hospedada no Ansible Galaxy, a palavra-chave src indica o URL da função.

Se a função estiver hospedada em um repositório de controle de fonte, o atributo scm é obrigatório. O comando ansible-galaxy é capaz de baixar e instalar funções de repositórios de software baseados em Git ou Mercurial. Um repositório baseado em Git exige um valor scm de git, enquanto uma função hospedada em um repositório Mercurial exige um valor hg. Se a função estiver hospedada no Ansible Galaxy ou como um arquivo TAR em um servidor web, a palavra-chave scm é omitida.

A palavra-chave name é usada para substituir o nome local da função. A palavra-chave version é usada para especificar a versão de uma função. A palavra-chave version pode ser qualquer valor que corresponda a um branch, tag ou commit hash do repositório de software da função.

Para instalar as funções associadas a um projeto de playbook, execute o comando ansible-galaxy install:

[user@host project]$ ansible-galaxy install -r roles/requirements.yml \
> -p roles 
- downloading role 'redis', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-redis/archive/1.6.0.tar.gz
- extracting geerlingguy.redis to /opt/project/roles/geerlingguy.redis
- geerlingguy.redis (1.6.0) was installed successfully
- downloading role 'redis', owned by geerlingguy
- downloading role from https://github.com/geerlingguy/ansible-role-redis/archive/1.5.0.tar.gz
- extracting redis_prod to /opt/project/roles/redis_prod
- redis_prod (1.5.0) was installed successfully
- extracting nginx-acme to /opt/project/roles/nginx-acme
- nginx-acme (56e00a54) was installed successfully
- extracting nginx-acme-ssh to /opt/project/roles/nginx-acme-ssh
- nginx-acme-ssh (master) was installed successfully
- downloading role from file:///opt/local/roles/myrole.tar
- extracting myrole to /opt/project/roles/myrole
- myrole was installed successfully

Gerenciamento de funções baixadas

O comando ansible-galaxy também pode gerenciar funções locais, como as funções encontradas no diretório roles de um projeto de playbook. O subcomando ansible-galaxy list lista as funções que são encontradas localmente.

[user@host project]$ ansible-galaxy list
- geerlingguy.redis, 1.6.0
- myrole, (unknown version)
- nginx-acme, 56e00a54
- nginx-acme-ssh, master
- redis_prod, 1.5.0

Uma função pode ser removida localmente com o subcomando ansible-galaxy remove.

[user@host ~]$ ansible-galaxy remove nginx-acme-ssh
- successfully removed nginx-acme-ssh
[user@host ~]$ ansible-galaxy list
- geerlingguy.redis, 1.6.0
- myrole, (unknown version)
- nginx-acme, 56e00a54
- redis_prod, 1.5.0

Use as funções transferidas e instaladas a em playbooks como qualquer outra função. Elas são referenciadas na seção roles usando seu nome de função transferido. Se uma função não estiver no diretório roles do projeto, roles_path será verificado para ver se a função está instalada em um desses diretórios, sendo usada a primeira correspondência. O playbook use-role.yml a seguir faz referência às funções redis_prod e geerlingguy.redis.

[user@host project]$ cat use-role.yml
---
- name: use redis_prod for Prod machines
  hosts: redis_prod_servers
  remote_user: devops
  become: true
  roles:
    - redis_prod
- name: use geerlingguy.redis for Dev machines
  hosts: redis_dev_servers
  remote_user: devops
  become: true
  roles:
    - geerlingguy.redis

Este playbook faz com que diferentes versões da função geerlingguy.redis sejam aplicadas aos servidores de produção e desenvolvimento. Dessa maneira, alterações na função podem ser sistematicamente testadas e integradas antes da implantação nos servidores de produção. Se uma alteração recente em uma função causar problemas, o uso do controle de versão para desenvolver a função permitirá reverter para uma versão anterior e estável da função.

britho commented 3 years ago

Neste exercício, você usará o Ansible Galaxy para baixar uma função do Ansible e instalá-la.

Resultados

Você deverá ser capaz de:

criar um arquivo de funções para especificar dependências de função para um playbook

instalar funções especificadas em um arquivo de funções

listar funções usando o comando ansible-galaxy 

Visão geral do cenário

Sua organização coloca arquivos personalizados no diretório /etc/skel em todos os hosts. Como resultado, novas contas de usuário são configuradas com um ambiente de bash específico da organização.

Você testará a versão de desenvolvimento da função do Ansible responsável por implantar os arquivos de esqueleto do ambiente de bash.

Faça login na workstation como student usando a senha student.

Na workstation, execute o comando lab role-galaxy start. Isso cria o diretório de trabalho, /home/student/role-galaxy, e o preenche com um arquivo de configuração e um inventário de host do Ansible.

[student@workstation ~]$ lab role-galaxy start

Mude para o diretório de trabalho role-galaxy.

[student@workstation ~]$ cd ~/role-galaxy
[student@workstation role-galaxy]$ 

Para testar a função do Ansible que configura os arquivos de esqueleto, adicione a especificação de função a um arquivo de funções.

Inicie seu editor de texto favorito e crie um arquivo chamado requirements.yml no subdiretório roles. O URL do repositório Git da função é: git@workstation. lab.example.com:student/bash_env. Para ver como a função afeta o comportamento dos hosts de produção, use o branch master do repositório. Defina o nome local da função como student. bash_env.

roles/requirements.yml agora tem o seguinte conteúdo:

---
# requirements.yml

- src: git@workstation.lab.example.com:student/bash_env
  scm: git
  version: master
  name: student.bash_env

Use o comando ansible-galaxy para processar o arquivo de funções que você criou e instale a função student.bash_env.

    Para comparar, exiba o conteúdo do subdiretório roles antes da instalação da função.

    [student@workstation role-galaxy]$ ls roles/
    requirements.yml

    Use o Ansible Galaxy para baixar e instalar as funções listada no arquivo roles/requirements.yml. Certifique-se de que todas as funções baixadas sejam armazenadas no subdiretório roles.

    [student@workstation role-galaxy]$ ansible-galaxy install -r \
    > roles/requirements.yml -p roles
    - extracting student.bash_env to /home/student/role-galaxy/roles/student.bash_env
    - student.bash_env (master) was installed successfully

    Exiba o subdiretório roles após instalar a função. Confirme se ele tem um novo subdiretório, chamado student.bash_env, que corresponda ao valor name especificado no arquivo YAML.

    [student@workstation role-galaxy]$ ls roles/
    requirements.yml  student.bash_env

    Tente usar o comando ansible-galaxy, sem opções, para listar as funções do projeto:

    [student@workstation role-galaxy]$ ansible-galaxy list
    # /usr/share/ansible/roles
    - linux-system-roles.kdump, (unknown version)
    - linux-system-roles.network, (unknown version)
    - linux-system-roles.postfix, (unknown version)
    - linux-system-roles.selinux, (unknown version)
    - linux-system-roles.timesync, (unknown version)
    - rhel-system-roles.kdump, (unknown version)
    - rhel-system-roles.network, (unknown version)
    - rhel-system-roles.postfix, (unknown version)
    - rhel-system-roles.selinux, (unknown version)
    - rhel-system-roles.timesync, (unknown version)
    # /etc/ansible/roles
     [WARNING]: - the configured path /home/student/.ansible/roles does not exist.

    Como você usou a opção -p com o comando ansible-galaxy install, a função student.bash_env não foi instalada no local padrão. Use a opção -p com o comando ansible-galaxy list para listar as funções baixadas:

    [student@workstation role-galaxy]$ ansible-galaxy list -p roles
    # /home/student/role-galaxy/roles
    - student.bash_env, master
    ...output omitted...
    [WARNING]: - the configured path /home/student/.ansible/roles does not exist.

    O diretório /home/student/.ansible/roles está no seu roles_path padrão, mas como você não tentou instalar uma função sem usar a opção -p, ansible-galaxy ainda não criou o diretório. 

Crie um playbook, chamado use-bash_env-role.yml, que use a função student.bash_env. O conteúdo do playbook deve corresponder ao seguinte:

---
- name: use student.bash_env role playbook
  hosts: devservers
  vars:
    default_prompt: '[\u on \h in \W dir]\$ '
  pre_tasks:
    - name: Ensure test user does not exist
      user:
        name: student2
        state: absent
        force: yes
        remove: yes

  roles:
    - student.bash_env

  post_tasks:
    - name: Create the test user
      user:
        name: student2
        state: present
        password: "{{ 'redhat' | password_hash('sha512', 'mysecretsalt') }}"

Para ver os efeitos da alteração de configuração, uma nova conta de usuário deve ser criada. As seções pre_tasks e post_tasks do playbook garantem que a conta de usuário student2 seja criada sempre que o playbook for executado. Após a execução do playbook, a conta student2 é acessada com a senha redhat.

A senha user2 é gerada usando um filtro. Filtros obtêm dados e os modificam; aqui, a string redhat é modificada ao passá-la para o módulo password_hash. Filtros são um tópico avançado não abordado neste curso.

Execute o playbook. A função student.bash_env cria arquivos de configuração padrão em /etc/skel no host gerenciado. Os arquivos criados incluem .bashrc, .bash_profile e .vimrc.

[student@workstation role-galaxy]$ ansible-playbook use-bash_env-role.yml

PLAY [use student.bash_env role playbook] ************************************

TASK [Gathering Facts] *******************************************************
ok: [servera.lab.example.com]

TASK [Ensure test user does not exist] ***************************************
ok: [servera.lab.example.com]

TASK [student.bash_env : put away .bashrc] ***********************************
changed: [servera.lab.example.com]

TASK [student.bash_env : put away .bash_profile] *****************************
ok: [servera.lab.example.com]

TASK [student.bash_env : put away .vimrc] ************************************
changed: [servera.lab.example.com]

TASK [Create the test user] **************************************************
changed: [servera.lab.example.com]

PLAY RECAP *******************************************************************
servera.lab.example.com    : ok=6    changed=4    unreachable=0    failed=0

Conecte-se a servera como usuário student2 usando SSH. Observe o prompt personalizado para o usuário student2 e, em seguida, desconecte-se de servera.

[student@workstation role-galaxy]$ ssh student2@servera
Activate the web console with: systemctl enable --now cockpit.socket

[student2 on servera in ~ dir]$ exit
logout
Connection to servera closed.
[student@workstation role-galaxy]$ 

Execute o playbook usando a versão de desenvolvimento da função student.bash_env.

A versão de desenvolvimento da função está localizada no branch dev do repositório Git. A versão de desenvolvimento da função usa uma nova variável, prompt_color. Antes de executar o playbook, adicione a variável prompt_color à seção vars do playbook e defina seu valor como azul.

    Atualize o arquivo roles/requirements.yml e defina o valor version como dev. O arquivo roles/requirements.yml agora contém:

    ---
    # requirements.yml

    - src: git@workstation.lab.example.com:student/bash_env
      scm: git
      version: dev
      name: student.bash_env

    Use o comando ansible-galaxy install para instalar a função usando o arquivo de funções atualizado. Use a opção --force para substituir a versão existente do master da função pela versão dev da função.

    [student@workstation role-galaxy]$ ansible-galaxy install \
    > -r roles/requirements.yml --force -p roles
    - changing role student.bash_env from master to dev
    - extracting student.bash_env to /home/student/role-galaxy/roles/student.bash_env
    - student.bash_env (dev) was installed successfully

    Edite o arquivo use-bash_env-role.yml. Adicione a variável prompt_color com o valor blue para a seção vars do playbook. O arquivo agora contém:

    ---
    - name: use student.bash_env role playbook
      hosts: devservers
      vars:
        prompt_color: blue
        default_prompt: '[\u on \h in \W dir]\$ '
      pre_tasks:
    ...output omitted...

    Execute o playbook use-bash_env-role.yml.

    [student@workstation role-galaxy]$ ansible-playbook use-bash_env-role.yml

    PLAY [use student.bash_env role playbook] ************************************

    TASK [Gathering Facts] *******************************************************
    ok: [servera.lab.example.com]

    TASK [Ensure test user does not exist] ***************************************
    changed: [servera.lab.example.com]

    TASK [student.bash_env : put away .bashrc] ***********************************
    changed: [servera.lab.example.com]

    TASK [student.bash_env : put away .bash_profile] *****************************
    changed: [servera.lab.example.com]

    TASK [student.bash_env : put away .vimrc] ************************************
    okay: [servera.lab.example.com]

    TASK [Create the test user] **************************************************
    changed: [servera.lab.example.com]

    PLAY RECAP *******************************************************************
    servera.lab.example.com    : ok=6    changed=4    unreachable=0    failed=0

Conecte-se novamente a servera como student2 usando SSH. Observe o erro para o usuário student2 e, em seguida, desconecte-se de servera.

[student@workstation role-galaxy]$ ssh student2@servera
Activate the web console with: systemctl enable --now cockpit.socket

-bash: [: missing `]'
[student2@servera ~]$ exit
logout
Connection to servera closed.
[student@workstation role-galaxy]$ 

Ocorreu um erro de bash durante a análise do arquivo .bash_profile do usuário student2.

Corrija o erro na versão de desenvolvimento da função student.bash_env e execute o playbook novamente.

    Edite o arquivo roles/student.bash_env/templates/_bash_profile.j2. Adicione o caractere ] ausente à linha 4 e salve o arquivo. A parte superior do arquivo agora é:

    # .bash_profile

    # Get the aliases and functions
    if [ -f ~/.bashrc ]; then
            . ~/.bashrc
    fi

    # User specific environment and startup programs

    PATH=$PATH:$HOME/.local/bin:$HOME/bin

    export PATH

    Salve o arquivo.

    Execute o playbook use-bash_env-role.yml.

    [student@workstation role-galaxy]$ ansible-playbook use-bash_env-role.yml

    PLAY [use student.bash_env role playbook] ************************************

    TASK [Gathering Facts] *******************************************************
    ok: [servera.lab.example.com]

    TASK [Ensure test user does not exist] ***************************************
    changed: [servera.lab.example.com]

    TASK [student.bash_env : put away .bashrc] ***********************************
    ok: [servera.lab.example.com]

    TASK [student.bash_env : put away .bash_profile] *****************************
    changed: [servera.lab.example.com]

    TASK [student.bash_env : put away .vimrc] ************************************
    ok: [servera.lab.example.com]

    TASK [Create the test user] **************************************************
    changed: [servera.lab.example.com]

    PLAY RECAP *******************************************************************
    servera.lab.example.com    : ok=6    changed=3    unreachable=0    failed=0

    Conecte-se novamente a servera como student2 usando SSH.

    [student@workstation role-galaxy]$ ssh student2@servera
    Activate the web console with: systemctl enable --now cockpit.socket

    [student2 on servera in ~ dir]$ exit
    logout
    Connection to servera closed.
    [student@workstation role-galaxy]$ 

    A mensagem de erro não está mais presente. O prompt personalizado para o usuário student2 agora é exibido com caracteres azuis. 

As etapas acima demonstram que a versão de desenvolvimento da função student.bash_env está com defeito. Com base nos resultados dos testes, os desenvolvedores confirmarão as correções necessárias no branch de desenvolvimento da função. Quando o branch de desenvolvimento passa pelas verificações de qualidade exigidas, os desenvolvedores mesclam os recursos do branch de desenvolvimento com o branch master.

Confirmar as mudanças de função em um repositório Git está além do escopo deste curso.

Ao controlar a versão mais recente de uma função em um projeto, reinstale periodicamente a função para atualizá-la. Isso garante que a cópia local permaneça atualizada com correções de bugs, patches e outros recursos.

Entretanto, se você estiver usando uma função de terceiros na produção, especifique a versão a ser usada para evitar interrupções devido a alterações inesperadas. Atualize periodicamente para a versão mais recente da função em seu ambiente de teste a fim de adotar melhorias e alterações de maneira controlada.

Encerramento

Execute o comando lab role-galaxy finish para limpar o host gerenciado.

[student@workstation ~]$ lab role-galaxy finish

Isso conclui o exercício orientado.

britho commented 3 years ago

Lista de verificação de desempenho

Neste laboratório, você criará funções do Ansible que usam variáveis, arquivos, modelos, tarefas e manipuladores.

Resultados

Você deverá ser capaz de:

Criar funções do Ansible que usam variáveis, arquivos, modelos, tarefas e manipuladores para configurar um servidor web de desenvolvimento.

Usar uma função hospedada em um repositório remoto em um playbook.

Usar um RedHat EnterpriseLinux em um playbook. 

Visão geral do cenário

Sua organização deve fornecer um único servidor web para hospedar o código de desenvolvimento para todos os desenvolvedores da web. Você está encarregado de escrever um playbook para configurar esse servidor web de desenvolvimento.

O servidor web de desenvolvimento deve atender a vários requisitos:

A configuração do servidor de desenvolvimento corresponde à configuração do servidor de produção. O servidor de produção é configurado usando uma função do Ansible, desenvolvida pela equipe de infraestrutura da organização.

Cada desenvolvedor recebe um diretório no servidor de desenvolvimento para hospedar código e conteúdo. O conteúdo de cada desenvolvedor é acessado usando uma porta designada e não padrão.

O SELinux é configurado para ser de imposição e direcionado. 

Seu playbook irá:

Usar uma função para configurar diretórios e portas para cada desenvolvedor no servidor web. Você deve gravar essa função.

Essa função depende de uma função gravada pela organização para configurar o Apache. Você deve definir a dependência usando a versão v1.4 da função organizacional. O URL do repositório de dependência é: git@workstation.lab.example.com:infra/apache

Use a função rhel-system-roles.selinux para configurar o SELinux para as portas HTTP não padrão usadas pelo seu servidor web. Você receberá um arquivo de variável selinux.yml que pode ser instalado como um arquivo group_vars para transmitir as configurações corretas para a função. 

Faça login na workstation como student usando a senha student.

Na workstation, execute o comando lab role-review start. O script cria o diretório de trabalho, /home/student/role-review, e o preenche com um arquivo de configuração e inventário de host do Ansible e outros arquivos do laboratório.

[student@workstation ~]$ lab role-review start

Mude para o diretório de trabalho /home/student/role-review.

[student@workstation ~]$ cd ~/role-review
[student@workstation role-review]$ 

Crie um playbook chamado web_dev_server.yml com uma única ação chamada Configure Dev Web Server. Configure a ação para ter como destino o grupo de hosts dev_webserver. Ainda não adicione funções ou tarefas à ação.

Certifique-se de que a ação força os manipuladores à execução, porque você pode encontrar um erro ao desenvolver o playbook.

Depois de concluído, o playbook /home/student/role-review/web_dev_server.yml conterá:


Verifique a sintaxe do playbook. Execute o playbook. A verificação de sintaxe deve ser transmitida e o playbook deve ser executado com sucesso.

[student@workstation role-review]$ ansible-playbook \

--syntax-check web_dev_server.yml

playbook: web_dev_server.yml [student@workstation role-review]$ ansible-playbook web_dev_server.yml PLAY [Configure Dev Web Server] **

TASK [Gathering Facts] *** ok: [servera.lab.example.com]

PLAY RECAP *** servera.lab.example.com : ok=1 changed=0 unreachable=0 failed=0

Certifique-se de que as dependências de função do playbook estejam instaladas.

A função apache.developer_configs que você criará depende da função infra.apache. Crie um arquivo roles/requirements.yml. Ele deve instalar a função do repositório Git em git@workstation.lab.example.com:infra/apache; use a versão v1.4 e nomeie-a infra.apache localmente. Você pode supor que suas chaves SSH estão configuradas para poder obter funções desse repositório automaticamente. Instale a função com o comando ansible-galaxy.

Além disso, instale o pacote rhel-system-roles se não estiver presente.

Crie um subdiretório roles para o projeto do playbook.

[student@workstation role-review]$ mkdir -v roles
mkdir: created directory 'roles'

Crie um arquivo roles/requirements.yml e adicione uma entrada para a função infra.apache. Use a versão v1.4 do repositório git da função.

Depois de concluído, o arquivo roles/requirements.yml conterá:

- name: infra.apache
  src: git@workstation.lab.example.com:infra/apache
  scm: git
  version: v1.4

Instale as dependências do projeto.

[student@workstation role-review]$ ansible-galaxy install \
> -r roles/requirements.yml -p roles
- extracting infra.apache to /home/student/role-review/roles/infra.apache
- infra.apache (v1.4) was installed successfully

Instale o pacote de funções do sistema RHEL se não estiver presente. Ele foi instalado durante um exercício anterior.

[student@workstation role-review]$ sudo yum install rhel-system-roles

Inicialize uma nova função chamada apache.developer_configs no subdiretório roles.

Adicione a função infra.apache como uma dependência para a nova função; faça isso usando as mesmas informações para nome, origem, versão e sistema de controle da versão como o arquivo roles/requirements.yml.

O arquivo developer_tasks.yml no diretório do projeto contém tarefas para a função. Mova esse arquivo para o local correto para que seja o arquivo de tarefas dessa função e substitua o arquivo existente no local.

O arquivo developer.conf.j2 no diretório do projeto é um template Jinja2 usado pelo arquivo de tarefas. Mova-o para o local correto para os arquivos de modelo usados por essa função.

Use o ansible-galaxy init para criar um esqueleto de função para a função apache.developer_configs.

[student@workstation role-review]$ cd roles
[student@workstation roles]$ ansible-galaxy init apache.developer_configs
- apache.developer_configs was created successfully
[student@workstation roles]$ cd ..
[student@workstation role-review]$ 

Atualize o arquivo roles/apache.developer_configs/meta/main.yml da função apache.developer_configs para refletir uma dependência da função infra.apache.

Após a edição, a variável dependencies é definida da seguinte forma:

dependencies:
  - name: infra.apache
    src: git@workstation.lab.example.com:infra/apache
    scm: git
    version: v1.4

Substitua o arquivo tasks/main.yml da função pelo arquivo developer_tasks.yml.

[student@workstation role-review]$ mv -v developer_tasks.yml \
> roles/apache.developer_configs/tasks/main.yml
renamed 'developer_tasks.yml' -> 'roles/apache.developer_configs/tasks/main.yml'

Coloque o arquivo developer.conf.j2 no diretório templates da função.

[student@workstation role-review]$ mv -v developer.conf.j2 \
> roles/apache.developer_configs/templates/
renamed 'developer.conf.j2' -> 'roles/apache.developer_configs/templates/developer.conf.j2'

A função apache.developer_configs processará uma lista de usuários definidos em uma variável denominada web_developers. O arquivo web_developers.yml no diretório do projeto define a variável da lista de usuários web_developers. Revise esse arquivo e use-o para definir a variável web_developers para o grupo de hosts do servidor web de desenvolvimento.

Revise o arquivo web_developers.yml.

---
web_developers:
  - username: jdoe
    name: John Doe
    user_port: 9081
  - username: jdoe2
    name: Jane Doe
    user_port: 9082

name, username e user_port são definidos para cada desenvolvedor da web.

Coloque web_developers.yml no subdiretório group_vars/dev_webserver.

[student@workstation role-review]$ mkdir -pv group_vars/dev_webserver
mkdir: created directory 'group_vars'
mkdir: created directory 'group_vars/dev_webserver'
[student@workstation role-review]$ mv -v web_developers.yml \
> group_vars/dev_webserver/
renamed 'web_developers.yml' -> 'group_vars/dev_webserver/web_developers.yml'

Adicione a função apache.developer_configs à ação no playbook web_dev_server.yml.

O playbook editado:


Verifique a sintaxe do playbook. Execute o playbook. A verificação de sintaxe deve ser transmitida, mas o playbook deve apresentar falha quando a função infra.apache tentar reiniciar o Apache HTTPD.

[student@workstation role-review]$ ansible-playbook \

--syntax-check web_dev_server.yml

playbook: web_dev_server.yml [student@workstation role-review]$ ansible-playbook web_dev_server.yml

PLAY [Configure Dev Web Server] **

TASK [Gathering Facts] *** ok: [servera.lab.example.com]

...output omitted...

TASK [infra.apache : Install a skeleton index.html] *** skipping: [servera.lab.example.com]

TASK [apache.developer_configs : Create user accounts] *** changed: [servera.lab.example.com] => (item={u'username': u'jdoe', u'user_port': 9081, u'name': u'John Doe'}) changed: [servera.lab.example.com] => (item={u'username': u'jdoe2', u'user_port': 9082, u'name': u'Jane Doe'})

...output omitted...

RUNNING HANDLER [infra.apache : restart firewalld] *** changed: [servera.lab.example.com]

RUNNING HANDLER [infra.apache : restart apache] ** fatal: [servera.lab.example.com]: FAILED! => {"changed": false, "msg": "Unable to restart service httpd: Job for httpd.service failed because the control process exited with error code. See \"systemctl status httpd.service\" and \"journalctl -xe\" for details.\n"}

NO MORE HOSTS LEFT *** to retry, use: --limit @/home/student/role-review/web_dev_server.retry

PLAY RECAP *** servera.lab.example.com : ok=13 changed=11 unreachable=0 failed=1
skipped=1 rescued=0 ignored=0

Um erro ocorre quando o serviço httpd é reiniciado. O daemon de serviço httpd não pode ser vinculado a portas HTTP não padrão devido ao contexto do SELinux nessas portas.

O HTTPD Apache apresentou falha ao reiniciar a etapa anterior porque as portas de rede que ele usa para seus desenvolvedores estão rotuladas com os contextos SELinux incorretos. Você recebeu um arquivo variável, selinux.yml, que pode ser usado com a função rhel-system-roles.selinux para corrigir o problema.

Crie uma seção pre_tasks para sua ação no playbook web_dev_server.yml. Nessa seção, use uma tarefa para incluir a função rhel-system-roles.selinux em uma estrutura block/rescue para que seja devidamente aplicada. Revise a aula ou a documentação sobre essa função para ver como fazer isso.

Inspecione o arquivo selinux.yml. Mova-o para o local correto para que suas variáveis sejam definidas para o grupo de host dev_webserver.

A seção pre_tasks pode ser adicionada ao final da ação no playbook web_dev_server.yml.

Você pode verificar o bloco em /usr/share/doc/rhel-system-roles-1.0/selinux/example-selinux-playbook.yml para ver uma definição básica de como aplicar a função, mas o RedHat Ansible Engine 2.7 permite substituir o complexo shell e a lógica wait_for pelo módulo reboot.

A seção pre_tasks deve conter:

  pre_tasks:
    - name: Check SELinux configuration
      block:
        - include_role:
            name: rhel-system-roles.selinux
      rescue:
        # Fail if failed for a different reason than selinux_reboot_required.
        - name: Check for general failure
          fail:
            msg: "SELinux role failed."
          when: not selinux_reboot_required

        - name: Restart managed host
          reboot:
            msg: "Ansible rebooting system for updates."

        - name: Reapply SELinux role to complete changes
          include_role:
            name: rhel-system-roles.selinux

O arquivo selinux.yml contém definições de variáveis para a função rhel-system-roles.selinux. Use o arquivo para definir variáveis para o grupo de hosts da ação.

[student@workstation role-review]$ cat selinux.yml
---
# variables used by rhel-system-roles.selinux

selinux_policy: targeted
selinux_state: enforcing

selinux_ports:
  - ports:
      - "9081"
      - "9082"
    proto: 'tcp'
    setype: 'http_port_t'
    state: 'present'

[student@workstation role-review]$ mv -v selinux.yml \
> group_vars/dev_webserver/
renamed 'selinux.yml' -> 'group_vars/dev_webserver/selinux.yml'

Verifique a sintaxe do playbook final. A verificação da sintaxe deve ser transmitida.

Não importa se o pre_tasks está no final da ação ou na posição "correta" em termos de ordem de execução no arquivo do playbook; isso não faz diferença para ansible-playbook. Ele ainda executará as tarefas da ação na ordem correta.

Execute o playbook. Ele deverá ser bem-sucedido.

[student@workstation role-review]$ ansible-playbook web_dev_server.yml

PLAY [Configure Dev Web Server] **

TASK [Gathering Facts] *** ok: [servera.lab.example.com]

TASK [include_role : rhel-system-roles.selinux] **

TASK [rhel-system-roles.selinux : Install SELinux python3 tools] ***** ok: [servera.lab.example.com]

...output omitted...

TASK [infra.apache : Apache Service is started] ** changed: [servera.lab.example.com]

...output omitted...

TASK [apache.developer_configs : Copy Per-Developer Config files] **** ok: [servera.lab.example.com] => (item={u'username': u'jdoe', u'user_port': 9081, u'name': u'John Doe'}) ok: [servera.lab.example.com] => (item={u'username': u'jdoe2', u'user_port': 9082, u'name': u'Jane Doe'})

PLAY RECAP *** servera.lab.example.com : ok=19 changed=3 unreachable=0 failed=0
skipped=14 rescued=0 ignored=0

Teste a configuração do servidor web de desenvolvimento. Verifique se todos os pontos de extremidade estão acessíveis e se atendem ao conteúdo de cada desenvolvedor.

[student@workstation role-review]$ curl servera servera.lab.example.com has been customized using Ansible. [student@workstation role-review]$ curl servera:9081 This is index.html for user: John Doe (jdoe) [student@workstation role-review]$ curl servera:9082 This is index.html for user: Jane Doe (jdoe2) [student@workstation role-review]$

Avaliação

Classifique seu trabalho executando o comando lab role-review grade a partir da sua máquina workstation. Corrija todas as falhas relatadas e execute novamente o script até que ele seja concluído com êxito.

[student@workstation ~]$ lab role-review grade

Encerramento

Na workstation, execute o script lab role-review finish para limpar este exercício.

[student@workstation ~]$ lab role-review finish

Isso conclui o laboratório.

britho commented 3 years ago

Neste capítulo, você aprendeu que:

As funções organizam códigos do Ansible para permitir a reutilização e o compartilhamento.

As funções do sistema RedHat Enterprise Linux são uma coleção de funções testadas e suportadas destinadas a ajudar você a configurar subsistemas de host em versões do RedHat EnterpriseLinux.

Ansible Galaxy é uma biblioteca pública de funções do Ansible gravadas por usuários do Ansible. O comando ansible-galaxy pode ser usado para pesquisar, exibir informações sobre, instalar, listar, remover ou inicializar funções.

As funções externas exigidas por um playbook podem ser definidas no arquivo roles/requirements.yml. O comando ansible-galaxy install -r roles/requirements.yml usa esse arquivo para instalar as funções no nó de controle.