Files
Blog/content/post/20-automating-proxmox-update-ansible/index.fr.md
Gitea Actions 2fac832345
All checks were successful
Blog Deployment / Deploy-Staging (push) Successful in 35s
Blog Deployment / Test-Staging (push) Successful in 3s
Blog Deployment / Merge (push) Successful in 7s
Blog Deployment / Deploy-Production (push) Successful in 35s
Blog Deployment / Test-Production (push) Successful in 3s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
Blog Deployment / Check-Rebuild (push) Successful in 6s
Blog Deployment / Build (push) Has been skipped
Auto-update blog content from Obsidian: 2026-06-09 20:17:47
2026-06-09 20:17:47 +00:00

311 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
slug: automating-proxmox-update-ansible
title: Automatiser les mises à jour de Proxmox VE avec Ansible
description: Automatisez les mises à jour dun cluster Proxmox VE avec Ansible, Semaphore UI et Ntfy, incluant les vérifications Ceph, les redémarrages progressifs et les rapports.
date: 2026-06-09
draft: false
tags:
- proxmox
- ansible
- semaphore-ui
- ntfy
categories:
- homelab
---
## Intro
Dans mon homelab, les mises à jour font partie de ces choses faciles à repousser.
Pas parce quelles sont compliquées, mais parce quelles sont manuelles. Je dois me connecter au bon système, vérifier létat, appliquer les mises à jour, redémarrer si nécessaire, vérifier que tout revient correctement, puis répéter le même processus pour le composant suivant.
Et comme cest manuel, je le garde généralement pour plus tard.
Quand Proxmox VE 9.1 est sorti, je voulais déjà mettre à jour mon cluster, mais pas manuellement. Puis Proxmox VE 9.2 est devenu disponible il y a quelques jours, et je navais toujours pas construit de processus propre autour de cela. Cétait un bon déclencheur pour enfin commencer à automatiser les mises à jour des parties importantes de mon homelab.
Lobjectif plus large est de simplifier et dautomatiser le patching de plusieurs composants clés :
- Proxmox VE
- OPNsense
- TrueNAS
Jai décidé de commencer par Proxmox parce quil est central dans le lab, et parce quun workflow de mise à jour progressive est un bon candidat pour lautomatisation.
---
## Les Outils Utilisés
Le processus de mise à jour est construit autour de quelques composants que jutilise déjà dans le lab.
[Proxmox VE](https://www.proxmox.com/en/proxmox-virtual-environment/overview) est ma plateforme de virtualisation. Le cluster utilise aussi Ceph, donc avant de toucher à un nœud, je veux massurer que le cluster est en bonne santé et que Ceph remonte `HEALTH_OK`.
[Ansible](https://docs.ansible.com/) est utilisé pour décrire le workflow de mise à jour sous forme de playbook.
[Semaphore UI](https://semaphoreui.com/) est utilisé pour exécuter le playbook depuis une interface web et le planifier.
[Ntfy](https://ntfy.sh/) est utilisé pour les notifications. Si les mises à jour sont planifiées, jai besoin de savoir quand quelque chose se passe, surtout si le cluster nest pas prêt ou si une mise à jour échoue.
---
## Création dun Topic Ntfy Dédié
Avant de planifier quoi que ce soit, je voulais un canal de notification dédié au homelab.
Jai créé un topic `homelab` dans Ntfy et un utilisateur dédié nommé `semaphore` avec un accès en écriture seule à ce topic.
```bash
ntfy user add semaphore
ntfy access semaphore homelab wo
```
Lidée est que Semaphore a uniquement besoin de publier des messages. Il na pas besoin dun accès en lecture.
Jai aussi ajouté le topic sur mon téléphone mobile afin de pouvoir recevoir des notifications lorsque lautomatisation sexécute.
Dans Semaphore, jai créé un groupe de variables nommé `Ntfy Homelab` pour stocker les valeurs nécessaires aux playbooks :
- `ntfy_url`
- `ntfy_topic`
- `ntfy_user`
- `NTFY_PASSWORD`
Le mot de passe est stocké comme variable denvironnement dans longlet `Secrets`.
![Groupe de variables Semaphore utilisé pour stocker la configuration Ntfy des notifications du homelab](images/semaphore-ntfy-homelab-variables.png)
---
## Conception du Workflow de Mise à Jour Proxmox
Pour Proxmox, je ne voulais pas dun playbook qui exécute simplement `apt upgrade` sur tous les nœuds. À la place, il fait les actions suivantes :
- Vérifier la santé du cluster
- Arrêter et envoyer une notification Ntfy si le cluster nest pas prêt
- Pour chaque nœud, vérifier si des mises à jour sont disponibles, et si oui :
- Activer le mode maintenance
- Attendre que les LXC et les VM quittent le nœud
- Mettre à jour les paquets
- Désactiver le rééquilibrage Ceph
- Redémarrer le nœud
- Activer le rééquilibrage Ceph
- Désactiver le mode maintenance
- Attendre que Ceph soit en bonne santé
- Envoyer un rapport Ntfy final
Le playbook complet est disponible sur mon [dépôt Homelab](https://git.vezpi.com/Vezpi/Homelab/src/branch/lab/ansible/proxmox/update_proxmox.yml)
---
## Détails du Workflow
Avant de démarrer la mise à jour progressive, le playbook vérifie :
- Le quorum du cluster Proxmox
- La santé de Ceph
Si lune de ces vérifications échoue, le playbook sarrête et envoie une notification Ntfy au lieu dessayer de continuer.
```yaml
- name: Verify cluster quorum
ansible.builtin.command: pvecm status
register: quorum_status
changed_when: false
failed_when: quorum_status.stdout is not search('Quorate:\\s*Yes')
- name: Verify Ceph health
ansible.builtin.command: ceph health
register: ceph_health
changed_when: false
failed_when: "'HEALTH_OK' not in ceph_health.stdout"
```
Cest une partie importante de lautomatisation. Une mise à jour planifiée ne doit pas continuer aveuglément si le cluster nest pas dans un bon état.
Le playbook met à jour les nœuds Proxmox avec `serial: 1`.
Cela signifie quun seul nœud est traité à la fois, ce qui est exactement ce que je veux pour une mise à jour de cluster.
Pour chaque nœud, le playbook commence par rafraîchir les dépôts et vérifie si des mises à jour sont disponibles en utilisant le mode check dAnsible.
```yaml
- name: Refresh repositories
ansible.builtin.apt:
update_cache: true
- name: Check if updates are available
ansible.builtin.apt:
upgrade: dist
check_mode: true
register: apt_check
```
Si aucune mise à jour nest disponible pour un nœud, la partie lourde du workflow est ignorée.
Si des mises à jour sont disponibles, le playbook stocke la version actuelle de Proxmox, active le mode maintenance, attend que les invités quittent le nœud, applique les mises à jour, redémarre le nœud, puis attend que Ceph soit de nouveau en bonne santé.
```yaml
- name: Enable maintenance mode
ansible.builtin.command: >
ha-manager crm-command node-maintenance enable {{ inventory_hostname_short }}
```
Une fois le mode maintenance activé, le playbook attend quil ne reste plus aucun LXC en cours dexécution sur le nœud :
```yaml
- name: Wait for LXCs to leave node
ansible.builtin.shell: |
pct list | awk 'NR>1 && $2=="running" {count++} END {print count+0}'
register: lxc_count
changed_when: false
until: lxc_count.stdout | int == 0
retries: 60
delay: 15
```
Il fait la même chose pour les VM en cours dexécution :
```yaml
- name: Wait for VMs to leave node
ansible.builtin.shell: |
qm list | awk 'NR>1 && $3=="running" {count++} END {print count+0}'
register: vm_count
changed_when: false
until: vm_count.stdout | int == 0
retries: 60
delay: 15
```
Une fois que le nœud est vide, la mise à niveau des paquets peut sexécuter :
```yaml
- name: Update packages
ansible.builtin.apt:
upgrade: full
autoremove: true
autoclean: true
```
Avant de redémarrer, le playbook définit `noout` sur les OSD Ceph :
```yaml
- name: Disable Ceph rebalancing
ansible.builtin.command: ceph osd set noout
```
Puis le nœud est redémarré :
```yaml
- name: Reboot node
ansible.builtin.reboot:
reboot_timeout: 900
post_reboot_delay: 30
```
Après le redémarrage, le rééquilibrage Ceph est réactivé, le mode maintenance est désactivé, et le playbook attend que Ceph revienne à `HEALTH_OK`.
```yaml
- name: Enable Ceph rebalancing
ansible.builtin.command: ceph osd unset noout
- name: Disable maintenance mode
ansible.builtin.command: >
ha-manager crm-command node-maintenance disable {{ inventory_hostname_short }}
- name: Wait for Ceph to be healthy
ansible.builtin.command: ceph health
register: ceph_status
changed_when: false
until: "'HEALTH_OK' in ceph_status.stdout"
retries: 60
delay: 15
delegate_to: "{{ groups['nodes'][0] }}"
```
Le résultat est une mise à jour progressive contrôlée au lieu dune procédure manuelle nœud par nœud.
---
## Envoi dun Rapport de Mise à Jour
À la fin du workflow, le playbook envoie un rapport via Ntfy. Il détermine dabord si au moins un nœud a été mis à jour :
```yaml
- name: Determine if updates occurred
ansible.builtin.set_fact:
updates_performed: "{{ groups['nodes'] | map('extract', hostvars) | selectattr('update_report', 'defined') | list | length > 0 }}"
```
Ensuite, il envoie un message au topic `homelab`.
Si aucune mise à jour nétait disponible, la notification lindique et utilise une priorité plus basse.
Si des mises à jour ont été appliquées, la notification liste les nœuds mis à jour et affiche la version de Proxmox avant et après la mise à jour.
La logique de rapport est basée sur le fact `update_report` sauvegardé pendant la mise à jour du nœud :
```yaml
- name: Save update report
ansible.builtin.set_fact:
update_report:
old: "{{ pve_old_version.stdout }}"
new: "{{ pve_new_version.stdout }}"
```
Le corps de la notification construit ensuite un résumé à partir de tous les nœuds :
```yaml
body: |
{% set updated_nodes = [] %}
{% for node in groups['nodes'] %}
{% if hostvars[node].update_report is defined %}
{% set _ = updated_nodes.append(node) %}
{% endif %}
{% endfor %}
{% if not updates_performed %}
No updates available on the cluster.
{% else %}
The following nodes were updated:
{% for node in updated_nodes %}
{% if hostvars[node].update_report.old == hostvars[node].update_report.new %}
- {{ hostvars[node].inventory_hostname_short }}: version {{ hostvars[node].update_report.old }} (unchanged)
{% else %}
- {{ hostvars[node].inventory_hostname_short }}: version {{ hostvars[node].update_report.old }} → {{ hostvars[node].update_report.new }}
{% endif %}
{% endfor %}
{% endif %}
```
Cela rend la tâche planifiée beaucoup plus facile à considérer comme fiable. Je nai pas besoin douvrir Semaphore à chaque fois pour savoir ce qui sest passé.
---
## Exécuter le Playbook depuis Semaphore
Une fois le playbook prêt, je lai poussé dans le dépôt et jai configuré un modèle de tâche Semaphore pour lexécuter.
![Modèle de tâche Semaphore utilisé pour exécuter le playbook de mise à jour Proxmox](images/semaphore-playbook-update-proxmox-template.png)
À partir de là, je pouvais lancer le workflow et le regarder agir sur le cluster.
Pendant lexécution, le nœud cible entre en mode maintenance et les workloads en cours dexécution sont migrés hors de celui-ci.
![Nœud Proxmox en mode maintenance pendant que le playbook de mise à jour migre les workloads hors du nœud](images/proxmox-update-playbook-maintenance.png)
Cest à ce moment-là que lautomatisation devient vraiment utile. Le playbook napplique pas seulement les mises à jour. Il prend aussi en charge les étapes opérationnelles autour de la mise à jour.
---
## Planification de la Mise à Jour
Après avoir affiné le playbook et validé le workflow, jai créé une planification dans Semaphore.
Dans `Schedule`, jai cliqué sur `New Schedule`, sélectionné `Cron`, donné un nom, sélectionné une planification hebdomadaire, puis choisi le vendredi à 4h00 UTC.
![Planification hebdomadaire Semaphore pour le playbook de mise à jour Proxmox](images/semaphore-schedule-proxmox-update.png)
À ce stade, le processus de mise à jour de Proxmox nest plus quelque chose dont je dois me souvenir pour le faire manuellement.
Il sexécute selon une planification, vérifie létat du cluster avant de faire quoi que ce soit, met à jour un nœud à la fois, et envoie une notification avec le résultat.
---
## Conclusion
Ce projet est parti dun problème simple : je ne mettais pas mon homelab à jour régulièrement parce que le processus était encore trop manuel.
Lautomatisation des mises à jour Proxmox était la première étape importante. La partie importante nétait pas seulement dexécuter les mises à niveau de paquets, mais de les entourer des vérifications et des étapes opérationnelles qui ont du sens pour un cluster Proxmox avec Ceph.
Semaphore me donne une façon propre dexécuter et de planifier le playbook. Ansible décrit le processus de manière répétable. Ntfy boucle la boucle en me disant ce qui sest passé.
Les prochaines étapes logiques sont de continuer avec la même approche pour les autres composants clés du lab : OPNsense et TrueNAS.