DevSecOps

2 mai, 2017

Automação e provisionamento ágil com Ansible

Publicidade

Hoje, vou falar um pouco sobre minha experiência com uma ferramenta muito útil de automação, o Ansible. Estou trabalhando em uma aplicação que precisa de uma série de dependências e serviços para funcionar. Meu desafio era, além de automatizar todo o processo de instalação dessas dependências, encontrar uma forma de manter todos os pacotes atualizados com a mesma versão, validar a disponibilidade dos serviços, agilizar o processo de Deploy e encapsular tudo isso de forma que eu, futuramente, possa rodar essa mesma aplicação e suas dependências em outros servidores, mantendo sempre tudo atualizado e replicado em real time para os nós.

Eu precisava pensar em uma maneira de validar de forma idempotent essas máquinas, mas só se existissem essas dependências nelas. Ou seja, o comando só poderia ser aplicado quando ele realmente necessitasse ser aplicado. Explicando de uma forma mais precisa o significado do termo idempotent em nosso cenário, imagine que você precisa instalar um determinado pacote em uma máquina, mas não sabemos se ele já está instalado. Então, você precisa validar se ele existe no(s) host(s) remoto(s) e, caso não esteja lá, a tarefa será executada e o pacote será instalado, mas caso exista, a tarefa não será executada. Depois de pesquisar um pouco e conversar com meus colegas de capítulo, conheci o Ansible, que me ajudou bastante com essa questão.

Neste artigo, vou falar um pouco sobre como é sua estrutura, como instalar a ferramenta e como a usei no meu projeto.

O que é o Ansible?

O Ansible é uma ferramenta open source de automação e provisionamento ágil desenvolvida, inicialmente, por Michael DeHaan e atualmente mantida pela comunidade e pela Red Hat. O Ansible é de fácil aprendizagem e utiliza SSH para se comunicar com os clientes (nodes) não necessitando de agent; e sua única dependência é ter Python2 instalado no(s) node(s), que já é nativo na maioria das distribuições Linux.

Com Ansible é possível automatizar tarefas como:

  • Instalação e atualização de pacotes;
  • Configuração e deploy de aplicações;
  • Gerenciamento de usuários;
  • E muitas outras tarefas administrativas com ganho enorme de desempenho, velocidade e produtividade.

A documentação oficial fica aqui.

A estrutura do Ansible

  • Inventory: arquivo de inventário no qual serão declarados quais os nós ou hosts-alvos serão gerenciados pelo Ansible-Server;
  • Modules: controlam os recursos (serviços, pacotes, arquivos etc) do(s) host(s) remoto(s);
  • Tasks: tarefas que serão executadas no(s) host(s);
  • Playbooks: conjunto de tarefas escritas em YAML (chave:valor) que serão executadas no(s) host(s).

Características do Ansible

  • Escrito em Python, linguagem interpretada de script, imperativa e orientada a objetos;
  • Não necessita que agents sejam instalados nos hosts remotos;
  • Utiliza SSH para se conectar aos hosts;
  • Para os Playbooks utiliza a linguagem YAML, facilmente entendida pelos seres humanos;
  • Utiliza linguagem Jinja2 para templates;
  • Enorme quantidade de módulos e códigos no Github. Neste site ou pelo comando ansible-galaxy é possível baixar e reutilizar playbooks escritos por outros usuários.

Instalando o Ansible

O que vamos precisar? Neste exemplo, usei duas máquinas virtuais com Sistema Operacional Ubuntu16.04 para os nós gerenciados e minha máquina como Ansible-Server. A instalação é relativamente simples, você precisa instalar somente na máquina que funcionará como ponto central.

Para a instalação do Ansible-Server você precisa seguir os seguintes passos:

APT-Ubuntu

YUM

Debian

PKG

Homebrew

Gerenciando servidores

O inventário

O arquivo de hosts de inventário do Ansible é usado para listar e agrupar seus servidores e sua localização default é /etc/ansible/hosts. Costumo fazer um backup do arquivo default para usá-lo como referência mais tarde:

- sudo mv /etc/ansible/hosts /etc/ansible/hosts.orig

Depois de mover o arquivo de inventário de exemplo, crie um novo /etc/ansible/hosts e defina os servidores que serão gerenciados. Caso queira ter seu arquivo de hosts Ansible em outro local particular, você pode definir esta variável de ambiente:

- export ANSIBLE_HOSTS=/root/ansible_hosts

Ou pode especificar o local de hosts Ansible ao executar comandos com a flag –inventory-file = (ou -i):

- ansible all --inventory-file=/root/ansible_hosts

Aqui vamos definir os dois servidores sob o rótulo “webservers” e um com “local”, para testes locais:

Conectando aos servidores

Gere a chave no nó master sem ter que digitar uma senha ou para o caso de você ainda não tiver autenticação via chave ssh, configurada para seus nós filhos:

Após o término das confirmações, teremos dois arquivos:

– ~/.ssh/id_rsa
– ~/.ssh/id_rsa.pub

Em seguida, copie sua chave pública para os servidores com o comando ssh-copy-id:

- $ ssh-copy-id -i ~/.ssh/id_rsa.pub <user>@<host>

ref: Post-Install Setup

