Aller au contenu
Conteneurs & Orchestration medium

CRICTL : Gérer les conteneurs avec les runtimes CRI

27 min de lecture

crictl est l’outil CLI officiel pour interagir avec les runtimes de conteneurs compatibles CRI (Container Runtime Interface) comme containerd ou CRI-O. Si vous administrez un cluster Kubernetes et devez déboguer des conteneurs au niveau du runtime (lister les pods, inspecter les logs, exécuter des commandes), crictl est l’outil qu’il vous faut. Version actuelle : v1.35.0 (décembre 2025).

  • Installer et configurer crictl pour containerd ou CRI-O
  • Lister et inspecter les conteneurs et pods
  • Déboguer les problèmes Kubernetes au niveau du runtime
  • Utiliser les fonctionnalités avancées (exec parallèle, filtrage par namespace, TLS)

En 2016, Kubernetes a introduit la CRI (Container Runtime Interface) pour découpler le runtime de conteneurs du reste de la plateforme. Avant cela, Docker était le seul runtime supporté.

L’objectif : permettre à plusieurs runtimes (containerd, CRI-O, etc.) de fonctionner avec Kubernetes via une API gRPC standardisée.

Un runtime CRI est un composant qui :

  1. Reçoit des ordres de Kubernetes via l’API gRPC CRI
  2. Crée et gère les conteneurs et leurs sandboxes (pods)
  3. Rapporte l’état des conteneurs au kubelet
RuntimeMaintenu parUsage principal
containerdCNCFDéfaut sur la plupart des distributions K8s
CRI-ORed HatOptimisé pour OpenShift
cri-dockerdMirantisPont vers Docker Engine

crictl est distribué dans le projet cri-tools qui suit les versions mineures de Kubernetes. Utilisez la même version mineure que votre cluster (ex: crictl 1.35 pour Kubernetes 1.35).

Fenêtre de terminal
# Définir la version
VERSION="v1.35.0"
ARCH="amd64" # ou arm64
# Télécharger et installer
curl -sL "https://github.com/kubernetes-sigs/cri-tools/releases/download/${VERSION}/crictl-${VERSION}-linux-${ARCH}.tar.gz" \
| sudo tar -xzf - -C /usr/local/bin
# Vérifier l'installation
crictl --version
# crictl version v1.35.0

crictl doit connaître le socket de votre runtime CRI. La configuration se fait dans /etc/crictl.yaml.

  1. Identifiez votre runtime

    Fenêtre de terminal
    # containerd
    ls -la /run/containerd/containerd.sock
    # CRI-O
    ls -la /run/crio/crio.sock
  2. Créez le fichier de configuration

    Fenêtre de terminal
    sudo tee /etc/crictl.yaml << EOF
    runtime-endpoint: unix:///run/containerd/containerd.sock
    image-endpoint: unix:///run/containerd/containerd.sock
    timeout: 10
    debug: false
    EOF
  3. Testez la connexion

    Fenêtre de terminal
    crictl info

    Si la commande retourne les informations du runtime, la configuration est correcte.

Si vous utilisez containerd en dehors de Kubernetes, le plugin CRI peut être désactivé par défaut.

  1. Générez la configuration par défaut

    Fenêtre de terminal
    sudo containerd config default | sudo tee /etc/containerd/config.toml
  2. Vérifiez que CRI est activé

    Ouvrez /etc/containerd/config.toml et assurez-vous que cette ligne est commentée ou absente :

    # disabled_plugins = ["cri"]
  3. Redémarrez containerd

    Fenêtre de terminal
    sudo systemctl restart containerd
    crictl info

