Solução de gerenciamento automatizado e construção de laboratórios de máquinas virtuais (VMs), via arquivo único ('Vagrantfile'), descartando todas etapas de interações com SO e suas necessidades, conectado a um Provider (Hypervisor como VirtualBox). Pode ser conectado localmente ou até mesmo em Clouds (AWS, Azure, GCP, Digital Ocean, etc). Utiliza linguagem HCL (Hashicorp Configuration Language), baseada em Ruby. Para a criação de Boxes, recomenda-se o software Packer, ao invés dos Boxes na Vagrant, pois os mesmos tendem a possuir vulnerabilidades. Códigos conforme documentação oficial: Site oficial.
Instalação (Debian): sudo apt install vagrant #Comando 'vagrant version' para verificar instalação, ou 'vagrant -h' para ajuda. Também opção de Download na página oficial.
vagrant init: Gerar novo Vagrantfile baseado em uma Box ('-m' após init especifica criação mínima. '-f' para sobrescrever criação)
vagrant up: Iniciar VM e executadar Provisioner (Subir ambiente. Pode-se relacionar com Provider, como 'vagrant up --provider=vmware_fusion')
vagrant reload: Reiniciar VM
vagrant provision: Executar Provisioner
vagrant halt: Desligar VM (destroy excluir VM)
vagrant suspend: Pausar VM (resume retomar VM)
vagrant ssh: Acessar ssh da VM (Sintaxe: 'vagrant ssh [name|id] [--extra_ssh_args]')
vagrant powershell: Abrir PowerShell de Box que possua suporte
vagrant box list: Listar Boxes
vagrant box add USER/BOX: Somente adicionar Box
vagrant box remove hashicorp/bionic64: Remover Box específico #No caso, removeria o hashicorp/bionic64
vagrant status: Ver status de Box
vagrant global-status: Ver status dos ambientes de Boxes
vagrant port [name|id]: Listar portas disponíveis/abertas das Boxes
Estrutura do arquivo Vagrantfile e exemplo passo a passo de sua construção (Comando 'vagrant validate' valida o Vagrantfile):
1.Estrutura básica:
Vagrant.configure("2") do |config|
Conteúdo aqui
end
2.Boxes: (Executar vagrant up para criar, depois vagrant ssh para acessar)
Vagrant.configure("2") do |config|
Conteúdo aqui, exemplos abaixo:
config.vm.box = "ubuntu/xenial64" #Definir Box (SO e versão opcional)
end
3.Provisioner: (Executar vagrant provision para atualizar)
Existem várias possibilidades de Provisioners, como Shell, Ansible, Chef, Docker, Podman, Puppet, Salt, entre outros.
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.provision "shell",
inline: "apt update"
config.vm.provision "shell", inline:<<-SHELL
apt install -y apache2
SHELL
end
4.Especifiar porta de acesso e plugins: (Executar vagrant reload para reiniciar. Após, acessar porta 8080 da VM o apache2)
Podem ser redes privadas ou públicas, incluir hosts personalizados, protocolos personalizados, IP estático, entre outras configurações pormenores.
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
config.vagrant.plugins = ["vagrant-plugin", "vagrant-other-plugin"]
config.vm.provision "shell",
inline: "apt update"
config.vm.provision "shell", inline:<<-SHELL
apt install -y apache2
SHELL
end
O diretório em que encontra-se o Vagrantfile (Host), e o diretório '/vagrant' (Guest) são sincronizados por padrão. Para testar, crie, na VM, algo dentro do '/vagrant', saia da VM e vá ao diretório do Vagrantfile do Host para verificar se sua criação também encontra-se lá. Pode-se usar tipos personalizados, como NFS, RSync, SMB e via VirtualBox diretamente. Para modificar os padrões, segue linha de código no Vagrantfile:
Vagrant.configure("2") do |config|
config.vm.synced_folder "src/", "/srv/website" #Diretório Host, diretório Guest
end
Upload:
Enviar arquivos do Host para o Guest
vagrant upload source [destination] [name|id]
Pode-se interagir com o Vagrant Cloud, hospedando novos Boxes diretamente do mesmo. Para isso, precisa-se cadastro no Vagrant Cloud, conforme links acima. Pode-se interagir, inclusive, usando comandos 'cloud_init' no Vagrantfile. Os comandos abaixo entre colchetes são parâmetros opcionais. Os comandos abaixo possuem outros parâmetros de refinamento, que podem ser acessados na documentação oficial.
Autenticação:
vagrant cloud auth login #Informe dados conforme cadastro Vagrant Cloud. Use 'logout' ao invés de login para fazer logout
vagrant cloud auth login --token ABCD1234 #Mesmo comando, usando token de autenticação (Gerado nas configurações do site Vagrant Cloud)
Gestão de Boxes:
vagrant cloud box create ORGANIZATION/BOX-NAME #Criar Box
vagrant cloud box delete ORGANIZATION/BOX-NAME #Deletar Box
vagrant cloud box show ORGANIZATION/BOX-NAME #Ver Box
vagrant cloud box update ORGANIZATION/BOX-NAME #Editar Box
vagrant cloud search TERMO #Pesquisar no Vagrant Cloud (Exemplo: vagrant cloud search hashicorp --limit 5)
Gestão de Providers:
vagrant cloud provider create ORGANIZATION/BOX-NAME PROVIDER-NAME VERSION [URL] #Criar Provider
vagrant cloud provider delete ORGANIZATION/BOX-NAME PROVIDER-NAME VERSION #Deletar Provider
vagrant cloud provider update ORGANIZATION/BOX-NAME PROVIDER-NAME VERSION [URL] #Editar Provider
vagrant cloud provider upload ORGANIZATION/BOX-NAME PROVIDER-NAME VERSION BOX-FILE #Upload arquivo de Box para Vagrant Cloud
vagrant cloud publish ORGANIZATION/BOX-NAME VERSION PROVIDER-NAME [PROVIDER-FILE] #Publicar no Vagrant Cloud
Gestão de Versões:
vagrant cloud version create ORGANIZATION/BOX-NAME VERSION
vagrant cloud version delete ORGANIZATION/BOX-NAME VERSION
vagrant cloud version release ORGANIZATION/BOX-NAME VERSION
vagrant cloud version revoke ORGANIZATION/BOX-NAME VERSION #Desfazer alteração
vagrant cloud version update ORGANIZATION/BOX-NAME VERSION
Exemplo:
Publicar Box no Vagrant Cloud
vagrant cloud publish briancain/supertest 1.0.0 virtualbox boxes/my/virtualbox.box -d "Descrição aqui" --version-description "Versão 1" --release --short-description "Download me!"
Compartilhar ambiente Vagrant, via padrão/http/ssh.
Instalação:
vagrant plugin install vagrant-share
Via HTTP:
vagrant share #Incluir '--https' para casos de HTTPS
Via SSH:
vagrant share --ssh
vagrant share --full #Ver todas portas possíveis para conexão
Conectar:
vagrant connect --ssh NAME #Criará IP estático para conexões
Após criar o Vagrantfile, pode-se empacotá-lo para futuro compartilhamento, conforme códigos abaixo:
Empacotar Vagrantfile:
vagrant package [name|id]
vagrant package --base idBox #Gerará arquivo 'package.box', que poderá ser aberto com 'vagrant box add nomePacote.box'
vagrant package --vagrantfile Vagrantfile.pkg #Pacote de Vagrantfile
Complementos personalizados para Boxes Vagrant
Instalar:
vagrant plugin install <name>
vagrant plugin install /path/to/my-plugin.gem
Desinstalar/Reparar:
vagrant plugin expunge my-plugin #Incluir --reinstall para reinstalar. Incluir --force para remover forçadamente.
vagrant plugin uninstall <name> [<name2> <name3> ...]
Editar:
vagrant plugin update [<name>]
Listar
vagrant plugin list
Pode-se configurar discos, memória, CPUs das Boxes, particionando-os e configurando-os de forma personalizada, via Vagrantfile, conforme trechos de comandos abaixo. Entre os tipos de discos, tem-se 'disk', 'dvd' e 'floppy'. Para remover o disco, precisa-se remover a linha no Vagrantfile e executar 'vagrant reload'. Pode-se relacionar os discos com Providers, como VirtualBox, Hyper-V e VMWare.
Definir discos:
config.vm.disk: disk, name: "backup", size: "10GB"
config.vm.disk: disk, size: "100GB", primary: true
config.vm.disk: dvd, name: "installer", file: "./installer.iso"
config.vm.disk: floppy, name: "cool_files"
Memória (MB), CPUs:
config.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
vb.cpus = "2"
end
Criar ambiente com múltiplas máquinas, conforme exemplo abaixo:
Vagrant.configure("2") do |config|
config.vm.provision "shell", inline: "echo Hello"
config.vm.define "web" do |web|
web.vm.box = "apache"
end
config.vm.define "db" do |db|
db.vm.box = "mysql"
end
end
Acessar:
vagrant ssh apache
Snapshots preservam a VM em determinado estado/condições, assim como seus dados nela.
vagrant snapshot save [vm-name] NAME #Criar Snapshot (Similar: vagrant snapshot push)
vagrant snapshot restore [vm-name] NAME #Restaurar Snapshot (Similar: vagrant snapshot pop)
vagrant snapshot delete [vm-name] NAME #Deletar Snapshot
vagrant snapshot list #Listar Snapshots
Publicar aplicação em determinado servidor. Primeiro, define-se o servidor e suas respectivas configurações, para então executar comando Push, conforme códigos abaixo:
1. Configurar Server:
config.push.define "staging", strategy: "ftp" do |push|
push.host = "ftp.example.com"
push.username = "nome"
push.password = "senha"
end
1.2. Configurar Server Heroku:
config.push.define "heroku" do |push|
push.app = "my_application"
end
1.3.1. Local (Path Remoto):
config.push.define "local-exec" do |push|
push.inline = <<-SCRIPT
scp -r . server:/var/www/website
SCRIPT
end
1.3.2. Local (Path Local):
config.push.define "local-exec" do |push|
push.inline = <<-SCRIPT
cp -r . /var/www/website
SCRIPT
end
1.4. Via Shell Script:
config.push.define "local-exec" do |push|
push.script = "my-script.sh"
end
2. Executar Push:
vagrant push staging #Se não especificar o nome acima ('staging') no Vagrantfile, não precisará especificá-lo no comando (Somente vagrant push)
Comandos gatilhos que são ativados/executados após determinadas condições, especificadas no cabeçalho do trecho específico no Vagrantfile, conforme trechos de comandos abaixo. Pode-se especificar o type da Tigger, onde tem-se:
Executar comando após 'up':
config.trigger.after :up do |trigger|
Comandos aqui
end
Outros modelos:
config.trigger.before [:up, :destroy, :halt, :package] do |trigger|
Comandos aqui
end
config.trigger.after :up, :destroy, :halt, :package do |trigger|
Comandos aqui
end
Sempre executar:
config.trigger.before :all do |myTrigger|
myTrigger.name = "Run Trigger"
myTrigger.info = "Running a before trigger!"
myTrigger.ignore = [:destroy, :halt]
end
Em escopo Guest:
config.vm.define "ubuntu" do |ubuntu|
ubuntu.vm.box = "ubuntu"
ubuntu.trigger.before :destroy do |trigger|
trigger.warn = "Dumping database to /vagrant/outfile"
trigger.run_remote = {inline: "pg_dump dbname > /vagrant/outfile"}
end
end
Inlcuindo type:
config.trigger.after :destroy, type: :command do |t|
t.warn = "Destroy command completed"
end
Ordem de execução:
Vagrantfile
global trigger 1
global trigger 2
machine defined
machine trigger 3
global trigger 4
end
1. Criar Vagrantfile:
vagrant init -m ubuntu/bionic64
2. Complementar Vagrantfile com o seguinte código:
$script = <<-EOF
sudo apt-get update
sudo apt-get install -y nginx
EOF
Vagrant.configure("2") do |config|
config.vm.define "server1" do |server1|
server1.vm.box = "ubuntu/bionic64"
server1.memory = "1000"
server1.cpus = "1"
server1.vm.network "private_network", ip: "192.168.56.2" #Comando do Provider VirtualBox (Outros Providers trazem comandos diferentes)
config.vm.provision "shell", inline: $script
end
config.vm.define "server2" do |server2|
server2.vm.box = "centos/7"
server2.vm.network "private_network", ip: "192.168.56.3"
end
end
3. Criar Boxes:
vagrant up
vagrant status
4. Acessar máquinas:
vagrant ssh server1
vagrant ssh server1 -c "cat /etc/*release" #Realizar comando na Box via ssh
vagrant ssh server1 -c "ip -c a show enp0s8" #Mostrar IP configurado da máquina Ubuntu
vagrant ssh server2 -c "ip -c a show eth1" #Mostrar IP configurado da máquina CentOS
curl 192.168.56.2 #Acessará nginx da máquina Ubuntu. No Browser da máquina Host, acessar url '192.168.56.2'
Elaborado por Mateus Schwede
ubsocial.github.io