Tutorial

Gerenciamento de Configuração 101: Escrevendo Playbooks Ansible

Published on February 20, 2020
Português
Gerenciamento de Configuração 101: Escrevendo Playbooks Ansible

Introdução

Em poucas palavras, o gerenciamento de configuração de servidor (também conhecido como IT Automation) é uma solução para transformar a sua administração de infraestrutura em uma base de código, descrevendo todos os processos necessários para fazer o deploy de um servidor em um conjunto de scripts de provisionamento que podem ser versionados e facilmente reutilizados. Isso pode melhorar muito a integridade de qualquer infraestrutura de servidor ao longo do tempo.

Em um guia anterior, falamos sobre os principais benefícios da implementação de uma estratégia de gerenciamento de configuração para a infraestrutura de servidor, como as ferramentas de gerenciamento de configuração funcionam e o que essas ferramentas têm em comum normalmente.

Esta parte da série o guiará pelo processo de automatização do provisionamento de servidores usando o Ansible, uma ferramenta de gerenciamento de configuração que fornece uma framework completo de automação e recursos de orquestração, enquanto mantém um objetivo final de simplicidade e minimalismo. Vamos nos concentrar na terminologia da linguagem, na sintaxe e nos recursos necessários para criar um exemplo simplificado para automatizar completamente o deployment de um servidor web Ubuntu 18.04 usando o Apache.

A lista a seguir contém todas os passos que precisamos automatizar para alcançar nosso objetivo:

  1. Atualizar o cache do apt
  2. Instalar o Apache
  3. Criar um diretório raiz de documentos personalizado
  4. Colocar um arquivo index.html no diretório raiz de documentos personalizado
  5. Aplicar um template para configurar nosso virtual host personalizado
  6. Reiniciar o Apache

Começaremos examinando a terminologia usada pelo Ansible, seguida de uma visão geral dos principais recursos da linguagem que podem ser usados para escrever playbooks. No final do guia, você encontrará o conteúdo de um exemplo completo de provisionamento para automatizar os passos descritos para configurar o Apache no Ubuntu 18.04.

Nota: este guia tem como objetivo apresentar a você a linguagem do Ansible e como escrever playbooks para automatizar o provisionamento do seu servidor. Para uma visão mais introdutória do Ansible, incluindo as etapas necessárias para a instalação e sobre como inciar o uso dessa ferramenta, bem como a execução de comandos e playbooks do Ansible, consulte nosso guia Como instalar e configurar o Ansible no Ubuntu 18.04

Iniciando

Antes de podermos avançar para uma visão mais prática do Ansible, é importante nos familiarizarmos com importantes terminologias e conceitos introduzidos por essa ferramenta.

Terminologia

A lista a seguir contém uma rápida visão geral dos termos mais relevantes usados pelo Ansible:

  • Control Node: a máquina em que o Ansible está instalado, responsável pela execução do provisionamento nos servidores que você está gerenciando.
  • Inventory: um arquivo INI que contém informações sobre os servidores que você está gerenciando.
  • Playbook: um arquivo YAML contendo uma série de procedimentos que devem ser automatizados.
  • Task: um bloco que define um único procedimento a ser executado, por exemplo: instalar um pacote.
  • Module: um módulo normalmente abstrai uma tarefa do sistema, como lidar com pacotes ou criar e alterar arquivos. O Ansible possui diversos módulos integrados, mas você também pode criar módulos personalizados.
  • Role: um conjunto de playbooks, modelos e outros arquivos relacionados, organizados de maneira predefinida para facilitar a reutilização e o compartilhamento.
  • Play: um provisionamento executado do início ao fim é chamado de play.
  • Facts: variáveis globais que contêm informações sobre o sistema, como interfaces de rede ou sistema operacional.
  • Handlers: usado para acionar alterações no status do serviço, como reiniciar ou recarregar um serviço.

Formato da Task

