Domine o Ansible: Aprenda a provisionar e configurar sua infraestrutura na nuvem

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!

CURSOSCONSULTORIA    CONTATO

Anterior Aumente a maturidade DevOps da sua empresa com a 4Linux
Próxima Recrutamento eficiente e assertivo com a plataforma Rankdone

About author

Você pode gostar também

Infraestrutura TI

Primeiros passos com OpenStack: Como criar um ambiente de testes

Sempre que falamos sobre “primeiros passos”  em alguma tecnologia, realizamos algum pequeno teste como um “Hello World” em uma linguagem ou um pequeno blog quando estamos estudando um framework web

DevOps

Guia definitivo: Como criar e implementar pipelines com Jenkins

O que é o Jenkins ? Jenkins é uma ferramenta de auxilio a construção de pipelines de construção de software. Com ele podemos automatizar toda as etapas de compilação e

Cloud

Entenda o papel crucial do API Gateway na infraestrutura de TI

Com o aumento considerável do uso dos conhecidos cloud providers, alguns tópicos que eram restritos ao vocabulário dos profissionais de infraestrutura acabaram transbordando para outras áreas, em especial para os