Was a long and dark December… Anos atrás…

Acessei meu servidor, e quando fui conferir o status de um banco de dados me deparei com a mensagem:

Send us 0.5 BTC to recover your database

Aquele vixe, atrás de eita.

Por pior que tenha sido ser hackeado, no futuro isso me faria estudar mais sobre segurança e a comprar bitcoins (isso não foi tão bom).

Apesar do susto, estava tranquilo, pois tinha comigo meu bloco de notas com os comandos para recuperar o servidor do zero.

Um bloco de notas com os comandos para recuperar o servidor do zero…

Um bloco de notas…

O importante é a gente ir evoluindo, né?

Não nego que, nesses anos, até foi divertido subir na unha um cluster spark, mapear cada porta do hadoop, resolver os bugs de colocar um servidor R-shiny num raspberry.

Mas, ter que refazer todo o processo duas, três vezes por ter bloqueado meu próprio ip, já era demais.

Todo esse ciclo mudou quando conheci as ferramentas de Infra as a Code (IaaC).

Neste post, quero compartilhar um projeto recente que escrevi para por um ponto final nesta trabalheira de subir e derrubar máquinas na cloud.

Tl;dr

O projeto Dirty Deeds Done Dirt Cheap disponibiliza um conjunto de scripts em Terraform e Ansible para criação de instâncias na cloud da Digital Ocean.

A ideia é reduzir o desgaste gerado na configuração dessas máquinas, já disponibilizando ferramentas de segurança e ambiente para prototipagem com docker.

Todas as instruções para operacionalização do projeto estão em seu README.

Infrastructure as a Code

Quando encaramos a construção e configuração da nossa infraestrutura de processamento (e.b. computadores) como um código, passamos a ter um menor custo (tempo, dinheiro), menor risco de erros humanos e podemos versionar nossos códigos para melhor rastreabilidade de erros e colaboração com parceiros.

Só vantagens para o desenvolvedor.

Existem diferentes linguagens, ferramentas para trabalharmos com IaaC. Direcionadas para uma cloud especifica ou multi-cloud; declarativas ou imperativas…

Vale apena explorar as alternativas. Se tiver interesse no tema, experimente o livro do Kief Morris - Infrastructure as Code

Aqui, vamos focar em duas ferramentas complementares: Terraform e Ansible.

Terraform

Terraform é um software de código aberto para gerenciamento de Infra as a Code que utiliza de linguagem proprietária (HCL) para comunicação com as APIs das provedoras de Cloud.

Duas características fazem o Terraform ser uma opção interessante pra sua IaaC.

Primeiro, antes de enviar requisições à API da cloud, Terraform cria um plano de execução que permite verificar todos os recursos e/ou modificações necessárias na sua infraestrutura.

O plano ainda conta um grafo de dependência das alterações necessárias, o que permite a paralelização de atividades.

Somado a isso, para realizar modificações numa infra já existente não é necessariamente obrigatório reconstruir ela do zero.

As execuções criam um arquivo (.tfstate) que armazena os recursos, configurações e metadados da infra criada pelo Terraform.

Caso tenha, interesse o material introdutório do Terraform é um bom ponto de partida.

Ansible

Ansible é uma ferramenta de provisionamento de software. De forma curta, ele é capaz de acessar uma máquina já existente via SSH e promover a instalação e configuração de softwares.

As chamadas tasks que ele executará devem estar contidas em arquivos .yaml, denominados playbooks.

Nos playbooks declaramos as instalações desejadas, não como uma linha de comando, mas utilizando módulos do próprio Ansible.

Se quisermos, por exemplo, instalar o python via apt, bastaria adicionar as seguintes linhas em um playbook.

- name: Install python
  apt:
    name: python

Além de tornar o trabalho de provisionamento automatizado, Ansible é escalável.

Ao definir as ações em cada playbook, também somos capazes de referenciar em qual máquina ou grupo de máquinas queremos aplicar cada task do playbook.

Isto é possível pelo Ansible trabalhar com o conceito de inventários.

