Administrer des machines virtuelles avec vagrant


Vagrant est un utilitaire pour aider au management des hyperviseurs tel que Virtualbox (présent par défaut) en ligne de commande.

Pour faire simple, les commandes ci-dessous fonctionne si l'on se trouve dans le dossier où il y a le fichier Vagrantfile.

Prérequis

J'utilise actuellement la version 1.6.5 de Vagrant sur ma Debian 8 dont la version du noyau est 3.16. Pour l'installer rien de plus simple vu que les paquets et dépendances se trouvent déjà dans les dépôts Debian :

apt-get install virtualbox vagrant

Pour utiliser les versions actuelles, voici comment s'y prendre :

echo "deb http://download.virtualbox.org/virtualbox/debian jessie contrib" > /etc/apt/sources.list.d/virtualbox.list
apt-get install virtualbox-5.1
wget https://releases.hashicorp.com/vagrant/1.9.1/vagrant_1.9.1_x86_64.deb
dpkg -i vagrant_1.9.1_x86_64.deb

Manipulations courantes

Commandes Résultat obtenu
vagrant init debian/contrib-jessie64 Initialiser une machine
vagrant up Pour démmarer une machine
vagrant reload Stoppe et redémarre la machine
vagrant provision Pour relancer le provisioning d'une machine (il se lance dès sa première sous tension)
vagrant halt Stoppe la machine
 vagrant ssh pour s'y connecter via ssh
vagrant box update pour mettre à jour la machine virtuelle à sa dernière version
vagrant box list Liste des machines virtuelles avec leur nom
 vagrant box remove ma_VM Supprime la machine virtuelle
vagrant global-status –prune Liste l'état des machines ainsi que leur localisation

Jouer les box

  • Lister les box :
vagrant box list
  • Mise à jour d'une box :
vagrant box update
  • Supprimer une box :
vagrant box remove <ma_box>

Jouer les Snapshots

Pour que ça fonctionne, il faut ce plugin :

vagrant plugin install vagrant-vbox-snapshot
Commandes Résultat obtenu
vagrant snapshot take <nom_snapshot> Prend une capture de l'image système
vagrant snapshot list <nom_snapshot> Liste des snapshot
vagrant snapshot back <nom_snapshot> Restaurer le dernier snapshot
vagrant snapshot delete <nom_snapshot> Supprimer un snapshot spécifique
vagrant snapshot go <nom_snapshot> Resaurer un snapshot spécifique

Partager les machines

  • Rassembler les fichiers de la machine virtuelle en question :
vagrant package <nom_de_la_box>
  • Importer la box depuis un autre machine physique :
vagrant box add <nom_de_la_box>
  • Puis on démarre la VM :
vagrant up

C'est tout!

Configurer avec Vagrantfile

Dans mon cas Vagrant est une surcouche de virtualbox. De ce fait, les options déjà apportées sur la VM seront pas modifié si elles ne sont pas spécifié dans le fichier Vagrantfile.

L'atlas permet de choisir la machine à importer sur son système. Intéressons nous à une Debian Jessie en 64bits.

Il suffit juste de lancer la commande d'initialisation:

vagrant init debian/contrib-jessie64

