Alisson Machado
25 December 2020

Capítulo 6: Automatizando sua infraestrutura como código

Este capítulo tem como objetivo explicar como funciona a infraestrutura como código, instalar o Vagrant, como utiliza-lo, criando novas Máquinas Virtuais de forma automatizada usando shell script e configuração de toda a infraestrutura que já fizemos antes. 

 

Estrutura: 

Neste capítulo discutiremos os seguintes tópicos: 

  • Introdução à Infraestrutura como Código 
  • Instalando vagrant e criando máquinas virtuais 
  • Configuração de um servidor LAMP 
  • Configuração de um servidor Docker 

 

Objetivos 

Depois de estudar esta unidade, você deve ser capaz de: 

  • O que é Vagrant e como ele funciona 
  • Configurar um ambiente Docker usando automação vagante 
  • Configuração de um servidor Apache 
  • Benefícios da Automação


Introdução à Infraestrutura como Código 

 

Infraestrutura como Código é uma técnica utilizada para documentar, versionar e manter o controle de sua infraestrutura de forma muito semelhante que fazemos com o Desenvolvimento de Software, então podemos criar um arquivo descrevendo o estado desejado da nossa infraestrutura, implantá-lo em um Ambiente de Teste, validar seu código, implantar em um ambiente de Staging e se tudo correr bem, você pode proceder para o ambiente de Produção. Utilizando Pipelines; portanto, você pode usar o mesmo código para todo o ambiente e alterar os tamanhos do Servidor usando variáveis definidas para cada um dos ambientes. 

 

O que é e Como funciona 

 

No início deste livro você aprendeu a configurar o VirtualBox, baixar a ISO, criar uma Máquina Virtual, anexar a ISO, formatar e instalar o Sistema Operacional, isso é uma tarefa muito recorrente no dia a dia de um Engenheiro DevOps, você pode se imaginar instalando 100 Máquinas Virtuais todos os dias e destruindo-as após o dia de trabalho para economizar dinheiro? É insano, mas quando usamos Infraestrutura como Código essa tarefa é muito fácil de fazer porque você só precisa fazer alguns cliques ou executar alguns comandos para criar e destruir tudo. 

 

Vagrant é uma ferramenta que pode ser integrada com a Virtual Box e é responsável por ler seu código, convertê-lo em comandos do VirtualBox e também executar o código dentro da Máquina Virtual. Então você não precisa executar todas essas etapas aprendidas no primeiro capítulo.


A Hashicorp é a empresa que criou o Vagrant e eles têm um repositório oficial de imagens que você pode usar para configurar seu ambiente, assim, você não precisa ir ao site oficial, baixar a ISO e configurar a máquina. 

 

Instalação do Vagrant 

 

Você pode baixar o Vagrant seguindo este link: 

 

https://www.vagrantup.com/downloads.html 

 

Estou usando Windows, então eu vou baixar a versão MSI. 


 

 

O processo de instalação é simples como qualquer software instalado no Windows, você só precisa abrir o arquivo MSI e seguir o processo, Next, Next, Finish com todas as opções Padrão. 

 

 


 

 

Agora, com a instalação concluída, vamos aprender o básico. 

 

Usando o Vagrant 

 

Em primeiro lugar, você pode criar uma pasta para armazenar seus arquivos como eu fiz. 

 

PS C:\Users\1511 MXTI> mkdir VagrantChapter

Directory: C:\Users\1511 MXTI

Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 4/13/2020 11:17 AM VagrantChapter


PS C:\Users\1511 MXTI> cd .\VagrantChapter\

PS C:\Users\1511 MXTI\VagrantChapter>

 

Criei uma pasta chamada VagrantChaper e entrei nessa pasta. Que está vazia, para criar seu primeiro código, você pode digitar o seguinte comando: 

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant init
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.
PS C:\Users\1511 MXTI\VagrantChapter>

 

O comando vagrant init, cria para você um arquivo de exemplo com a configuração comum para a maioria dos casos de Máquinas Virtuais, vamos dar uma olhada no conteúdo do arquivo. 

 

PS C:\Users\1511 MXTI\VagrantChapter> cat .\Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "base"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access

# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
# vb.memory = "1024"
# end
#
# View the documentation for the provider you are using for more
# information on available options.
# Enable provisioning with a shell script. Additional provisioners such as
# Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# apt-get update
# apt-get install -y apache2
# SHELL

end

 

Na mesma pasta, você pode executar este comando: 

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant status Current machine states:

default not created (virtualbox)


 Significa que temos uma Máquina Virtual chamada padrão e ela ainda não foi criada, mas não vamos criá-la. 

 