Executando comandos

Comandos Ad-Hoc

Assim que tiver um inventário configurado, podemos começar a executar tarefas nos servidores definidos.

O Ansible assumirá que você tem acesso SSH disponível para seus servidores, normalmente baseado em SSH-Key. Como o Ansible usa SSH, o servidor em que ele está instalado precisa de acesso aos servidores do inventário.

A saída que temos do Ansible é JSON, que nos diz se a tarefa fez alguma alteração e qual foi o seu resultado. Se precisarmos definir o usuário e talvez algumas outras configurações para nos conectar ao servidor, podemos fazer o uso das seguintes FLAGS:

- $ ansible all -m ping -k -u <user>

Nas quais:

  • All – use todos os servidores definidos a partir do arquivo de inventário;
  • m ping – use o módulo “ping”, que simplesmente executa o comando e retorna os resultados;
  • s – use “sudo” para executar os comandos;
  • k – solicite uma senha ao invés de usar a autenticação baseada em chave;
  • u – utilize outro usuário.

Modules

Ansible usa “módulos” para realizar a maioria de suas tarefas, como instalar softwares, atualizar pacotes, copiar arquivos etc.

- ansible local -s -m apt -a 'name=nginx'

Nota: perceba que usei o rótulo “local” para limitar a ação feita somente em minha máquina.

Acima, o comando sudo apt-get install nginx foi executado usando o módulo “shell”; o sinalizador -a é usado para transmitir argumentos para o módulo. Utilizo -s para executar esse comando usando sudo e se usarmos um módulo mais apropriado, podemos executar comandos com uma garantia de resultado. Os módulos Ansible asseguram idempotência, ou seja, poderemos executar as mesmas tarefas sem afetar o resultado final.

- ansible local -m apt -a 'name=nginx state=installed' --ask-sudo

Ele fará uso do módulo apt para instalar o Nginx (se não estiver instalado). O resultado da execução da tarefa foi “changed”: false. Isso mostra que não houve mudanças, pois já havia instalado o Nginx nesta máquina. Logo, posso executar este comando repetidamente sem me preocupar com ele afetando o resultado desejado.

Algumas FLAGS:

  • All – executar em todos os hosts definidos a partir do arquivo de inventário;
  • s – executar usando o sudo;
  • m apt – use o módulo apt;
  • a ‘name=nginx state=instalado’ – fornece os argumentos para o módulo apt, incluindo o nome do pacote e o estado final desejado;.
  • –ask-sudo – pede senha de sudo.

Podemos executar todas as nossas tarefas necessárias (por meio de módulos) da forma ad-hoc, mas vamos tornar isso mais gerenciável. Vamos mover tudo isso para um Playbook, assim ele vai executar e coordenar várias tarefas ao mesmo tempo.

Playbook básico

Os Playbooks podem executar várias Tarefas (TASKS) e oferecer algumas funcionalidades mais avançadas.

Segue o exemplo de um playbook no qual executo a instalação dos requisitos do Apache LAMP.

Perceba que neste playbook a primeira tarefa declarada foi instalar o php5, apache2, mysql etc. Na segunda, ele executa o comando que habilita o module rewrite do Apache e por último, reinicia o serviço Apache. Rá!

Para cada tarefa, você pode especificar o grupo-alvo de nós e o usuário remoto para executar a operação:

Se você precisar executar a tarefa com usuário diferentes, especifique da seguinte forma:

Executar com sudo:

As tarefas do playbook serão executadas em todos os nós declarados no grupo webservers, dentro do arquivo de inventário.

Para executar o playbook, use o comando:

Dando continuidade ao exemplo anterior, vou colocar os comandos ad-hoc que executamos para instalar o NGINX dentro de um playbook ordenado em Tasks:

Crie o arquivo nginx.yml com a configuração abaixo:

Esta tarefa faz exatamente o mesmo que o nosso comando ad-hoc, no entanto, escolhi especificar o meu grupo “local” de servidores em vez de “all” ou “webservers”. Podemos executar o playbook com o comando ansible-playbook:

Usei –ask-sudo dizendo ao Ansible para usar sudo pedindo senha e, em seguida, informei o arquivo Playbook nginx.yml. Costumo adicionar -vvv para visualizar com mais detalhes a execução das tarefas e seu resultado final. Como vemos acima, ele executou as tarefas com sucesso, porém nada foi alterado, pois já tenho o Nginx instalado.

A sintaxe do comando para execução dos playbooks é:

- $ ansible-playbook -i inventário playbook

ref: Documentação Ansible-Playbooks.

Conclusão

Como vimos, o Ansible é uma ótima ferramenta de provisionamento de ambientes e me ajudou bastante de forma rápida e eficiente. Existem alguns pontos negativos, como a sintaxe exigente e a identação do seu playbook. No entanto, a lógica é bastante simples, sua documentação é bem completa e há muitas opções que poderão te ajudar a construir seus próprios módulos para os playbooks, de acordo com a necessidade. Ficou alguma dúvida ou tem algo a dizer? Aproveite os campos abaixo! Até a próxima.

***

Artigo publicado originalmente em: https://www.concretesolutions.com.br/2017/04/26/automacao-e-provisionamento-agil-com-ansible/