ci
Some checks failed
Talks slides — image & chart / vars (push) Successful in 2s
Talks slides — image & chart / Build container image (push) Failing after 41s
Talks slides — image & chart / Helm chart (push) Failing after 43s

This commit is contained in:
Le Prévost-Corvellec Arnault
2026-04-08 20:13:50 +02:00
parent 4c921843a6
commit 4ffed1b5fa
19 changed files with 695 additions and 0 deletions

View File

@@ -0,0 +1,804 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Kubernetes Operators — De lenfer au paradis</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.6.1/reveal.min.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.6.1/theme/moon.min.css" />
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.6.1/plugin/highlight/monokai.min.css" />
<link rel="stylesheet" href="css/custom.css" />
<!--
Reveal.js 4.6.1 — plugins : Notes orateur + surlignage code.
S : fenêtre notes (même origine, servir en HTTP, pas file://).
? : aide raccourcis · Échap : aperçu · F : plein écran
-->
</head>
<body>
<div class="reveal">
<div class="slides">
<section>
<h1>Kubernetes Operators — De lenfer… au paradis</h1>
<blockquote>
<p>Kubernetes nest <strong>pas</strong> compliqué.<br />
Mais <strong>mal compris</strong>… cest un enfer.</p>
</blockquote>
<aside class="notes">
<p>On va parler de Kubernetes… mais surtout de pourquoi les opérateurs changent complètement la manière de
travailler — et pourquoi cest <strong>puissant</strong> mais <strong>dangereux</strong> si on se plante sur
le mental model.</p>
<p>Illustration suggérée : diagramme moderne et minimal, flat design, lisible (éviter le poster CNCF
illisible).</p>
</aside>
</section>
<section>
<h1>Kubernetes : délire dOps ?</h1>
<blockquote>
<p>On vous la vendu comme un truc dinfra</p>
</blockquote>
<ul>
<li>Complexe</li>
<li>Réservé aux DevOps</li>
<li>Magie noire</li>
</ul>
<aside class="notes">
<p>On vous a vendu Kubernetes comme un délire dinfra, réservé à des gens chelous.<br />
En réalité… cest beaucoup plus proche de ce que vous faites déjà.</p>
<p><em>Chaos scripts</em> — dev entouré de scripts, crons, alertes, terminal chargé, ambiance tendue
(contraste avec la suite).</p>
</aside>
</section>
<section>
<h1>Kubernetes = API + état + boucle</h1>
<ul>
<li>API REST</li>
<li>Base détat</li>
<li>Boucle de réconciliation</li>
<li>Pas de mystère : des mécanismes explicites</li>
</ul>
<aside class="notes">
<p>Kubernetes, cest juste une API, une base détat, et une boucle qui corrige la réalité.<br />
Pas de magie — des patterns quon retrouve ailleurs en dev.</p>
</aside>
</section>
<section>
<h1>De vos outils au noyau Linux</h1>
<pre><code class="language-mermaid">flowchart LR
A[Clients] --&gt; B[kube-api]
B --&gt; C[etcd]
B --&gt; D[Controllers]
D --&gt; E[kubelet]
E --&gt; F[containerd]
F --&gt; G[Kernel Linux]
</code></pre>
<ul>
<li><strong>kube-api</strong> — point dentrée</li>
<li><strong>etcd</strong> — source de vérité</li>
<li><strong>kubelet</strong> — agent sur chaque nœud</li>
<li><strong>container runtime</strong> (ex. containerd) — exécution des conteneurs</li>
</ul>
<aside class="notes">
<p>Tout ça, ce sont des clients : Helm, kubectl, Flux… ils appellent lAPI.<br />
LAPI parle à etcd, les controllers poussent le travail vers les kubelets, et le runtime lance les
conteneurs.</p>
<p>Schéma ASCII de secours :</p>
<pre><code>Clients → kube-api → etcd
controllers → kubelet → containerd → kernel
</code></pre>
</aside>
</section>
<section>
<h1>Kubernetes ne fait pas tourner vos apps</h1>
<ul>
<li>Il <strong>orchestre</strong></li>
<li>Il <strong>délègue</strong></li>
<li>Il <strong>observe</strong></li>
</ul>
<aside class="notes">
<p>Ce nest pas Kubernetes qui « exécute votre métier » comme un process magique : il coordonne, délègue aux
agents, et observe létat.<br />
La suite : le cœur, cest la boucle de réconciliation.</p>
<p>(Cette slide remplace lancien zoom « kube-api → etcd » seul : le détail etcd est déjà dans la vue
densemble slide 4.)</p>
</aside>
</section>
<section class="slide-boucle">
<div class="slide-boucle-inner">
<h1 class="slide-boucle-title">État voulu → réel : la boucle</h1>
<pre><code class="language-mermaid">flowchart LR
A[Désiré] --&gt; B[API] --&gt; C[Controllers] --&gt; D[Réel]
</code></pre>
<p class="slide-boucle-foot">
<strong></strong> réinjecte vers les contrôleurs · <em>chaque tour : observer, décider, agir</em>
</p>
</div>
<aside class="notes">
<p>Des agents exécutent les instructions côté nœud (kubelet, runtime), mais le fil conducteur, cest : état
voulu, comparaison, correction en boucle.</p>
</aside>
</section>
<section>
<h1>Sous containerd : cgroups et namespaces</h1>
<pre><code class="language-mermaid">flowchart TD
F[containerd] --> K[Linux Kernel]
</code></pre>
<ul>
<li><strong>cgroups</strong></li>
<li><strong>namespaces</strong></li>
</ul>
<aside class="notes">
<p>Et derrière containerd… le noyau Linux. Cgroups, namespaces…</p>
<p><em>(pause)</em></p>
<p>Et ça… vous navez pas envie dy manipuler les fichiers à la main au quotidien.</p>
<p><em>Kernel danger zone</em> — mécanique dense, style industriel sombre (le « trou du souffleur » sous
Kubernetes).</p>
</aside>
</section>
<section>
<h1>Kubernetes vous évite de vivre dans le noyau</h1>
<ul>
<li>Manipuler les <strong>cgroups</strong> à la main</li>
<li>Gérer <strong>isolation</strong>, <strong>CPU</strong>, <strong>mémoire</strong> au niveau noyau</li>
</ul>
<blockquote>
<p>À côté de ça, un cluster qui râle, cest presque du repos.</p>
</blockquote>
<aside class="notes">
<p>Si Kubernetes existe, cest pour vous éviter de vivre dans ces couches-là.<br />
À côté du noyau, Kubernetes est presque rassurant.</p>
</aside>
</section>
<section>
<h1>CNI, CSI, CRI : de linfra branchable</h1>
<ul>
<li><strong>CNI</strong> → réseau (ex : Istio, Cilium ,Calico, Flannel, etc.)</li>
<li><strong>CSI</strong> → stockage (ex : Ceph, Longhorn , Amazon,etc.)</li>
<li><strong>CRI</strong> → runtime (ex : containerd, CRI-O,etc.)</li>
<li>Ici : brancher linfra — pas encoder la logique métier (<em></em> opérateur)</li>
</ul>
<aside class="notes">
<p>On peut brancher réseau, stockage, runtime… mais ce nest pas notre sujet du jour — et surtout, ne les
confondez pas avec la logique métier.</p>
</aside>
</section>
<section>
<h1>Brancher linfra ou coder le métier ?</h1>
<table>
<thead>
<tr>
<th>Type</th>
<th>Rôle</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>CNI / CSI / CRI</strong></td>
<td>Infrastructure</td>
</tr>
<tr>
<td><strong>Opérateur</strong></td>
<td>Logique métier</td>
</tr>
</tbody>
</table>
<aside class="notes">
<p>Dun côté : des briques dinfra branchables.<br />
De lautre : du <strong>code</strong> qui encode <strong>comment</strong> votre système doit se comporter
dans le cluster.</p>
<p>Icônes utiles :</p>
<ul>
<li><a href="https://github.com/kubernetes/community/tree/master/icons">Icônes Kubernetes (officiel)</a>
</li>
<li><a href="https://landscape.cncf.io/">CNCF Landscape</a></li>
<li><a href="https://simpleicons.org/">Simple Icons (SVG)</a></li>
</ul>
</aside>
</section>
<section>
<h1>Qui écrit la logique du cluster ?</h1>
<aside class="notes">
<p>Qui décide de ce quil faut faire quand létat réel diverge de ce quon veut ?</p>
<p><em>(pause)</em></p>
</aside>
</section>
<section>
<h1>La logique vit dans les controllers</h1>
<p><em>Ils ferment la boucle : observation, décision, action.</em></p>
<aside class="notes">
<p>La vraie intelligence de Kubernetes… elle est dans les controllers.<br />
Ce sont eux qui ferment la boucle : observation, décision, action.</p>
</aside>
</section>
<section>
<h1>Les opérateurs : des controllers spécialisés</h1>
<aside class="notes">
<p>Les opérateurs, ce sont des controllers… mais focalisés sur un domaine métier ou un logiciel précis (base,
queue, etc.).<br />
Même mécanisme, autre niveau dabstraction.</p>
</aside>
</section>
<section>
<h1>Automatiser le métier… en code dans le cluster</h1>
<aside class="notes">
<p>Un opérateur, cest du code qui dit au cluster comment faire vivre un service au-delà du simple « Pod +
Service » : upgrades, backup, réplication, etc.</p>
</aside>
</section>
<section>
<h1>Sans opérateur : scripts, crons, humains dans la boucle</h1>
<ul>
<li>Scripts bash</li>
<li>Cron jobs</li>
<li>Interventions humaines</li>
<li>État incohérent</li>
</ul>
<aside class="notes">
<p>Avant : bricolage, des humains dans la boucle, et un état qui part dans tous les sens dès quil y a une
alerte à 3 h du matin.</p>
</aside>
</section>
<section>
<h1>Automatisation éclatée : la logique reste dans les têtes</h1>
<ul>
<li>Runbooks Confluence</li>
<li>Scripts bash « magiques »</li>
<li>Cron jobs oubliés</li>
<li>Interventions humaines</li>
</ul>
<aside class="notes">
<p>Avant les opérateurs, lautomatisation existe… mais elle est <strong>fragmentée</strong>.<br />
Chaque problème a sa solution bricolée.</p>
<p>Et surtout :<br />
<strong>la logique est dans la tête des gens, pas dans le système.</strong>
</p>
</aside>
</section>
<section>
<h1>Drift, pas de reproductibilité, 3 h du matin</h1>
<ul>
<li>Drift de configuration</li>
<li>Actions non reproductibles</li>
<li>Dépendance aux humains</li>
<li>Incidents à 3 h du matin</li>
</ul>
<aside class="notes">
<p>Le problème, ce nest pas juste « moins automatisé ».</p>
<p>Cest :</p>
<ul>
<li>pas <strong>reproductible</strong></li>
<li>pas <strong>observable</strong> au sens cluster</li>
<li>pas <strong>fiable</strong> dans le temps</li>
</ul>
<p>Surtout : impossible de <strong>raisonner globalement</strong> sur létat du système.</p>
</aside>
</section>
<section>
<h1>Vous déclarez ; le système réconcilie</h1>
<pre><code class="language-yaml">kind: Database
spec:
size: 3
</code></pre>
<aside class="notes">
<p>Après : on décrit létat voulu… et le contrôleur / lopérateur fait le travail répétitif et les
transitions.</p>
<p><em>Paradis opérateur</em> — ingénieur calme, infra automatisée, UI claire, atmosphère sereine (contraste
avec slide enfer).</p>
</aside>
</section>
<section>
<h1>Spec, opérateur, cluster : ça tourne en boucle</h1>
<pre><code class="language-mermaid">flowchart LR
A[Spec] --&gt; B[Operator]
B --&gt; C[Cluster]
C --&gt; B
</code></pre>
<p><em>Dès que le réel diverge, la réconciliation repart.</em></p>
<aside class="notes">
<p>Le système réobserve, recompare, recorrige. Cest la même philosophie que le reste de Kubernetes, appliquée
à votre domaine.</p>
<p>Quelques <strong>exemples réels</strong> : dabord des outils qui <strong>étendent</strong> des ressources
natives avec des <strong>annotations</strong>, puis des opérateurs qui posent de <strong>vrais CRD</strong>
— et un projet maison pour ancrer le discours.</p>
</aside>
</section>
<section>
<h1>Reflector &amp; Reloader : la puissance des annotations</h1>
<table>
<thead>
<tr>
<th>Outil</th>
<th>Idée</th>
<th>Déclencheur typique</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Reflector</strong> (EmberStack)</td>
<td>Copie / réplique des <strong>Secrets</strong> et <strong>ConfigMaps</strong> (autres namespaces,
miroirs)</td>
<td>Annotations sur la ressource source ou la copie</td>
</tr>
<tr>
<td><strong>Reloader</strong> (Stakater)</td>
<td><strong>Redémarre</strong> les Pods quand un Secret / ConfigMap référencé change</td>
<td>Annotation sur le <strong>Deployment</strong> / <strong>StatefulSet</strong> / etc.</td>
</tr>
</tbody>
</table>
<ul>
<li>Reflector : annotations du type <code>reflector.v1.k8s.emberstack.com/*</code> pour autoriser la réflexion
et cibler où copier.</li>
<li>Reloader : <code>reloader.stakater.com/auto: "true"</code> (ou annotations plus fines par config) pour
lier redéploiement ↔ mise à jour de config.</li>
</ul>
<aside class="notes">
<p>Ce nest pas toujours un « gros » opérateur avec CRD : parfois cest un <strong>contrôleur</strong> qui
<strong>regarde</strong> des objets standards et réagit à des <strong>annotations</strong>.<br />
Très utile pour TLS partagé, configs dupliquées, ou « je change un secret → je veux un rollout » sans
pipeline ad hoc.
</p>
<ul>
<li><a href="https://github.com/emberstack/kubernetes-reflector">kubernetes-reflector</a></li>
<li><a href="https://github.com/stakater/Reloader">Reloader</a></li>
</ul>
</aside>
</section>
<section>
<h1>Cert-manager, Postgres, Keycloak : la spec devient une entité</h1>
<table>
<thead>
<tr>
<th>Opérateur</th>
<th>CRD (exemples)</th>
<th>Ce que ça <strong>matérialise</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>cert-manager</strong></td>
<td><code>Certificate</code>, <code>Issuer</code>, <code>ClusterIssuer</code></td>
<td>Secrets TLS, chaînes ACME / PKI</td>
</tr>
<tr>
<td><strong>Postgres Operator</strong> (Zalando)</td>
<td><code>postgresql</code> (<code>acid.zalan.do</code>)</td>
<td>Cluster PostgreSQL (Patroni, volumes, users…)</td>
</tr>
<tr>
<td><strong>Keycloak Operator</strong></td>
<td><code>Keycloak</code>, <code>KeycloakRealm</code>, <code>KeycloakClient</code>, …</td>
<td>Instances Keycloak, royaumes, clients</td>
</tr>
</tbody>
</table>
<p>La spec décrit létat métier (cert, base, realm) ; le contrôleur crée / met à jour Deployments, Services,
Secrets, etc.</p>
<aside class="notes">
<p>On est dans le pattern « Database, size: 3 » mais en prod : certificats, bases gérées, IdP.<br />
Trois domaines, <strong>même mécanisme</strong> : CRD + boucle de réconciliation.</p>
<p>Liens :</p>
<ul>
<li><a href="https://cert-manager.io/">cert-manager</a></li>
<li><a href="https://github.com/zalando/postgres-operator">Zalando Postgres operator</a></li>
<li><a href="https://www.keycloak.org/operator/installation">Keycloak Operator</a></li>
</ul>
</aside>
</section>
<section>
<h1>Un certificat déclaratif, tout le cycle TLS en dessous</h1>
<pre><code class="language-yaml">apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: api-example
spec:
dnsNames:
- api.example.com
</code></pre>
<p>La suite est dérivée automatiquement :</p>
<ul>
<li><code>CertificateRequest</code></li>
<li>Challenge ACME</li>
<li>Secret TLS</li>
</ul>
<aside class="notes">
<p>Tu déclares <strong>juste</strong> un certificat.</p>
<p>Et derrière : génération de clé, challenge ACME, renouvellement automatique.</p>
<p><strong>Aucun humain dans la boucle</strong> pour le cycle de vie du cert.</p>
</aside>
</section>
<section>
<h1>Certificats : du Certbot au renouvellement automatique</h1>
<p><em>Avant — sans opérateur</em></p>
<ul>
<li>Certbot manuel</li>
<li>Scripts cron</li>
<li>Cert expiré = prod down</li>
</ul>
<p><em>Avec cert-manager</em></p>
<ul>
<li>Déclaratif</li>
<li>Auto-renouvellement</li>
<li>Observabilité native (<code>Certificate</code>, conditions, events)</li>
</ul>
<aside class="notes">
<p>cert-manager, cest typiquement : <strong>une complexité énorme</strong> encapsulée dans un opérateur.</p>
<p><strong>Là, ça vaut clairement le coup</strong> — parce que le domaine est clair, répétitif et critique.
</p>
</aside>
</section>
<section>
<h1>Postgres répliqué sans bricoler le failover à la main</h1>
<pre><code class="language-yaml">apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
name: my-cluster
spec:
numberOfInstances: 3
</code></pre>
<p>Derrière cette spec, le contrôleur soccupe de :</p>
<ul>
<li>Réplication</li>
<li>Failover</li>
<li>Backup</li>
<li>Users / rôles</li>
</ul>
<aside class="notes">
<p>Ça, cest intéressant parce que ce nest <strong>pas</strong> trivial : ce nest <strong>pas</strong>
stateless, ce nest <strong>pas</strong> safe à bricoler à la main sur du long terme.</p>
<p>Un opérateur mature sur ce terrain, cest du <strong>métier base de données</strong> version déclarative.
</p>
</aside>
</section>
<section>
<h1>Quand un opérateur est légitime</h1>
<ul>
<li>Système <strong>complexe</strong></li>
<li><strong>Règles</strong> claires et stables</li>
<li><strong>État</strong> critique pour lactivité</li>
<li>Opérations <strong>répétitives</strong></li>
</ul>
<aside class="notes">
<p>Un opérateur est pertinent quand tu peux formaliser des règles du type <strong>« si X alors Y »</strong>,
que tu dois les appliquer <strong>souvent</strong>, et que tu veux <strong>réduire lerreur
humaine</strong>.</p>
<p>Si tu ne peux pas écrire ça proprement… <strong>pause</strong><strong>ça, cest une très mauvaise
idée</strong> en opérateur.</p>
</aside>
</section>
<section>
<h1>Keycloak Credential Manager — le même schéma, chez moi</h1>
<ul>
<li>Objectif : <strong>réconcilier</strong> des <strong>credentials Keycloak</strong> (clients, secrets,
rotation…) avec ce qui est <strong>déclaré dans le cluster</strong> (CRD, Secrets annotés, ou les deux —
selon ton design).</li>
<li>Intérêt conf : montrer le <strong>même schéma</strong> que les opérateurs « connus » : <em>observe →
compare → corrige</em> sur <strong>ton</strong> domaine métier.</li>
</ul>
<aside class="notes">
<p>Je vous montre ça pas pour vendre un produit, mais pour prouver que <strong>la logique</strong> est la même
: une API Kubernetes, un état désiré, et du code qui parle à Keycloak à la place dun humain et dun
runbook.</p>
<ul>
<li><strong>Lien repo</strong> : <code>https://…</code> (README, une spec dexemple, capture dun
<code>kubectl get</code>).
</li>
<li><strong>Une phrase</strong> sur le périmètre exact : ex. clients OAuth uniquement, rotation de secrets,
sync depuis External Secrets, etc.</li>
</ul>
<p>Schéma minimal : <code>CRD / Secret</code><strong>Keycloak Credential Manager</strong> → API Keycloak,
style diagramme propre (flat design).</p>
</aside>
</section>
<section>
<h1>Ce quun opérateur bien choisi vous apporte</h1>
<ul>
<li>Automatiser du <strong>répétitif</strong></li>
<li><strong>Encapsuler</strong> de la complexité</li>
<li><strong>Stabiliser</strong> un système</li>
</ul>
<aside class="notes">
<p>On remplace des opérations manuelles par du code — quand cest le bon outil pour du vrai répétitif et des
règles claires.</p>
<p>On vient de voir du <strong>concret</strong> (annotations, CRD, projet maison). La question :
<strong>quand</strong> est-ce un bon outil ?
</p>
<p><strong>mais</strong> les opérateurs peuvent aussi devenir un enfer.</p>
</aside>
</section>
<section>
<h1>Quand ne pas écrire dopérateur</h1>
<ul>
<li>Logique <strong>floue</strong> ou en perpétuelle négociation métier</li>
<li>Processus <strong>instables</strong> (la règle change toutes les semaines)</li>
<li>Dépendances <strong>externes</strong> imprévisibles</li>
<li><strong>One-shot</strong> : automatisation ponctuelle sans cycle de vie</li>
</ul>
<aside class="notes">
<p>Si tu ne peux pas écrire clairement <strong>« si X alors Y »</strong> avec des conditions observables… tu
nas <strong>rien à faire</strong> dans un opérateur.</p>
<p>Sinon tu recodes un outil métier opaque <strong>dans</strong> le cluster.</p>
</aside>
</section>
<section>
<h1>Cinq signaux quun opérateur part en vrille</h1>
<ul>
<li>Spec <strong>incompréhensible</strong> sans lire le code</li>
<li>Effets <strong>implicites</strong> (créations ailleurs sans que ce soit visible)</li>
<li><strong>Couplage</strong> externe fort (APIs fragiles, ordre dappels magique)</li>
<li><strong>Debug</strong> impossible sans les mainteneurs à côté de toi</li>
<li><strong>État</strong> non observable (pas de conditions / status utiles)</li>
</ul>
<aside class="notes">
<p>Un opérateur doit être <strong>lisible</strong>, <strong>prévisible</strong>, <strong>observable</strong>.
</p>
<p>Sinon, ce nest pas de la plateforme : cest une <strong>bombe à retardement</strong> avec un
<code>kubectl</code> dessus.
</p>
</aside>
</section>
<section>
<h1>Débugger un opérateur : describe, events, status, logs</h1>
<ul>
<li><code>kubectl describe</code> (resource + events)</li>
<li><strong>Events</strong> du namespace</li>
<li><strong>Status / conditions</strong> sur la CRD</li>
<li><strong>Logs</strong> du contrôleur</li>
</ul>
<aside class="notes">
<p>Le debug devient <strong>indirect</strong>, <strong>distribué</strong>, parfois <strong>opaque</strong>.
</p>
<p>Si ton opérateur est mal conçu — pas de status clair, pas devents utiles — <strong>bonne chance</strong>
pour le post-mortem à 3 h du matin.</p>
</aside>
</section>
<section>
<h1>Un opérateur, cest un produit logiciel — pas un script</h1>
<ul>
<li><strong>Code</strong> et revues</li>
<li><strong>Tests</strong> (unitaires, intégration, e2e si possible)</li>
<li><strong>Maintenance</strong> dans la durée</li>
<li><strong>Compatibilité</strong> avec les versions Kubernetes</li>
<li><strong>Migrations</strong> de CRD / spec</li>
</ul>
<aside class="notes">
<p>Un opérateur, ce nest <strong>pas</strong> un script du vendredi.</p>
<p>Cest un <strong>produit logiciel</strong> avec un <strong>cycle de vie</strong> — et une dette si tu
labandonnes.</p>
<p>Ensuite : la synthèse <strong>« ça part en vrille »</strong> — smells quon a déjà nommés, mais côté vécu
déquipe.</p>
</aside>
</section>
<section>
<h1>Quand lopérateur devient lenfer</h1>
<ul>
<li>Logique <strong>implicite</strong></li>
<li><strong>Effets de bord</strong></li>
<li><strong>Debugging</strong> difficile</li>
<li><strong>Couplage</strong> fort</li>
</ul>
<p>En pratique, ça donne souvent :</p>
<ul>
<li>Tout mettre en opérateur</li>
<li>Logique métier <strong>floue</strong></li>
<li>Effets <strong>cachés</strong></li>
</ul>
<blockquote>
<p>Un opérateur mal conçu, cest un microservice sous LSD.</p>
</blockquote>
<aside class="notes">
<p>Un mauvais opérateur, cest de la complexité distribuée avec un debugger qui vous hait.<br />
Le piège classique : « formation Kubernetes par la trappe » parce quon empile des comportements opaques.
</p>
</aside>
</section>
<section>
<h1>Kubernetes, plateforme de programmation</h1>
<ul>
<li>Kubernetes vous évite <strong>lenfer de linfrastructure</strong> bas niveau.</li>
<li>Les bons opérateurs vous évitent <strong>lenfer du manuel</strong> — les mauvais vous y renvoient
autrement.</li>
</ul>
<aside class="notes">
<p>Kubernetes nest pas quun outil dinfra : cest une surface où lon encode du
<strong>comportement</strong>.<br />
Les opérateurs sont lextension naturelle… à condition de rester honnêtes sur la complexité.
</p>
<p>Fil de la conf (rappel) :</p>
<ol>
<li>Kubernetes nest pas magique </li>
<li>API + état + boucle ; kernel = vrai « enfer » bas niveau </li>
<li>Controllers / opérateurs : où vit la logique </li>
<li><strong>Avant</strong> : vécu (runbooks, scripts, drift) → <strong>pourquoi</strong> ça casse </li>
<li><strong>Après</strong> + boucle ; exemples Reflector/Reloader, panorama CRD, creux cert-manager &amp;
Postgres </li>
<li>Projet perso ; <strong>bon usage</strong> puis <strong>quand ne pas</strong>, smells, debug,
<strong>coût</strong>
</li>
<li>Pièges ; plateforme de programmation ; <strong>checklist</strong> ; dernière phrase + conclusion brutale
</li>
</ol>
</aside>
</section>
<section>
<h1>Avant décrire un opérateur : la checklist</h1>
<ul>
<li>Répétitif</li>
<li>Règles claires</li>
<li>Déclaratif possible</li>
<li>Idempotent</li>
<li>Observable</li>
</ul>
<p>Si une case importante manque, reculez : pas dopérateur (ou pas tout de suite).</p>
<aside class="notes">
<p>Cest probablement <strong>la</strong> slide la plus importante pour une salle de devs.</p>
<p>Kubernetes donne <strong>envie</strong> den mettre partout. <strong>Mauvaise idée</strong> par défaut.</p>
<p>👉 Tu valides la checklist, ou tu <strong>recules</strong>.</p>
<p>Les <strong>pauses</strong> et les <strong>regards</strong> sur la salle après « Mauvaise idée » font
autant le travail quun diagramme.</p>
</aside>
</section>
<section>
<h1>Votre logique, exécutée par le cluster au lieu dun humain</h1>
<aside class="notes">
<p>Tu vises deux réactions :</p>
<ul>
<li>« OK, Kubernetes je comprends enfin le cadre. »</li>
<li>« OK, les opérateurs : puissants, mais à manier avec précision. »</li>
</ul>
<p><strong>Éviter le piège</strong> : faire une « formation Kubernetes » sans le vouloir — rester sur le
message <em>comportement / automatisation / risques</em>.</p>
<p>Un opérateur, cest votre logique métier… mais exécutée par le cluster au lieu dun humain.<br />
À vous de garder cette logique <strong>lisible</strong>, <strong>testable</strong>, et
<strong>bornée</strong>.
</p>
</aside>
</section>
<section>
<h1>Kubernetes simplifie linfra — les opérateurs, ça peut simplifier ou empirer</h1>
<aside class="notes">
<p>Kubernetes vous évite une partie du chaos du bas niveau.</p>
<p>Mais les opérateurs : soit ils <strong>encapsulent</strong> intelligemment une complexité maîtrisée, soit
ils recréent un enfer <strong>plus sophistiqué</strong>.</p>
<p>Ce que la salle retient : les <strong>pauses</strong>, les <strong>« très mauvaise idée »</strong>
honnêtes, plus que chaque ligne du deck.</p>
</aside>
</section>
</div>
<footer class="deck-footer">
<a href="https://specificat.io/" rel="noopener noreferrer" target="_blank">Specificat.io</a>
<span class="deck-footer-sep" aria-hidden="true">·</span>
<span class="deck-footer-rights">All rights reserved</span>
</footer>
</div>
<!-- Ordre : cœur Reveal → plugins officiels (notes, highlight) → Mermaid -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.6.1/reveal.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.6.1/plugin/notes/notes.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reveal.js/4.6.1/plugin/highlight/highlight.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
<script>
(function () {
if (typeof RevealNotes === "undefined" || typeof RevealHighlight === "undefined") {
console.error("Reveal : plugins Notes ou Highlight introuvables (vérifiez le réseau / CDN).");
}
/* Thème Mermaid aligné sur https://specificat.io/ (variables en hex — requis par Mermaid) */
mermaid.initialize({
startOnLoad: false,
theme: "base",
securityLevel: "loose",
/* foreignObject + thème base = libellés vides chez certains navigateurs ; SVG text est fiable */
htmlLabels: false,
fontFamily:
'system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", sans-serif',
themeVariables: {
darkMode: true,
background: "#050709",
fontSize: "15px",
primaryColor: "#0d1115",
primaryTextColor: "#f5f5f5",
primaryBorderColor: "#2bc9c6",
secondaryColor: "#1b1f22",
secondaryTextColor: "#f5f5f5",
secondaryBorderColor: "#3d6d6a",
tertiaryColor: "#050709",
tertiaryTextColor: "#c8d0d4",
tertiaryBorderColor: "#2bc9c6",
lineColor: "#4dbfb8",
textColor: "#f5f5f5",
mainBkg: "#0d1115",
nodeBorder: "#2bc9c6",
nodeTextColor: "#f5f5f5",
clusterBkg: "#0a1014",
clusterBorder: "#2bc9c6",
defaultLinkColor: "#4dbfb8",
edgeLabelBackground: "#0d1115",
titleColor: "#f5f5f5",
nodeSpacing: 10,
rankSpacing: 10
},
flowchart: {
useMaxWidth: true,
curve: "natural",
},
});
function upgradeMermaidBlocks(container) {
container.querySelectorAll("pre code.language-mermaid").forEach(function (code) {
var pre = code.parentElement;
var div = document.createElement("div");
div.className = "mermaid";
var raw = code.textContent.replace(/\r\n/g, "\n");
div.setAttribute("data-mermaid-src", raw);
div.textContent = raw;
pre.parentNode.replaceChild(div, pre);
});
}
/** Mermaid dans une slide display:none a souvent largeur 0 → SVG vide ou taille absurde : on ne rend que la slide visible. */
function resetMermaidIfBroken(el) {
if (!el.getAttribute("data-processed")) return;
var svg = el.querySelector("svg");
if (svg && svg.getBoundingClientRect().height > 8) return;
var src = el.getAttribute("data-mermaid-src");
if (!src) return;
el.removeAttribute("data-processed");
el.innerHTML = "";
el.textContent = src;
}
function runMermaidInSlide(slide) {
if (!slide || typeof mermaid.run !== "function") return;
slide.querySelectorAll(".mermaid").forEach(resetMermaidIfBroken);
var pending = slide.querySelectorAll(".mermaid:not([data-processed])");
if (!pending.length) return;
requestAnimationFrame(function () {
requestAnimationFrame(function () {
mermaid.run({ nodes: pending, suppressErrors: true }).catch(function () { });
});
});
}
function applyHighlight() {
if (typeof hljs === "undefined") return;
document.querySelectorAll(".reveal .slides pre code").forEach(function (el) {
if (!el.classList.contains("language-mermaid")) hljs.highlightElement(el);
});
}
Reveal.initialize({
hash: true,
slideNumber: "c/t",
progress: true,
center: true,
transition: "slide",
backgroundTransition: "fade",
// Notes orateur en premier (touche S) ; puis coloration des blocs de code
plugins: [RevealNotes, RevealHighlight],
}).then(function () {
applyHighlight();
document.querySelectorAll(".reveal .slides section").forEach(function (sec) {
upgradeMermaidBlocks(sec);
});
runMermaidInSlide(Reveal.getCurrentSlide());
});
Reveal.on("slidechanged", function (event) {
runMermaidInSlide(event.currentSlide);
/* Slide « boucle » : sans ça, flex + centrage Reveal donnent souvent une 1ʳᵉ mesure de largeur fausse ; resize appelle déjà layout() — on le déclenche ici. */
if (event.currentSlide && event.currentSlide.classList.contains("slide-boucle")) {
requestAnimationFrame(function () {
requestAnimationFrame(function () {
if (typeof Reveal.layout === "function") Reveal.layout();
});
});
}
});
})();
</script>
</body>
</html>