## Introduction

Lorsque des incidents de production surviennent, les opérateurs Kubernetes passent d’un problème observé à un résultat vérifié. Cette liste de contrôle aide les développeurs, les consultants DevOps et les équipes techniques de startups à travailler en toute sécurité avec les charges de travail Kubernetes Event en reliant les opérations, les meilleures pratiques et la maintenance à des commandes spécifiques, à des résultats attendus, à des signaux d’échec et à des décisions de reprise.

Le principe fondamental est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d’impact, ne jamais coller de secrets dans les commandes, vérifier le résultat et documenter la façon de récupérer si l’état attendu n’est pas atteint. Chaque section nomme le composant concerné, la plage de versions prise en charge (Kubernetes 1.24 à 1.30 le cas échéant), les prérequis, les observations en lecture seule, le plus petit changement justifié et la commande de vérification.

Ce guide est écrit pour les ingénieurs qui gèrent des services événementiels avec état sur Kubernetes. Il suppose que vous avez `kubectl` installé et configuré pour un cluster, et que vous connaissez l’espace de noms et le nom de la charge de travail que vous examinez. Tous les exemples utilisent des valeurs fictives comme `<nom-du-pod>` ou `<espace-de-noms>` que vous devez remplacer par vos valeurs réelles.

## Inventaire des versions et de l’environnement

Avant de toucher à quoi que ce soit, établissez un inventaire des versions et de l’environnement. Cela évite l’erreur classique d’appliquer un correctif conçu pour une version de Kubernetes à une autre et facilite la reproduction des problèmes ou l’annulation des modifications.

Commencez par les versions du cluster et du client :

```bash
kubectl version --short
# Client Version: v1.29.2
# Server Version: v1.28.7
```

Si le client et le serveur diffèrent de plus d’une version mineure, mettez à niveau ou utilisez un client correspondant. Kubernetes prend en charge un écart d’une version mineure entre le client et le serveur. Une incompatibilité peut entraîner des erreurs d’analyse ou des champs d’API non pris en charge.

Ensuite, inspectez les nœuds et les pods qui exécutent votre charge de travail événementielle :

```bash
kubectl get nodes -o wide
# NAME          STATUS   ROLES           AGE   VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION     CONTAINER-RUNTIME
# node-1        Ready    control-plane   10d   v1.28.7   10.0.1.10     none          Ubuntu 22.04.3 LTS   5.15.0-91-generic  containerd://1.7.13
# node-2        Ready    <none>          10d   v1.28.7   10.0.1.11     none          Ubuntu 22.04.3 LTS   5.15.0-91-generic  containerd://1.7.13
```

Recherchez les nœuds en état `NotReady`, `SchedulingDisabled` ou avec une pression élevée sur le processeur ou la mémoire. Ces conditions peuvent empêcher la planification des pods d’événements ou entraîner leur éviction.

Listez ensuite les pods dans l’espace de noms de votre charge de travail :

```bash
kubectl get pods -n production -o wide
# NAME                              READY   STATUS             RESTARTS      AGE   IP            NODE     NOMINATED NODE   READINESS GATES
# event-processor-7f9c8b5d6-8x2w   0/1     CrashLoopBackOff   4 (2m ago)    15m   10.244.2.5    node-2   <none>           <none>
# event-queue-5d4f6b7c8-9q3z       1/1     Running            0             15m   10.244.1.8    node-1   <none>           <none>
```

Un pod en `CrashLoopBackOff` indique immédiatement que l’application à l’intérieur est en échec. Notez le nombre exact de redémarrages et l’âge, car ils aident à déterminer si le problème est nouveau ou récurrent.

Vérifiez également les événements Kubernetes pour l’espace de noms :

```bash
kubectl get events -n production --sort-by='.lastTimestamp'
# LAST SEEN   TYPE      REASON              OBJECT                                MESSAGE
# 2m          Warning   BackOff             pod/event-processor-7f9c8b5d6-8x2w   Back-off restarting failed container
# 5m          Normal    Scheduled           pod/event-processor-7f9c8b5d6-8x2w   Successfully assigned production/event-processor-7f9c8b5d6-8x2w to node-2
# 15m         Normal    Created             pod/event-queue-5d4f6b7c8-9q3z       Created container event-queue
# 15m         Normal    Started             pod/event-queue-5d4f6b7c8-9q3z       Started container event-queue
```