Uma task ou tarefa define uma única etapa automatizada que deve ser executada pelo Ansible. Geralmente envolve o uso de um módulo ou a execução de um comando raw. É assim que uma tarefa se parece:

- name: Esta é uma task
  apt: name=vim state=latest

A parte do name é opcional na verdade, mas recomendada, pois aparece na saída do provisionamento quando a tarefa é executada. A parte do apt é um módulo Ansible embutido que abstrai o gerenciamento de pacotes em distribuições baseadas no Debian. Este exemplo de tarefa informa ao Ansible que o pacote vim deve ter seu estado alterado para latest, o que fará com que o gerenciador de pacotes instale este pacote, caso ainda não esteja instalado.

Formato do Playbook

Playbooks são arquivos YAML que contêm uma série de diretivas para automatizar o provisionamento de um servidor. O exemplo a seguir é um playbook simples que executa duas tasks: atualiza o cache do apt e instala o vim posteriormente:

---
- hosts: all
  become: true
  tasks:
     - name: Update apt-cache 
       apt: update_cache=yes

     - name: Install Vim
       apt: name=vim state=latest

O YAML depende da identação para serializar estruturas de dados. Por esse motivo, ao escrever playbooks e, especialmente, ao copiar exemplos, você precisa ter cuidado extra para manter a identação correta.

Antes do final deste guia, veremos um exemplo mais real de um playbook, explicado em detalhes. A próxima seção fornecerá uma visão geral dos elementos e recursos mais importantes que podem ser usados para escrever playbooks do Ansible.

Escrevendo Playbooks

Agora que você conhece a terminologia básica e o formato geral dos playbooks e tasks no Ansible, aprenderemos sobre alguns recursos do playbook que podem nos ajudar a criar automações mais versáteis.

Trabalhando com Variables

Existem diferentes maneiras pelas quais você pode definir variáveis no Ansible. A maneira mais simples é usar a seção vars de um playbook. O exemplo abaixo define uma variável package que mais tarde é usada dentro de uma task:

---
- hosts: all
  become: true
  vars:
     package: vim
  tasks:
     - name: Install Package
       apt: name={{ package }} state=latest

A variável package possui um escopo global, o que significa que pode ser acessada a partir de qualquer ponto do provisionamento, mesmo a partir dos arquivos e modelos incluídos.

Usando Loops

Os loops são normalmente usados para repetir uma task usando diferentes valores de entrada. Por exemplo, em vez de criar 10 tasks para instalar 10 pacotes diferentes, você pode criar uma única task e usar um loop para repetir a tarefa com todos os pacotes diferentes que deseja instalar.

Para criar um loop dentro de uma task, inclua a opção with_items com uma matriz de valores. O conteúdo pode ser acessado através da variável de loop item, conforme mostrado no exemplo abaixo:

- name: Install Packages
  apt: name={{ item }} state=latest
  with_items:
     - vim
     - git
     - curl  

Você também pode usar uma variável matriz para definir seus itens:

---
- hosts: all
  become: true
  vars:
     packages: [ 'vim', 'git', 'curl' ]
  tasks:
     - name: Install Package
       apt: name={{ item }} state=latest
       with_items: "{{ packages }}"

Usando Condicionais

Condicionais podem ser usados para decidir dinamicamente se uma tarefa deve ou não ser executada, baseado em uma variável ou em uma saída de um comando, por exemplo.

O exemplo a seguir vai encerrar apenas os sistemas baseados em Debian:

- name: Shutdown Debian Based Systems
  command: /sbin/shutdown -t now
  when: ansible_os_family == "Debian"

O condicional when recebe como argumento uma expressão a ser avaliada. A task é executada apenas no caso de a expressão ser avaliada como true. Em nosso exemplo, testamos um fact para verificar se o sistema operacional é da família Debian.

