MET : Ansible automation (3/6)


Configurer un serveur manuellement est acceptable. En configurer dix est fastidieux. En configurer cent est impossible. Ansible résout ce problème avec élégance.
Dans l’ article précédent, nous avons vu comment Terraform crée nos serveurs. Mais un serveur fraîchement créé est « nu » : pas de Kubernetes, pas de configuration, rien. C’est là qu’Ansible intervient.
Le problème : la configuration manuelle
Après la création d’un serveur, la liste des tâches est longue :
- Mettre à jour le système
- Installer les dépendances
- Configurer le pare-feu
- Désactiver le swap (requis pour Kubernetes)
- Charger les modules du noyau
- Installer Kubernetes
- Configurer le réseau
- …
Faire cela manuellement pose plusieurs problèmes :
- Temps : 2-3 heures par serveur, minimum
- Erreurs : Un oubli, une faute de frappe, et cela ne fonctionne plus
- Dérive : Avec le temps, les serveurs divergent (configurations différentes)
- Documentation : « Comment avons-nous configuré cela déjà ? »
La solution : Ansible
Ansible est un outil d’automatisation open source qui permet de configurer des serveurs de manière déclarative et idempotente.
Idempotent : Vous pouvez exécuter le même playbook 100 fois, le résultat sera toujours le même. Si quelque chose est déjà configuré, Ansible ne le refait pas.
Avantages clés :
- Sans agent : Ansible se connecte via SSH, rien à installer sur les serveurs
- Lisible : Les playbooks sont en YAML, compréhensibles par tous
- Idempotent : Exécution sûre et reproductible
- Modulaire : Des milliers de modules disponibles
L’inventaire : définir vos serveurs
Tout commence par l’inventaire, qui liste les serveurs et leurs caractéristiques :
# inventory/hosts.yml all: children: k8s_cluster: children: control_plane: hosts: k8s-master: ansible_host: 128.140.xxx.xxx private_ip: 10.0.1.10 workers: hosts: k8s-worker-1: ansible_host: 91.99.xxx.xxx private_ip: 10.0.1.11 vars: ansible_user: root ansible_ssh_private_key_file: ~/.ssh/id_rsa k3s_version: "v1.28.5+k3s1" cluster_cidr: "10.42.0.0/16" service_cidr: "10.43.0.0/16"
Cet inventaire définit :
- Groupes : control_plane, workers, k8s_cluster
- Variables par hôte : Adresses IP publiques et privées
- Variables globales : Version K3s, configuration réseau
Playbook 1 : Préparation des serveurs
Notre premier playbook prépare les serveurs pour Kubernetes :
# playbooks/prepare-servers.yml --- - name: Préparation des serveurs hosts: k8s_cluster become: true # Exécuter en tant que root tasks: - name: Mettre à jour les paquets apt: update_cache: yes cache_valid_time: 3600 - name: Installer les dépendances apt: name: - curl - wget - git - htop - open-iscsi # Requis pour Longhorn - nfs-common # Requis pour le stockage NFS - cryptsetup # Chiffrement - jq # Analyse JSON state: present - name: Désactiver le swap shell: swapoff -a when: ansible_swaptotal_mb > 0 - name: Désactiver le swap de manière permanente replace: path: /etc/fstab regexp: '^([^#].*?sswaps+sws+.*)$' replace: '# \1'
Chaque tâche est explicite :
- name : Description lisible de ce que fait la tâche
- apt : Module Ansible pour la gestion des paquets Debian/Ubuntu
- when : Condition d’exécution (ici, uniquement si le swap existe)
Configuration du noyau
Kubernetes nécessite certains modules du noyau et paramètres système :
- name: Configurer les modules du noyau
copy:
dest: /etc/modules-load.d/k8s.conf
content: |
overlay
br_netfilter
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
- name: Charger les modules
modprobe:
name: "{{ item }}"
state: present
loop:
- overlay
- br_netfilter
- ip_vs
- name: Configurer sysctl
sysctl:
name: "{{ item.key }}"
value: "{{ item.value }}"
state: present
reload: yes
loop:
- { key: 'net.bridge.bridge-nf-call-iptables', value: '1' }
- { key: 'net.bridge.bridge-nf-call-ip6tables', value: '1' }
- { key: 'net.ipv4.ip_forward', value: '1' }
- { key: 'fs.inotify.max_user_watches', value: '524288' }
Notez l’utilisation de loop pour répéter une tâche avec différentes valeurs. C’est plus propre que de dupliquer le code.
Playbook 2 : Installation de Kubernetes (K3s)
Une fois les serveurs préparés, nous installons K3s :
# playbooks/install-k3s.yml
---
- name: Installation du plan de contrôle K3s
hosts: control_plane
become: true
tasks:
- name: Télécharger le script K3s
get_url:
url: https://get.k3s.io
dest: /tmp/k3s-install.sh
mode: '0755'
- name: Installer le serveur K3s
shell: |
INSTALL_K3S_VERSION={{ k3s_version }} \
K3S_TOKEN={{ k3s_token }} \
INSTALL_K3S_EXEC="server \
--cluster-init \
--disable traefik \
--write-kubeconfig-mode 644 \
--tls-san {{ ansible_host }} \
--node-ip {{ private_ip }} \
--advertise-address {{ private_ip }} \
--cluster-cidr {{ cluster_cidr }} \
--service-cidr {{ service_cidr}}" \
sh /tmp/k3s-install.sh
args:
creates: /usr/local/bin/k3s # Exécuter uniquement si k3s n'existe pas
- name: Récupérer le kubeconfig
fetch:
src: /etc/rancher/k3s/k3s.yaml
dest: ../kubeconfig
flat: yes
Points importants :
- creates : Rend la tâche idempotente (s’exécute uniquement si le fichier n’existe pas)
- fetch : Récupère le kubeconfig sur notre machine locale
- –disable traefik : Nous installerons notre propre Traefik configuré
Installation des workers
- name: Installation des workers K3s
hosts: workers
become: true
tasks:
- name: Installer l'agent K3s
shell: |
INSTALL_K3S_VERSION={{ k3s_version }} \
K3S_URL=https://{{ hostvars['k8s-master']['private_ip'] }}:6443 \
K3S_TOKEN={{ hostvars['k8s-master']['k3s_join_token'] }} \
INSTALL_K3S_EXEC="agent \
--node-ip {{ private_ip }}" \
sh /tmp/k3s-install.sh
args:
creates: /usr/local/bin/k3s
Les workers rejoignent automatiquement le cluster en utilisant le jeton du plan de contrôle.
Playbook 3 : Services de base
Après K3s, nous installons les services essentiels via Helm :
# playbooks/install-core-services.yml --- - name: Installation des services de base hosts: control_plane become: true tasks: - name: Installer Helm shell: | curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash args: creates: /usr/local/bin/helm - name: Ajouter les dépôts Helm shell: | helm repo add traefik https://traefik.github.io/charts helm repo add longhorn https://charts.longhorn.io helm repo add jetstack https://charts.jetstack.io helm repo add argo https://argoproj.github.io/argo-helm helm repo update environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml - name: Installer Traefik shell: | helm upgrade --install traefik traefik/traefik \ --namespace infra-system \ --create-namespace \ --set ports.web.redirectTo.port=websecure \ --wait --timeout 5m environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml - name: Installer Cert-Manager shell: | helm upgrade --install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace \ --set installCRDs=true \ --wait --timeout 5m environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml - name: Installer Longhorn shell: | helm upgrade --install longhorn longhorn/longhorn \ --namespace longhorn-system \ --create-namespace \ --set defaultSettings.defaultReplicaCount=2 \ --wait --timeout 10m environment: KUBECONFIG: /etc/rancher/k3s/k3s.yaml
Exécution des playbooks
Pour exécuter un playbook :
# Tester la connexion aux serveurs ansible all -i inventory/hosts.yml -m ping # Exécuter un playbook ansible-playbook -i inventory/hosts.yml playbooks/prepare-servers.yml # Mode simulation (voir ce qui serait fait sans exécuter) ansible-playbook -i inventory/hosts.yml playbooks/install-k3s.yml --check
Dans notre projet, nous avons simplifié avec des commandes Make :
# Tester la connexion make ansible-ping # Installer K3s make ansible-install-k3s # Installer les services de base make ansible-core-services
Nos bonnes pratiques Ansible
📁 Organisation
ansible/ ├── inventory/ │ ├── hosts.yml # Inventaire des serveurs │ └── group_vars/ # Variables par groupe ├── playbooks/ │ ├── prepare-servers.yml │ ├── install-k3s.yml │ └── install-core-services.yml ├── templates/ # Fichiers de configuration Jinja2 └── ansible.cfg # Configuration Ansible
🔐 Sécurité
- Ansible Vault : Chiffrer les variables sensibles
- Clés SSH : Jamais de mots de passe en clair
- become : Utiliser sudo plutôt que root direct
✅ Idempotence
- Utiliser creates ou removes pour les commandes shell
- Préférer les modules Ansible aux commandes shell lorsque c’est possible
- Tester avec –check avant d’appliquer
Le résultat
Avec nos playbooks Ansible :
| Avant (manuel) | Après (Ansible) |
|---|---|
| 2-3 heures par serveur | 15 minutes pour l’ensemble du cluster |
| Documentation séparée (souvent obsolète) | Le code EST la documentation |
| Configuration différente entre les serveurs | Configuration identique garantie |
| « Ça marchait avant… » | 100 % reproductible |
Et ensuite ?
Nous avons maintenant :
- ✅ Des serveurs créés par Terraform
- ✅ Un cluster Kubernetes configuré par Ansible
- ✅ Des services de base installés (Traefik, Longhorn, Cert-Manager)
Dans le prochain article, nous verrons comment Kubernetes et Rancher nous permettent de gérer nos applications avec une interface intuitive et des fonctionnalités puissantes.
🚀 Vous passez trop de temps à configurer vos serveurs ?
Nous pouvons vous aider à automatiser votre infrastructure avec Ansible. Gagnez du temps, réduisez les erreurs, dormez tranquille.