Les événements sont souvent le premier endroit à regarder lorsqu’un pod ne se comporte pas correctement. Ils montrent les décisions de planification, les échecs d’extraction d’image, les échecs de sonde et les évictions.

Pour une inspection approfondie d’un pod spécifique, utilisez `kubectl describe` :

```bash
kubectl describe pod event-processor-7f9c8b5d6-8x2w -n production
```

Examinez la section `Events` en bas pour les événements récents du cycle de vie, et la section `Conditions` pour les conditions `PodScheduled`, `Initialized`, `ContainersReady` et `Ready`. Si une condition est `False`, le message qui l’accompagne explique souvent pourquoi.

Enfin, vérifiez la version de l’API Kubernetes utilisée par vos manifestes. Par exemple, `events.k8s.io/v1` est stable depuis Kubernetes 1.19, mais les clusters plus anciens peuvent encore être en `v1beta1`. Vérifiez avec :

```bash
kubectl api-versions | grep events
# events.k8s.io/v1
```

Utilisez la version d’API correcte pour votre cluster afin d’éviter les erreurs de validation des manifestes.

## Chemin de configuration sécurisé

Apporter des modifications de configuration en production doit suivre un chemin sûr : petit, limité et réversible. Ne modifiez jamais un déploiement en direct directement avec `kubectl edit` ; mettez plutôt à jour le fichier manifeste, appliquez-le et observez le déploiement.

Supposons que vous deviez augmenter la limite de mémoire du conteneur event-processor de 512 Mo à 1 Go parce qu’il est tué par OOM (Out-Of-Memory). Commencez par vérifier l’utilisation actuelle des ressources :

```bash
kubectl top pod event-processor-7f9c8b5d6-8x2w -n production
# NAME                              CPU(cores)   MEMORY(bytes)
# event-processor-7f9c8b5d6-8x2w   120m         495Mi
```

L’utilisation de la mémoire est proche de la limite de 512 Mo, donc le pod est probablement tué lorsque l’utilisation atteint un pic. Vérifiez les raisons de terminaison récentes du pod :

```bash
kubectl describe pod event-processor-7f9c8b5d6-8x2w -n production | grep -A 5 'Last State'
# Last State:     Terminated
#   Reason:       OOMKilled
#   Exit Code:    137
```

Le code de sortie 137 indique que le conteneur a été tué par le tueur OOM. Cela confirme la nécessité d’une limite de mémoire plus élevée.

Ensuite, modifiez le fichier manifeste du déploiement (jamais `kubectl edit` en production sans sauvegarde). Trouvez la spécification du conteneur :

```yaml
# event-processor-deployment.yaml (extrait)
containers:
- name: event-processor
  image: registry.example.com/event-processor:1.4.2
  resources:
    limits:
      memory: "512Mi"
    requests:
      memory: "256Mi"
```

Changez la limite à `1Gi` et éventuellement la requête à `512Mi` pour refléter l’utilisation attendue. Appliquez ensuite le changement :

```bash
kubectl apply -f event-processor-deployment.yaml -n production
# deployment.apps/event-processor configured
```

Après l’application, surveillez l’état du déploiement :

```bash
kubectl rollout status deployment/event-processor -n production
# Waiting for deployment "event-processor" rollout to finish: 1 out of 3 new replicas have been updated...
# deployment "event-processor" successfully rolled out
```

Si le déploiement échoue, vérifiez les journaux et les événements du nouveau pod. Par exemple, si le nouveau pod est toujours tué par OOM parce que 1 Go ne suffit pas, le déploiement peut être bloqué. Vous pouvez mettre le déploiement en pause :

```bash
kubectl rollout pause deployment/event-processor -n production
```

Enquêtez, ajustez à nouveau la limite, puis reprenez :

```bash
kubectl rollout resume deployment/event-processor -n production
```

