troubleshoot-ssi

Par datadog-labs · agent-skills

Diagnostiquer et résoudre les problèmes d'instrumentation en une seule étape (SSI) sur Kubernetes — La SSI instrumente automatiquement les applications pour l'APM sans modification du code. À utiliser uniquement si l'agent et la SSI sont déjà configurés mais que les traces sont manquantes ou que l'instrumentation ne fonctionne pas.

npx skills add https://github.com/datadog-labs/agent-skills --skill troubleshoot-ssi

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-ssi en 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 :

  1. Le webhook d'admission (enregistré par le Cluster Agent) intercepte la création de pods
  2. Le webhook mute la spécification du pod — ajoute un conteneur init datadog-lib-<language>-init
  3. Le conteneur init télécharge la bibliothèque tracer sur un volume partagé
  4. La variable d'environnement LD_PRELOAD est définie pointant vers le fichier .so de la bibliothèque
  5. 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 list affiche le pod avec le langage/version correct
  • pup fleet tracers list affiche le service comme actif
  • kubectl get pod -o jsonpath='{.spec.initContainers[*].name}' inclut datadog-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 namespace admission.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œud
    • pup apm service-library-config get --service-name <SERVICE_NAME> --env <ENV> — affiche la configuration du SDK de runtime du tracer

    Exécutez-les si pup est disponible ; recommandez à l'utilisateur de les exécuter si ce n'est pas le cas. Ne substituez PAS pup fleet instrumented-pods list ou pup 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 :

  1. Quelle preuve confirme mon hypothèse ?
  2. Quelle preuve la contredirait — et l'ai-je vérifiée ?
  3. 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 delete sans confirmation de l'utilisateur
  • Ne jamais modifier les paramètres admissionController directement
  • docker push vers un registre nécessite toujours la confirmation de l'utilisateur

Skills similaires