Introdução
Em poucas palavras, a gestão de configuração de servidor (também popularmente referida como Automação de TI) é uma solução para transformar a administração da sua infraestrutura em um código-fonte, descrevendo todos os processos necessários para implantar um servidor em um conjunto de scripts de provisionamento que podem ser versionados e facilmente reutilizados. Isso pode melhorar significativamente a integridade de qualquer infraestrutura de servidor ao longo do tempo.
Em um guia anterior, falamos sobre os principais benefícios de implementar uma estratégia de gestão de configuração para sua infraestrutura de servidor, como funcionam as ferramentas de gestão de configuração e o que essas ferramentas geralmente têm em comum.
Esta parte da série irá guiá-lo pelo processo de automação de provisionamento de servidor usando o Ansible, uma ferramenta de gestão de configuração que fornece um framework de automação completo e capacidades de orquestração, mantendo um objetivo de máxima 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 a implantação de um servidor web Ubuntu 18.04 usando o Apache.
A lista a seguir contém todos os passos que precisamos automatizar para alcançar nosso objetivo:
- Atualizar o cache do
apt
- Instalar o Apache
- Criar um diretório de raiz de documento personalizado
- Coloque um arquivo
index.html
no diretório raiz personalizado - Aplique um modelo para configurar nosso host virtual personalizado
- Reinicie o Apache
Começaremos dando uma olhada na terminologia usada pelo Ansible, seguida por uma visão geral das principais características da linguagem que podem ser usadas para escrever playbooks. No final do guia, você encontrará o conteúdo de um exemplo completo de provisionamento para automatizar as etapas descritas para configurar o Apache no Ubuntu 18.04.
Nota: este guia tem como objetivo familiarizá-lo com 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 os passos necessários para instalar e começar a usar esta ferramenta, bem como como executar comandos e playbooks do Ansible, consulte nosso guia Como Instalar e Configurar o Ansible no Ubuntu 18.04.
Começando
Antes de podermos avançar para uma visão mais prática do Ansible, é importante que nos familiarizemos com a terminologia e os conceitos importantes introduzidos por esta ferramenta.
Terminologia
A seguinte lista contém uma visão geral rápida dos termos mais relevantes usados pelo Ansible:
- Nó de Controle: a máquina onde o Ansible está instalado, responsável por executar a provisionamento nos servidores que você está gerenciando.
- Inventário: 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. - Tarefa: um bloco que define um único procedimento a ser executado, por exemplo: instalar um pacote.
- Módulo: um módulo geralmente abstrai uma tarefa do sistema, como lidar com pacotes ou criar e alterar arquivos. O Ansible possui uma infinidade de módulos integrados, mas você também pode criar módulos personalizados.
- Função: um conjunto de playbooks relacionados, modelos e outros arquivos, organizados de uma maneira predefinida para facilitar o reuso e compartilhamento.
- Play: uma provisão executada do início ao fim é chamada de play.
- Fatos: variáveis globais contendo informações sobre o sistema, como interfaces de rede ou sistema operacional.
- Manipuladores: usados para acionar mudanças no status de serviço, como reiniciar ou recarregar um serviço.
Formato da Tarefa
A task defines a single automated step that should be executed by Ansible. It typically involves the usage of a module or the execution of a raw command. This is how a task looks:
- name: This is a task
apt: name=vim state=latest
A parte name
é realmente opcional, mas recomendada, pois aparece na saída do provisionamento quando a tarefa é executada. A parte apt
é um módulo integrado do Ansible que abstrai o gerenciamento de pacotes em distribuições baseadas no Debian. Esta tarefa de exemplo 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
Os playbooks são arquivos YAML
contendo uma série de diretivas para automatizar o provisionamento de um servidor. O exemplo a seguir é um playbook simples que realiza duas tarefas: atualiza o cache do apt
e depois instala o vim
:
---
- hosts: all
become: true
tasks:
- name: Update apt-cache
apt: update_cache=yes
- name: Install Vim
apt: name=vim state=latest
YAML
depende da indentaçã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 indentação correta.
Antes do final deste guia, veremos um exemplo mais realista de um playbook, explicado detalhadamente. A próxima seção lhe dará uma visão geral dos elementos e recursos mais importantes que podem ser usados para escrever playbooks do Ansible.
Escrevendo Playbooks
Agora que está familiarizado com a terminologia básica e o formato geral dos playbooks e tarefas no Ansible, vamos aprender sobre algumas características dos playbooks que podem nos ajudar a criar automações mais versáteis.
Trabalhando com Variáveis
Existem diferentes maneiras de definir variáveis no Ansible. A maneira mais simples é usando a seção vars
de um playbook. O exemplo abaixo define uma variável package
que posteriormente é usada dentro de uma tarefa:
---
- hosts: all
become: true
vars:
package: vim
tasks:
- name: Install Package
apt: name={{ package }} state=latest
A variável package
tem um escopo global, o que significa que pode ser acessada de qualquer ponto do provisionamento, até mesmo de arquivos incluídos e modelos.
Usando Loops
Os loops são geralmente usados para repetir uma tarefa usando diferentes valores de entrada. Por exemplo, em vez de criar 10 tarefas para instalar 10 pacotes diferentes, você pode criar uma única tarefa e usar um loop para repetir a tarefa com todos os pacotes diferentes que deseja instalar.
Para criar um loop dentro de uma tarefa, 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
, como 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 de 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
As condicionais podem ser usadas para decidir dinamicamente se uma tarefa deve ser executada ou não, com base em uma variável ou em uma saída de um comando, por exemplo.
O exemplo a seguir só desligará sistemas baseados no Debian:
A condicional when
recebe como argumento uma expressão a ser avaliada. A tarefa só é executada caso a expressão seja avaliada como true
. No nosso exemplo, testamos um fato para verificar se o sistema operacional é da família Debian.
A common use case for conditionals in IT automation is when the execution of a task depends on the output of a command. With Ansible, the way we implement this is by registering a variable to hold the results of a command execution, and then testing this variable in a subsequent task. We can test for the command’s exit status (if failed or successful). We can also check for specific contents inside the output, although this might require the usage of regex expressions and string parsing commands.
O próximo exemplo mostra duas tarefas condicionais com base na saída de um comando php -v
. Testaremos o status de saída do comando, já que sabemos que ele falhará ao ser executado caso o PHP não esteja instalado neste servidor. A parte ignore_errors
da tarefa é importante para garantir que o provisionamento continue mesmo quando o comando falha na execução.
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 (quando usando o argumento msg
) ou imprimir o conteúdo de uma variável (quando usando o argumento var
).
Trabalhando com Modelos
Os modelos são tipicamente usados para configurar arquivos de configuração, permitindo o uso de variáveis e outras funcionalidades destinadas a tornar esses arquivos mais versáteis e reutilizáveis. O Ansible usa o mecanismo de modelos Jinja2.
O exemplo a seguir é um modelo para configurar um host virtual do Apache, usando uma variável para configurar o diretório 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 integrado template
é usado para aplicar o modelo a partir de uma tarefa. Se você nomeou o arquivo de modelo acima como vhost.tpl
, e o colocou no mesmo diretório do seu playbook, assim é como você aplicaria o modelo para substituir o host virtual padrão do Apache:
Definindo e Acionando Manipuladores
Os manipuladores são usados para acionar uma mudança de estado em um serviço, como uma reinicialização ou um parada. Mesmo que pareçam bastante semelhantes às tarefas regulares, os manipuladores são executados apenas quando previamente acionados a partir de uma diretiva notify
em uma tarefa. Eles são tipicamente definidos como um array em uma seção handlers
do playbook, mas também podem existir em arquivos separados.
Vamos considerar nosso exemplo anterior de uso de modelo, onde configuramos um host virtual do Apache. Se você deseja garantir que o Apache seja reiniciado após uma alteração no host virtual, primeiro precisa criar um manipulador para o serviço Apache. Assim é como os manipuladores são definidos dentro de um playbook:
A diretiva name
aqui é importante porque será o identificador único deste manipulador. Para acionar este manipulador a partir de uma tarefa, você deve usar a opção notify
:
Vimos algumas das características mais importantes que você pode usar para começar a escrever playbooks do Ansible. Na próxima seção, mergulharemos em um exemplo mais real de um playbook que automatizará a instalação e configuração do Apache no Ubuntu.
Exemplo de Playbook
Agora vamos dar uma olhada em um playbook que automatizará a instalação de um servidor web Apache em um sistema Ubuntu 18.04, conforme discutido na introdução deste guia.
O exemplo completo, incluindo o arquivo de modelo 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 Vagrantfile 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:
- ---
- - hosts: all
- become: true
- vars:
- doc_root: /var/www/example
- tasks:
- - name: Update apt
- apt: update_cache=yes
-
- - name: Install Apache
- apt: name=apache2 state=latest
-
- - name: Create custom document root
- file: path={{ doc_root }} state=directory owner=www-data group=www-data
-
- - name: Set up HTML file
- copy: src=index.html dest={{ doc_root }}/index.html owner=www-data group=www-data mode=0644
-
- - name: Set up Apache virtual host file
- template: src=vhost.tpl dest=/etc/apache2/sites-available/000-default.conf
- notify: restart apache
- handlers:
- - name: restart apache
- service: name=apache2 state=restarted
-
Vamos examinar cada parte deste playbook com mais detalhes:
hosts: all
O playbook começa declarando que deve ser aplicado a todos
os hosts em seu inventário (hosts: all
). É possível restringir a execução do playbook para um host específico ou um grupo de hosts. Essa opção pode ser sobrescrita no momento da execução.
become: true
A parte become: true
diz ao Ansible para usar escalonamento de privilégios (sudo) para executar todas as tarefas neste playbook. Essa opção pode ser sobrescrita em uma base de tarefa por tarefa.
vars
Define uma variável, doc_root
, que é posteriormente usada em uma tarefa. Esta seção poderia conter várias variáveis.
tasks
A seção onde as tarefas reais são definidas. A primeira tarefa atualiza o cache apt
, e a segunda tarefa instala o pacote apache2
.
A terceira tarefa usa o módulo integrado file para criar um diretório para servir como nossa raiz de documento. Este módulo pode ser usado para gerenciar arquivos e diretórios.
A quarta tarefa usa o módulo copy para copiar um arquivo local para o servidor remoto. Estamos copiando um arquivo HTML simples para ser servido como nosso site hospedado pelo Apache.
handlers
Por fim, temos a seção de handlers
, onde os serviços são declarados. Definimos o manipulador restart apache
que é notificado pela quarta tarefa, onde o modelo do Apache é aplicado.
Executando um Playbook
Depois de baixar o conteúdo deste playbook para o nó de controle do Ansible, você pode usar ansible-playbook
para executá-lo em um ou mais nós do seu inventário. O comando a seguir executará o playbook em todos os hosts do seu arquivo de inventário padrão, usando autenticação de par de chaves SSH para se conectar como o usuário do sistema atual:
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:
Se você precisar especificar um usuário SSH diferente para se conectar ao servidor remoto, pode incluir o argumento -u usuário
nesse comando:
Para obter mais informações sobre como executar comandos e playbooks do Ansible, consulte nosso guia sobre Como Instalar e Configurar o Ansible no Ubuntu 18.04.
Conclusão
Ansible é uma ferramenta de automação de TI minimalista que possui uma curva de aprendizado baixa, usando YAML
para seus scripts de provisionamento. Possui uma grande quantidade de módulos integrados que podem ser usados para abstrair tarefas como instalação de pacotes e trabalho com modelos. Seus requisitos de infraestrutura simplificados e linguagem simples podem ser adequados para aqueles que estão começando com gerenciamento de configuração. No entanto, pode faltar 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 prática do Puppet, uma ferramenta de gerenciamento de configuração popular e bem estabelecida que usa uma DSL personalizada expressiva e poderosa baseada em Ruby para escrever scripts de provisionamento.