- 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.
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 |
|
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 à jourapp-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 ?
- Dépôt : git.specificat.io/arnault/Talks
- Site : specificat.io
- Index des slides : portail talks (page d'accueil des présentations)