Files
Talks/slides/kubernetes-operators/slides.md
T
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

580 lines
14 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.
---
theme: default
# Par défaut Slidev : record: "dev" → pas d’UI caméra/enregistrement dans `slidev build`. true = inclus en prod.
record: true
title: Kubernetes Operators — De l'enfer au paradis
info: |
Mental model Kubernetes, boucles de contrôle, opérateurs, exemples et pièges.
highlighter: shiki
# Comme Reveal « center: true » : planche centrée (layout intégré Slidev).
defaults:
layout: center
---
# Kubernetes Operators — De l'enfer… au paradis
> Kubernetes n'est **pas** compliqué.
> Mais **mal compris**… c'est un enfer.
<!--
On parle surtout de pourquoi les opérateurs changent la manière de travailler — puissants mais dangereux si le mental model est faux.
-->
---
## 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
<!--
Souvent présenté comme réservé aux spécialistes — en réalité proche de ce qu'on fait déjà en dev.
-->
---
## Kubernetes c'est un délire de dev
> Kubernetes c'est un délire de dev
<!--
Transition : contraste avec la slide précédente.
-->
---
## 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.)
<!--
Pas de magie — des patterns qu'on retrouve ailleurs en dev.
-->
---
## De vos outils au noyau Linux
```mermaid
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
<!--
Helm, kubectl, Flux… appellent l'API. L'API parle à etcd, les controllers poussent vers les kubelets, le runtime lance les conteneurs.
-->
---
## Kubernetes ne fait pas tourner vos apps : la boucle de contrôle
Il **orchestre** · il **délègue** · il **observe**
```mermaid
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.
<!--
Aligné sur la doc Kubernetes : observer, rapprocher le courant du spec ; informers / watches → files d'événements. etcd derrière l'API.
-->
---
## Sous containerd : cgroups et namespaces
```mermaid
flowchart TD
F[containerd] --> K[Linux Kernel]
```
- **cgroups**
- **namespaces**
<!--
Derrière containerd, le noyau — vous ne voulez pas manipuler les fichiers à la main au quotidien.
-->
---
## 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 |
<!--
D'un côté briques branchables ; de l'autre du code qui encode le comportement dans le cluster. Icônes : icônes K8s officielles, CNCF Landscape, Simple Icons.
-->
---
## Qui écrit la logique du cluster ?
<!--
Qui décide quand l'état réel diverge ? (pause)
-->
---
## La logique vit dans les controllers
*Ils ferment la boucle : observation, décision, action.*
<!--
L'intelligence du cluster est dans les controllers.
-->
---
## Les opérateurs : des controllers spécialisés
<!--
Même mécanisme, focalisé sur un domaine métier ou un logiciel (base, queue…).
-->
---
## 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
```yaml
kind: Database
spec:
size: 3
```
<!--
État voulu → le contrôleur fait les transitions répétitives.
-->
---
## Spec, opérateur, cluster : ça tourne en boucle
```mermaid
flowchart LR
A[Spec] --> B[Operator]
B --> C[Cluster]
C --> B
```
*Dès que le réel diverge, la réconciliation repart.*
<!--
Exemples : annotations sur ressources natives, puis vrais CRD ; projet maison pour ancrer le discours.
-->
---
## 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"`
<!--
Pas toujours un gros opérateur CRD — parfois contrôleur sur objets standards + annotations. Liens : kubernetes-reflector, Reloader sur GitHub.
-->
---
## 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.*
```yaml
# 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
```yaml
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…
<!--
Trois domaines, même mécanisme CRD + réconciliation. Liens cert-manager.io, Zalando postgres-operator, Keycloak operator.
-->
---
## Un certificat déclaratif, tout le cycle TLS en dessous
```yaml
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)
<!--
Complexité énorme encapsulée — pertinent quand le domaine est clair, répétitif et critique.
-->
---
## Postgres répliqué sans bricoler le failover à la main
```yaml
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**
<!--
Si tu ne peux pas formaliser « si X alors Y » proprement — très mauvaise idée en opérateur.
-->
---
## 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.
<!--
Pas pour vendre un produit — prouver que la logique est la même : API K8s, état désiré, code à la place du runbook.
-->
---
## Exemple — `KeycloakClientCredential`
*CRD* `secrets.carbogame.com/v1alpha1` — `spec.source` (realm, client) → `spec.target` (Secret, rafraîchissement, mapping).
```yaml
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.
<!--
Fil : pas magique → API + boucle → controllers / opérateurs → avant/après → exemples → bon usage / pièges → conclusion.
-->
---
## 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 ?**
<ClosingQr />
- Dépôt : [git.specificat.io/arnault/Talks](https://git.specificat.io/arnault/Talks)
- Site : [specificat.io](https://specificat.io/)
- Index des slides : portail talks (page d'accueil des présentations)
<!--
Laisser le temps pour les questions ; rappeler l'URL du dépôt à l'oral.
-->