O arquivo de exemplo tem algumas configurações e muitos comentários dando uma breve explicação do que os comandos fazem. Este arquivo com a configuração padrão permite criar apenas uma Máquina Virtual, neste capítulo criaremos duas máquinas virtuais, uma com o servidor LAMP instalado e outra com o Docker instalado. Vou modificar esse arquivo e explicar as diferenças entre o arquivo de exemplo e o novo. 

 

# -*- mode: ruby -*-

# vi: set ft=ruby :

Vagrant.configure("2") do |config|
    config.vm.box = "ubuntu/focal64"
    config.vm.box_check_update = false
    config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
end


config.vm.define "lamp" do |lamp|
    lamp.vm.network "private_network", ip: "192.168.33.10"
    lamp.vm.provision "shell", inline: <<-SHELL
    apt-get clean
    apt update -y
SHELL

end

config.vm.define "docker" do |docker|
    docker.vm.network "private_network", ip: "192.168.33.11"
    docker.vm.provision "shell", inline: <<-SHELL
    apt-get clean
    apt update -y
SHELL
end

config.vm.provision "shell", inline: <<-SHELL
    apt-get clean
    apt update -y
SHELL
End

 

Acima está o meu novo arquivo, ele é mais limpo do que o exemplo e está fazendo mais coisas. Vamos executar o comando vagrant status, para ver se algo mudou. 

  

PS C:\Users\1511 MXTI\VagrantChapter> vagrant status Current machine states:

lamp not created (virtualbox)
docker not created (virtualbox)

 

Interessante, agora temos duas máquinas virtuais, uma é chamada de LAMP e a outra é chamada Docker ambas ainda não foram criadas. No novo arquivo eu usei um recurso do Vagrant chamado Multi-Machine, ele permite que você crie mais de uma máquina no mesmo arquivo. 

 

Agora vamos analisar o arquivo e o que acontecerá antes de criarmos as Máquinas Virtuais. 

 

config.vm.box = "ubuntu/focal64"
  config.vm.box_check_update = false
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
end

 

Esta parte com config.vm é a configuração comum para todas as máquinas virtuais declaradas no arquivo, então todas as máquinas serão criadas com 1024mb de RAM, config.vm.box é a imagem que será usada na máquina, no nosso caso usaremos o Servidor Ubuntu, versão 20.04. 

 

config.vm.define "lamp" do |lamp|
  lamp.vm.network "private_network", ip: "192.168.33.10"
  lamp.vm.provision "shell", inline: <<-SHELL
    apt-get clean
    apt update -y
  SHELL
end

 

Nesta parte temos uma configuração local apenas para a máquina chamada LAMP, esta VM terá o Endereço IP 192.168.33.10 e os comandos que serão executados no provisionamento da VM estao dentro desta parte: lamp.vm.provision, as mesmas configuracaoes se aplicam para a VM Docker. 

 

config.vm.provision "shell", inline: <<-SHELL
    apt-get clean
    apt update -y
  SHELL


A parte final temos o config.vm.provision , dentro desse bloco você pode definir o comando que será executado em todas as VMs, diferente de lamp.vm.provision, que será executado apenas na VM LAMP e docker.vm.provision, que será executado apenas na VM docker.


Portanto, podemos ter configurações globais que serão executadas em todas as VMs e configurações locais que serão executadas apenas na VM especificada. 

 

Up and Running 

 

Com o arquivo explicado e tudo configurado para criar as VMs, digite o seguinte comando: 

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant up --provider=virtualbox 
Bringing machine 'lamp' up with 'virtualbox' provider...
Bringing machine 'docker' up with 'virtualbox' provider...
==> lamp: Box 'ubuntu/focal64' could not be found. Attempting to find and install...
lamp: Box Provider: virtualbox
lamp: Box Version: >= 0
==> lamp: Loading metadata for box 'ubuntu/focal64'
lamp: URL: https://vagrantcloud.com/ubuntu/focal64

                                                                                                                                                                                                                                 

Vai demorar um pouco porque o Vagrant baixar as Boxes. 

 

==> lamp: Loading metadata for box 'ubuntu/focal64'
lamp: URL: https://vagrantcloud.com/ubuntu/focal64
==> lamp: Adding box 'ubuntu/focal64' (v20200409.0.0) for provider: virtualbox
lamp: Downloading: https://vagrantcloud.com/ubuntu/boxes/focal64/versions/20200409.0.0/providers/virtualbox.box
lamp: Download redirected to host: cloud-images.ubuntu.com
lamp: Progress: 11% (Rate: 1411k/s, Estimated time remaining: 0:06:09)