Puis de modifier le fichier de configuration pour apporter ses propres besoins. Ci-dessous, je liste quelques exemple :

Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "debian/contrib-jessie64"
 
  # Redirection de ports (forwarding) :
  config.vm.network "forwarded_port", guest: 80, host: 8080
 
  # Définir le hostname :
  config.vm.hostname = "hostname"
 
  # Definir des adresses mac aux interfaces (dans le cas d'un routeur virtualisé):
  # A noté que la 1er interface est utilisé par vagrant pour une connexion via ssh en local. 
  config.vm.network "public_network", adapter: 2, :bridge => "usb0", :mac => "0800279B84E8", ip: "192.168.1.1"
  config.vm.network "public_network", adapter: 3, :bridge => "eth0" # Les paramètres non mentionné sont celle utilisé par défaut.
 
  # Définir une Ip dans un réseau interne appelé "mynetwork" :
  config.vm.network "private_network", adapter:2, ip: "192.168.50.3", virtualbox__intnet: "mynetwork"
 
  # Provisionnement via Ansible :
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "provisioning/playbook.yml"
    ansible.inventory_path = "provisioning/inventory"
    ansible.sudo = true
  end
 
  # Installer des paquets lors du premier boot :
  config.vm.provision "shell", inline: "sudo -p vagrant apt-get install iftop htop iotop tmux -y"
 
  # Ou sur plusieurs lignes (les commandes sont exécuter en tant que root) :
  config.vm.provision "shell", inline: <<-SHELL
     apt-get update
     apt-get install -y apache2
 
     # Cela permet de se connecter avec un compte utilisateur de la VM au lieu d'être obligé d'échanger les certificats :
     sed -i.bak 's/^PasswordAuthentication/#/' /etc/ssh/sshd_config
     sed -i.bak 's/^PermitRootLogin/#/' /etc/ssh/sshd_config
 
     service ssh restart
   SHELL
 
  # Désactive la sécurité par l'échange de clé :
  config.ssh.insert_key=false
 
  # Si la machine hôte dispose que d'un seul core et que le boot est lent (par défaut c'est 300 secondes).
  config.vm.boot_timeout = 600
 
  # Si l'on souhaite pas avoir de proposition de mise à jour de la VM :
  config.vm.box_check_update = false
 
  # Synchronisation des dossiers entre l'hôte et la machine virtuelle :
  config.vm.synced_folder "/dossier_machine_hote", "/mnt"
 
  # Ou pour désactiver celui par défaut :
  config.vm.synced_folder "/chemin/absolue/de/la/vm","/vagrant", disabled:true
 
  # Personnaliser le hardware de la machine :
  config.vm.provider "virtualbox" do |vb|
    vb.gui = true
    vb.customize ["modifyvm", :id, "--memory", "2048"]
    vb.customize ["modifyvm", :id, "--cpus", "2"]
    # Création d'un second disque de 5Go :
    vb.customize ['createhd', '--filename', "/tmp/disk.vdi", '--size', 5 * 1024]
    vb.customize ["storageattach", :id, "--storagectl", "SATA Controller", "--port", "1", "--device", "0", "--type", "hdd", "--medium", "/tmp/disk.vdi"]
  end
# pour KVM : config.vm.provider :libvirt do |vb|
end

Voici au minimum un fichier de configuration valide :

Cliquez pour afficher ⇲

Cliquez pour masquer ⇱

Vagrant.configure("2") do |config|

  config.vm.box = "debian/jessie64"

   config.vm.network "forwarded_port", guest: 80, host: 80
   config.vm.hostname = "debian64"
   config.vm.box_check_update = false
   config.vm.network "public_network", adapter: 2, :bridge => "enp0s20f0u9" 
   config.vm.provision "shell", inline: <<-SHELL
	
   apt-get update
   apt install htop nmon tmux iotop -y
   sed -i.bak 's/^PasswordAuthentication/#/' /etc/ssh/sshd_config
   sed -i.bak 's/^PermitRootLogin/#/' /etc/ssh/sshd_config:x  
   service ssh restart
   SHELL

   config.vm.synced_folder "/home/btatu/vagrant/debian8", "/vagrant", disabled:true

end

Vu que c'est un fichier écrit en Ruby, il est tout à fait possible d'aller beaucoup plus loin et par exemple automatiser le lancement d'une ferme de serveur faisant tourner docker swarm :

Cliquez pour afficher ⇲

Cliquez pour masquer ⇱

Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Faire au dépant des hostname
 
Vagrant.configure("2") do |config|
  config.vm.box = "fujimakishouten/debian-stretch64"
  config.vm.box_check_update = false
 
# Provision des deux machines :
  config.vm.provision "shell", inline: <<-EOS
set -x
sudo echo "deb [trusted=yes] https://apt.dockerproject.org/repo debian-stretch main" > /etc/apt/sources.list.d/docker.list
sudo apt-get install apt-transport-https ca-certificates iftop curl htop iotop tmux dirmngr sshpass -y
sudo apt-get --allow-unauthenticated update
 
# Onstallatio nde docker :
#sudo curl -sSL get.docker.com |sh
sudo sudo apt-get --allow-unauthenticated install docker-engine -y
 
# L'utilisateur swarm aura les droits d'executer les conteneurs :
sudo useradd -m -s /bin/bash -g users swarm
echo swarm:swarm |chpasswd
sudo usermod -aG docker swarm
 
sudo sed -i.bak 's/^PasswordAuthentication/#/' /etc/ssh/sshd_config
sudo service ssh restart
    EOS
 
# Configuration matériel appliqué aux machines :
  config.vm.provider "virtualbox" do |vb|
    vb.customize ["modifyvm", :id, "--memory", "1024"]
    vb.customize ["modifyvm", :id, "--cpus", "1"]
  end
 
