Aller au contenu
Conteneurs & Orchestration medium

Stern : suivre les logs de plusieurs pods Kubernetes en temps réel

24 min de lecture

Stern

Stern permet de suivre les logs de plusieurs pods Kubernetes simultanément avec une seule commande. Chaque pod est coloré différemment pour faciliter le débogage. Contrairement à kubectl logs qui ne cible qu’un seul pod, Stern utilise des expressions régulières ou des ressources Kubernetes (deployment/nginx) pour aggréger automatiquement les logs de tous les pods correspondants.

  • Installer Stern sur Linux, macOS ou Windows
  • Cibler des pods avec des regex ou des ressources Kubernetes
  • Filtrer les logs par namespace, labels, containers, ou contenu
  • Formater la sortie avec des templates Go et des fonctions comme prettyJSON ou levelColor
  • Configurer Stern via un fichier de configuration

kubectl logs est limité à un seul pod à la fois. Dans un déploiement réel, vous avez souvent plusieurs réplicas du même service, et suivre leurs logs nécessite d’ouvrir plusieurs terminaux :

Fenêtre de terminal
# Sans Stern : un terminal par pod
kubectl logs -f nginx-deployment-7fb96c846b-abc12
kubectl logs -f nginx-deployment-7fb96c846b-def34
kubectl logs -f nginx-deployment-7fb96c846b-ghi56

Avec Stern, une seule commande suffit :

Fenêtre de terminal
# Avec Stern : tous les pods en une commande
stern nginx-deployment

Stern détecte automatiquement les nouveaux pods et les ajoute au flux. Si un pod est supprimé, il est retiré. C’est idéal pour suivre un déploiement en cours ou débugger un service avec plusieurs réplicas.

Avant de plonger dans les commandes, comprenez comment Stern identifie les pods à suivre. Ces concepts sont fondamentaux pour utiliser l’outil efficacement.

L’argument principal de stern est le pod-query. C’est la façon dont vous dites à Stern “quels pods m’intéressent”. Deux approches sont possibles :

  1. Une expression régulière : stern nginx matche tous les pods contenant “nginx
  2. Une ressource Kubernetes : stern deployment/nginx matche tous les pods du déploiement
FormatExempleCe qu’il matche
Regex simplestern nginxTous les pods contenant “nginx”
Regex complexestern "web-\w+"web-backend, web-frontend, mais pas web-123
Deploymentstern deployment/nginxTous les pods du deployment nginx
StatefulSetstern statefulset/redisTous les pods du StatefulSet redis
Servicestern service/apiTous les pods derrière le service api
DaemonSetstern daemonset/fluentdTous les pods du DaemonSet
Jobstern job/backupTous les pods du Job
Toutstern .Tous les pods (regex . matche tout)

La coloration automatique : différenciez visuellement vos pods

Section intitulée « La coloration automatique : différenciez visuellement vos pods »

Chaque pod reçoit une couleur différente. Si un pod contient plusieurs containers, vous pouvez activer --diff-container pour les différencier visuellement.

Fenêtre de terminal
# Colorer aussi les containers différemment
stern nginx --diff-container

Stern est disponible pour Linux, macOS et Windows via plusieurs gestionnaires de paquets.

Fenêtre de terminal
# Télécharger la dernière version
VERSION="1.33.1"
curl -LO "https://github.com/stern/stern/releases/download/v${VERSION}/stern_${VERSION}_linux_amd64.tar.gz"
tar xzf stern_${VERSION}_linux_amd64.tar.gz
chmod +x stern
sudo mv stern /usr/local/bin/
# Vérification
stern --version
# version: 1.33.1
# commit: 72148a9169efb0cefc43086c1ff05216e88ed829
# built at: 2025-11-04T11:17:30Z

Vérification :

Fenêtre de terminal
stern --version

Maintenant que vous comprenez comment Stern cible les pods, voyons les commandes que vous utiliserez au quotidien. Chaque exemple est tiré de scénarios réels de debugging.

C’est l’usage le plus courant : vous avez déployé une application avec plusieurs réplicas et vous voulez voir tous leurs logs ensemble.

