Files
Le Prévost-Corvellec Arnault 777e74f04b
Talks slides — image & chart / vars (push) Successful in 1s
Talks slides — image & chart / Helm chart (push) Failing after 4s
Talks slides — image & chart / Build container image (push) Failing after 1m27s
Add record configuration to Slidev presentations for improved recording functionality
- Enabled recording feature in slides for Kubernetes Operators and Spring AI presentations.
- Updated slides.md files to include 'record: true' for both presentations, allowing for camera and recording options during development.
2026-04-11 17:05:19 +02:00

14 KiB

theme, record, title, info, highlighter, defaults
theme record title info highlighter defaults
default true Kubernetes Operators — De l'enfer au paradis Mental model Kubernetes, boucles de contrôle, opérateurs, exemples et pièges. shiki
layout
center

Kubernetes Operators — De l'enfer… au paradis

Kubernetes n'est pas compliqué.
Mais mal compris… c'est un enfer.


Kubernetes : délire d'Ops ?

On nous l'a surtout vendu comme un truc d'infra.
Moi aussi, je suis passé par ce réflexe.

  • « Trop complexe »
  • Réservé aux spécialistes plateforme
  • Magie noire / pas « mon » métier

Kubernetes c'est un délire de dev

Kubernetes c'est un délire de dev


Kubernetes = API + état + boucle

  • API REST
  • Base d'état (etcd)
  • Boucle de réconciliation → events
  • Pas de mystère → mécanismes explicites (controllers, kubelet, containerd, etc.)

De vos outils au noyau Linux

flowchart LR
  B[kube-api]
  subgraph Clients["Clients"]
    A01[kubectl]
    A02[Helm]
    A03[Kustomize]
  end
  A01 --> B
  A02 --> B
  A03 --> B
  B --> C[(etcd)]
  B --> D[Controllers]
  D --> B
  D --> E[kubelet]
  E --> F[containerd]
  F --> G[Kernel Linux]
  • kube-api — point d'entrée
  • etcd — source de vérité
  • kubelet — agent sur chaque nœud
  • container runtime (ex. containerd) — exécution des conteneurs

Kubernetes ne fait pas tourner vos apps : la boucle de contrôle

Il orchestre · il délègue · il observe

flowchart LR
  DS["Spec · désir"] --> AP[kube-apiserver]
  AP <-->|objets cluster| ET[(etcd)]
  AP --> EV["Watch · événements"]
  EV --> CTRL[Controllers]
  CTRL -->|réconciliation · requêtes API| AP
  subgraph NODE["Nœud"]
    K[kubelet] -->|CRI| CD[containerd]
  end
  AP -->|spec Pods · synchro| K
  K -->|status| AP

↻ Les changements d'objets vivent dans l'API ; le kubelet synchronise depuis l'API, traduit en CRI vers containerd. Le status remonte par le kubelet.


Sous containerd : cgroups et namespaces

flowchart TD
  F[containerd] --> K[Linux Kernel]
  • cgroups
  • namespaces

Kubernetes vous évite de vivre dans le noyau

  • Manipuler les cgroups à la main
  • Gérer isolation, CPU, mémoire sur vos nœuds

À côté de ça, un cluster qui râle, c'est presque du repos.


CNI, CSI, CRI : de l'infra branchable

  • CNI → réseau (ex. Istio, Cilium, Calico, Flannel…)
  • CSI → stockage (ex. Ceph, Longhorn, Amazon…)
  • CRI → runtime (ex. containerd, CRI-O…)
  • Ici : brancher l'infra — pas encoder la logique métier (≠ opérateur)

Brancher l'infra ou coder le métier ?

Type Rôle
CNI / CSI / CRI Infrastructure
Opérateur Logique métier

Qui écrit la logique du cluster ?


La logique vit dans les controllers

Ils ferment la boucle : observation, décision, action.


Les opérateurs : des controllers spécialisés


Sans opérateur : scripts, crons, humains dans la boucle

  • Scripts bash
  • Cron jobs
  • Interventions humaines
  • État incohérent

Automatisation éclatée : la logique reste dans les têtes

  • Runbooks Confluence
  • Scripts bash « magiques »
  • Cron jobs oubliés
  • Interventions humaines