Par défaut, le socket containerd appartient à root:root, ce qui oblige à utiliser sudo. Pour permettre l’accès sans privilèges root, créez un groupe dédié et configurez le socket.

  1. Créez le groupe containerd et ajoutez votre utilisateur

    Fenêtre de terminal
    sudo groupadd containerd
    sudo usermod -aG containerd $USER
  2. Changez le groupe du socket

    Fenêtre de terminal
    sudo chgrp containerd /run/containerd/containerd.sock
  3. Rendez le changement permanent

    Créez un override systemd pour appliquer le changement à chaque démarrage :

    Fenêtre de terminal
    sudo mkdir -p /etc/systemd/system/containerd.service.d
    sudo tee /etc/systemd/system/containerd.service.d/socket-group.conf << 'EOF'
    [Service]
    ExecStartPost=/bin/chgrp containerd /run/containerd/containerd.sock
    EOF
    sudo systemctl daemon-reload
  4. Appliquez les changements de groupe

    Déconnectez-vous et reconnectez-vous, ou utilisez :

    Fenêtre de terminal
    newgrp containerd
  5. Vérifiez l’accès sans sudo

    Fenêtre de terminal
    crictl info -o json | jq '{runtime: .config.containerd.defaultRuntimeName}'
    Sortie
    {
    "runtime": "runc"
    }

crictl permet de gérer les images de conteneurs stockées par le runtime.

Fenêtre de terminal
crictl images
Sortie
IMAGE TAG IMAGE ID SIZE
docker.io/library/busybox 1.36 114f4abb67995 2.22MB
docker.io/library/nginx 1.27 1e5f3c5b981a9 72.4MB
registry.k8s.io/pause 3.10.1 cd073f4c5f6a8 320kB
Fenêtre de terminal
# Télécharger une image
crictl pull nginx:1.27
# Inspecter les métadonnées d'une image
crictl inspecti docker.io/library/busybox:1.36 | jq '{
digest: .status.id[0:50],
size: .status.size,
tags: .status.repoTags
}'
Sortie
{
"digest": "sha256:114f4abb67995cfe8e368760f3bc8a1d00e12ac98",
"size": "2217150",
"tags": ["docker.io/library/busybox:1.36"]
}
Fenêtre de terminal
crictl rmi alpine:3.19
# Deleted: docker.io/library/alpine:3.19
Fenêtre de terminal
# Conteneurs en cours d'exécution
crictl ps
Sortie
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
209fb8b19830c docker.io/library/busybox:1.36 2 minutes ago Running test-container 0 027378143d3ff
Fenêtre de terminal
# Tous les conteneurs (y compris arrêtés)
crictl ps -a
# Filtrer par état
crictl ps --state running
# Filtrer par nom
crictl ps --name test
# Filtrer par namespace Kubernetes (v1.32+)
crictl ps --namespace kube-system
# Filtrer par pod
crictl ps --pod <POD_ID>
# Sortie JSON
crictl ps -o json
Fenêtre de terminal
crictl inspect 209fb8b19830c | jq '{
id: .status.id[0:12],
state: .status.state,
pid: .info.pid,
image: .status.image.image
}'
Sortie
{
"id": "209fb8b19830",
"state": "CONTAINER_RUNNING",
"pid": 136906,
"image": "docker.io/library/busybox:1.36"
}
Fenêtre de terminal
# Démarrer un conteneur
crictl start <CONTAINER_ID>
# Arrêter un conteneur
crictl stop <CONTAINER_ID>
# Supprimer un conteneur
crictl rm <CONTAINER_ID>
Fenêtre de terminal
# Voir les logs
crictl logs <CONTAINER_ID>
Sortie
Hello from crictl test container
Hello from crictl test container
Hello from crictl test container
Fenêtre de terminal
# Dernières N lignes
crictl logs --tail 2 <CONTAINER_ID>
# Suivre en temps réel
crictl logs -f <CONTAINER_ID>
# Filtrer par flux (v1.33+)
crictl logs --stream stdout <CONTAINER_ID>
crictl logs --stream stderr <CONTAINER_ID>
# Logs avec timestamps
crictl logs -t <CONTAINER_ID>
Fenêtre de terminal
# Commande simple
crictl exec <CONTAINER_ID> uname -a
Sortie
Linux master1 6.8.0-90-generic #91-Ubuntu SMP ... x86_64 GNU/Linux
Fenêtre de terminal
# Shell interactif
crictl exec -it <CONTAINER_ID> /bin/sh
# Exécution parallèle sur plusieurs conteneurs (v1.32+)
crictl exec --image nginx -x -- cat /etc/nginx/nginx.conf
# Avec support TLS (v1.32+)
crictl exec --tls-ca /path/to/ca.crt \
--tls-cert /path/to/client.crt \
--tls-key /path/to/client.key \
-it <CONTAINER_ID> /bin/sh
Fenêtre de terminal
# Stats d'un conteneur spécifique
crictl stats <CONTAINER_ID>
Sortie
CONTAINER NAME CPU % MEM DISK INODES SWAP
209fb8b19830c test-container 0.01 327.7kB 16.38kB 7 0B
Fenêtre de terminal
# Stats de tous les conteneurs
crictl stats