Fenêtre de terminal
# Tous les pods dont le nom contient "nginx"
stern nginx
# Tous les pods d'un déploiement spécifique
stern deployment/nginx
# Résultat :
# + nginx-deployment-7fb96c846b-abc12 › nginx
# + nginx-deployment-7fb96c846b-def34 › nginx
# nginx-deployment-7fb96c846b-abc12 nginx 10.244.0.5 - - [12/Feb/2026:13:00:00 +0000] "GET / HTTP/1.1" 200 612
# nginx-deployment-7fb96c846b-def34 nginx 10.244.0.6 - - [12/Feb/2026:13:00:01 +0000] "GET /api HTTP/1.1" 200 42

Le préfixe + indique qu’un pod a été ajouté au suivi. Le préfixe - indique qu’il a été retiré.

Dans un cluster avec plusieurs environnements (dev, staging, production), vous voudrez cibler un namespace précis pour éviter le bruit des autres environnements.

Fenêtre de terminal
# Namespace spécifique
stern nginx -n production
# Plusieurs namespaces
stern nginx -n production -n staging
# ou
stern nginx -n production,staging
# Tous les namespaces
stern nginx -A
# ou
stern nginx --all-namespaces

Les labels sont le mécanisme natif Kubernetes pour organiser les ressources. Les utiliser avec Stern est souvent plus robuste que les regex, car ils correspondent exactement à votre organisation logique.

Fenêtre de terminal
# Pods avec un label spécifique
stern -l app=nginx
# Plusieurs labels (AND)
stern -l app=nginx -l environment=production
# Utiliser le label pour cibler sans regex
stern -l component -n kube-system --template '{{.Labels.component}}: {{.Message}}{{"\n"}}'
# Résultat :
# kube-scheduler: I0211 07:32:50.587032 1 tlsconfig.go:243] "Starting..."
# etcd: {"level":"info","ts":"2026-02-12T12:57:53Z",...}

Les architectures modernes utilisent souvent des sidecars (Istio, Envoy, agents de logging). Ces containers génèrent beaucoup de logs qui polluent votre debugging. Stern vous permet de les filtrer.

Fenêtre de terminal
# Suivre un container spécifique (regex)
stern nginx -c nginx
# Exclure un container (ex: sidecar istio)
stern nginx --exclude-container istio-proxy
stern nginx -E istio-proxy
# Inclure les init containers (par défaut : inclus)
stern nginx --init-containers=true
# Exclure les containers éphémères
stern nginx --ephemeral-containers=false

Par défaut, Stern affiche tout l’historique disponible, ce qui peut être écrasant. Ces options vous permettent de ne voir que ce qui vous intéresse.

Fenêtre de terminal
# Dernières N lignes par container (équivalent à tail -n)
stern nginx --tail 100
# Logs des dernières X minutes/heures
stern nginx --since 10m
stern nginx --since 2h
stern nginx -s 30s
# Ne pas suivre en continu (afficher et quitter)
stern nginx --no-follow
# Combiner pour un snapshot rapide
stern nginx --tail 50 --no-follow
Fenêtre de terminal
# Logs des pods sur un node spécifique
stern nginx --node worker-01
# Avec field-selector
stern nginx --field-selector spec.nodeName=worker-01

Les filtres précédents ciblent quels pods suivre. Maintenant, voyons comment filtrer le contenu des logs eux-mêmes. C’est particulièrement utile quand vos applications sont verbeuses.

Utilisez --include quand vous cherchez quelque chose de précis. Seules les lignes matchant votre pattern s’afficheront. C’est l’équivalent de grep.

Afficher uniquement les lignes qui matchent une regex :

Fenêtre de terminal
# Logs contenant ERROR ou WARN
stern nginx -i "ERROR|WARN"
# Logs contenant une IP spécifique
stern nginx -i "192\.168\.1\."
# Plusieurs patterns (OR)
stern nginx -i "error" -i "failed" -i "timeout"

L’inverse de --include : vous voulez tout voir sauf certaines lignes. Utile pour masquer les logs de santé (healthchecks) ou les niveaux DEBUG qui encombrent la sortie.