A Box é uma imagem em nuvem, mas com configurações específicas para rodar em cima do Vagrant, como você pode ver nos logs, o Vagrant está baixando a imagem para VirtualBox, também é possível provisionar usando Hyper-V ou KVM. 

 

Vagrant Cloud ( http://vagrantcloud.com/), é o repositório oficial para baixar as imagens, mas é claro que não é o único, você também pode criar suas próprias imagens usando Packer (https://packer.io/).

 

 

 

Após o provisionamento, se você quiser verificar suas Boxes locais, você pode usar o seguinte comando: 

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant box list 
centos/7 (virtualbox, 1801.02)
fedora/28-cloud-base (virtualbox, 20180425)
ubuntu/bionic64 (virtualbox, 20190807.0.0)
ubuntu/focal64 (virtualbox, 20200409.0.0)
ubuntu/xenial64 (virtualbox, 20180413.0.0)Status: Downloaded newer image for

 

Se você tem uma nova instalação provavelmente você só tem o ubuntu/focal64, esse é o que baixamos. 

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant status
Current machine states:
lamp running (virtualbox)
docker running (virtualbox)

 

Se tudo correu bem com o seu provisionamento, executando o comando vagrant status, ele mostrara-lhe as VMs em execução. Se houver uma máquina que ainda não foi criada, você pode tentar executar o vagrant up –provider=virtualbox novamente e ver se ele funciona, se não funciona, verifique sua instalação e sua conexão com a internet. 

 

Você não definiu nenhuma senha ou chave ssh para conexão com esses VMs, então, como nos conectamos a eles? O Vagrant também está gerenciando isso para nós, com o vagrant status podemos ver os nomes VM e podemos usar esses nomes para conectar usando o comando vagrant ssh. 

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant ssh docker

Welcome to Ubuntu Focal Fossa (development branch) (GNU/Linux 5.4.0-21-generic x86_64)

* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage

 

A VM foi provisionada com sucesso e como você pode ver com a versão Ubuntu que definimos, o Vagrant também criou um usuário vagrant, para se conectar nos VMs, que tem permissão sudo, para que possamos apenas alterar o usuário e executar todos os comandos. 

vagrant@ubuntu-focal:~$ sudo su -
root@ubuntu-focal:~#                                                                                                                                                                        

 

Agora você pode gerenciar tudo como fizemos nos capítulos anteriores, mas vamos ver como podemos prover uma LAMP de forma automatizada. 

 

Configuração de um servidor LAMP 

 

Você já conhece os comandos, então podemos basicamente colocar os comandos na seção de provisão do arquivo e provisão do VM novamente. 

 

# -*- mode: ruby -*-

# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/focal64"
  config.vm.box_check_update = false
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
  end


config.vm.define "lamp" do |lamp|
  lamp.vm.network "private_network", ip: "192.168.33.10"
  lamp.vm.hostname = "lamp"
  lamp.vm.provision "shell", inline: <<-SHELL
    sudo apt-get clean
    sudo apt update -y
    sudo apt install apache2 mysql-server php7.4 -y
  SHELL
end


config.vm.define "docker" do |docker|
  docker.vm.network "private_network", ip: "192.168.33.11"
  docker.vm.hostname = "docker"
  docker.vm.provision "shell", inline: <<-SHELL
    apt-get clean
    apt update -y
  SHELL
end


config.vm.provision "shell", inline: <<-SHELL
  apt-get clean
  apt update -y
SHELL

end

 

Neste caso mudei o lamp.vm.provision, incluindo o script shell para instalar o PHP, Apache e MySQL Server, para executar os comandos com a VM já em execução, voce pode executar o comando vagrant provision: 

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant provision lamp
==> lamp: Running provisioner: shell...
lamp: Running: inline script
lamp:
lamp: WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
lamp: Get:1 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]
lamp: Hit:2 http://security.ubuntu.com/ubuntu focal-security InRelease
lamp: Hit:3 http://archive.ubuntu.com/ubuntu focal-updates InRelease

 

Você pode seguir o processo de provisionamento em seu terminal, após o término da instalação, você pode fazer login na VM. 


 PS C:\Users\1511 MXTI\VagrantChapter> vagrant ssh lamp
Welcome to Ubuntu Focal Fossa (development branch) (GNU/Linux 5.4.0-21-generic x86_64)

 

Verifique os serviços em execução. 

 

