PI-GROUPE
Edge ComputingInfrastructureKubernetesIaCSécuritéOpen SourceDevOps

Kairos : traiter le système d'exploitation comme une image de conteneur

Un système immuable construit, versionné et distribué comme une image OCI. Démarrage réseau, montée de version atomique avec retour arrière, K3s intégré : l'approche qui rend la périphérie gérable.

Gérer cent serveurs dans un centre de données est un problème résolu. Gérer cent serveurs répartis dans cent sites, sans administrateur sur place et parfois derrière une liaison instable, ne l'est pas.

Les outils de configuration classiques supposent un système mutable qu'on fait converger. Sur un parc en périphérie, cette hypothèse se retourne : au bout de deux ans, chaque machine a dérivé différemment, et personne ne sait exactement ce qui tourne où.

Kairos renverse la logique. Le système d'exploitation devient une image de conteneur : construite par une chaîne d'intégration, versionnée dans un registre, distribuée et démarrée telle quelle. La machine ne se configure plus, elle se remplace.

Le principe

dockerfile
# Le système d'exploitation se décrit dans un Dockerfile
FROM quay.io/kairos/ubuntu:24.04-standard-amd64-generic-v3.6.0-k3sv1.31.4-k3s1

# Paquets spécifiques au site
RUN apt-get update && apt-get install -y --no-install-recommends       chrony lldpd smartmontools nvme-cli     && rm -rf /var/lib/apt/lists/*

# Agent interne de supervision
COPY --chmod=0755 agent-supervision /usr/local/bin/agent-supervision
COPY agent-supervision.service /etc/systemd/system/
RUN systemctl enable agent-supervision.service

# Durcissement appliqué à la construction, pas au démarrage
COPY durcissement/ /etc/
RUN /usr/local/bin/appliquer-durcissement.sh

# Autorité de certification interne
COPY pki/ca-interne.crt /usr/local/share/ca-certificates/
RUN update-ca-certificates

Cette image se construit dans GitLab CI, se signe, se pousse dans le registre interne. Chaque machine du parc démarre exactement la même — au bit près.

La conséquence la plus utile. « Quelle version tourne sur le site de Lyon ? » devient une question à réponse unique : l'empreinte de l'image. Plus de dérive possible.

L'installation sans intervention

Kairos démarre depuis une image ISO, une clé USB ou le réseau, puis lit sa configuration dans un fichier de type cloud-init.

yaml
#cloud-config

install:
  device: "auto"
  auto: true
  reboot: true
  image: "oci:registry.interne/edge/socle-k3s:v3.6.0-r12"
  grub_options:
    extra_cmdline: "rd.neednet=1 console=tty1 console=ttyS0,115200"

users:
  - name: exploitation
    groups: ["admin"]
    ssh_authorized_keys:
      - "ssh-ed25519 AAAAC3Nza... exploitation@pi-groupe"
    lockPasswd: true          # aucune connexion par mot de passe

k3s:
  enabled: true
  args:
    - --disable=traefik
    - --disable=servicelb
    - --flannel-backend=wireguard-native     # chiffrement entre nœuds
    - --node-label=site=lyon-usine-2
    - --node-label=topologie=peripherie
    - --kubelet-arg=eviction-hard=memory.available<200Mi
    - --tls-san=k3s.lyon-usine-2.interne

kairos:
  network_token: "{{ jeton_reseau_p2p }}"    # maillage chiffré entre nœuds du site

stages:
  boot:
    - name: "Attendre l'horloge"
      commands:
        - chronyc waitsync 30 0.1 || true     # certificats invalides sans heure juste
  network:
    - name: "Déclarer la machine à l'inventaire"
      commands:
        - |
          curl -sf --retry 5 --retry-delay 10             -H "Authorization: Bearer ${JETON_INVENTAIRE}"             -X POST https://inventaire.interne/api/noeuds             -d "{\"serie\":\"$(dmidecode -s system-serial-number)\",\"site\":\"lyon-usine-2\"}"

L'étape de synchronisation d'horloge n'est pas cosmétique. Un serveur en périphérie dont la pile de la carte mère est morte démarre en 1970. Tous les certificats TLS sont alors invalides, et le nœud ne rejoint jamais le cluster. Cette panne représente une part étonnante des incidents d'installation.

La montée de version atomique

C'est l'apport décisif de Kairos. Deux partitions système coexistent : l'active et la passive. La mise à jour écrit dans la passive, bascule le chargeur de démarrage, redémarre. En cas d'échec, le retour arrière se fait tout seul.

yaml
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
  name: montee-socle-v3-7
  namespace: system-upgrade
spec:
  concurrency: 2                    # deux machines à la fois sur tout le parc
  nodeSelector:
    matchExpressions:
      - { key: topologie, operator: In, values: ["peripherie"] }
      - { key: canal-maj, operator: In, values: ["stable"] }
  serviceAccountName: system-upgrade
  cordon: true
  drain:
    force: true
    skipWaitForDeleteTimeout: 60
  upgrade:
    image: quay.io/kairos/kairos-upgrade
    args:
      - "--source=oci:registry.interne/edge/socle-k3s:v3.7.0-r3"
      - "--verify-signature"
    envs:
      - name: COSIGN_PUBLIC_KEY
        valueFrom: { secretKeyRef: { name: cle-signature, key: cosign.pub } }

La vérification de signature avant bascule est indispensable. Sans elle, quiconque peut pousser dans le registre décide du système qui démarre sur vos sites.

La progressivité l'est tout autant. concurrency: 2 sur un parc de quatre-vingts machines étale la montée sur plusieurs heures. Une régression se détecte sur deux sites, pas sur quatre-vingts.

Le canal de déploiement

Le déploiement progressif par étiquette reprend le schéma éprouvé des mises à jour de flotte.

CanalParcDélai après publication
canari2 sites non critiquesimmédiat
stable70 % du parc7 jours
conservateursites critiques21 jours
bash
kubectl label node edge-lyon-01 edge-nantes-03 canal-maj=canari --overwrite

Vingt et un jours entre le canari et les sites critiques laissent le temps de découvrir ce qu'aucun test ne révèle : l'incompatibilité avec un automate industriel, le pilote réseau qui régresse, la carte qui n'aime pas le nouveau noyau.

L'immuabilité en pratique

Le système de fichiers racine est monté en lecture seule. Ce que vous devez conserver se déclare explicitement.

yaml
install:
  bind_mounts:
    - /var/lib/rancher
    - /var/lib/kubelet
    - /var/lib/donnees-metier
  ephemeral_mounts:
    - /tmp
    - /var/tmp

Cette contrainte force une hygiène salutaire. Si une charge écrit dans un chemin non déclaré, elle perd ses données au redémarrage — et vous le découvrez en recette plutôt qu'en production. Le système documente ce qui compte.

Ce qu'il faut accepter

Le dépannage change de nature. Impossible d'installer un paquet pour diagnostiquer. Prévoyez vos outils dans l'image, ou un conteneur de dépannage prêt à l'emploi.

Le poids de l'image compte. Un socle avec K3s tourne autour de 1,2 Gio. Sur un site en 4 Mbit/s, la montée de version prend quarante minutes. Soignez vos couches, ou prévoyez un miroir local.

La construction devient un élément critique. Votre chaîne d'intégration produit désormais le système d'exploitation de votre parc. Elle mérite le même niveau de protection que la production.

Le bilan

Le gain n'est pas technique, il est organisationnel. Un parc en périphérie sous Kairos se raisonne comme un déploiement applicatif : une version, un canal, un déploiement progressif, un retour arrière.

Les questions qui empoisonnaient l'exploitation — quelle version, quel correctif, quelle configuration — trouvent une réponse unique et vérifiable. Sur cent sites, cela change tout.