Si le changement cause des problèmes, revenez à la révision précédente :

```bash
kubectl rollout undo deployment/event-processor -n production
# deployment.apps/event-processor rolled back
```

Enregistrez toujours le numéro de révision précédent avec `kubectl rollout history deployment/event-processor -n production` afin de pouvoir spécifier `--to-revision` si nécessaire.

Pour les changements de configuration impliquant des ConfigMaps ou des Secrets, utilisez le même principe. N’utilisez pas `kubectl create secret` avec du texte en clair sur la ligne de commande, car il apparaît dans l’historique du shell. Créez plutôt le Secret à partir d’un fichier :

```bash
echo -n 's3cr3tValue' > secret.txt
kubectl create secret generic event-processor-secret --from-file=api-key=secret.txt -n production
rm secret.txt
```

Référencez ensuite la clé du secret dans la spécification de votre pod. Utilisez `kubectl get secret event-processor-secret -n production -o jsonpath='{.data.api-key}' | base64 --decode` uniquement pour la vérification, pas dans les journaux.

## Vérification et diagnostics

La vérification et les diagnostics sont au cœur des opérations Kubernetes. Vous avez besoin d’une approche systématique pour confirmer que votre charge de travail événementielle fonctionne correctement et pour diagnostiquer les problèmes lorsqu’elle ne fonctionne pas.

Commencez par les bases : vérifiez l’état des pods, les journaux et les événements.

```bash
kubectl get pods -n production -l app=event-processor -o wide
# NAME                              READY   STATUS    RESTARTS   AGE   IP            NODE     NOMINATED NODE   READINESS GATES
# event-processor-7f9c8b5d6-8x2w   1/1     Running   0          30m   10.244.2.5    node-2   <none>           <none>
```

Si un pod n’est pas `Running`, utilisez `kubectl describe` pour voir les événements. S’il est en boucle de crash, récupérez les journaux de l’instance actuelle et précédente du conteneur :

```bash
kubectl logs event-processor-7f9c8b5d6-8x2w -n production --tail=50
# ... journaux de l’application ...
kubectl logs event-processor-7f9c8b5d6-8x2w -n production --previous --tail=50
# ... journaux de l’instance précédente qui a planté, pouvant montrer l’erreur fatale ...
```

Pour les pods multi-conteneurs, précisez le nom du conteneur avec `-c <nom-du-conteneur>`.

Ensuite, vérifiez la santé de votre service d’événements. Si vous avez un Service et un Ingress, vérifiez les points de terminaison et la connectivité.

```bash
kubectl get svc event-processor -n production
# NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
# event-processor    ClusterIP   10.96.52.114    <none>        8080/TCP   30m

kubectl get endpoints event-processor -n production
# NAME               ENDPOINTS           AGE
# event-processor   10.244.2.5:8080     30m
```

Si les points de terminaison sont vides, le sélecteur du Service ne correspond à aucune étiquette de pod, ou les pods ne sont pas prêts. Comparez le sélecteur du Service et les étiquettes des pods.

Testez la connectivité depuis l’intérieur du cluster :

```bash
kubectl run curl-test --rm -it --image=curlimages/curl -n production -- sh
# Depuis l’intérieur du pod :
curl http://event-processor.production.svc.cluster.local:8080/healthz
# Attendu : {"status":"ok"}
```

Pour les systèmes pilotés par événements, vérifiez que les messages sont consommés. Si vous utilisez Kafka, vérifiez le retard (lag) du groupe de consommateurs. Par exemple, en utilisant `kafka-consumer-groups.sh` :

```bash
kafka-consumer-groups.sh --bootstrap-server kafka-broker:9092 --describe --group event-processor
# TOPIC           PARTITION  CURRENT-OFFSET  LOG-END-OFFSET  LAG   CONSUMER-ID     HOST            CLIENT-ID
# events          0          100             150             50    consumer-1-...  /10.244.2.5     consumer-1
# events          1          200             250             50    consumer-1-...  /10.244.2.5     consumer-1
```

