Domine o Ansible: Aprenda a provisionar e configurar sua infraestrutura na nuvem
Introdução
O Ansible é uma ferramenta extremamente poderosa, podendo fazer todo a orquestração da sua infraestrutura. Porém, o que mais me chama atenção nele, é que podemos provisionar todo nosso ambiente na nuvem primeiramente e já configurá-lo em seguida.
Aqui vou demonstrar como conseguimos provisionar a seguinte infraestrutura e configurá-la com apenas uma playbook.
Iremos provisionar 4 instâncias, uma que será nosso LoadBalancer (LB01), duas que serão nossos servidores web (APP01 e APP02) e por fim o nosso banco de dados (Database).
Sem mais delongas vamos provisionar nosso ambiente:
Pré-requisitos:
Ansible, Python 2.7, Pip, Pip modules (boto, botocore), EC2 Key Pair, AWS Access key e Secret Key
Começamos baixando nossos arquivos
git clone https://github.com/guilhermewolf/aws-loadbalancer-ansible.git
Vamos editar dois arquivos
group_vars/all.yml
│
└──key_name: lb-ansible
Altere o nome da chave com a que você criou na AWS
inventory/hosts
│
└──ansible_ssh_private_key_file= ~/lb-ansible.pem
Altere para o local onde está a chave na sua máquina
Vamos colocar nossas credenciais da AWS como variáveis de ambiente
export AWS_ACCESS_KEY_ID=#SUA ACESSKEY#
export AWS_SECRET_ACCESS_KEY=#SUA SECRET KEY#
All set, let’s go!
ansible-playbook playbook.yml
Agora veja toda a infraestrutura ser provisionada diante de seus olhos.
Mas como tudo isso funciona?
O Ansible precisa primeiramente de uma relação de confiança tanto com a AWS quanto com as máquinas que foram provisionadas, por isso provemos para ele as credenciais da AWS e a chave privada que criamos para as instâncias. O Ansible precisa de um inventário, que é composto pelo endereço IP das máquinas das quais ele irá configurar, porém nossa playbook primeiramente irá criar as máquinas e só depois de criadas teremos os IP’s delas, precisamos então criar um inventário que seja dinâmico – por nossa sorte o próprio Ansible oferece um script em Python no Github para facilitar nossa vida, onde ele acessa a AWS pelas credenciais que oferecemos via variável de ambiente e lista nossas instâncias e seus devidos IP’s.
Essa é a estrutura de diretórios da nossa playbook.
.
├── group_vars
├── inventory
├── playbooks
└── roles
├── apache2
├── aws
├── demo_app
├── mysql
└── nginx
O arquivo playboook.yml contêm 8 etapas, em cada etapa ele irá chamar alguma role que está dentro do diretório roles.
Nossa playbook se inicia chamando o diretório roles/aws e criando as instâncias na AWS com o módulo ec2_instance, para o módulo oferecemos alguns itens, as credenciais da AWS, um nome para a máquina, a chave que ela irá usar, o security group, tipo da instância, id da imagem a ser usada e a região que ela irá ficar.
- name: Provision Loadbalancer
ec2_instance:
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
name: lb01
key_name: "{{ key_name }}"
security_group: "{{ security_group }}"
instance_type: "{{ instance_type }}"
image_id: "{{ image }}"
wait: true
state: running
region: "{{ region }}"
Fazemos isso para as 4 máquinas, porém nosso inventário iniciou na playbook sem nenhum IP dentro dele, pois as máquinas ainda não existiam, agora precisamos atualizar nosso inventário para receber esses IP’s
- name: refresh_inventory
hosts: localhost
gather_facts: False
tasks:
- meta: refresh_inventory
Agora com nosso inventário populado aguardamos nossas máquinas ficarem 100% provisionadas, iremos fazer isso aguardando que o Ansible consiga fazer uma conexão SSH nelas.
- name: Wait vms go up
hosts: all
user: ubuntu
gather_facts: False
tasks:
- wait_for_connection:
timeout: 300
Quando as máquinas são provisionadas na AWS um script é chamado pelo CloudInit para fazer uma configuração inicial das máquinas, adicionando alguns pacotes essenciais para a máquinas, nós precisamos garantir que esse script tenha encerrado a sua execução antes de começarmos a configurar as máquinas
- name: Wait for cloud init to finish
hosts: cluster
gather_facts: False
become: yes
tasks:
- cloud_init_data_facts:
filter: status
register: res
until: "res.cloud_init_data_facts.status.v1.stage is defined and not res.cloud_init_data_facts.status.v1.stage"
retries: 50
delay: 5
Após concluir esse estágio, daremos início as configurações das máquinas. Primeiramente, vamos atualizar a lista de pacotes disponíveis nos repositórios:
- hosts: all
become: true
user: ubuntu
gather_facts: true
tasks:
- name: update apt cache
apt: update_cache=yes cache_valid_time=86400
Agora vamos configurar cada máquina individualmente, começaremos pela database, dentro de nossa estrutura de diretórios temos a seguinte pasta:
roles
├── apache2
│ ├── handlers
│ ├── tasks
│ └── tests
├── aws
│ └── tasks
├── demo_app
│ ├── files
│ ├── handlers
│ ├── tasks
│ ├── templates
│ └── tests
├── mysql
│ ├── handlers
│ ├── tasks
│ └── tests
└── nginx
├── defaults
├── handlers
├── tasks
├── templates
└── test
Dentro de cada pasta das roles temos algumas outras dentro, a mais importante delas é a tasks, que será onde encontramos quais etapas de configurações serão feitas em nossas máquinas.
A pasta handlers contém ações a serem executadas caso sejam chamadas no arquivo main.yml dentro da pasta tasks (como por exemplo o comando systemctl restart caso alguma configuração seja feita).
Na pasta files podemos deixar arquivos que desejamos enviar para as máquinas remotas, em nosso exemplo temos os arquivos de configuração e o site em python. No arquivo main.yml dentro de tasks passamos o diretório do nosso arquivo e o destino dele na máquina remota.
- name: copy demo app source
copy: src=demo/app/ dest=/var/www/demo mode=0755
Dentro de templates podemos encontrar arquivos com o formato .j2 que é uma linguagem de templates para o python. Podemos criar arquivos de configurações para ele e ao invés de colocarmos os valores específicos que precisaremos, deixamos variáveis que o Ansible utiliza para serem populadas na hora de escrever o arquivo na máquina remota. Como é o caso em roles/demo_app/templates/demo.wsgi.j2
import os
os.environ['DATABASE_URI'] = 'mysql://{{ db_user }}:{{ db_pass }}@{{ groups.database[0] }}/{{ db_name }}'
Passamos as variáveis dbuser, dbpass e dbname para serem escritas no arquivo, assim podemos alterar apenas as variáveis que o Ansible utiliza no arquivo groupvars e todo nosso parque será provisionado corretamente.
Explore essa playbook e a utilize para criar suas futuras playbooks. Ela irá servir tanto para aprender a configurar seu parque de máquinas, tanto para aprender a provisionamento de instâncias na AWS.
Até mais pessoal!
About author
Você pode gostar também
Provisionamento de Data Platform na Azure com Terraform: Um Guia Prático
Um dos exemplos citados no ebook Governance as Code da 4Linux, é uma plataforma de dados na azure. Esse exemplo foi baseado no cenário atual em que eu trabalho, onde
Descubra o futuro do desenvolvimento de software com Docker e Kubernetes
Docker, Kubernetes, Openshift, enfim … escalabilidade! A tecnologia de containers está moldando o futuro do desenvolvimento de software e está causando uma mudança estrutural no mundo da computação, principalmente quando
Acelere seus algoritmos de Machine Learning com CUDA no Linux
Se você deseja trabalhar com algoritmos de Machine Learning, provavelmente precisará usar processamento paralelo para acelerar os resultados dos seus algoritmos. Muitos frameworks como por exemplo, o TensorFlow, já possuem