La logique est dans la tête des gens, pas dans le système.


Drift, pas de reproductibilité, 3 h du matin

  • Drift de configuration

  • Actions non reproductibles

  • Dépendance aux humains

  • Incidents à 3 h du matin

  • Pas reproductible / pas observable cluster / pas fiable dans le temps

  • Impossible de raisonner globalement sur l'état


Vous déclarez ; le système réconcilie

kind: Database
spec:
  size: 3

Spec, opérateur, cluster : ça tourne en boucle

flowchart LR
  A[Spec] --> B[Operator]
  B --> C[Cluster]
  C --> B

Dès que le réel diverge, la réconciliation repart.


Reflector & Reloader : la puissance des annotations

Outil Idée Déclencheur typique
Reflector (EmberStack) Copie / réplique Secrets et ConfigMaps (autres ns, miroirs) Annotations sur la ressource source ou la copie
Reloader (Stakater) Redémarre les Pods si Secret / ConfigMap référencé change Annotation sur Deployment / StatefulSet / etc.
  • Reflector : reflector.v1.k8s.emberstack.com/*
  • Reloader : reloader.stakater.com/auto: "true"

Exemple Reflector : secret DB → namespace applicatif

Le secret « source de vérité » vit avec la base ; Reflector recrée un miroir là où l'app tourne.

# Namespace database — secret maître
apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: database
  annotations:
    reflector.v1.k8s.emberstack.com/reflection-allowed: "true"
    reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
    reflector.v1.k8s.emberstack.com/reflection-auto-namespaces: "app-shop"
stringData:
  DATABASE_URL: "postgres://…"
  • Reflector maintient un Secret du même nom dans app-shop, à jour quand la source change.
  • Alternative : reflector.v1.k8s.emberstack.com/reflects: "database/db-credentials"

Exemple Reloader : rollout quand le secret miroir change

apiVersion: apps/v1
kind: Deployment
metadata:
  name: shop-api
  namespace: app-shop
  annotations:
    reloader.stakater.com/auto: "true"
spec:
  template:
    spec:
      containers:
        - name: api
          envFrom:
            - secretRef:
                name: db-credentials
  • Rotation dans database/db-credentials → Reflector met à jour app-shop/db-credentials → Reloader déclenche un rollout.
  • Sans Reloader, les Pods gardent l'ancienne valeur en mémoire.

Cert-manager, Postgres, Keycloak : la spec devient une entité

Opérateur CRD (exemples) Ce que ça matérialise
cert-manager Certificate, Issuer, ClusterIssuer Secrets TLS, ACME / PKI
Postgres Operator (Zalando) postgresql (acid.zalan.do) Cluster PG (Patroni, volumes, users…)
Keycloak Operator Keycloak, KeycloakRealm, KeycloakClient… Instances, royaumes, clients

La spec décrit l'état métier ; le contrôleur crée / met à jour Deployments, Services, Secrets…


Un certificat déclaratif, tout le cycle TLS en dessous

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: api-example
spec:
  dnsNames:
    - api.example.com

Suite dérivée automatiquement : CertificateRequest, challenge ACME, Secret TLS.


Certificats : du Certbot au renouvellement automatique

Avant — sans opérateur

  • Certbot manuel
  • Scripts cron
  • Cert expiré = prod down

Avec cert-manager

  • Déclaratif
  • Auto-renouvellement
  • Observabilité native (Certificate, conditions, events)

Postgres répliqué sans bricoler le failover à la main

apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: my-cluster
spec:
  numberOfInstances: 3

Derrière : réplication, failover, backup, users / rôles.


Quelle techno pour développer votre opérateur ?

Piste Outils typiques À retenir
Go (référence) Kubebuilder, controller-runtime, client-go Même patterns upstream ; sous charge : goroutines, files, back-off — peu de RAM en plus.
Operator SDK CLI Red Hat · Go · Ansible / Helm Go solide ; Ansible/Helm = wrapper — court si la logique métier épaissit.
Autres Python Kopf, Rust kube-rs, Java… Selon l'équipe ; moins d'exemples core.

Go + controller-runtime pour un opérateur maison sérieux ; sinon celui que l'équipe maintient le mieux.

Charge ↑ : un runtime qui gonfle la RAM par événement mange votre quota.


Quand un opérateur est légitime

  • Système complexe
  • Règles claires et stables
  • État critique pour l'activité
  • Opérations répétitives

Keycloak Credential Manager — le même schéma, chez moi

  • Objectif : réconcilier des credentials Keycloak avec ce qui est déclaré dans le cluster (CRD, Secrets annotés…).
  • Montrer le même schéma : observe → compare → corrige sur ton domaine.
  • Incident / compromission : reload Keycloak → événements côté IdP ; l'opérateur interroge (ex. toutes les minutes), repère l'écart et propage la correction.

Exemple — KeycloakClientCredential

CRD secrets.carbogame.com/v1alpha1 — spec.source (realm, client) → spec.target (Secret, rafraîchissement, mapping).

apiVersion: secrets.carbogame.com/v1alpha1
kind: KeycloakClientCredential
metadata:
  name: gitea-creds
  namespace: keycloak
spec:
  source:
    keycloakServer: prod-keycloak
    realm: operator
    clientId: gitea
  target:
    secretName: gitea-secret-creds
    namespace:
      - gitea
    refreshPeriod: 10m
    fields:
      clientId: key
      clientSecret: secret

En chart Helm, namespace et keycloakServer sont souvent injectés via templates.


Développer son opérateur : réutiliser les autres

  • Ne pas tout recoder : s'appuyer sur des contrôleurs existants pour ce qu'ils font déjà bien.
  • Ex. Secrets / ConfigMaps vers d'autres namespaces : brancher Reflector plutôt que dupliquer la logique — une politique de réflexion, un RBAC à raisonner.
  • Votre code se concentre sur le métier.

Ce qu'un opérateur bien choisi vous apporte

  • Automatiser du répétitif
  • Encapsuler de la complexité
  • Stabiliser un système

… mais les opérateurs peuvent aussi devenir un enfer.


Quand ne pas écrire d'opérateur

  • Logique floue ou en perpétuelle négociation métier
  • Processus instables
  • Dépendances externes imprévisibles
  • One-shot sans cycle de vie

Cinq signaux qu'un opérateur part en vrille

  • Spec incompréhensible sans lire le code
  • Effets implicites (créations ailleurs invisibles)
  • Couplage externe fort
  • Debug impossible sans les mainteneurs
  • État non observable (pas de conditions / status utiles)

Un opérateur mal conçu, c'est un microservice dont plus personne ne tient les règles du jeu.


Débugger un opérateur : describe, events, status, logs

  • kubectl describe (resource + events)
  • Events du namespace
  • Status / conditions sur la CRD
  • Logs du contrôleur

Un opérateur, c'est un produit logiciel — pas un script

  • Code et revues
  • Tests (unitaires, intégration, e2e si possible)
  • Maintenance dans la durée
  • Compatibilité avec les versions Kubernetes
  • Migrations de CRD / spec

Quand l'opérateur devient l'enfer

  • Logique implicite, effets de bord, debugging difficile, couplage fort

En pratique :

  • Tout mettre en opérateur
  • Logique métier floue
  • Effets cachés

Kubernetes, plateforme de programmation

  • Kubernetes évite l'enfer de l'infrastructure bas niveau.
  • Les bons opérateurs évitent l'enfer du manuel — les mauvais y renvoient autrement.

Avant d'écrire un opérateur : la checklist

  • Répétitif
  • Règles claires
  • Déclaratif possible
  • Idempotent
  • Observable

Si une case importante manque : reculez.


Votre logique, exécutée par le cluster au lieu d'un humain

  • « OK, je comprends enfin le cadre Kubernetes. »
  • « Les opérateurs : puissants, à manier avec précision. »

Un opérateur, c'est votre logique métier — lisible, testable, bornée.


Kubernetes simplifie l'infra — les opérateurs, ça peut simplifier ou empirer

Les bons encapsulent une complexité maîtrisée ; les mauvais recréent un enfer plus sophistiqué.


Merci

Merci pour votre attention.

Des questions ?