Chapitre 14 : Extensibilité¶
Objectifs du chapitre
- Citer les principaux points d'extension de Kubernetes
- Expliquer ce qu'est une CustomResourceDefinition (CRD) et une ressource personnalisée
- Décrire le fonctionnement d'un contrôleur et le modèle « opérateur »
- Reconnaître les CRD déjà rencontrées dans le cours (Traefik, Argo CD, cert-manager)
- Décrire les fonctions d'un service mesh, son architecture et son coût
- Évaluer l'intérêt d'une extension pour un besoin donné
- Acquis d'apprentissage visé : AA8
1. Pourquoi étendre Kubernetes ?¶
Kubernetes connaît des objets généraux : Pod, Deployment, Service. Mais un besoin comme « une base PostgreSQL avec sauvegardes et bascule automatique » ou « un certificat TLS renouvelé tout seul » n'y a pas d'objet dédié. Plutôt que de multiplier les objets natifs, Kubernetes permet d'ajouter les siens, qui se manipulent ensuite avec les mêmes outils (kubectl, RBAC, YAML, GitOps).
| Point d'extension | Ce qu'on ajoute | Exemple |
|---|---|---|
| CRD (CustomResourceDefinition) | De nouveaux types d'objets dans l'API | Application d'Argo CD, Certificate de cert-manager |
| Contrôleur / opérateur | La logique qui donne vie à ces objets | L'opérateur d'une base de données |
| Webhooks d'admission | Un contrôle ou une modification à la création d'un objet | Refuser les images non signées |
| Plugins d'infrastructure (CNI, CSI, CRI) | Réseau, stockage, moteur de conteneurs | Flannel, local-path (chapitres 1 et 5) |
Plugins kubectl |
De nouvelles sous-commandes | kubectl neat, kubectl ctx |
Ce chapitre traite des deux premiers, puis présente le service mesh.
2. Les CRD : de nouveaux types d'objets¶
Une CRD déclare à l'API server un nouveau type. Après son enregistrement, l'API accepte, valide et stocke (dans etcd) des objets de ce type : les ressources personnalisées (custom resources, CR).
flowchart LR
CRD["CRD<br/>« Website existe »"] -- "enregistre le type" --> API["API server"]
CR["Ressource personnalisée<br/>kind: Website, nom demo"] -- "kubectl apply" --> API
API --> E[("etcd")]
Exemple de CRD pour un type fictif Website :
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: websites.cours.example.org # <pluriel>.<groupe>
spec:
group: cours.example.org
scope: Namespaced
names:
plural: websites
singular: website
kind: Website
shortNames: [ws]
versions:
- name: v1
served: true
storage: true
subresources:
status: {}
additionalPrinterColumns:
- name: Replicas
type: integer
jsonPath: .spec.replicas
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
required: [message]
properties:
message:
type: string
replicas:
type: integer
minimum: 1
maximum: 5
default: 1
status:
type: object
properties:
phase:
type: string
| Champ | Rôle |
|---|---|
group, names, versions |
Identité du type : cours.example.org/v1, kind: Website |
scope |
Namespaced (dans un namespace) ou Cluster |
schema.openAPIV3Schema |
Validation : types, champs obligatoires, bornes. L'API refuse un objet non conforme |
subresources.status |
Sépare l'état observé (status) de l'état voulu (spec) : même principe que pour les Pods |
additionalPrinterColumns |
Colonnes affichées par kubectl get |
Une ressource personnalisée se rédige comme n'importe quel objet :
apiVersion: cours.example.org/v1
kind: Website
metadata:
name: demo
spec:
message: "Bonjour"
replicas: 2
Une CRD seule ne fait rien
Créer un objet Website ne crée ni Pod ni Service. L'API stocke simplement l'objet. Il faut un contrôleur pour agir.
3. Contrôleurs et opérateurs¶
Vous connaissez la boucle de réconciliation (chapitre 1) : un contrôleur compare l'état voulu et l'état réel, et agit pour les rapprocher. Les Deployments ont leur contrôleur dans le cluster. Pour une CRD, c'est vous (ou un éditeur) qui fournissez le contrôleur.
flowchart LR
U["Utilisateur<br/>crée un Website"] --> API["API server"]
API -- "événements<br/>(watch)" --> C["Contrôleur<br/>(dans un Pod)"]
C -- "crée / ajuste" --> O["Deployment<br/>Service<br/>ConfigMap"]
C -- "écrit status" --> API
O -. "état réel" .-> C
Un contrôleur typique :
- observe les objets de son type (mécanisme de watch de l'API) ;
- compare à l'état réel (Pods, Services, etc.) ;
- crée, modifie ou supprime les objets nécessaires ;
- écrit le
statusde l'objet ; - recommence à chaque événement, et à intervalle régulier.
Un opérateur est un contrôleur qui encode le savoir-faire d'un exploitant pour une application : installation, configuration, sauvegarde, mise à jour, bascule en cas de panne. Typiquement : une CRD (« un cluster PostgreSQL ») + un contrôleur déployé dans le cluster.
| Sans opérateur | Avec opérateur | |
|---|---|---|
| Déployer une base répliquée | Manifestes StatefulSet, scripts, procédures | Un objet Cluster de quelques lignes |
| Sauvegarde, bascule, mise à jour | Procédures manuelles | Gérés par le contrôleur |
| Risque | Erreur humaine | Dépendance à la qualité de l'opérateur |
Les opérateurs se construisent avec des outils comme Operator SDK ou Kubebuilder (langage Go le plus souvent). Les opérateurs existants se trouvent dans des catalogues publics.
Quand écrire (ou installer) un opérateur ?
Quand une application a un cycle de vie complexe que des manifestes ne suffisent pas à décrire (état, réplication, sauvegarde). Pour une application sans état, un Deployment et un chart Helm suffisent : un opérateur serait une complexité inutile.
Les CRD que vous avez déjà rencontrées¶
| CRD | Apportée par | Chapitre | Rôle |
|---|---|---|---|
Application |
Argo CD | 12 | Décrit l'application à synchroniser depuis Git |
Middleware, IngressRoute, TraefikService |
Traefik | 3, 13 | Redirections, limites de débit, routage avancé |
Certificate, ClusterIssuer |
cert-manager | 13 | Certificats TLS obtenus et renouvelés automatiquement |
HelmChart |
k3s | 11 | Installe un chart Helm sans la commande helm |
Pour les lister : kubectl get crd.
4. Le service mesh (aperçu)¶
Dans une architecture en microservices, chaque service appelle d'autres services. Il faut alors, entre les services, chiffrer les échanges, réessayer en cas d'échec, mesurer la latence, répartir le trafic entre versions, limiter les accès. Faire cela dans le code de chaque application, dans chaque langage, est coûteux. Un service mesh déplace ces fonctions dans l'infrastructure.
| Fonction | Apport |
|---|---|
| Sécurité | Chiffrement mutuel (mTLS) entre services, identité de chaque service, règles d'autorisation |
| Fiabilité | Délais d'attente (timeouts), nouvelles tentatives, coupe-circuit |
| Gestion du trafic | Répartition pondérée entre versions (canary), bascule progressive, tests A/B |
| Observabilité | Latence, débit et taux d'erreur de chaque appel, sans modifier le code |
Architecture¶
flowchart TB
CP["Plan de contrôle<br/>(configuration, certificats)"]
subgraph PA["Pod A"]
A["Application A"] --- PXA["Proxy sidecar"]
end
subgraph PB["Pod B"]
B["Application B"] --- PXB["Proxy sidecar"]
end
PXA -- "mTLS" --> PXB
CP -. "configure" .-> PXA
CP -. "configure" .-> PXB
- Chaque Pod reçoit un proxy sidecar (vous connaissez ce motif depuis le chapitre 6) qui intercepte tout le trafic entrant et sortant de l'application.
- Le plan de contrôle distribue la configuration et les certificats aux proxys.
- Les applications ne changent pas : elles croient communiquer directement.
Des variantes récentes évitent un proxy par Pod (un agent par nœud, ou « sidecarless »), pour réduire le coût.
Le coût d'un service mesh¶
| Coût | Détail |
|---|---|
| Ressources | Un proxy par Pod : CPU et mémoire supplémentaires, multipliés par le nombre de Pods |
| Latence | Chaque appel traverse deux proxys de plus |
| Complexité | Un composant de plus à installer, mettre à jour, déboguer |
| Compétences | Concepts et outils supplémentaires pour l'équipe |
Un mesh n'est pas toujours la bonne réponse
Pour quelques services, un Ingress, des NetworkPolicies et une bonne observabilité suffisent. Le mesh se justifie quand le nombre de services, les exigences de sécurité (mTLS généralisé) ou la gestion du trafic le demandent. Dans ce cours, vos VMs de 2 Go sont trop justes pour en installer un de façon fiable : le Lab 14.2 en manipule les fonctions avec Traefik et en étudie le coût.
À retenir
- Kubernetes s'étend par des CRD (nouveaux types d'objets) et des contrôleurs (la logique qui les anime).
- Une CRD déclare un type et le valide ; sans contrôleur, un objet n'est que des données stockées dans etcd.
- Un opérateur = CRD + contrôleur qui encode le savoir-faire d'exploitation d'une application.
- Vous utilisez déjà des CRD : Argo CD, Traefik, cert-manager,
HelmChartde k3s (kubectl get crd). - Un service mesh fournit mTLS, fiabilité, gestion du trafic et observabilité grâce à un proxy sidecar par Pod.
- Son coût (ressources, latence, complexité) doit être pesé contre le besoin.
Pour vérifier votre compréhension¶
Vous créez un objet Website après avoir enregistré la CRD, mais aucun Pod n'apparaît. Pourquoi ?
La CRD fait seulement accepter et stocker l'objet par l'API. Aucun contrôleur n'observe les Website pour créer des Deployments et des Services : il faut en installer un.
À quoi sert le schéma openAPIV3Schema d'une CRD ?
À valider les objets à la création : types des champs, champs obligatoires, valeurs minimales et maximales, valeurs par défaut. Un objet non conforme est refusé par l'API.
Que devient-il des ressources personnalisées quand on supprime leur CRD ?
Elles sont supprimées avec elle : le type n'existe plus, ses objets non plus. Il faut donc sauvegarder les ressources avant de supprimer une CRD.
Quelle différence entre un contrôleur et un opérateur ?
Tous deux réconcilient l'état voulu et l'état réel. Un opérateur est un contrôleur spécialisé qui encode le savoir-faire d'exploitation d'une application précise (sauvegarde, bascule, mise à jour).
Citez deux fonctions d'un service mesh que vous ne pouviez pas obtenir avec un Service et un Ingress seuls.
Le chiffrement mutuel (mTLS) entre services avec identité de chaque service ; les nouvelles tentatives et délais d'attente appliqués aux appels internes ; la répartition pondérée du trafic interne entre versions ; la mesure de la latence de chaque appel entre services.
Votre application compte 3 services sur un cluster de 3 VMs de 2 Go. Un service mesh est-il pertinent ?
Probablement non : les proxys sidecar consomment de la mémoire sur des nœuds déjà justes, et le nombre de services est faible. Un Ingress, des NetworkPolicies et la supervision répondent au besoin avec moins de complexité.