Un retard élevé signifie que le consommateur prend du retard. Vérifiez les journaux de l’application pour détecter des ralentissements de traitement ou des erreurs.

La configuration des sondes est critique. Assurez-vous que les sondes de vivacité (liveness) et de préparation (readiness) sont correctement définies. Pour un service HTTP, votre déploiement pourrait ressembler à :

```yaml
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 15
  periodSeconds: 20
readinessProbe:
  httpGet:
    path: /readyz
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10
```

Vérifiez le succès des sondes avec `kubectl describe pod` ; si les sondes échouent, le pod redémarre fréquemment ou est marqué non prêt.

Pour des diagnostics plus approfondis, utilisez `kubectl exec` pour exécuter des commandes à l’intérieur du conteneur et inspecter le système de fichiers ou l’environnement :

```bash
kubectl exec -it event-processor-7f9c8b5d6-8x2w -n production -- sh
# À l’intérieur du conteneur : vérifiez les variables d’environnement, les fichiers de configuration, exécutez des commandes de diagnostic
```

Préférez toujours `kubectl logs` et `kubectl exec` pour les vérifications en lecture seule avant d’apporter des modifications.

## Modes de défaillance et reprise

Les systèmes de production échouent de manière prévisible. Connaître les modes de défaillance courants des charges de travail Kubernetes Event et comment s’en remettre réduira les temps d’arrêt.

### 1. Pod en CrashLoopBackOff

**Symptôme** : L’état du pod est `CrashLoopBackOff`, le nombre de redémarrages augmente.

**Diagnostic** : Utilisez `kubectl logs <pod> --previous` pour voir l’erreur du dernier crash. Causes courantes : configuration manquante, arguments invalides, exceptions non gérées, manque de mémoire.

**Reprise** : Corrigez la cause sous-jacente dans l’image ou la configuration, puis appliquez le changement. Si le pod est coincé dans une boucle de crash et que vous devez l’arrêter rapidement, réduisez le déploiement à zéro :

```bash
kubectl scale deployment event-processor --replicas=0 -n production
```

Enquêtez, corrigez, puis remontez à l’échelle. Cela arrête la boucle de crash et libère des ressources.

### 2. ImagePullBackOff

**Symptôme** : L’état du pod est `ImagePullBackOff` ou `ErrImagePull`.

**Diagnostic** : Décrivez le pod et vérifiez les événements :

```bash
kubectl describe pod event-processor-7f9c8b5d6-8x2w -n production | grep -A 10 Events
# Events:
#   Type     Reason          Age                From     Message
#   ----     ------          ----               ----     -------
#   Normal   Scheduled       10m                default-scheduler  Successfully assigned production/event-processor-7f9c8b5d6-8x2w to node-2
#   Warning  Failed          9m                 kubelet  Failed to pull image "registry.example.com/event-processor:1.4.3": rpc error: code = NotFound desc = failed to pull and unpack image
#   Warning  Failed          8m                 kubelet  Error: ErrImagePull
#   Normal   BackOff         7m                 kubelet  Back-off pulling image "registry.example.com/event-processor:1.4.3"
```

**Reprise** : Vérifiez le nom et l’étiquette de l’image. Assurez-vous que les informations d’identification du registre sont correctes et que l’image existe. Si l’étiquette est incorrecte, mettez à jour le déploiement pour utiliser une étiquette valide. S’il s’agit d’un registre privé, vérifiez que le `imagePullSecret` est correct et présent dans l’espace de noms.

### 3. Mémoire insuffisante (OOMKilled)

**Symptôme** : Le pod se termine avec la raison `OOMKilled` et le code de sortie 137.

**Diagnostic** : Vérifiez le dernier état du pod :

```bash
kubectl describe pod event-processor-7f9c8b5d6-8x2w -n production | grep -A 5 'Last State'
# Last State:     Terminated
#   Reason:       OOMKilled
#   Exit Code:    137
```

Vérifiez également les événements de pression mémoire du nœud.

**Reprise** : Augmentez la limite de mémoire du conteneur, ou réduisez son utilisation de la mémoire en optimisant l’application ou en passant à l’échelle horizontale. Assurez-vous que les requêtes sont définies de manière appropriée ; une requête trop faible peut entraîner une éviction sous la pression du nœud.