Um caso de uso comum para condicionais na automação de TI é quando a execução de uma task depende da saída de um comando. Com o Ansible, a maneira como implementamos isso é registrando uma variável para armazenar os resultados de uma execução de comando e testando essa variável em uma tarefa subseqüente. Podemos testar o status de saída do comando (se houve falha ou êxito). Também podemos verificar um conteúdo específico dentro da saída, embora isso possa exigir o uso de expressões regulares (regex) e comandos de parsing de string.

O próximo exemplo mostra duas tarefas condicionais baseadas na saída de um comando php -v. Testaremos o status de saída do comando, pois sabemos que ele falhará na execução caso o PHP não esteja instalado neste servidor. A parte ignore_errors da task é importante para garantir que o provisionamento continue mesmo quando o comando falha na execução.

- name: Check if PHP is installed
  register: php_installed
  command: php -v
  ignore_errors: true

- name: This task is only executed if PHP is installed
  debug: var=php_install
  when: php_installed|success
  
- name: This task is only executed if PHP is NOT installed
  debug: msg='PHP is NOT installed'
  when: php_installed|failed

O módulo debug usado aqui é um módulo útil para mostrar o conteúdo de variáveis ou mensagens de depuração. Ele pode imprimir uma string (ao usar o argumento msg) ou imprimir o conteúdo de uma variável (ao usar o argumento var).

Trabalhando com Templates

Os templates são usados geralmente para configurar arquivos de configuração, permitindo o uso de variáveis e outros recursos destinados a tornar esses arquivos mais versáteis e reutilizáveis. O Ansible usa o mecanismo de template Jinja2.

O exemplo a seguir é um template para configurar um virtual host no Apache, usando uma variável para configurar a raiz de documentos para este host:

<VirtualHost *:80>
    ServerAdmin webmaster@localhost
    DocumentRoot {{ doc_root }}

    <Directory {{ doc_root }}>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

O módulo interno template é usado para aplicar o template a partir de uma tarefa. Se você nomeou o arquivo de template acima de vhost.tpl e o colocou no mesmo diretório que seu playbook, é assim que você aplicaria o template para substituir o virtual host padrão do Apache:

- name: Change default Apache virtual host
  template: 
    src: vhost.tpl
    dest: /etc/apache2/sites-available/000-default.conf

Definindo e Acionando Handlers

Handlers são usados para acionar uma alteração de estado em um serviço, como um restart ou um stop. Mesmo que possam parecer bastante semelhantes às tasks regulares, os handlers são executados apenas quando acionados anteriormente a partir de uma diretiva notify em uma task. Eles geralmente são definidos como uma matriz em uma seção handlers do playbook, mas também podem estar em arquivos separados.

Vamos levar em consideração o nosso exemplo anterior de uso de templates, onde configuramos um virtual host no Apache. Se você deseja garantir que o Apache seja reiniciado após uma alteração no virtual host, primeiro você precisa criar um handler para o serviço Apache. É assim que os handlers são definidos dentro de um playbook:

handlers:
    - name: restart apache
      service: name=apache2 state=restarted
    
    - name: other handler
      service: name=other state=restarted

A diretiva name aqui é importante porque ela será o identificador exclusivo desse handler. Para acionar esse handler a partir de uma tarefa, você deve usar a opção notify:

- name: Change default Apache virtual host
  template: 
    src: vhost.tpl
    dest: /etc/apache2/sites-available/000-default.conf
  notify: restart apache

Vimos alguns dos recursos mais importantes que você pode usar para começar a escrever playbooks Ansible. Na próxima seção, veremos um exemplo mais real de um playbook que automatizará a instalação e configuração do Apache no Ubuntu.

Playbook de Exemplo

Agora, vamos dar uma olhada em um playbook que automatizará a instalação de um servidor web Apache dentro de um sistema Ubuntu 18.04, conforme discutido na introdução deste guia.

O exemplo completo, incluindo o arquivo de template para configurar o Apache e um arquivo HTML para ser servido pelo servidor web, pode ser encontrado no Github. A pasta também contém um arquivo Vagrant que permite testar o playbook em uma configuração simplificada, usando uma máquina virtual gerenciada pelo Vagrant.