vagrant@lamp:~$ ss -ntpl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 151 127.0.0.1:3306 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:53 0.0.0.0:*
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 70 *:33060 *:*
LISTEN 0 511 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*

 

E verifique o Ip Adddress, que é o definido no Vagrantfile. 

 

vagrant@lamp:~$ ip a
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:69:a5:81 brd ff:ff:ff:ff:ff:ff
inet 192.168.33.10/24 brd 192.168.33.255 scope global enp0s8
valid_lft forever preferred_lft forever

 

Portanto, você pode verificar o endereço IP no navegador e ver o apache em execução. 



 

 

 

Agora, toda vez que você quiser prover um novo servidor LAMP, você pode basicamente copiar o código ou incluir um novo VM com o código de provisão e ele funcionará. 

 

Configuração do Servidor Docker 

 

Este processo não é diferente do primeiro, então vamos editar o Vagrantfile novamente. 

 

# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/bionic64"
  config.vm.box_check_update = false
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
  end

config.vm.define "lamp" do |lamp|
  lamp.vm.network "private_network", ip: "192.168.33.10"
  lamp.vm.hostname = "lamp"
  lamp.vm.provision "shell", inline: <<-SHELL
    sudo apt-get clean
    sudo apt update -y
    sudo apt install apache2 mysql-server php7.4 -y
  SHELL
 end
  
  
config.vm.define "docker" do |docker|
  docker.vm.box = "ubuntu/bionic64"
  docker.vm.network "private_network", ip: "192.168.33.11"
  docker.vm.hostname = "docker"
  docker.vm.provision "shell", inline: <<-SHELL
      apt clean
      apt-get update
      apt-get remove docker docker-engine docker.io containerd runc -y
      apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common -y
      curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
      add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
      apt-get update -y
      apt-get install docker-ce docker-ce-cli containerd.io -y
    SHELL
  end
  config.vm.provision "shell", inline: <<-SHELL
    apt-get clean
    apt update -y
  SHELL
end

 

Note que mudei apenas para a Docker VM, pois no Docker repo o suporte para Focal Fosse ainda não estava disponível, mas também é interessante nos mostrar como podemos criar diferentes VMs com diferentes versões de Sistemas Operacionais. 

 

Agora, dentro da parte de provisionamento da VM Docker temos todas as etapas de instalação para configurar o servidor, então você pode iniciar a máquina novamente. 

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant up docker
Bringing machine 'docker' up with 'virtualbox' provider...
==> docker: Importing base box 'ubuntu/focal64'...
==> docker: Matching MAC address for NAT networking...
==> docker: Setting the name of the VM: VagrantChapter_docker_1586798805547_50415
==> docker: Fixed port collision for 22 => 2222. Now on port 2200.

 

Execute o comando de provisão: 

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant provision docker
==> docker: Running provisioner: shell...
docker: Running: inline script
docker: WARNING:
docker: apt
docker:
docker: does not have a stable CLI interface.
docker: Use with caution in scripts.
docker: Get:1 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]

 

Vamos verificar se a instalação ocorreu com sucesso,  

 

PS C:\Users\1511 MXTI\VagrantChapter> vagrant ssh docker
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-55-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantageSuccessfully installed Jinja2-2.11.1 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.1 flask-1.1.1 itsdangerous-1.1.0

 

Verificando se Docker está funcionando. 

 

Se você enfrentar alguns problemas de conexão, é importante verificar se o Host Network Manager no VirtualBox está ativado. 

 

 

 

Verifique a coluna DHCP Server se ela está habilitada e se o Endereço IPv4 está na rede 192.168.33.0/24, como na imagem a seguir. 

 

 

 

 

 

Conclusão 

                                                                                                                                                   

Neste capítulo pudemos ver os benefícios de usar uma ferramenta como Vagrant, que nos permite escrever as configurações da Máquina Virtual como Imagem O.S, Endereço IP, Hostname, VM Memory e etc.

Na parte de provisionamento podemos escrever um Script Shell e o script será executado durante a inicialização, se ele não for executado ou se você quiser executar o script novamente, você pode executar a comando vagrant provision.


O Vagrant permite que você use diferentes tecnologias como Ansible, Puppet ou Chef para criar seus próprios scripts de provisionamento, usei o Shell Script como exemplo, mas sinta-se livre para testar e criar seus próprios scripts. Outra coisa importante aprendida é o Vagrantfile, neste arquivo você definiu tudo e você pode compartilhar o conteúdo com sua equipe, para que eles estejam disponíveis para contribuir com você para desenvolver o seu ambiente.