### 4. Nœud NotReady

**Symptôme** : Un ou plusieurs nœuds affichent `NotReady`, et les pods qui s’y trouvent peuvent être évincés ou ne pas répondre.

**Diagnostic** : Vérifiez l’état et les conditions du nœud :

```bash
kubectl get nodes
# NAME          STATUS     ROLES           AGE   VERSION
# node-1        Ready      control-plane   10d   v1.28.7
# node-2        NotReady   <none>          10d   v1.28.7

kubectl describe node node-2 | grep -A 10 Conditions
# Conditions:
#   Type             Status  LastHeartbeatTime                 LastTransitionTime                Reason                       Message
#   ----             ------  -----------------                 ------------------                ------                       -------
#   MemoryPressure   False   Thu, 13 Jun 2024 10:00:00 +0000   Thu, 13 Jun 2024 09:00:00 +0000   KubeletHasSufficientMemory   kubelet has sufficient memory available
#   DiskPressure     False   ...
#   PIDPressure      False   ...
#   Ready            False   Thu, 13 Jun 2024 10:05:00 +0000   Thu, 13 Jun 2024 10:05:00 +0000   KubeletNotReady              container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin is not ready
```

La condition `Ready` est `False` avec la raison `KubeletNotReady` et un message concernant le plugin réseau. Cela indique souvent une défaillance du plugin CNI sur le nœud.

**Reprise** : Vérifiez l’état du kubelet sur le nœud (si accessible) : `systemctl status kubelet`, `journalctl -u kubelet -n 100`. Si le plugin réseau n’est pas prêt, le réseau des pods peut devoir être redémarré. Si le nœud ne peut pas être récupéré rapidement, cordonnez-le et drainez-le pour déplacer les pods vers des nœuds sains :

```bash
kubectl cordon node-2
kubectl drain node-2 --ignore-daemonsets --delete-emptydir-data
```

Ensuite, enquêtez et corrigez le nœud. Après la récupération, décordonnez-le :

```bash
kubectl uncordon node-2
```

### 5. Échec de livraison des événements (retard du consommateur)

**Symptôme** : Les consommateurs d’événements ne traitent pas les messages aussi vite qu’ils sont produits ; le retard du groupe de consommateurs augmente.

**Diagnostic** : Vérifiez le retard du groupe de consommateurs (comme montré précédemment). Vérifiez également les journaux des pods consommateurs pour détecter des erreurs de traitement.

**Reprise** : Augmentez le nombre de répliques du déploiement du consommateur pour accroître la capacité de traitement :

```bash
kubectl scale deployment event-processor --replicas=5 -n production
```

Assurez-vous que la source d’événements (le courtier) est saine et ne limite pas le débit. S’il y a un message empoisonné provoquant des tentatives répétées, envisagez de le déplacer vers une file d’attente de lettres mortes ou de corriger le consommateur pour le gérer avec élégance.

Pour tous les modes de défaillance, documentez l’incident et les étapes de reprise. Utilisez `kubectl get events --sort-by='.lastTimestamp' -n production` pour capturer la chronologie. Conservez ces enregistrements dans un runbook pour référence future.

## Liste de contrôle des opérations

Utilisez cette liste de contrôle comme routine quotidienne ou avant/après un changement pour les charges de travail de production Kubernetes Event.

### Observation en lecture seule

- [ ] Vérifiez les versions du cluster et du client avec `kubectl version --short`. Notez tout écart supérieur à une version mineure.
- [ ] Listez les nœuds et les pods avec `kubectl get nodes -o wide` et `kubectl get pods -n production -o wide`. Enregistrez tout nœud non prêt ou pod avec des redémarrages.
- [ ] Examinez les événements récents avec `kubectl get events -n production --sort-by='.lastTimestamp'`. Cherchez les avertissements ou les erreurs.
- [ ] Pour les pods clés, exécutez `kubectl describe pod <nom-du-pod> -n production` et inspectez les conditions et les événements.
- [ ] Vérifiez l’utilisation des ressources avec `kubectl top pod -n production` et `kubectl top node`. Identifiez les pods ou nœuds dépassant les seuils (par exemple, > 80 % de mémoire ou de processeur).
- [ ] Vérifiez les points de terminaison des services avec `kubectl get endpoints -n production`. Assurez-vous que tous les pods attendus sont listés.
- [ ] Pour les consommateurs d’événements, vérifiez le retard du groupe de consommateurs et comparez-le aux seuils.

