Automatize o gerenciamento de servidores com Ansible

Configurar um servidor para ser utilizado em produção é uma tarefa um pouco complexa e que demanda tempo, mas isso pode ser automatizado de forma simples e executado rapidamente com Ansible.

Ansible é uma ferramenta open source de gerenciamento de configurações, escrita em Python serve para automatizar suas tarefas de provisionamento de servidores, a curva de aprendizagem é mínima e tudo o que ele necessita para funcionar é ter acesso SSH ao servidor e fazer a leitura dos Playbooks (livros de receitas) que são arquivos de provisionamento escritos em YAML.

O setup

Imagine que temos a tarefa de configurar um servidor de produção para uma aplicação Rails, logo precisamos instalar o Ruby, Nginx, criar um usuário para deploy, adicionar regras de firewall, etc.

Tudo isso poderia ser feito manualmente via SSH, porém o que vamos fazer é delegar essa tarefa ao Ansible, neste post veremos um exemplo de como seria a automatização do processo para instalar o web server Nginx.

Primeiro precisamos instalar o Ansible na nossa máquina local, isso pode ser feito via pip:

$ sudo easy_install pip
$ sudo pip install ansible

Ou se preferir instalar pelo fonte faça:

$ git clone git@github.com:ansible/ansible.git
$ cd ansible
$ sudo python setup.py install

Supondo que temos acesso SSH ao servidor remoto que vamos configurar e que o mesmo já está com a nossa chave pública adicionada ao authorized_keys, vamos executar nosso primeiro teste com o Ansible.

O Ansible faz uso de um arquivo chamado hosts, esse arquivo deve conter o nome ou ip do servidor que queremos configurar:

server01
server02
server03

ou

192.168.10.1
192.168.10.2
192.168.10.3

No hosts é possível também separar os servidores em grupos, por exemplo:

[application]
server01

[database]
server02
server03

Por padrão o arquivo hosts fica em /etc/ansible/hosts eu gosto de manter o arquivo separado nas receitas que utilizo.

Para o nosso primeiro teste, podemos criar o arquivo hosts e adicionar o ip do nosso servidor:

$ touch hosts
$ echo "192.168.10.15" > hosts

Feito isso podemos executar o comando ansible informando o arquivo hosts com o ip do servidor e executar o módulo ping para ver se está tudo ok:

$ ansible -i hosts -m ping all
192.168.10.15 | success >> {
    "changed": false,
    "ping": "pong"
}

Basicamente o que fizemos foi instruir o Ansible a utilizar o módulo ping e testar a comunicação com o servidor remoto para verificar a conectividade.

Escrevendo receitas

Agora que já verificamos a conectividade do Ansible com nosso servidor remoto, podemos escrever nosso primeiro Playbook. Um Playbook nada mais é do que um conjunto de regras que deverão ser executadas no servidor remoto.

Para este exemplo vamos montar uma estrutura que deverá conter os nossos Playbooks com regras para instalar alguns pacotes, a estrutura deverá ficar parecida com a seguinte:

├── hosts
├── roles
│   ├── nginx
│   │   └── tasks
│   │       └── main.yml
│   └── ruby
│       └── tasks
│           └── main.yml
└── server.yml

Então criaremos um diretório chamado roles e dentro dele outro chamado nginx, essa organização é entendida pelo Ansible na hora da execução.

Dentro do diretório nginx crie outro chamado tasks e um arquivo main.yml, este arquivo deve conter as regras de instalação do nginx:

$ mkdir -p nginx/tasks
$ touch nginx/tasks/main.yml

No arquivo main.yml do nginx temos as regras para instalação, esse é o nosso primeiro Playbook:

---
- name: Add the key used to Nginx pkg
  apt_key: url=http://nginx.org/keys/nginx_signing.key state=present

- name: Add repository for install Nginx
  copy: src=nginx.list dest=/etc/apt/sources.list.d/

- name: Update packages and install Nginx
  apt: name=nginx update_cache=yes

Vamos entender o que está acontecendo, na linha 1 temos o parâmetro --- que é obrigatório para que o arquivo seja interpretado como um documento YAML, no caso do Ansible esse parâmetro só pode estar presente uma vez por arquivo e sempre no início.

Nas linhas 2,5 e 8 vemos o - name: que é usado para descrição de cada tarefa, basicamente ele funciona como key: value.

Na linha 3 vemos o apt-key: que faz parte de um módulo do ansible para o comando apt, basicamente ele realizará o download do arquivo nginx_signing.key e executará o comando apt-key add nginx_signing.key.

A opção copy: na linha 6 informa para o ansible copiar um arquivo que contém os repositórios necessários para o apt instalar o Nginx. A opção src indica o source do arquivo que queremos copiar e o dest o destino. Nesse exemplo a nossa estrutura teria mais um diretório dentro de nginx:

$ mkdir nginx/files
$ touch nginx/files/nginx.list

O último comando na linha 9 é o apt: que recebe como parâmetro o nome do pacote que queremos instalar name=nginx e outro argumento update_cache=yes que seria o mesmo que apt-get update && apt-get install nginx.

E para executar nosso playbook, precisamos escrever mais um arquivo, chamado de server.yml:

---
- name: Install Server
  hosts: server01
  user: root

  roles:
    - nginx
    - ruby

Desta forma o ansible entende quais playbooks ele deve executar para o server01:

$ ansible-playbook -i hosts server.yml
PLAY [Install Server] ************************************************

GATHERING FACTS ******************************************************
ok: [192.168.10.15]

TASK: [nginx | Add the key used to Nginx pkg] ************************
ok: [192.168.10.15]

TASK: [nginx | Add repository for install Nginx] *********************
ok: [192.168.10.15]

TASK: [nginx | Update packages and install Nginx] ********************
ok: [192.168.10.15]

PLAY RECAP ***********************************************************
192.168.10.15    : ok=4  changed=0  unreachable=0  failed=0

Lembra que podemos separar o hosts em grupos ? Pois bem, imagine que você precisa configurar vários servidores, aplicação, banco de dados, cache, backup, etc. No arquivo server.yml os hosts podem ser organizados para executarem playbooks específicos, por exemplo instalar o Postgresql ou o Memcached em servidores diferentes.

Observe a simplicidade do Ansible para descrever as tarefas, o mesmo poderia ser feito com outros pacotes como o Ruby ou para definir regras de firewall, o ansible suporta muitos módulos e sua documentação é rica em detalhes.

Finalizando

Agora você pode construir suas regras para automatizar tarefas complexas com o Ansible. O exemplo que vimos serve apenas como um ponto de partida, explore o potencial da ferramenta.

Caso tenha interesse, verifique alguns playbooks que disponibilizei no github.

Happy Hacking ;)

Referências

Comentários