[master]
127.0.0.1
bar.example.com

[workers]
one.example.com
two.example.com

Exemplo de inventário

O inventário é um arquivo contendo o endereço das máquinas que terão provisionamento realizado pelo Ansible.

Nos headers do aquivo temos a denominação que daremos para aplicar uma certa instrução àquelas máquinas.

Para aplicar a instrução de instalação do python apenas nas máquinas workers e de instalação do docker nas máquinas master, podemos escrever o seguinte playbook.

- hosts: master
  become: yes
  tasks:
    - name: install Docker  
      apt:
        name: docker.io

- hosts: workers
  become: yes
  tasks:
    - name: install python  
      apt:
        name: python

Caso se interesse pelo tema, recomendo o livro Ansible for DevOps

Dirty Deeds Done Dirt Cheap (D4C)

Quando procurei um nome pra esse projeto, não esperava algo tão alinhado com seu propósito.

Sua referência pode ser AC/DC ou JoJo Bizarre Adventures, no fim, o que queremos é fazer algo entediante da forma mais ráṕida.

O D4C se propõe a criar um instância de tamanho e distribuição personalizavel usando a Digital Ocean como provedora de Cloud. No processo também é criada uma chave de acesso SSH para conexão.

Após criada a instância, o Ansible realiza o provisionamento, configurando o firewall via ufw, levantando proteção contra ataques via fail2ban e impedindo o acesso via root.

Finalmente, docker é instalado para que as aplicações deployadas no servidor sejam na forma de containers.

Para entrarmos em maiores detalhes, vejamos a árvore de arquivos e diretórios do projeto.

.
├── ansible/
│   ├── jail.local
│   ├── provision.yml
│   └── SSHd_config
├── connect.sh
├── create.sh
├── credentials/
│   ├── id_rsa
│   └── id_rsa.pub
├── destroy.sh
├── setup.sh
└── terraform/
    ├── env/
    │   ├── keys.tfvars
    │   ├── project.tfvars
    │   └── provider.tfvars
    ├── main.tf
    ├── out/
    ├── outputs.tf
    └── variables.tf

O arquivo main.tf é o coração do projeto. Além de criar a instância e as chaves SSH, é ele que executa o playbook de Ansible para o posterior provisionamento de recursos.

Com o módulo provider possibilitamos a comunicação do Terraform com as API da cloud.

Os módulos resource se referem a tudo que iremos criar de forma transparente na DIgital Ocean. A digitalocean_droplet se refere às instàncias de máquina virtual que desejamos, referenciamos ela com o nome “droplet”.

No módulo de connection, definimos o tipo de acesso, usuário, e outros parâmetros de conexão com a droplet.

Nos módulos de provisioner, temos uma distinção do provisionamento executado de dentro da instância (remote-exec) e aquele executado pela máquina local (local-exec).

Apesar dos playbooks em Ansible permitirem executar os comandos que estão no provisionamento remoto, adicionamos um provisionamento remoto para garantir que o local-exec só seja executado com a instância já criada.

Observe que o main.tf é completamente parametrizado. O valor assumido pelas variáveis utilizadas estão contidos nos arquivos keys.tfvars, project.tfvars e provider.tfvars.

Desses arquivos, o provider.tfvars é um lista contendo as opções disponíveis pela API da Digital Ocean para cada recurso. Use o keys.tfvars para adicionar seu API token e personalize o arquivo project.tfvars com informações do seu projeto.

Não recomendo alterar qualquer outro arquivo, exceto se desejar adicionar alguma funcionalidade adicional.

Conforme o README disponibilizado, personalize os arquivos .tfvars comentados acima, e execute os arquivos .sh para ter sua instância pronta para uso em poucos minutos.

Devaneios finais

Foi um projeto bem divertido!

Me esforcei em comentar todos os códigos, e tornar a operacionalização bem transparente.

Deu tão certo para mim, que uso o servidor criado pelo D4C para o deploy de minhas aplicações.

Espero que possa ser útil a você também!