Fenêtre de terminal
# Exclure les logs DEBUG et TRACE
stern nginx -e "DEBUG|TRACE"
# Exclure les health checks
stern nginx -e "GET /healthz|GET /ready"
# Combiner include et exclude
stern nginx -i "error" -e "timeout"

Vous voulez le contexte complet mais repérer rapidement les éléments importants ? --highlight colore les patterns matchés sans filtrer les autres lignes. Idéal pour comprendre ce qui se passait autour d’une erreur.

Fenêtre de terminal
# Highlight les erreurs sans filtrer
stern nginx --highlight "error|Error|ERROR"
stern nginx -H "error|Error|ERROR"
# Highlight plusieurs patterns
stern nginx -H "error" -H "warn" -H "failed"

Jusqu’ici, on a laissé Stern formater les logs avec ses couleurs par défaut. Mais quand vous devez intégrer les logs dans des scripts, les analyser avec jq, ou simplement les rendre plus lisibles, vous aurez besoin de contrôler le format de sortie.

Stern propose plusieurs formats prédéfinis adaptés à différents cas d’usage :

FormatDescriptionCas d’usage
defaultNamespace, pod, container colorésDébogage visuel
rawMessage uniquementPiping vers jq, scripts
jsonJSON structuréIntégration programmatique
extjsonJSON étendu coloréAnalyse avec métadonnées
ppextjsonJSON étendu pretty-printLisibilité maximale
Fenêtre de terminal
# Format par défaut (coloré)
stern nginx
# Format brut (pour jq)
stern nginx -o raw | jq .
# Format JSON (pour scripts)
stern nginx -o json
# {"message":"...","nodeName":"minikube","namespace":"default","podName":"nginx-abc12",...}

Les formats prédéfinis ne couvrent pas tous les besoins. Les templates Go vous donnent un contrôle total sur la sortie. Si vous n’avez jamais utilisé les templates Go, pas de panique : la syntaxe de base est simple.

Un template Go utilise {{}} pour insérer des valeurs. Par exemple, {{.PodName}} insère le nom du pod. Le \n à la fin ajoute un retour à la ligne.

Variables disponibles :

VariableTypeDescription
.MessagestringLe message de log
.NodeNamestringLe nom du node
.NamespacestringLe namespace
.PodNamestringLe nom du pod
.ContainerNamestringLe nom du container
.Labelsmap[string]stringLes labels du pod
.Annotationsmap[string]stringLes annotations du pod
.PodColorcolor.ColorLa couleur assignée au pod
.ContainerColorcolor.ColorLa couleur assignée au container
Fenêtre de terminal
# Template simple
stern nginx --template '{{.PodName}}/{{.ContainerName}}: {{.Message}}{{"\n"}}'
# nginx-abc12/nginx: GET / HTTP/1.1 200
# Avec couleurs
stern nginx --template '{{.Message}} ({{.Namespace}}/{{color .PodColor .PodName}}){{"\n"}}'
# Avec labels (v1.33+)
stern -l component -n kube-system --template '{{.Labels.component}}: {{.Message}}{{"\n"}}'
# etcd: {"level":"info","msg":"storing new hash",...}
# kube-scheduler: I0211 07:32:50.587032 "Starting..."

Les variables seules ne suffisent pas quand vos logs sont en JSON. Stern fournit des fonctions pour parser, colorier et formater. Pensez-y comme des outils dans une boîte : prenez ceux dont vous avez besoin.

FonctionDescriptionExemple
parseJSONParse JSON (erreur si invalide){{.Message | parseJSON}}
tryParseJSONParse JSON (nil si invalide){{with $m := .Message | tryParseJSON}}
prettyJSONPretty-print JSON{{.Message | prettyJSON}}
levelColorColore selon le level (info, warn, error){{levelColor $m.level}}
bunyanLevelColorColore les levels Bunyan (10, 20, 30…){{bunyanLevelColor $m.level}}
toTimestampFormate un timestamp{{toTimestamp $m.ts "15:04:05" "Local"}}
toRFC3339NanoFormate en RFC3339{{toRFC3339Nano $m.ts}}
extractJSONPartsExtrait des clés JSON{{extractJSONParts .Message "level" "msg"}}
colorRed, colorGreenColorent le texte{{colorRed "ERROR"}}

