Dépanner SSI APM sur Kubernetes
Déclencheurs
Invoquez cette skill quand l'utilisateur exprime l'intention de :
- Déboguer pourquoi un pod n'est pas instrumenté
- Enquêter pourquoi les traces n'apparaissent pas dans Datadog
- Diagnostiquer les défaillances du webhook d'admission ou de l'injection du conteneur init
- Faire un suivi sur les vérifications échouées de
verify-ssi - Signaler qu'un service ou pod spécifique n'a pas de traces
N'invoquez PAS cette skill si :
- SSI n'a pas encore été activé — exécutez
enable-ssien premier
Prérequis
- [ ] kubectl configuré pour cibler le cluster —
kubectl config current-context
pup-cli : vérifier, installer et s'authentifier
Claude exécute
pup --version
Si non trouvé, installer (détection du système d'exploitation) :
Claude exécute
if [[ "$(uname)" == "Darwin" ]]; then
brew tap datadog-labs/pack && brew install pup
else
PUP_VERSION=$(curl -s https://api.github.com/repos/datadog-labs/pup/releases/latest | grep '"tag_name"' | cut -d'"' -f4)
curl -L "https://github.com/datadog-labs/pup/releases/download/${PUP_VERSION}/pup_linux_amd64.tar.gz" | tar xz -C /usr/local/bin pup
chmod +x /usr/local/bin/pup
fi
pup --version
Vérifier l'authentification :
pup auth status
Si non authentifié :
Claude exécute
pup auth login
Cela ouvre un onglet de navigateur pour OAuth. Complétez la connexion — Claude continuera une fois la commande terminée.
Si aucun navigateur disponible : export DD_APP_KEY=<your-app-key>.
Contexte à résoudre avant d'agir
| Variable | Comment résoudre |
|---|---|
AGENT_NAMESPACE |
Namespace où l'Agent Datadog est installé |
APP_NAMESPACE |
Namespace de l'application avec traces manquantes |
CLUSTER_NAME |
kubectl config current-context ou spec.global.clusterName dans datadog-agent.yaml |
SERVICE_NAME |
Label tags.datadoghq.com/service sur le Deployment, ou demander à l'utilisateur |
ENV |
Label tags.datadoghq.com/env sur le Deployment, ou demander à l'utilisateur |
POD_NAME |
kubectl get pods -n <APP_NAMESPACE> — utiliser le pod spécifique mentionné par l'utilisateur |
DEPLOYMENT_NAME |
Vérifier metadata.name dans le manifeste Deployment, ou demander à l'utilisateur |
APP_LABEL |
Vérifier spec.selector.matchLabels.app dans le manifeste Deployment |
Comment SSI fonctionne — Connaissances métier
Lisez ceci avant d'enquêter. Cela vous donne le modèle mental pour raisonner sur les défaillances nouvelles, pas seulement les connues.
Chaîne d'injection :
- Le webhook d'admission (enregistré par le Cluster Agent) intercepte la création de pods
- Le webhook mute la spécification du pod — ajoute un conteneur init
datadog-lib-<language>-init - Le conteneur init télécharge la bibliothèque tracer sur un volume partagé
- La variable d'environnement
LD_PRELOADest définie pointant vers le fichier.sode la bibliothèque - Le processus applicatif charge la bibliothèque automatiquement au démarrage via
LD_PRELOAD
Ce que chaque couche diagnostique peut voir :
- pup — voit ce que le backend Datadog a reçu. Aveugle aux défaillances d'injection côté cluster. Si pup n'affiche aucun pod instrumenté, le problème est dans le cluster.
- kubectl — voit l'état du cluster. Aveugle au fait que les données ont atteint Datadog. Si kubectl affiche le conteneur init mais pup n'affiche aucune trace, le problème est post-injection.
À quoi ressemble un état sain :
pup fleet instrumented-pods listaffiche le pod avec le langage/version correctpup fleet tracers listaffiche le service comme actifkubectl get pod -o jsonpath='{.spec.initContainers[*].name}'inclutdatadog-lib-<language>-init
Défaillances silencieuses connues — SSI ne produit aucune erreur quand celles-ci se produisent :
- Instrumentation ddtrace ou OTel existante — SSI le détecte et se désactive silencieusement
- Version de runtime non supportée — ignorée silencieusement
- Annotation
admission.datadoghq.com/enabled: "false"— le webhook ignore entièrement le pod - Pod non redémarré après activation de SSI — l'injection se produit au démarrage ; les pods existants continuent de s'exécuter sans instrumentation
- Pod dans le namespace de l'Agent — SSI n'instrumente jamais son propre namespace
Raccourcis de raisonnement :
- Pas de conteneur init → webhook n'a pas déclenché → vérifier : ciblage de namespace, pod-selector, annotation opt-out, enregistrement du webhook, pod non redémarré
- Conteneur init présent + aucune trace → injection tentée mais échouée ou tracer ne rapporte pas → vérifier : ddtrace existant, version de runtime, connectivité de l'Agent, incompatibilité DD_SITE
Étape 1 : Triage
Exécutez les sept commandes simultanément et présentez-les à l'utilisateur comme les diagnostiques que vous exécutez. Tout ce qui suit est guidé par ce que vous trouvez ici. Résolvez <NODE_HOSTNAME> depuis kubectl get pod <POD_NAME> -n <APP_NAMESPACE> -o jsonpath='{.spec.nodeName}' une fois que vous avez un nom de pod ; si pas encore de contexte de pod, exécutez les commandes pup sans --hostname d'abord.
Claude exécute
pup traces search --query "service:<SERVICE_NAME>" --from 1h --limit 5
pup fleet instrumented-pods list <CLUSTER_NAME>
pup apm troubleshooting list --hostname <NODE_HOSTNAME> --timeframe 1h
pup apm service-library-config get --service-name <SERVICE_NAME> --env <ENV>
kubectl get pod <POD_NAME> -n <APP_NAMESPACE> \
-o jsonpath='{.spec.initContainers[*].name}'
kubectl describe pod <POD_NAME> -n <APP_NAMESPACE> | grep -A 10 "Events:"
kubectl get mutatingwebhookconfigurations | grep datadog
La dernière commande confirme que le webhook du contrôleur d'admission est enregistré au niveau du cluster — c'est la condition préalable pour que l'injection SSI fonctionne du tout et doit être vérifiée même quand la plupart des autres services sont instrumentés (toute déviation dans une configuration de webhook peut silencieusement ignorer un sous-ensemble de pods).
pup apm troubleshooting list met en surface les erreurs d'injection que le backend Datadog a reçues du cluster — celles-ci pointent vers des défaillances de mutation côté cluster qui peuvent ne pas être visibles depuis kubectl describe seul. pup apm service-library-config get affiche la configuration du SDK de runtime sous laquelle le tracer fonctionne ; un résultat vide avec ddTraceConfigs configuré, ou des valeurs inattendues, pointent vers des problèmes UST/propagation de configuration.
Présenter vos résultats (obligatoire)
Votre réponse finale est le livrable — pas votre transcription d'enquête. Elle doit inclure chaque diagnostic de cette skill que vous avez exécuté ou qui s'applique, avec son objectif et ce que vous avez trouvé. Trois modes de défaillance à éviter :
-
Exécuter une vérification mais ne pas la rapporter. Si vous avez exécuté
kubectl get mutatingwebhookconfigurations, la vérification du label du namespaceadmission.datadoghq.com/mutate-pods, ou toute autre commande pendant l'enquête, déclarez la commande et son résultat dans votre réponse. Une vérification que vous avez exécutée mais ne vous avez pas présentée ne donne rien au lecteur — et les vérifications du label du namespace et du webhook en particulier doivent apparaître explicitement. -
Omettre les deux diagnostiques pup obligatoires. Chaque diagnostic doit inclure explicitement ces deux commandes, par nom, pour chaque service affecté — ce sont des sorties de triage obligatoires, pas optionnelles :
pup apm troubleshooting list --hostname <NODE_HOSTNAME>— met en surface les erreurs d'injection que Datadog a reçues du nœudpup apm service-library-config get --service-name <SERVICE_NAME> --env <ENV>— affiche la configuration du SDK de runtime du tracer
Exécutez-les si
pupest disponible ; recommandez à l'utilisateur de les exécuter si ce n'est pas le cas. Ne substituez PASpup fleet instrumented-pods listoupup traces searchà ceux-ci — ce sont des vérifications différentes et ne satisfont pas le runbook. Si vous ne connaissez pas<ENV>, déclarez votre valeur supposée et exécutez quand même la commande. -
S'arrêter à la première cause racine. Quand plusieurs services sont affectés, enquêtez et rapportez chacun indépendamment — ils peuvent avoir des causes différentes — et donnez une remédiation par service.
Étape 2 : Énoncez vos hypothèses
Avant d'enquêter, énoncez explicitement vos hypothèses classées en fonction de la sortie de triage. Ne sautez pas cette étape.
Quand l'utilisateur signale plusieurs services affectés dans le même namespace, diagnostiquez chacun indépendamment. Deux pods peuvent échouer l'injection pour des raisons entièrement différentes (une annotation opt-out, une label de namespace manquante, une avec ddtrace préexistant). Ne supposez pas une cause partagée — enquêtez sur la spécification de pod, les annotations et le runtime de chaque service séparément et présentez les résultats par service.
| Signal de triage | Hypothèse forte |
|---|---|
| Traces arrivant + pod dans la liste instrumentée | Pas un vrai problème — probablement un filtre UI ou une fenêtre de temps. Dites-le à l'utilisateur et arrêtez |
| Aucune trace + pod PAS dans la liste instrumentée + pas de conteneur init | Injection ne s'est jamais produite — enquêtez : ciblage de namespace, webhook, pod-selector, annotation opt-out, pod non redémarré |
| Aucune trace + pod PAS dans la liste instrumentée + conteneur init présent | Injection tentée mais échouée — vérifier pup apm troubleshooting list pour les erreurs d'injection |
| Aucune trace + pod dans la liste instrumentée + conteneur init présent | Tracer injecté mais ne rapporte pas — enquêtez : connectivité, DD_SITE, clé API |
| Les événements du pod affichent CrashLoopBackOff ou des erreurs de conteneur init | Défaillance du conteneur init — vérifier ddtrace préexistant, version de runtime |
| Traces arrivant mais service/env incorrect | Labels UST manquants ou mal configurés sur le Deployment |
Énoncez explicitement vos 1-3 hypothèses principales : « Sur la base du triage, je pense que la cause la plus probable est X parce que Y. »
Étape 3 : Enquêter
Utilisez uniquement les outils pertinents pour vos hypothèses. Chaque observation informe votre prochaine action.
Outils d'enquête côté cluster
Le pod est-il dans le namespace de l'Agent ? SSI n'instrumente jamais les pods dans le même namespace que l'Agent Datadog.
kubectl get pods -n <AGENT_NAMESPACE>
Les pods ont-ils été redémarrés après activation de SSI ?
Confirmer auprès de l'utilisateur avant de redémarrer. Dites à l'utilisateur : « Les pods doivent être redémarrés pour que SSI les injecte. Je vais redémarrer
<DEPLOYMENT_NAME>dans<APP_NAMESPACE>. Prêt à continuer ? » Attendez la confirmation.
Claude exécute
kubectl rollout restart deployment/<DEPLOYMENT_NAME> -n <APP_NAMESPACE>
kubectl wait --for=condition=Ready pod -l app=<APP_LABEL> -n <APP_NAMESPACE> --timeout=120s
Claude exécute
pup fleet instrumented-pods list <CLUSTER_NAME>
Le namespace porte-t-il le label opt-in du contrôleur d'admission ?
Quand le contrôleur d'admission s'exécute avec mutateUnlabelled: false, l'injection se produit uniquement dans les namespaces explicitement étiquetés admission.datadoghq.com/mutate-pods=true. Un namespace manquant ce label a silencieusement SSI ignoré pour chaque pod dedans — une cause courante quand la plupart des services du cluster sont instrumentés mais pas ceux d'un namespace.
kubectl get namespace <APP_NAMESPACE> -o jsonpath='{.metadata.labels}'
kubectl get namespace <APP_NAMESPACE> --show-labels
Correction : labelliser le namespace, puis redémarrer les deployments affectés pour que l'AC les mute à la recréation des pods.
kubectl label namespace <APP_NAMESPACE> admission.datadoghq.com/mutate-pods=true
Le ciblage de namespace filtre-t-il le pod ?
kubectl get datadogagent datadog -n <AGENT_NAMESPACE> -o yaml | grep -A 15 instrumentation
Correction : mettre à jour enabledNamespaces dans datadog-agent.yaml.
Claude exécute
kubectl apply -f datadog-agent.yaml
Un podSelector cible-t-il filtrant le pod ?
Si targets avec podSelector est configuré, seuls les pods dont les labels correspondent au sélecteur sont instrumentés. Vérifiez si les labels du pod app correspondent à une cible :
kubectl get datadogagent datadog -n <AGENT_NAMESPACE> -o yaml | grep -A 20 targets
kubectl get pod <POD_NAME> -n <APP_NAMESPACE> --show-labels
Correction : ajouter un label correspondant au modèle de pod, ou élargir le podSelector, puis appliquer et redémarrer.
Une annotation de pod l'exclut-elle — ou lui manque-t-elle l'annotation de succès d'injection de l'AC ? Deux annotations à regarder :
admission.datadoghq.com/enabled: "false"— opt-out explicite, l'AC ignore le pod.admission.datadoghq.com/status: injected— défini par l'AC après mutation réussie ; son absence sur un pod en cours d'exécution est une preuve positive que l'AC ne l'a jamais muté.
kubectl get pod <POD_NAME> -n <APP_NAMESPACE> -o jsonpath='{.metadata.annotations}'
kubectl get pod <POD_NAME> -n <APP_NAMESPACE> -o yaml | grep -A 10 annotations
Correction : supprimer une annotation opt-out du modèle de pod du Deployment, puis appliquer et redémarrer.
*Les variables d'environnement `DD_attendues sont-elles présentes dans le pod en cours d'exécution ?** SSI injecteDD_SERVICE,DD_ENV,DD_VERSION,DDTRACE*etLD_PRELOADdans l'env du conteneur quand il mute un pod. Leur absence confirme que la mutation ne s'est pas exécutée ; leur présence avec des valeurs inattendues pointent vers des incompatibilités de labels UST ou des problèmes deddTraceConfigs`.
kubectl exec -n <APP_NAMESPACE> <POD_NAME> -- env | grep -E '^(DD_|LD_PRELOAD)'
kubectl describe pod <POD_NAME> -n <APP_NAMESPACE> | grep -E 'DD_|LD_PRELOAD'
Claude exécute
kubectl apply -f <your-app-deployment.yaml>
Confirmer auprès de l'utilisateur avant de redémarrer. Dites à l'utilisateur : « Je dois redémarrer
<DEPLOYMENT_NAME>dans<APP_NAMESPACE>pour que cette modification prenne effet. Prêt à continuer ? » Attendez la confirmation.
Claude exécute
kubectl rollout restart deployment/<DEPLOYMENT_NAME> -n <APP_NAMESPACE>
L'application a-t-elle une instrumentation personnalisée existante ? SSI se désactive silencieusement quand elle détecte du code tracer existant. Scannez les fichiers source pour :
- Python :
import ddtrace,ddtrace.patch_all() - Node.js :
require('dd-trace'),DD.init() - Java :
GlobalTracer.register(,dd-java-agent - .NET :
Tracer.Instance,DD.Trace - Ruby :
require 'ddtrace',Datadog.configure - PHP :
DDTrace\
Vérifiez aussi les manifestes de dépendance : requirements.txt, package.json, Gemfile, pom.xml.
Correction : supprimer l'import/paquet, reconstruire l'image, recharger dans le cluster, redémarrer le pod.
L'image de base est-elle Alpine (musl libc) ?
K8s SSI injecte LD_PRELOAD comme variable d'environnement dans le pod — il ne s'appuie pas sur /etc/ld.so.preload, donc les images musl/Alpine sont supportées. Ce n'est pas un bloqueur pour Kubernetes SSI.
La version de runtime est-elle supportée ?
kubectl exec -n <APP_NAMESPACE> <POD_NAME> -- python --version
kubectl exec -n <APP_NAMESPACE> <POD_NAME> -- node --version
kubectl exec -n <APP_NAMESPACE> <POD_NAME> -- java -version
Vérifier contre la matrice de compatibilité SSI.
Le webhook d'admission est-il enregistré ?
kubectl get mutatingwebhookconfigurations | grep datadog
kubectl get pods -n <AGENT_NAMESPACE> -l app=datadog-cluster-agent
kubectl logs -n <AGENT_NAMESPACE> -l app=datadog-cluster-agent --tail=100
L'injection a-t-elle produit des erreurs ? Obtenez d'abord le nom d'hôte du nœud, puis interrogez Datadog pour les erreurs d'injection :
kubectl get pod <POD_NAME> -n <APP_NAMESPACE> -o jsonpath='{.spec.nodeName}'
pup apm troubleshooting list --hostname <NODE_HOSTNAME> --timeframe 1h
L'Agent envoie-t-il des données à Datadog ?
kubectl exec -n <AGENT_NAMESPACE> \
$(kubectl get pod -n <AGENT_NAMESPACE> -l app=datadog-agent -o name | head -1) \
-- agent status | grep -A 5 "APM Agent"
Outils d'enquête côté Datadog
Le tracer rapporte-t-il ?
pup fleet tracers list --filter "service:<SERVICE_NAME>"
APM reconnaît-il le service ?
pup apm services list --env <ENV>
Quelle configuration SDK le service exécute-t-il ?
Affiche les variables d'environnement avec lesquelles le tracer est configuré (p. ex. DD_TRACE_ENABLED, DD_SERVICE, DD_ENV, règles d'échantillonnage). Une sortie vide est attendue si ddTraceConfigs n'a pas été défini dans enable-ssi ; une sortie peuplée ne correspondant pas à ce qui a été configuré indique que la modification n'a pas propagé.
pup apm service-library-config get --service-name <SERVICE_NAME> --env <ENV>
Les traces arrivent-elles ?
pup traces search --query "service:<SERVICE_NAME>" --from 1h --limit 10
Auquel l'Agent le tracer est-il connecté ? À utiliser si la connectivité entre le tracer et l'Agent est suspectée.
pup fleet agents list --filter "hostname:<NODE_HOSTNAME>"
pup fleet agents tracers <AGENT_KEY> --filter "service:<SERVICE_NAME>"
Étape 4 : Réfléchir avant de conclure
Avant d'appliquer une correction, répondez :
- Quelle preuve confirme mon hypothèse ?
- Quelle preuve la contredirait — et l'ai-je vérifiée ?
- Y a-t-il une explication plus simple que je n'ai pas considérée ?
Si la conclusion ne tient pas, retournez à l'étape 2 avec les nouvelles hypothèses. Continuez l'itération jusqu'à ce que vous puissiez défendre la conclusion contre les trois questions.
Étape 5 : Corriger
Appliquez la correction pour la cause racine confirmée. Si la correction nécessite une modification de code ou Dockerfile, reconstruisez et rechargez :
Claude exécute
docker build -f <DOCKERFILE_PATH> -t <IMAGE_NAME> <BUILD_CONTEXT>
[DÉCISION : type de cluster]
- kind (local) : charger l'image dans le cluster
Claude exécute
kind load docker-image <IMAGE_NAME> --name <CLUSTER_NAME>
- Basé sur registre : ignorer — l'image sera tirée au prochain déploiement
Confirmer auprès de l'utilisateur avant de redémarrer. Dites à l'utilisateur : « Je dois redémarrer
<DEPLOYMENT_NAME>dans<APP_NAMESPACE>pour appliquer la correction. Prêt à continuer ? » Attendez la confirmation.
Claude exécute
kubectl rollout restart deployment/<DEPLOYMENT_NAME> -n <APP_NAMESPACE>
kubectl wait --for=condition=Ready pod -l app=<APP_LABEL> -n <APP_NAMESPACE> --timeout=120s
Étape 6 : Vérifier
Réexécutez le triage pour confirmer que la correction a fonctionné :
Claude exécute
pup traces search --query "service:<SERVICE_NAME>" --from 1h --limit 5
pup fleet instrumented-pods list <CLUSTER_NAME>
Si les traces arrivent et le pod est dans la liste instrumentée — résolu. Procédez automatiquement à onboarding-summary maintenant — ne demandez pas la permission à l'utilisateur.
ERREUR : Toujours non résolu — retournez à l'étape 2 avec les nouvelles données de triage et formez les hypothèses mises à jour.
Contraintes de sécurité
- Ne jamais écrire une clé API brute dans un fichier ou un message de chat
- Ne jamais exécuter
kubectl deletesans confirmation de l'utilisateur - Ne jamais modifier les paramètres
admissionControllerdirectement docker pushvers un registre nécessite toujours la confirmation de l'utilisateur