# Déclaration des VMs :
 
  config.vm.define "swarm2" do |server|
 
        config.vm.hostname = "swarm2"
        config.vm.network "public_network", adapter: 2, :bridge => "eno1", ip: "192.168.1.205"
 
        sleep(2)
 
        if ARGV.include?("--provision") then
 
                config.vm.provision "shell", inline: <<-EOS
                        set -x
                        token=$(cat /tmp/token.txt |grep token |head -1 |awk '{ print $2 }')
                        docker swarm join --token $token 192.168.1.201
                EOS
        end
 
  end
 
  config.vm.define "swarm3" do |server|
 
        config.vm.hostname = "swarm3"
        config.vm.network "public_network", adapter: 2, :bridge => "eno1", ip: "192.168.1.203"
 
        sleep(2)
 
        if ARGV.include?("--provision") then
 
                config.vm.provision "shell", inline: <<-EOS
                        set -x
                        token=$(cat /tmp/token.txt |grep token |head -1 |awk '{ print $2 }')
                        docker swarm join --token $token 192.168.1.201
                EOS
        end
 
  end 
 
  config.vm.define "swarm4" do |server|
 
        config.vm.hostname = "swarm4"
        config.vm.network "public_network", adapter: 2, :bridge => "eno1", ip: "192.168.1.204"
 
        sleep(2)
 
        if ARGV.include?("--provision") then
 
                config.vm.provision "shell", inline: <<-EOS
                        set -x
                        token=$(cat /tmp/token.txt |grep token |head -1 |awk '{ print $2 }')
                        docker swarm join --token $token 192.168.1.201
                EOS
        end
 
  end
 
  config.vm.define "swarm1" do |server|
 
        config.vm.hostname = "swarm1"
        config.vm.network "public_network", adapter: 2, :bridge => "eno1", ip: "192.168.1.201"
 
        config.vm.provision "shell", inline: <<-EOS
                set -x
                sudo -u swarm docker swarm init --listen-addr 192.168.1.201 --advertise-addr enp0s8 > /tmp/token.txt
                sudo -u swarm sshpass -p swarm scp -o StrictHostKeyChecking=no /tmp/token.txt swarm@192.168.1.205:/tmp/token.txt
                sudo -u swarm sshpass -p swarm scp -o StrictHostKeyChecking=no /tmp/token.txt swarm@192.168.1.203:/tmp/token.txt
                sudo -u swarm sshpass -p swarm scp -o StrictHostKeyChecking=no /tmp/token.txt swarm@192.168.1.204:/tmp/token.txt
        EOS
  end
 
end

Il s'agira ensuite de lancer ces commandes :

vagrant up
vagrant up --provision

Pour des infos complémentaires, il y a la doc : https://www.vagrantup.com/docs/

Utiliser KVM comme provider

Nous avons desoin de ces dépendances :

apt-get install qemu-utils libvirt-dev libxslt-dev libxml2-dev zlib1g-dev ruby-dev

Nous téléchargeons ensuite le paquet officiel depuis le site Internet Hashicorp :

wget https://releases.hashicorp.com/vagrant/1.9.5/vagrant_1.9.5_x86_64.deb
dpkg -i vagrant_1.9.5_x86_64.deb

Il faudra également installer les plugins suivant :

vagrant plugin install vagrant-mutate
vagrant plugin install vagrant-libvirt

Après avoir attendu quelques minutes, nous pouvons définir les caractéristiques de la machine de la manière suivante (dans le Vagrantfile):

    machine.vm.provider :libvirt do |setting|
      setting.memory = 2048
      setting.cpus = 2
      setting.random_hostname = "foreman"
    end

Il restera plus qu'a lancer la machine ainsi :

vagrant up

Automatiquement il prendra le provider libvirt de KVM car nous l'avons défini dans le fichier de configuration. Sinon, il prendra automatiquement le provider virtualbox.

Si nous le voulons pas toucher au Vagrantfile :

vagrant up --provider libvirt

Déplacer le stockage des VMs

VBoxManage setproperty machinefolder /nouveau/dossier

Migrer de Virtualbox à Vagrant

Ne sachant pas encore comment fonctionne le routage de paquets avec des réseaux différents sous Linux, j'utilise une machine virtuel basé sur IPFire sous Windows. Légère et rapide à mettre en place (et surtout cross-platform!). Voici la procédure de son importation :

On répère le nom de la VM :

VBoxManage list vms

J'obtiens :

"ipfire" {b8aedeb3-9780-4d19-9145-6ee8bd01368b}

On récupère son ID pour signaler à vagrant que l'on veut utiliser cette machine

vagrant package --base b8aedeb3-9780-4d19-9145-6ee8bd01368b --output ipfire.box  
vagrant box add ipfire.box --name ipfire

On initialise puis on lance la VM :

vagrant init ipfire
vagrant up

Source : http://ebarnouflant.com/posts/7-convert-a-virtualbox-ova-vm-into-a-vagrant-box