Exemple : parser des logs JSON structurés

Voici comment transformer des logs JSON bruts en sortie lisible et colorée :

Fenêtre de terminal
# Logs JSON d'etcd
stern etcd -n kube-system --tail 1 --no-follow --template '{{.Message | prettyJSON}}{{"\n"}}'
# {
# "caller": "mvcc/hash.go:157",
# "level": "info",
# "msg": "storing new hash",
# "revision": 214439,
# "ts": "2026-02-12T13:02:53.245388Z"
# }
# Extraire et colorier les parties importantes
stern backend --template '{{with $m := .Message | tryParseJSON}}[{{levelColor $m.level}}] {{$m.msg}}{{end}}{{"\n"}}'
# [info] Application started
# [error] Connection failed
# [warn] High memory usage

Pour des templates complexes, utilisez un fichier :

Fenêtre de terminal
# Créer le template
cat > ~/.stern.tpl << 'EOF'
{{with $m := .Message | tryParseJSON -}}
[{{toTimestamp $m.ts "15:04:05" "Local"}}] {{levelColor $m.level}} {{$m.msg}}
{{- else -}}
{{.Message}}
{{- end}}
{{"\n"}}
EOF
# Utiliser le fichier
stern backend --template-file ~/.stern.tpl

Vous maîtrisez maintenant les bases. Voyons les fonctionnalités qui font gagner du temps au quotidien : configuration persistante, parsing de fichiers locaux, et options d’expert.

Fichier de configuration : vos préférences par défaut

Section intitulée « Fichier de configuration : vos préférences par défaut »

Depuis v1.25, vous pouvez configurer les valeurs par défaut dans ~/.config/stern/config.yaml :

~/.config/stern/config.yaml
# Valeurs par défaut
tail: 10
since: 1h
timestamps: short
max-log-requests: 100
# Couleurs personnalisées (SGR sequences)
# Vert, Jaune, Bleu, Magenta, Cyan, Blanc
pod-colors: "32,33,34,35,36,37"
# Couleurs avec souligné pour les containers
container-colors: "32;4,33;4,34;4,35;4,36;4,37;4"
# Différencier les containers par couleur
diff-container: true

Vous pouvez spécifier un autre fichier avec --config ou la variable STERNCONFIG.

Fenêtre de terminal
# Timestamp par défaut (RFC3339)
stern nginx -t
stern nginx --timestamps=default
# nginx-abc12 nginx 2026-02-12T13:00:00.123456789Z GET / HTTP/1.1 200
# Timestamp court (MM-DD HH:MM:SS)
stern nginx -t=short
# nginx-abc12 nginx 02-12 13:00:00 GET / HTTP/1.1 200
# Timezone spécifique
stern nginx -t=short --timezone Europe/Paris
stern nginx -t=short --timezone Asia/Tokyo

Stern n’est pas limité aux clusters Kubernetes ! Vous pouvez l’utiliser comme un parser de logs local grâce à --stdin. C’est parfait pour :

  • Tester vos templates avant de les utiliser sur le cluster
  • Analyser des logs exportés avec la même syntaxe
  • Débugger en local pendant le développement
Fenêtre de terminal
# Parser un fichier de logs JSON
stern --stdin < application.log
# Tester un template avant de l'utiliser sur le cluster
echo '{"level":"info","msg":"test","ts":"2026-02-12T10:00:00Z"}
{"level":"error","msg":"failure","ts":"2026-02-12T10:00:01Z"}' | \
stern --stdin --template '{{with $m := .Message | tryParseJSON}}[{{levelColor $m.level}}] {{$m.msg}}{{end}}{{"\n"}}'
# [info] test
# [error] failure

Parfois, vous voulez voir uniquement les logs des pods qui ont un problème. L’option --condition filtre par condition Kubernetes (Ready, ContainersReady, etc.). Particulièrement utile pour diagnostiquer pourquoi certains pods ne démarrent pas.

