Introdução
Em poucas palavras, o gerenciamento de configuração do servidor (também popularmente referido como Automação de TI) é uma solução para transformar a administração de 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 da implementação de uma estratégia de gerenciamento de configuração para sua infraestrutura de servidor, como funcionam as ferramentas de gerenciamento de configuração e o que essas ferramentas geralmente têm em comum.
Esta parte da série irá orientá-lo pelo processo de automação do provisionamento do servidor usando o Ansible, uma ferramenta de gerenciamento de configuração que fornece um framework de automação completo e capacidades de orquestração, mantendo um objetivo de simplicidade e minimalismo. Vamos nos concentrar na terminologia da linguagem, sintaxe e 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 raiz de documento personalizado
- Coloque um arquivo
index.html
no diretório de documentos 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 de provisionamento completo para automatizar as etapas descritas para configurar o Apache no Ubuntu 18.04.
Nota: este guia destina-se a introduzi-lo à linguagem 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 instalar e começar a usar esta ferramenta, além de 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 passar 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 normalmente abstrai uma tarefa do sistema, como lidar com pacotes ou criar e alterar arquivos. O Ansible tem 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 a reutilização e o compartilhamento.
- Jogo: um provisionamento executado do início ao fim é chamado de jogo.
- 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 do 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
na verdade é 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 em Debian. Esta tarefa de exemplo diz 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 instala o vim
em seguida:
---
- 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 essa razão, ao escrever playbooks e especialmente ao copiar exemplos, é necessário ter cuidado extra para manter a indentaçã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ê 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
Há diferentes maneiras de definir variáveis no Ansible. A forma 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, inclusive de arquivos e modelos incluídos.
Usando Loops
Os loops são tipicamente 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 diferentes pacotes que deseja instalar.
Para criar um loop dentro de uma tarefa, inclua a opção with_items
com um array 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 array 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 irá desligar apenas os sistemas baseados em Debian:
A condicional when
recebe como argumento uma expressão a ser avaliada. A tarefa é executada apenas se a expressão for avaliada como true
. No nosso exemplo, testamos um fact 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 baseadas na saída de um comando php -v
. Vamos testar 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 falhar 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 modelo Jinja2.
O exemplo a seguir é um modelo para configurar um host virtual Apache, usando uma variável para configurar o diretório raiz do documento 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 que seu playbook, assim é como você aplicaria o modelo para substituir o host virtual Apache padrão:
Definindo e Acionando Manipuladores
Manipuladores são usados para acionar uma mudança de estado em um serviço, como um reinício ou um parada. Embora possam parecer bastante semelhantes às tarefas regulares, os manipuladores só são executados quando previamente acionados por uma diretiva notify
em uma tarefa. Eles são tipicamente definidos como uma matriz em uma seção de 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 Apache. Se você quiser garantir que o Apache seja reiniciado após uma alteração no host virtual, primeiro é necessário 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, vamos mergulhar 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égio (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 é usada posteriormente em uma tarefa. Esta seção pode conter múltiplas variáveis.
tasks
A seção onde as tarefas reais são definidas. A primeira tarefa atualiza o cache do 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 nosso diretório raiz de documentos. 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 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
Assim que você baixar o conteúdo deste playbook para o seu 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 precisar especificar um usuário SSH diferente para se conectar ao servidor remoto, você 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
O Ansible é uma ferramenta de automação de TI minimalista que possui uma curva de aprendizado baixa, utilizando YAML
para seus scripts de provisionamento. Possui um grande número 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.