### Procédure de changement sécurisé

- [ ] Avant tout changement, capturez l’état actuel : `kubectl get deployment <nom> -o yaml -n production > backup.yaml`.
- [ ] Modifiez le fichier manifeste, pas les objets en direct.
- [ ] Appliquez le changement avec `kubectl apply -f <fichier> -n production`.
- [ ] Surveillez le déploiement avec `kubectl rollout status deployment/<nom> -n production`.
- [ ] Si le déploiement échoue, examinez les journaux et les événements des nouveaux pods. Utilisez `kubectl rollout undo` si nécessaire.
- [ ] Après un déploiement réussi, vérifiez l’état et les journaux du nouveau pod.

### Vérification après changement

- [ ] Vérifiez la préparation des pods : `kubectl get pods -n production -l app=<app>` doit montrer tous les pods prêts.
- [ ] Effectuez un test de fumée : exécutez un curl dans un pod ou utilisez `kubectl run` pour tester le point de terminaison du service.
- [ ] Vérifiez à nouveau le retard du consommateur pour vous assurer que le traitement rattrape son retard.
- [ ] Examinez les événements pour tout nouvel avertissement.
- [ ] Si le changement impliquait des ressources, vérifiez que les limites sont suffisantes et ne provoquent pas de OOMKills ou de limitation.

### Documentation

- [ ] Enregistrez le changement dans votre runbook avec l’heure, la cible, la commande et le résultat observé.
- [ ] Si une annulation a été nécessaire, notez la révision et la raison.
- [ ] Mettez à jour les tableaux de bord ou les alertes en fonction des métriques observées.

Cette liste de contrôle n’est pas exhaustive mais couvre les tâches opérationnelles les plus critiques. Adaptez-la à votre environnement, en ajoutant des vérifications spécifiques pour votre courtier d’événements, votre stockage et vos configurations réseau.

## Conclusion

Une liste de contrôle des opérations de production Kubernetes Event ne devient précieuse que lorsqu’elle est limitée à une version, observable et réversible. Copier des commandes sans vérifier les prérequis et les résultats attendus n’est pas une procédure opérationnelle ; c’est un risque.

Commencez par une vérification à faible risque : choisissez un déploiement dans un espace de noms de développement, enregistrez son état actuel à l’aide de `kubectl get deployment -o yaml`, exécutez un diagnostic en lecture seule comme `kubectl logs --tail=50`, comparez le résultat au comportement attendu, puis apportez seulement un petit changement et vérifiez le déploiement. Examinez les dépendances telles que la version du cluster, la santé des nœuds et la préparation des pods après chaque étape.

Un flux de travail technique fiable rend les défaillances visibles, protège les valeurs sensibles, limite les changements à la ressource prévue et définit la vérification de la reprise avant qu’un incident ne se produise. En suivant les listes de contrôle de cet article, les équipes peuvent exploiter les charges de travail pilotées par événements sur Kubernetes avec confiance et réduire le temps moyen de récupération lorsque des problèmes surviennent inévitablement.

**Prochaines étapes** :

- Choisissez une charge de travail proche de la production et exécutez la liste de contrôle complète d’observation en lecture seule.
- Documentez les résultats et comparez-les à vos références.
- Pratiquez un changement et une annulation en toute sécurité dans un environnement de préproduction.
- Créez ou mettez à jour votre runbook avec les modes de défaillance décrits ici.

Les opérations Kubernetes sont une pratique continue. L’utilisation régulière de ces listes de contrôle et procédures développera la mémoire musculaire nécessaire à la réponse aux incidents et à l’amélioration continue.