> ./deploy_cluster.sh --with-control-node_

Vagrant & Ansible : L'Art du "Control Node" Automatisé

Par Nicolas DELAHAYE | v.1974 | Architecte Solution

STATUS: SSH_KEYS_DISTRIBUTED


C'est un mur que tout ingénieur DevOps rencontre tôt ou tard. Vous voulez construire un lab réaliste : Une VM "Maître" (Control Node) qui configure plusieurs VMs "Esclaves" (Workers) via Ansible.

Le problème ? Vagrant est conçu pour isoler. Par défaut, il génère une clé SSH unique par machine. Résultat : votre VM Maître ne peut pas se connecter aux Workers. La solution naïve consiste à lancer ansible_local sur chaque machine indépendamment, mais c'est un anti-pattern qui ne simule pas la réalité d'un cluster.

// Pour comprendre en détail pourquoi l'architecture ansible_local est souvent incontournable (surtout sur Windows), je vous invite à lire mon comparatif : Vagrant : Ansible vs Ansible_Local et le mythe du Control Node.

Pour réussir une Vagrant Ansible Inventory propre et automatisée, nous devons inverser la logique : générer une clé de confiance unique et construire l'inventaire dynamiquement.

Au lieu de laisser Vagrant gérer ses clés, nous allons créer une paire de clés "Cluster" sur l'hôte (votre PC) et la distribuer.

Le Flux Architectural :
1. Host : Génère une paire de clés SSH (Privée/Publique).
2. Vagrant : Injecte la clé Publique dans tous les Workers.
3. Vagrant : Monte la clé Privée dans le Control Node.
4. Ruby : Génère le fichier d'inventaire .ini automatiquement.

Voici le code complet. Il fait tout le travail sale à votre place. Pas de bidouille manuelle.

Note : Ce script écrit le fichier d'inventaire sur votre machine hôte pour qu'il soit accessible dans la VM via le dossier partagé /vagrant. Si vous rencontrez des problèmes de performance ou de permissions sur ce partage, vérifiez votre configuration de montage (voir mon article : Vagrant Synced Folders : Le casse-tête Windows vs Linux).

# 1. Génération de la clé Cluster (si absente)
KEY_PATH = ".vagrant/cluster_key"
unless File.exist?(KEY_PATH)
  system("ssh-keygen -t ed25519 -f #{KEY_PATH} -N '' -C 'vagrant-cluster'")
end
CLUSTER_PUBKEY = File.read("#{KEY_PATH}.pub")

# 2. Préparation de l'inventaire dynamique
inventory_content = ["[all:vars]", 
                     "ansible_user=vagrant", 
                     "ansible_ssh_private_key_file=/vagrant/#{KEY_PATH}", 
                     "ansible_ssh_common_args='-o StrictHostKeyChecking=no'", 
                     "", "[controllers]", "control-node ansible_host=192.168.56.10",
                     "", "[workers]"]

Vagrant.configure("2") do |config|
  
  # --- DEFINITION DES WORKERS ---
  (1..2).each do |i|
    ip = "192.168.56.2#{i}"
    name = "worker#{i}"
    
    config.vm.define name do |node|
      node.vm.box = "ubuntu/jammy64"
      node.vm.network "private_network", ip: ip
      node.vm.hostname = name
      
      # Injection de la clé publique
      node.vm.provision "shell", inline: "echo '#{CLUSTER_PUBKEY}' >> /home/vagrant/.ssh/authorized_keys"
      
      # Ajout à l'inventaire en mémoire
      inventory_content << "#{name} ansible_host=#{ip}"
    end
  end

  # --- DEFINITION DU CONTROL NODE ---
  config.vm.define "control-node" do |node|
    node.vm.box = "ubuntu/jammy64"
    node.vm.network "private_network", ip: "192.168.56.10"
    node.vm.hostname = "control-node"

    # Injection de la clé publique (pour qu'il puisse se connecter à lui-même si besoin)
    node.vm.provision "shell", inline: "echo '#{CLUSTER_PUBKEY}' >> /home/vagrant/.ssh/authorized_keys"

    # Installation d'Ansible sur le Control Node uniquement
    node.vm.provision "shell", inline: "apt-add-repository ppa:ansible/ansible -y && apt-get update && apt-get install ansible -y"

    # 3. Écriture du fichier d'inventaire sur le disque Hôte
    # Il sera accessible dans la VM via /vagrant/inventory.ini
    File.write("inventory.ini", inventory_content.join("\n"))

    # 4. Lancement du Playbook (Mode Parallel Execution)
    node.vm.provision "ansible_local" do |ansible|
      ansible.playbook = "playbook.yml"
      ansible.inventory_path = "/vagrant/inventory.ini"
      ansible.limit = "all"
      ansible.verbose = true
    end
  end
end

Avec cette configuration :

  • Zéro Friction : Un simple vagrant up construit le cluster, les clés et lance Ansible.
  • Isolation Propre : Votre machine Windows/Mac ne lance pas Ansible. C'est la VM "control-node" qui le fait, via le montage /vagrant.
  • Scalabilité : Changez (1..2) en (1..10) et votre inventaire se met à jour automatiquement.

C'est la différence entre "bidouiller des scripts" et faire de l'Infrastructure as Code. Vous respectez le principe DRY (Don't Repeat Yourself) et vous préparez un environnement qui ressemble à 99% à une production réelle (Bastion + Private Subnet).

Share This