Fenêtre de terminal
# Logs des pods qui ne sont pas prêts
stern . -A --condition=ready=false --tail=0
# Affiche les pods en échec (Completed, Error, etc.)
# + ingress-nginx-admission-create-kmsbr › create
# + lab-cleanup-29515015-sphdj › cleanup

Stern supporte les mêmes options d’authentification que kubectl. Listez-les avec :

Fenêtre de terminal
stern --show-hidden-options
# --as, --as-group, --as-uid
# --certificate-authority, --client-certificate, --client-key
# --cluster, --context, --user
# --insecure-skip-tls-verify
# --token
# ...

Voici des recettes éprouvées pour les situations courantes. Copiez-collez et adaptez à votre contexte.

Situation : Vous venez de déployer une nouvelle version et voulez vérifier que tout démarre correctement.

Fenêtre de terminal
# Suivre le déploiement en temps réel
stern deployment/api -n production --since 1m

Situation : Des utilisateurs se plaignent de ne pas pouvoir se connecter. Vous voulez voir toutes les erreurs 401/403.

Fenêtre de terminal
# Logs auth avec timestamps et highlight des erreurs
stern auth -n production -t=short --since 15m -H "401|403|unauthorized"

Situation : Vous voulez reconstruire la chronologie d’un incident impliquant plusieurs services.

Fenêtre de terminal
# Snapshot des 5 dernières minutes, trié par timestamp
stern . -A --since 5m --no-follow --only-log-lines -t | sort -k4

Situation : Votre cluster utilise Istio et les logs des proxies envoy polluent votre vue.

Fenêtre de terminal
# Tous les logs sauf istio-proxy et envoy
stern . -n default -E istio-proxy -E envoy

Situation : Vos applications loggent en JSON structuré et vous voulez filtrer programmatiquement.

Fenêtre de terminal
# Extraire uniquement les erreurs avec context
stern backend -o raw | jq 'select(.level == "error")'

Si vous avez besoin de Stern dans un pod (debugging avancé) :

clusterrole-stern.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: stern
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "watch", "list"]
Fenêtre de terminal
# Exécuter via Docker
docker run --rm \
-v "$HOME/.kube:/root/.kube" \
ghcr.io/stern/stern nginx

SymptômeCause probableSolution
no matches foundAucun pod ne matche la queryVérifier le nom/regex avec kubectl get pods
error: You must be logged inPas de kubeconfig valideConfigurer KUBECONFIG ou ~/.kube/config
maximum number of concurrent logs (50) reachedTrop de pods matchésUtiliser --max-log-requests 100 ou filtrer plus
Pas de couleursTerminal non-TTY ou --color neverUtiliser --color always
--no-follow cannot be used with --tail=0Combinaison invalideUtiliser l’un ou l’autre, pas les deux
Logs tronquésLigne trop longueRediriger vers un fichier ou utiliser -o raw

Pour débugger les interactions avec l’API Kubernetes :

Fenêtre de terminal
stern nginx --verbosity 6
Fenêtre de terminal
# Vérifier le fichier de config
cat ~/.config/stern/config.yaml
# Utiliser un autre fichier
stern nginx --config /path/to/config.yaml

Stern supporte l’auto-complétion pour bash, zsh et fish :

Fenêtre de terminal
# Ajouter à ~/.bashrc
source <(stern --completion=bash)

Si installé via Krew :

Fenêtre de terminal
source <(kubectl stern --completion bash)
complete -o default -F __start_stern kubectl stern

  1. Une commande = tous les podsstern nginx suit tous les pods matchant “nginx”
  2. Regex ou ressourcestern "web-\w+" ou stern deployment/nginx
  3. Coloration automatique — chaque pod a sa couleur, --diff-container pour les containers
  4. Filtres puissants — par namespace (-n), labels (-l), containers (-c), contenu (-i, -e)
  5. Templates Go{{.Message | prettyJSON}}, {{levelColor $m.level}}
  6. Fichier de config~/.config/stern/config.yaml pour les valeurs par défaut
  7. —stdin — parser des logs locaux avec les mêmes templates

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.