Chapitre 05

Mises à jour automatiques

Une plateforme qui ne se met pas à jour finit par se faire visiter. La nôtre se met à jour toutes les nuits, pendant que tout le monde dort, et elle prévient avant.

Niveau avancé  ·  Lecture 11 min  ·  Base Talos 1.14, Kubernetes 1.36

01Proposer le jour, appliquer la nuit

QuoiQui proposeQui appliqueQuand
Charts Helm et images du socleRenovate, en merge requestUn humain fusionne, puis le bootstrap ou Argo CD appliqueRenovate passe chaque nuit à 01:00
Talos et KubernetesRenovate, en merge requesttuppr, noeud par noeuddemo 02:00 à 03:30, mgmt 05:30 à 06:30
Routeur DebianDebianunattended-upgradesChaque jour, redémarrage à 04:30 si nécessaire

La règle qui gouverne le tout : une machine propose, un humain décide, une machine applique. Personne ne surveille les sorties de versions, personne ne tape de commande de mise à jour à 2 heures du matin, et rien ne change sans une trace dans Git.

02Renovate : la veille automatique

Renovate tourne en CronJob sur mgmt, avec un jeton GitLab limité au dépôt. Chaque nuit, il compare les versions écrites dans le dépôt aux dernières publiées, ouvre une merge request par mise à jour avec les notes de version, et tient un tableau de bord dans un ticket. Comme nos versions sont dans des fichiers simples, une règle générique suffit par composant :

Extrait de renovate.json
{
  "customType": "regex",
  "description": "Chart Helm traefik",
  "managerFilePatterns": ["/^k8s/traefik/version$/"],
  "matchStrings": ["^(?<currentValue>\\S+)"],
  "depNameTemplate": "traefik",
  "datasourceTemplate": "helm",
  "registryUrlTemplate": "https://traefik.github.io/charts"
}

Ce fichier est lui-même généré par un petit script à partir de la liste des composants : ajouter un composant suivi, c'est ajouter une ligne, pas réécrire du JSON. Dix-huit dépendances sont ainsi surveillées, de Cilium à l'image d'installation de Talos.

Le jeton a une date de péremption

Le jeton GitLab de Renovate expire au bout d'un an. Notez la date dans votre agenda : un Renovate qui ne peut plus se connecter ne prévient personne, il se tait. Ce sera l'une des premières alertes de la page observabilité.

03Plafonds et regroupements

Règles de Renovate
"packageRules": [
  { "matchDepNames": ["ghcr.io/siderolabs/installer"],
    "groupName": "Talos", "allowedVersions": "<1.15.0" },
  { "matchDepNames": ["registry.k8s.io/kube-apiserver"],
    "groupName": "Kubernetes", "allowedVersions": "<1.37.0" },
  { "matchDepNames": ["velero", "velero/velero-plugin-for-aws"],
    "groupName": "Velero" }
]
  • Les plafonds bloquent les versions majeures que l'écosystème n'accepte pas encore (Kubernetes 1.37 pour Rancher 2.15). Les versions correctives continuent de passer. On lève le plafond d'une ligne le jour où Rancher suit.
  • Les groupes évitent les mises à jour qui n'ont de sens qu'ensemble : Velero et son plugin AWS avancent dans la même merge request, après un coup d'oeil à leur table de compatibilité.

04tuppr : Talos et Kubernetes

Mettre à jour Talos et Kubernetes, c'est redémarrer chaque noeud à son tour, en vérifiant que le cluster va bien entre deux. tuppr est un petit opérateur qui fait exactement cela, en appelant l'API Talos. On lui décrit la version visée, la fenêtre autorisée et les contrôles de santé :

Extrait de k8s/tuppr/demo/upgrades.yaml
apiVersion: tuppr.home-operations.com/v1alpha1
kind: TalosUpgrade
metadata:
  name: talos
spec:
  talos:
    version: v1.14.4
  parallelism: 1
  maintenance:
    windows:
      - start: "0 2 * * *"
        duration: 1h30m
        timezone: Europe/Paris
  healthChecks:
    - apiVersion: v1
      kind: Node
      expr: status.conditions.exists(c, c.type == 'Ready' && c.status == 'True')
      description: Tous les noeuds sont Ready
      timeout: 10m
    - apiVersion: apps/v1
      kind: Deployment
      name: ceph-csi-rbd-provisioner
      namespace: ceph-csi-rbd
      expr: has(status.availableReplicas) && status.availableReplicas == status.replicas
      description: Le stockage Ceph est opérationnel
      timeout: 10m

Une ressource KubernetesUpgrade du même modèle pilote la version de Kubernetes. Le cycle complet devient : Renovate propose v1.14.5, un humain fusionne, la ressource est appliquée, et tuppr fait sa ronde de nuit, noeud après noeud.

Cinq essais, pas un de plus

tuppr garde l'historique de ses exécutions et s'arrête après cinq tentatives pour une même version. Si une mise à jour a échoué plusieurs fois pour une raison désormais corrigée, il faut vider le champ .status.history de la ressource pour qu'il reprenne.

05Fenêtres et contrôles de santé

Les fenêtres sont décalées : demo entre 02:00 et 03:30, mgmt entre 05:30 et 06:30. Si une mise à jour de demo tourne mal, la console et Argo CD sont encore là pour la réparer au réveil. Les contrôles de santé arrêtent la ronde au premier signe de faiblesse : un noeud qui ne revient pas, ou un stockage qui ne répond plus.

Côté applications, une règle suffit pour traverser ces nuits sans coupure : deux réplicas au moins, une sonde de disponibilité, et si possible un PodDisruptionBudget. Le guide développeurs le rappelle avec insistance.

06Le routeur et les applications

  • Le routeur Debian applique les correctifs de sécurité chaque jour et redémarre à 04:30 si le noyau l'exige, entre les deux fenêtres des clusters.
  • Les applications des équipes restent sous leur responsabilité : Renovate peut surveiller leurs dépôts de la même façon, et Argo CD appliquera la fusion.
  • Les noeuds Proxmox se mettent à jour à part, avec migration des VM : notre guide cluster Proxmox VE décrit la procédure.

Une plateforme Kubernetes, sans y laisser vos nuits

Nous concevons, montons et exploitons des plateformes Kubernetes sur Proxmox VE pour des équipes qui veulent se consacrer à leur code : mises à jour nocturnes, sauvegardes testées, déploiement en GitOps. Reprise d'un cluster existant, plateforme clé en main ou astreinte : nous intervenons au forfait comme au long cours.