Dans Kubernetes, un pod est un groupe de conteneurs partageant réseau et stockage. crictl permet de gérer les pods directement au niveau du runtime.

Fenêtre de terminal
# Lister tous les pods
crictl pods
Sortie
POD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIME
027378143d3ff 5 minutes ago Ready test-pod default 0
Fenêtre de terminal
# Filtrer par namespace
crictl pods --namespace kube-system
# Inspecter un pod
crictl inspectp <POD_ID> | jq '{
id: .status.id[0:12],
state: .status.state,
ip: .status.network.ip
}'
Sortie
{
"id": "027378143d3f",
"state": "SANDBOX_READY",
"ip": "10.88.0.2"
}
Fenêtre de terminal
# Stats des pods (v1.28+)
crictl statsp

Pour créer un pod manuellement (utile pour les tests), vous avez besoin d’un fichier de configuration JSON :

pod-config.json
{
"metadata": {
"name": "test-pod",
"namespace": "default",
"uid": "test-pod-uid-001"
},
"log_directory": "/tmp/crictl-logs",
"linux": {}
}
Fenêtre de terminal
# Créer le pod
crictl runp pod-config.json
# 027378143d3ff23e276aeffbd06002ac40a7c03c280ceb9ce94f971d4c7f90c5
# Lister pour vérifier
crictl pods

Une fois le pod créé, vous pouvez y ajouter un conteneur :

container-config.json
{
"metadata": {
"name": "test-container"
},
"image": {
"image": "docker.io/library/busybox:1.36"
},
"command": ["sh", "-c", "while true; do echo 'Hello'; sleep 5; done"],
"log_path": "test-container.log",
"linux": {}
}
Fenêtre de terminal
# Créer le conteneur (sans le démarrer)
POD_ID=$(crictl pods -q)
crictl create $POD_ID container-config.json pod-config.json
# 209fb8b19830c2e569d778285035b55db673fd88816d066a9b0cd1b83db076e3
# Démarrer le conteneur
crictl start 209fb8b19830c
Fenêtre de terminal
# Arrêter le pod (arrête les conteneurs)
crictl stopp <POD_ID>
# Stopped sandbox 027378143d3ff
# Supprimer le pod
crictl rmp <POD_ID>
# Removed sandbox 027378143d3ff

Les versions récentes de crictl ont introduit des fonctionnalités puissantes pour le débogage et la gestion à grande échelle. Voici les plus utiles, avec leurs dates de sortie et cas d’usage concrets.

Fenêtre de terminal
# Informations de version
crictl version
Sortie
Version: v1.35.0
RuntimeName: containerd
RuntimeVersion: v2.2.1
RuntimeApiVersion: v1
Fenêtre de terminal
# Configuration du runtime
crictl runtime-config
# cgroup driver: CGROUPFS
# Informations détaillées
crictl info -o json | jq '{
runtimeSpec: .config.containerd.defaultRuntimeName,
cgroupDriver: .config.containerd.runtimes.runc.options.SystemdCgroup
}'
Fenêtre de terminal
crictl imagefsinfo
Sortie
{
"status": {
"imageFilesystems": [{
"fsId": {
"mountpoint": "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs"
},
"inodesUsed": { "value": "5908" },
"usedBytes": { "value": "212267008" }
}]
}
}

La commande events affiche les événements du runtime en temps réel. Utile pour surveiller ce qui se passe sur le nœud :

Fenêtre de terminal
crictl events
Sortie (exemple)
{
"containerId": "209fb8b19830c...",
"containerEventType": "CONTAINER_STARTED_EVENT",
"podSandboxStatus": {
"id": "027378143d3ff...",
"state": "SANDBOX_READY",
"network": { "ip": "10.88.0.2" }
}
}

L’exécution parallèle permet de lancer une commande dans plusieurs conteneurs simultanément, filtré par image, pod, nom ou état. C’est indispensable pour :

  • Audit rapide : vérifier une config sur tous les conteneurs d’un type
  • Diagnostic de masse : collecter des infos système (date, env, mémoire)
  • Nettoyage : exécuter un script de maintenance sur tous les conteneurs

