Introduction
Opérer les runtimes de conteneurs Kubernetes en production exige des étapes rigoureuses et vérifiables plutôt qu'un dépannage improvisé. Les runtimes de conteneurs, tels que containerd et CRI-O, se situent directement sous le kubelet et gèrent le cycle de vie complet des conteneurs sur chaque nœud. Un runtime mal configuré peut entraîner des échecs de planification des pods, des erreurs de récupération d'images, une mise en réseau instable et des vulnérabilités de sécurité qui se propagent à travers le cluster.
Cet article fournit une liste de contrôle axée sur la production pour les opérations des runtimes de conteneurs Kubernetes. Il couvre l'inventaire des versions et de l'environnement, les modifications de configuration sûres, la vérification et les diagnostics, les modes de défaillance et la récupération, ainsi qu'une liste de contrôle opérationnelle. Chaque section inclut des commandes concrètes, les sorties attendues et des exemples utilisant containerd (le runtime par défaut pour la plupart des clusters gérés et auto-gérés) et CRI-O (courant dans OpenShift et certains environnements basés sur RHEL).
L'objectif est la sécurité opérationnelle : observer avant de modifier, limiter le rayon d'impact, utiliser des espaces réservés au lieu de secrets lors du partage de commandes, vérifier les résultats et documenter les chemins de récupération avant qu'un incident ne force une action rapide.
Inventaire des versions et de l'environnement
Avant de modifier un runtime de conteneurs, sachez exactement ce qui est installé, où il s'exécute et quelle version de Kubernetes il doit prendre en charge. Un runtime trop ancien peut manquer des fonctionnalités CRI requises ; un runtime trop récent peut ne pas encore être validé avec votre version de Kubernetes.
Étape 1 : Identifier le runtime sur chaque nœud
Utilisez kubectl pour inspecter l'état du nœud et les informations sur le runtime. La sortie de kubectl get nodes -o wide affiche la version du runtime de conteneurs signalée par le kubelet.
kubectl get nodes -o wide
Exemple de sortie (abrégée) :
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
node-1 Ready control-plane 30d v1.28.5 10.0.0.11 <none> Ubuntu 22.04.3 LTS 5.15.0-91-generic containerd://1.7.11
node-2 Ready <none> 30d v1.28.5 10.0.0.12 <none> Ubuntu 22.04.3 LTS 5.15.0-91-generic containerd://1.7.11
Si la colonne CONTAINER-RUNTIME est absente, utilisez kubectl describe node <node-name> et cherchez le champ Container Runtime Version dans la section System Info.
Pour une vérification plus directe sur un nœud, connectez-vous en SSH et exécutez :
# Pour containerd
containerd --version
# Sortie attendue : containerd github.com/containerd/containerd 1.7.11
# Pour CRI-O
crio --version
# Sortie attendue : crio version 1.28.2
Étape 2 : Vérifier l'état du plugin CRI
Le kubelet communique avec le runtime via le plugin Container Runtime Interface (CRI). Pour containerd, vérifiez que le plugin CRI est activé et que le socket correct existe.
# Sur le nœud
sudo crictl info
Extrait de sortie exemple :
{
"status": {
"conditions": [
{
"type": "RuntimeReady",
"status": true,
"reason": "",
"message": ""
},
{
"type": "NetworkReady",
"status": true,
"reason": "",
"message": ""
}
]
}
}
Si RuntimeReady est false, le runtime a peut-être planté ou est mal configuré. Vérifiez l'état du service du runtime :
sudo systemctl status containerd
# ou
sudo systemctl status crio
Étape 3 : Confirmer la compatibilité avec Kubernetes
Kubernetes publie une matrice de compatibilité pour les runtimes de conteneurs. Pour Kubernetes 1.28, containerd 1.7.x et CRI-O 1.28.x sont pris en charge. Exécuter une version inadaptée peut causer des défaillances subtiles, comme des pods qui ne démarrent pas après une mise à niveau.
Enregistrez les éléments suivants dans votre inventaire :
- Version de Kubernetes :
kubectl version --shortoukubectl version - Nom et version du runtime : depuis
kubectl get nodes -o wideou les commandes sur le nœud - Chemin du socket CRI : généralement
/run/containerd/containerd.sockpour containerd,/var/run/crio/crio.sockpour CRI-O - Configuration du kubelet :
cat /var/lib/kubelet/config.yamlsur le nœud (le chemin peut varier)
Exemple pratique : Inventaire sur un seul nœud
kubectl get nodes -o wide
Sortie attendue :
containerd://1.7.11
Si la sortie est vide ou docker:// (héritage), vous devrez peut-être migrer ou enquêter. Ne procédez aux modifications de configuration qu'une fois cet inventaire complet et cohérent sur tous les nœuds.
Chemin de configuration sûr
Modifier la configuration d'un runtime peut affecter chaque pod sur ce nœud. Suivez un chemin sûr : sauvegardez la configuration actuelle, effectuez une modification ciblée, redémarrez le runtime et vérifiez que le nœud reste Ready et qu'un pod de test peut démarrer.
Étape 1 : Sauvegarder la configuration actuelle
Pour containerd, le fichier de configuration principal est généralement /etc/containerd/config.toml sous Linux. Avant de le modifier, créez une sauvegarde avec un horodatage.
sudo cp /etc/containerd/config.toml /etc/containerd/config.toml.bak.$(date +%Y%m%d%H%M%S)
Pour CRI-O, la configuration se trouve souvent dans /etc/crio/crio.conf ou dans des fichiers drop-in sous /etc/crio/crio.conf.d/. Sauvegardez de la même manière.
Étape 2 : Effectuer une modification minimale et documentée
Supposons que vous deviez changer le niveau de journalisation du runtime de info à debug pour le dépannage. Pour containerd, modifiez config.toml et définissez :
[debug]
level = "debug"
Pour CRI-O, dans crio.conf :
[crio.runtime]
log_level = "debug"
Évitez de modifier plusieurs paramètres à la fois. Si un problème survient plus tard, vous pourrez isoler la cause.
Étape 3 : Redémarrer le service du runtime
sudo systemctl restart containerd
# ou
sudo systemctl restart crio
Vérifiez que le service est actif et sans erreur :
sudo systemctl status containerd --no-pager -l
Sortie attendue (partielle) :
● containerd.service - containerd container runtime
Loaded: loaded (/lib/systemd/system/containerd.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2024-02-05 10:15:22 UTC; 5s ago
Étape 4 : Vérifier la santé du nœud et exécuter un pod de test
Après le redémarrage du runtime, le kubelet devrait se reconnecter. Confirmez que le nœud reste Ready :
kubectl get node node-1
Sortie attendue :
NAME STATUS ROLES AGE VERSION
node-1 Ready control-plane 30d v1.28.5
Si le nœud passe brièvement NotReady puis revient, c'est normal lors d'un redémarrage du runtime. S'il reste NotReady, examinez les journaux du kubelet et le socket du runtime.
Exécutez un pod de test minimal sur ce nœud en utilisant un sélecteur de nœud (si vous devez cibler un nœud spécifique) :
apiVersion: v1
kind: Pod
metadata:
name: runtime-test
spec:
nodeName: node-1
containers:
- name: busybox
image: busybox:1.36
command: ["sleep", "3600"]
kubectl apply -f runtime-test.yaml
kubectl get pod runtime-test -o wide
Sortie attendue :
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
runtime-test 1/1 Running 0 10s 10.244.1.5 node-1 <none> <none>
Si le pod ne démarre pas, vérifiez les événements et les journaux :
kubectl describe pod runtime-test
kubectl logs runtime-test
Une fois vérifié, supprimez le pod de test.
Modifications de configuration courantes et notes de sécurité
- Changer le chemin du binaire du runtime : Assurez-vous que le kubelet a le bon drapeau
--container-runtime-endpoint. Pour containerd, c'estunix:///run/containerd/containerd.sock; pour CRI-O,unix:///var/run/crio/crio.sock. - Miroirs de registre d'images : Configurez-les dans
config.tomlde containerd sous[plugins."io.containerd.grpc.v1.cri".registry.mirrors]. Pour CRI-O, utilisezregistries.conf. Une mauvaise configuration peut entraîner des échecs de récupération d'images. - Changer le propriétaire/les permissions du socket CRI : Le kubelet s'exécute généralement en tant que root, mais si vous modifiez les permissions, assurez-vous que le kubelet peut toujours se connecter. Testez avec
sudo crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps.
Vérification et diagnostics
Une fois une modification effectuée, vérifiez que le runtime est sain et que le comportement attendu est observé. Cette section fournit des diagnostics systématiques à l'aide de crictl, kubectl et d'outils spécifiques au runtime.
1. Vérifier la santé du runtime via crictl
crictl est une CLI pour les runtimes compatibles CRI. Elle vous permet d'inspecter les conteneurs, les images et les sandboxes directement, en contournant le kubelet.
Listez les conteneurs en cours d'exécution sur un nœud :
sudo crictl ps
Sortie attendue (abrégée) :
CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT POD ID
1a2b3c4d5e6f7 nginx:1.25.3 2 hours ago Running nginx 0 0a1b2c3d4e5f6
Listez les images :
sudo crictl images
Inspectez un conteneur spécifique :
sudo crictl inspect 1a2b3c4d5e6f7
Cette sortie inclut les informations sur le runtime, les limites de ressources et les montages.
2. Vérifier les journaux du kubelet pour les erreurs CRI
Si les pods ne démarrent pas, les journaux du kubelet contiennent souvent des erreurs CRI.
journalctl -u kubelet -n 100 --no-pager | grep -i cri
Recherchez des messages comme Failed to create pod sandbox, rpc error: code = Unavailable desc = connection error, ou failed to start container.
Exemple de journal problématique :
Feb 05 10:20:15 node-1 kubelet[1234]: E0205 10:20:15.123456 1234 remote_runtime.go:176] "CreatePodSandbox for pod failed" err="rpc error: code = Unknown desc = failed to setup network for sandbox ..."
3. Déboguer les échecs de récupération d'images
Les échecs de récupération d'images sont des problèmes de runtime courants. Utilisez kubectl describe pod pour voir les événements :
kubectl describe pod <pod-name> | grep -A5 Events
Recherchez Failed to pull image, ErrImagePull ou ImagePullBackOff.
Sur le nœud, récupérez manuellement l'image à l'aide de l'outil du runtime :
Pour containerd :
sudo ctr image pull docker.io/library/nginx:1.25.3
Pour CRI-O (en utilisant crictl) :
sudo crictl pull docker.io/library/nginx:1.25.3
Si la récupération échoue, vérifiez la connectivité réseau, les identifiants de registre et la configuration du registre du runtime.
4. Vérifier les journaux des conteneurs
Utilisez crictl logs pour afficher les journaux au niveau du runtime d'un conteneur, qui peuvent différer de kubectl logs.
sudo crictl logs 1a2b3c4d5e6f7
Pour un pod en boucle de crash, obtenez les journaux du conteneur précédent avec kubectl :
kubectl logs <pod-name> --previous
Exemple de sortie pour une boucle de crash :
Error: unable to open database file: /data/app.db
Cela indique un problème de volume ou de permission plutôt qu'un problème de runtime, mais il est important de faire la distinction.
Modes de défaillance et récupération
Les runtimes de conteneurs peuvent échouer de plusieurs manières. Connaître les modes de défaillance courants et leurs étapes de récupération réduit les temps d'arrêt.
Mode de défaillance 1 : Crash du service du runtime
Symptôme : Le nœud devient NotReady, les pods ne peuvent pas démarrer ou s'arrêter, kubectl describe node montre ContainerRuntimeUnhealthy.
Diagnostic (sur le nœud) :
sudo systemctl status containerd
Peut montrer Active: failed ou inactive (dead).
Vérifiez les journaux :
journalctl -u containerd -n 50 --no-pager
Causes courantes : état corrompu, disque plein, erreur de configuration.
Récupération :
- Assurez-vous de l'espace disque :
df -h /etdf -h /var/lib/containerd(pour containerd). - Corrigez la configuration si elle a récemment changé (restaurez la sauvegarde).
- Redémarrez le service :
sudo systemctl restart containerd. - Surveillez l'état avec
sudo systemctl status containerdetjournalctl -u containerd -f. - Après le redémarrage, vérifiez que le nœud redevient Ready :
kubectl get nodes.
Si le runtime plante de manière répétée, envisagez de réinitialiser l'état du runtime (mais cela supprime tous les conteneurs sur le nœud) :
Pour containerd :
sudo systemctl stop containerd
sudo rm -rf /var/lib/containerd/*
sudo systemctl start containerd
AVERTISSEMENT : Ceci est destructif. Ne le faites que si vous pouvez replanifier les charges de travail et que vous avez des sauvegardes.
Mode de défaillance 2 : Défaillance du plugin CNI (réseau non prêt)
Symptôme : Les pods restent bloqués dans ContainerCreating, les événements montrent failed to setup network ou network plugin is not ready.
Diagnostic :
- Vérifiez l'état du plugin CNI :
kubectl get pods -n kube-systempour vous assurer que les pods CNI (par exemple, Calico, Cilium, Flannel) fonctionnent. - Sur le nœud, vérifiez la configuration CNI :
ls /etc/cni/net.d/etcat /etc/cni/net.d/*.conf. - Les journaux du runtime peuvent montrer des erreurs du plugin CNI.
Récupération :
- Si les pods CNI plantent, redémarrez-les :
kubectl rollout restart daemonset <cni-daemonset> -n kube-system. - Assurez-vous que le binaire et la configuration CNI sont présents et corrects sur le nœud.
- S'ils manquent, réinstallez le plugin CNI ou copiez-les depuis un nœud fonctionnel.
Mode de défaillance 3 : Backoff de récupération d'image
Symptôme : Les pods affichent ImagePullBackOff ou ErrImagePull.
Diagnostic :
kubectl describe pod <pod-name> | tail -20
Recherchez l'erreur spécifique : échec d'authentification, délai d'attente, introuvable.
Récupération :
- Si l'authentification a échoué, vérifiez les secrets de récupération d'image :
kubectl get secret <secret-name> -o yamlet assurez-vous que les identifiants sont corrects. - Si délai d'attente, vérifiez l'accès réseau du nœud au registre :
curl -v https://registry-1.docker.io/v2/depuis le nœud. - Si introuvable, vérifiez le nom et l'étiquette de l'image.
- Pour les registres privés, assurez-vous que le runtime est configuré avec le miroir de registre et les identifiants. Pour containerd, vérifiez
config.tomlpour[plugins."io.containerd.grpc.v1.cri".registry.configs]. Pour CRI-O, vérifiez/etc/containers/registries.confetauth.json.
Mode de défaillance 4 : Pression du disque due aux artefacts du runtime
Symptôme : Le nœud affiche DiskPressure, des pods sont évincés, les images de conteneurs ou les journaux remplissent le disque.
Diagnostic :
sudo du -sh /var/lib/containerd /var/log/containers /var/log/pods
Récupération :
- Supprimez les images inutilisées :
sudo crictl rmi --prunepour CRI-O ousudo ctr images prunepour containerd (containerd peut nécessiter des drapeaux supplémentaires). - Nettoyez les conteneurs terminés :
sudo crictl rm $(sudo crictl ps -a -q --state exited). - Ajustez les paramètres de rotation des journaux dans la configuration du runtime ou du kubelet (par exemple,
containerLogMaxSizeetcontainerLogMaxFilesdans la configuration du kubelet). - Surveillez l'utilisation du disque à l'avenir.
Vérification de la récupération
Après toute récupération, vérifiez :
- Le nœud est
Ready:kubectl get nodes - Le service du runtime est actif :
sudo systemctl is-active containerd - Un pod de test peut démarrer : appliquez un manifeste de pod simple et vérifiez
kubectl get pod. crictl infomontreRuntimeReady: trueetNetworkReady: true.
Liste de contrôle des opérations
Utilisez la liste de contrôle suivante pour les opérations de routine et lors de modifications. Chaque élément inclut une commande ou une vérification concrète.
| # | Tâche | Commande / Vérification | Résultat attendu |
|---|---|---|---|
| 1 | Vérifier la version du runtime sur tous les nœuds | kubectl get nodes -o wide et regardez la colonne CONTAINER-RUNTIME | Version cohérente, par exemple containerd://1.7.11 sur tous les nœuds |
| 2 | Vérifier la santé du runtime sur un nœud | SSH sur le nœud, sudo crictl info | RuntimeReady: true, NetworkReady: true |
| 3 | Confirmer le point de terminaison CRI du kubelet | Sur le nœud, ps aux | grep kubelet et cherchez --container-runtime-endpoint | Chemin de socket correct, par exemple unix:///run/containerd/containerd.sock |
| 4 | Sauvegarder la configuration du runtime avant les modifications | sudo cp /etc/containerd/config.toml /etc/containerd/config.toml.bak.$(date +%s) | Le fichier de sauvegarde existe, aucune erreur |
| 5 | Tester le changement de configuration sur un nœud | Modifiez la configuration, redémarrez le runtime, puis exécutez un pod de test avec nodeName | Le pod démarre avec succès, le nœud reste Ready |
| 6 | Surveiller les journaux du runtime pendant le changement | journalctl -u containerd -f pendant l'application du changement | Pas d'erreurs fatales, entrées de journal attendues |
| 7 | Nettoyer périodiquement les images inutilisées | sudo crictl rmi --prune (CRI-O) ou sudo ctr images prune (containerd) | Images supprimées, espace disque libéré |
| 8 | Vérifier la pression du disque | df -h /var/lib/containerd /var/log/containers | Utilisation idéalement inférieure à 80 % |
| 9 | Vérifier les récupérations d'images depuis des registres privés | Exécutez un pod qui utilise une image privée, vérifiez les événements | Le pod s'exécute ou erreur d'authentification claire si mal configuré |
| 10 | Documenter le plan de retour arrière | Conservez la sauvegarde de configuration précédente et notez la commande de redémarrage | Retour arrière possible : restaurez la sauvegarde et redémarrez le runtime |
Exemple de procédure de retour arrière
Supposons que vous ayez changé le niveau de journalisation de containerd en debug et que vous souhaitiez revenir en arrière.
- Restaurez la sauvegarde :
sudo cp /etc/containerd/config.toml.bak.$(date +%s -d '1 hour ago') /etc/containerd/config.toml
(Utilisez le nom de fichier de sauvegarde réel.)
- Redémarrez containerd :
sudo systemctl restart containerd
- Vérifiez que le service est actif et que le nœud est Ready :
sudo systemctl status containerd
kubectl get node node-1
- Supprimez les pods de test éventuels.
Suggestions d'automatisation
- Planifiez une tâche cron hebdomadaire sur chaque nœud pour exécuter
crictl infoet alerter si le runtime n'est pas prêt. Par exemple :
# /etc/cron.d/runtime-check
0 3 * * * root /usr/local/bin/check-runtime.sh
Contenu du script :
#!/bin/bash
if ! sudo crictl info | grep -q '"RuntimeReady": true'; then
echo "Runtime not ready on $(hostname)" | mail -s "Runtime alert" [email protected]
fi
- Utilisez un DaemonSet qui vérifie la santé du runtime et la rapporte comme métrique Prometheus. De nombreuses piles de surveillance incluent node-exporter avec le collecteur textfile ; vous pouvez écrire un petit script pour exporter l'état de
crictl info.
Conclusion
Opérer les runtimes de conteneurs Kubernetes en production exige des procédures rigoureuses et reproductibles. La liste de contrôle et les exemples de cet article fournissent une base pour l'inventaire des versions, les modifications de configuration sûres, la vérification, la récupération après défaillance et les opérations de routine. Observez toujours avant de modifier, sauvegardez les configurations, limitez les modifications à un seul élément ciblé à la fois et vérifiez avec des commandes concrètes et des sorties attendues.
Comme prochaine étape, choisissez une vérification à faible risque de la liste de contrôle des opérations sur un nœud dans un environnement de préproduction. Enregistrez l'état actuel, exécutez le diagnostic, comparez avec les résultats attendus et examinez les dépendances telles que le kubelet, la mise en réseau des pods (CNI) et les registres d'images. Appliquez ensuite le même processus aux nœuds de production un par un, en surveillant la santé du cluster après chaque nœud.
Un flux de travail fiable rend les défaillances visibles, protège les valeurs sensibles, limite le rayon d'impact et définit la vérification de la récupération avant qu'un incident ne force une décision hâtive. En intégrant ces pratiques dans vos opérations, vous réduisez les temps d'arrêt et améliorez la stabilité de votre plateforme Kubernetes.