Conteúdo do Playbook

O conteúdo completo do playbook está disponível aqui para sua conveniência:

playbook.yml
  1. ---
  2. - hosts: all
  3. become: true
  4. vars:
  5. doc_root: /var/www/example
  6. tasks:
  7. - name: Update apt
  8. apt: update_cache=yes
  9. - name: Install Apache
  10. apt: name=apache2 state=latest
  11. - name: Create custom document root
  12. file: path={{ doc_root }} state=directory owner=www-data group=www-data
  13. - name: Set up HTML file
  14. copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644
  15. - name: Set up Apache virtual host file
  16. template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
  17. notify: restart apache
  18. handlers:
  19. - name: restart apache
  20. service: name=apache2 state=restarted

Vamos examinar cada parte deste playbook em mais detalhes:

hosts: all O playbook começa afirmando que deve ser aplicado a todos os hosts em seu inventário (hosts: all). É possível restringir a execução do playbook a um host específico ou a um grupo de hosts. Esta opção pode ser substituída no momento da execução.

become: true A parte become: true diz ao Ansible para usar a escalação de privilégios (sudo) para executar todas as tarefas neste playbook. Esta opção pode ser substituída em uma base de task por task.

vars Define uma variável, doc_root, que é usada posteriormente em uma task. Esta seção pode conter várias variáveis.

tasks A seção em que as tasks reais são definidas. A primeira task atualiza o cache do apt e a segunda task instala o pacote apache2.

A terceira task usa o módulo interno file para criar um diretório para servir como a raiz de documentos. Este módulo pode ser usado para gerenciar arquivos e diretórios.

A quarta task usa o módulo copy para copiar um arquivo local para o servidor remoto. Estamos copiando um arquivo HTML simples para servir como nosso site hospedado pelo Apache.

handlers Finalmente, temos a seção handlers, onde os serviços são declarados. Definimos o handler restart apache que é notificado a partir da quarta tarefa, onde o template Apache é aplicado.

Executando um Playbook

Depois de baixar o conteúdo deste playbook para o control node Ansible, você pode usar o ansible-playbook para executá-lo em um ou mais nodes do seu inventário. O comando a seguir executará o playbook em todos os hosts do seu arquivo de inventário padrão, usando a autenticação de par de chaves SSH para conectar-se como o usuário atual do sistema:

  1. ansible-playbook playbook.yml

Você também pode usar -l para limitar a execução a um único host ou a um grupo de hosts do seu inventário:

  1. ansible-playbook -l host_ou_grupo playbook.yml

Se você precisar especificar um usuário SSH diferente para se conectar ao servidor remoto, poderá incluir o argumento -u user nesse comando:

  1. ansible-playbook -l host_ou_grupo playbook.yml -u usuário_remoto

Para obter mais informações sobre como executar comandos Ansible e playbooks, consulte o nosso guia Como instalar e configurar o Ansible no Ubuntu 18.04.

Conclusão

O Ansible é uma ferramenta minimalista de automação de TI que possui uma baixa curva de aprendizado, usando o YAML para seus scripts de provisionamento. Ele possui um grande número de módulos internos que podem ser usados para abstrair tasks, como instalar pacotes e trabalhar com templates. Seus requisitos simplificados de infraestrutura e linguagem simples podem ser uma boa opção para quem está iniciando o gerenciamento de configurações. No entanto, pode haver alguns recursos avançados que você pode encontrar em ferramentas mais complexas, como Puppet e Chef.

Na próxima parte desta série, veremos uma visão geral prática do Puppet, uma ferramenta de gerenciamento de configuração popular e bem estabelecida que usa uma DSL personalizada expressiva e poderosa baseada no Ruby para escrever scripts de provisionamento.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar

Developer Advocate

Dev/Ops passionate about open source, PHP, and Linux.



Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.