Pour tester l’exécution parallèle, créez plusieurs conteneurs busybox :

Fenêtre de terminal
# Créer le fichier de configuration du pod (UID unique requis)
cat > /tmp/test-pod.json << EOF
{
"metadata": {
"name": "test-parallel",
"namespace": "default",
"uid": "test-parallel-$(date +%s)"
},
"log_directory": "/tmp/crictl-logs",
"linux": {}
}
EOF
# Créer le pod
crictl runp /tmp/test-pod.json
# Récupérer l'ID du pod
POD_ID=$(crictl pods -q)
echo "Pod créé: $POD_ID"
# Créer et démarrer 3 conteneurs avec des noms uniques
for i in 1 2 3; do
cat > /tmp/test-container-$i.json << EOF
{
"metadata": { "name": "worker-$i" },
"image": { "image": "docker.io/library/busybox:1.36" },
"command": ["sh", "-c", "while true; do sleep 3600; done"],
"log_path": "worker-$i.log",
"linux": {}
}
EOF
CID=$(crictl create $POD_ID /tmp/test-container-$i.json /tmp/test-pod.json)
crictl start $CID
done
# Vérifier
crictl ps
Sortie
CONTAINER IMAGE STATE NAME POD ID
720505c9523ac docker.io/library/busybox:1.36 Running worker-3 9418c9638da39
82e328bd61005 docker.io/library/busybox:1.36 Running worker-2 9418c9638da39
0f83e10e7e4b3 docker.io/library/busybox:1.36 Running worker-1 9418c9638da39
Fenêtre de terminal
# Voir le hostname de tous les conteneurs busybox (nom complet requis)
crictl exec --image "docker.io/library/busybox:1.36" --parallel -- hostname
Sortie
master1
master1
master1
Fenêtre de terminal
# Voir les variables d'environnement de tous les conteneurs actifs
crictl exec --state running -x -- env | grep "^PATH"
Sortie
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Fenêtre de terminal
# Lister les processus de tous les conteneurs d'un pod spécifique
crictl exec --pod $POD_ID -x -- ps aux
# Ignorer les erreurs et continuer sur tous les conteneurs
crictl exec --state running -x -e -- cat /etc/os-release
Fenêtre de terminal
# Arrêter et supprimer tous les conteneurs du pod
for CID in $(crictl ps -q); do
crictl stop $CID
crictl rm $CID
done
# Supprimer le pod
crictl stopp $POD_ID
crictl rmp $POD_ID
OptionDescriptionExemple
--imageFiltre par nom d’image (conteneurs actifs uniquement)--image busybox
--podFiltre par ID de pod--pod abc123def
--stateFiltre par état--state running
--nameFiltre par nom de conteneur--name worker
-x, --parallelActive l’exécution parallèle-x
-q, --quietMasque les IDs conteneurs dans la sortie-q
-e, --ignore-errorContinue même si une commande échoue-e

Les commandes exec, attach et portforward supportent maintenant le chiffrement TLS. C’est essentiel pour :

  • Conformité sécurité : exigences PCI-DSS, HIPAA, SOC2
  • Débogage distant : accès sécurisé aux conteneurs via réseau externe
  • Zero-trust : ne jamais faire confiance au réseau interne
Fenêtre de terminal
# Exécution avec authentification TLS mutuelle
crictl exec \
--tls-ca /etc/kubernetes/pki/ca.crt \
--tls-cert /etc/kubernetes/pki/admin.crt \
--tls-key /etc/kubernetes/pki/admin.key \
--tls-server-name containerd.local \
-it abc123 /bin/sh
OptionDescription
--tls-caCertificat CA pour valider le serveur
--tls-certCertificat client
--tls-keyClé privée du certificat client
--tls-server-nameNom du serveur pour la validation SNI

L’option --stream permet de récupérer uniquement stdout ou stderr, facilitant le tri des logs :

Fenêtre de terminal
# Voir uniquement les erreurs (stderr)
crictl logs --stream stderr abc123
# Voir uniquement les logs normaux (stdout)
crictl logs --stream stdout abc123
# Combiner avec tail pour les dernières erreurs
crictl logs --stream stderr --tail 50 abc123

Cas d’usage typique : un conteneur produit beaucoup de logs INFO sur stdout. Vous cherchez une erreur spécifique. Avec --stream stderr, vous isolez instantanément les messages d’erreur.

L’API CRI permet d’interroger les capacités du runtime installé. C’est utile pour :

  • Vérifier la compatibilité : le runtime supporte-t-il les user namespaces ?
  • Diagnostic : pourquoi une fonctionnalité ne marche pas ?
  • Automatisation : scripts qui s’adaptent aux capacités disponibles
Fenêtre de terminal
# Voir toutes les fonctionnalités du runtime
crictl info -o json | jq '.features'
Sortie
{
"supplementalGroupsPolicy": true,
"recursiveReadOnlyMounts": true,
"userNamespaces": true
}
FonctionnalitéDescription
supplementalGroupsPolicyGestion avancée des groupes Linux
recursiveReadOnlyMountsMontages récursifs en lecture seule
userNamespacesIsolation des user namespaces (rootless)

La commande metricdescs (introduite en v1.33, stabilisée en v1.34) liste les métriques disponibles via l’API ListMetricDescriptors :

Fenêtre de terminal
crictl metricdescs | head -20
Sortie
{
"descriptors": [
{
"name": "container_fs_reads_bytes_total",
"help": "Cumulative count of bytes read",
"labelKeys": ["id", "name", "device"]
},
{
"name": "container_fs_reads_total",
"help": "Cumulative count of reads completed",
"labelKeys": ["id", "name", "device"]
}
]
}

Cas d’usage : avant de configurer votre monitoring (Prometheus, Datadog), vérifiez quelles métriques le runtime expose nativement.

La commande crictl update --oom-score-adj permet de modifier la priorité OOM d’un conteneur en cours d’exécution, sans redémarrage :

Fenêtre de terminal
# Protéger un conteneur critique (base de données)
# Score -500 = moins susceptible d'être tué
crictl update --oom-score-adj -500 abc123
# Rendre un conteneur moins prioritaire (tâche batch)
# Score +500 = plus susceptible d'être tué en cas de pénurie mémoire
crictl update --oom-score-adj 500 def456
# Vérifier le score actuel
crictl inspect abc123 | jq '.status.resources.oomScoreAdj'

Cas d’usage : votre cluster a une pression mémoire temporaire. Vous voulez protéger la base de données mais accepter que les workers de tâches batch soient tués en premier. Avec --oom-score-adj, vous ajustez les priorités sans redéployer.

ValeurComportement
-1000Jamais tué par l’OOM killer (réservé au système)
-500Fortement protégé
0Comportement par défaut
+500Prioritaire pour être tué
+1000Tué en premier
Cas d’usagekubectlcrictl
Gestion normale des workloads
Débogage kubelet défaillant
Inspection bas niveau
Pods bloqués en Terminating
  1. Identifiez le problème avec kubectl

    Fenêtre de terminal
    kubectl get pods -A | grep -v Running
  2. Connectez-vous au nœud concerné

    Fenêtre de terminal
    ssh worker-node-1
  3. Listez les pods avec crictl

    Fenêtre de terminal
    crictl pods
  4. Inspectez le pod problématique

    Fenêtre de terminal
    crictl inspectp <POD_ID>
  5. Vérifiez les logs des conteneurs

    Fenêtre de terminal
    crictl logs <CONTAINER_ID>
ProblèmeCause probableSolution
FATA: Cannot connect to runtimeSocket introuvableVérifiez /etc/crictl.yaml
error: no running containersAucun conteneur actifUtilisez crictl ps -a
permission deniedDroits insuffisantsExécutez avec sudo
CRI plugin is disabledcontainerd mal configuréActivez CRI dans config.toml
  • crictl est l’outil de débogage bas niveau pour les runtimes CRI
  • Configurez le socket dans /etc/crictl.yaml
  • Utilisez la même version mineure que Kubernetes
  • crictl ps → conteneurs, crictl pods → pods
  • Fonctionnalités avancées : exécution parallèle (-x), filtrage namespace, TLS
  • Filtrage des logs par flux (stdout/stderr), ajustement OOM score