mcpField
T
troubleshoot-ssi

troubleshoot-ssi

github.com/datadog-labs云与 DevOps180430 次安装6 天前更新
代码仓库

关于 troubleshoot-ssi

用于排查 Kubernetes 上 Datadog Single Step Instrumentation(SSI)的技能,适合诊断未注入或缺少 Trace 的情况。它结合集群状态检查与 Datadog 后端诊断,并依据观测信号引导调查。

主要功能

  1. 01检查 Pod 注入与 Webhook 状态
  2. 02查询 Trace 和追踪器遥测
  3. 03查看后端注入错误
  4. 04根据诊断信号分析原因

适用场景

  1. 01调查未被注入的 Pod
  2. 02诊断 Datadog Trace 缺失
  3. 03跟进 SSI 验证失败

安装

复制下面的命令,在终端中运行。

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

安装后在 Claude Code 中输入/troubleshoot-ssi确认已加载。

详细介绍

排查 Kubernetes 上的 APM SSI

触发条件

当用户表达以下意图时,调用此技能:

  • 调试 Pod 未被插桩的原因
  • 调查 Datadog 中未显示追踪的原因
  • 诊断准入 Webhook 或 init 容器注入失败
  • 跟进 verify-ssi 的失败检查
  • 报告某个特定服务或 Pod 没有追踪

如果以下情况成立,请勿调用此技能:

  • 尚未启用 SSI——请先运行 enable-ssi

前提条件

  • 已配置 kubectl,使其指向目标集群 — kubectl config current-context
pup-cli:检查、安装并进行身份验证
Claude 运行
pup --version

如果未找到,请根据操作系统安装:

Claude 运行
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

检查身份验证:

pup auth status

如果尚未通过身份验证:

Claude 运行
pup auth login

这会打开浏览器标签页以进行 OAuth。请在其中完成登录——命令退出后,Claude 会继续执行。

如果无法使用浏览器:export DD_APP_KEY=<your-app-key>。


操作前需要确定的上下文

变量确定方式
AGENT_NAMESPACE安装 Datadog Agent 的命名空间
APP_NAMESPACE缺少追踪的应用所在的命名空间
CLUSTER_NAMEkubectl config current-context 或 datadog-agent.yaml 中的 spec.global.clusterName
SERVICE_NAMEDeployment 上的 tags.datadoghq.com/service 标签,或询问用户
ENVDeployment 上的 tags.datadoghq.com/env 标签,或询问用户
POD_NAMEkubectl get pods -n <APP_NAMESPACE>——使用用户提到的特定 Pod
DEPLOYMENT_NAME检查 Deployment 清单中的 metadata.name,或询问用户
APP_LABEL检查 Deployment 清单中的 spec.selector.matchLabels.app

SSI 的工作原理 — 领域知识

调查前请先阅读。本节介绍用于分析新型故障的思维模型,而不只是已知故障。

注入链:

  1. 准入 webhook(由 Cluster Agent 注册)拦截 Pod 创建
  2. Webhook 修改 Pod 规格 — 添加一个 datadog-lib-<language>-init init 容器
  3. Init 容器将追踪器库下载到共享卷
  4. 设置 LD_PRELOAD 环境变量,使其指向库 .so 文件
  5. 应用进程在启动时通过 LD_PRELOAD 自动加载该库

各诊断层能看到什么:

  • pup — 可以看到 Datadog 后端收到的内容。无法看到集群侧注入故障。如果 pup 中没有该服务的追踪器遥测数据,说明追踪器要么从未注入(集群侧问题 — 通过 kubectl init 容器检查确认),要么已注入但尚无法上报(连接问题、DD_SITE、API 密钥或遥测延迟)。不要直接假定是集群问题;请交叉检查 kubectl。
  • kubectl — 可以看到集群状态。无法确认数据是否已到达 Datadog。如果 kubectl 显示存在 init 容器,但 pup 中没有追踪数据,问题发生在注入之后。

健康状态应呈现如下:

  • pup fleet tracers list 显示该服务处于活跃状态,且语言符合预期
  • kubectl get pod -o jsonpath='{.spec.initContainers[*].name}' 的结果包含 datadog-lib-<language>-init

已知的静默故障 — 发生以下情况时,SSI 不会报错:

  • 已有 ddtrace 或 OTel 插桩 — SSI 会检测到它并静默禁用自身
  • 不支持的运行时版本 — 静默跳过
  • admission.datadoghq.com/enabled: "false" 注解 — webhook 会完全跳过该 Pod
  • 启用 SSI 后未重启 Pod — 注入发生在启动时;现有 Pod 会继续运行,但未启用插桩
  • Pod 位于 Agent 命名空间 — SSI 从不会对其自身命名空间进行插桩

推理捷径:

  • 没有 init 容器 → webhook 未触发 → 检查:命名空间目标、pod-selector、退出注解、webhook 注册、Pod 未重启
  • 存在 init 容器但没有追踪数据 → 检查 pup fleet tracers list 中是否有该服务:不存在 → 追踪器未上报(Agent 连接、DD_SITE 不匹配、API 密钥、出口流量受阻;或追踪器从未加载 — 已有 ddtrace/OTel、不支持的运行时);存在 → 遥测数据已上报,但 span 未到达(没有流量、采样、摄取/保留过滤器)

步骤 1:分诊

同时运行以下七项,并向用户展示正在运行的诊断。此后的所有操作都由此处的检查结果决定。获得 Pod 名称后,通过 kubectl get pod <POD_NAME> -n <APP_NAMESPACE> -o jsonpath='{.spec.nodeName}' 解析 <NODE_HOSTNAME>;如果尚无 Pod 上下文,先运行不带 --hostname 的 pup 命令。

Claude 运行
pup traces search --query "service:<SERVICE_NAME>" --from 1h --limit 5
pup fleet tracers list --filter "service:<SERVICE_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

最后一条命令用于确认 Admission Controller webhook 已在整个集群范围内注册 — 这是 SSI 注入正常工作的前提条件,即使其他大多数服务都已启用插桩,也必须检查这一项(任何一个 webhook 配置出现偏差,都可能导致一部分 Pod 被静默跳过)。

pup apm troubleshooting list 会显示 Datadog 后端从集群收到的注入错误。这些错误指向集群侧的修改故障,单靠 kubectl describe 可能无法发现。pup apm service-library-config get 会显示追踪器所使用的运行时 SDK 配置;意外的取值可能表明存在 UST/配置传播问题。此视图不会列出每个 SDK 的所有设置,因此若缺少某个值,请在断定配置未传播前,先使用 verify-ssi 步骤 3 中的命令检查 Pod 环境变量。


展示调查结果(必需)

最终回复就是交付内容,而不是调查记录。回复必须包含这项技能中你已运行或适用的每一项诊断,并说明每项诊断的用途和发现。请避免以下三种失误:

  • 运行检查却不报告。 如果你在调查期间运行了 kubectl get mutatingwebhookconfigurations、命名空间 admission.datadoghq.com/mutate-pods 标签检查或其他任何命令,都必须在回复中说明命令及其结果。运行了检查却不展示,读者就一无所知;尤其必须明确列出命名空间标签检查和 Webhook 检查。

  • 遗漏两项必需的 pup 诊断。 对每个受影响的服务,每次诊断都必须明确包含以下两条命令,逐条列出;这是必需的分诊输出,而非可选项:

    • pup apm troubleshooting list --hostname <NODE_HOSTNAME> — 显示 Datadog 从节点收到的注入错误
    • pup apm service-library-config get --service-name <SERVICE_NAME> --env <ENV> — 显示追踪器的运行时 SDK 配置

    如果 pup 可用,就运行这些命令;如果不可用,就建议用户运行。如果不知道 <ENV>,请说明你假定的值,并照常运行命令。不要用 pup traces search 代替;这是另一项检查,不能满足运行手册要求。

  • 找到第一个根因就停止。 如果有多个服务受影响,请分别调查和报告;它们的原因可能不同,并且应针对每项服务分别给出修复措施。

步骤 2:陈述你的假设

调查前,请根据分诊输出明确列出按可能性排序的假设。不要跳过此步骤。

当用户报告同一命名空间中有多个受影响的服务时,请分别诊断每个服务。 两个 Pod 的注入失败可能有完全不同的原因(一个有选择退出注解,一个缺少命名空间标签,一个已有 ddtrace)。不要假设它们有共同的根本原因——请分别检查每个服务的 Pod 规范、注解和运行时,并逐个呈现调查结果。

分诊信号强假设
收到跟踪数据 + 服务在 tracers 列表中这两个信号都针对服务,因此在部分滚动发布期间,即使用户提到的特定 Pod 未经过插桩,它们也可能呈现为正向信号。首先确认此 Pod 已经过插桩(在分诊 kubectl 检查中存在 init 容器,或带有 admission.datadoghq.com/status: injected 注解)。如果已经过插桩,则问题可能是 UI 筛选条件或时间范围——告知用户后停止
没有跟踪数据 + 此 Pod 上没有 init 容器此 Pod 从未进行过注入——请调查:命名空间目标、webhook、Pod 选择器、选择退出注解、Pod 尚未重启(部分滚动发布)。逐 Pod 的 init 容器检查具有权威性:在部分滚动发布期间,服务仍可能因其他 Pod 而出现在 tracers list 中,因此针对服务的正向信号不能掩盖此 Pod 未经过插桩的事实
没有跟踪数据 + 服务不在 tracers 列表中 + 存在 init 容器Tracer 已注入但未上报——tracers list 基于遥测数据,因此无法上报或尚未上报的正确注入 Pod 不会出现在列表中。请调查:与 Agent 的连接、DD_SITE 不匹配、API 密钥、出口流量被阻止或遥测延迟。(真正的注入失败会表现为 init 容器缺失或 init 容器错误——见下方 CrashLoopBackOff 行,而不是这里。)
没有跟踪数据 + 服务在 tracers 列表中 + 存在 init 容器Tracer 正在上报遥测数据(因此与 Agent 的连接、API 密钥和 DD_SITE 均正常),但没有跟踪跨度到达——请调查跟踪特定原因:没有流量/应用尚未处理请求、采样规则、摄取/保留筛选器或 trace-agent 接收器
Pod 事件显示 CrashLoopBackOff 或 init 容器错误init 容器故障——检查已有的 ddtrace、运行时版本
收到跟踪数据但 service/env 错误Deployment 中缺少或配置错误的 UST 标签

明确陈述你认为最可能的 1–3 个假设:"根据分诊结果,我认为最可能的原因是 X,因为 Y。"


步骤 3:调查

仅使用与你的假设相关的工具。每项观察结果都将为下一步行动提供依据。


集群端调查工具

Pod 是否位于 Agent 命名空间中? SSI 不会对与 Datadog Agent 位于同一命名空间中的 Pod 进行插桩。

kubectl get pods -n <AGENT_NAMESPACE>

启用 SSI 后是否重启了 Pod?

重启前请先向用户确认。 告诉用户:“Pod 必须重启,SSI 才能向其中注入内容。我将重启 <DEPLOYMENT_NAME>(位于 <APP_NAMESPACE> 中)。现在可以继续吗?”等待确认。

Claude 运行
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 runs
# Primary — authoritative and immediate: confirm the freshly-restarted pods carry the init container.
# Label-scoped, not by <POD_NAME>: a rolling restart replaces the old pod with new-suffixed ones.
kubectl get pod -l app=<APP_LABEL> -n <APP_NAMESPACE> \
  -o jsonpath='{.items[0].spec.initContainers[*].name}'
# Secondary — eventual: the service reappears here once the restarted pod reports telemetry
# (subject to a propagation delay of a minute or more, and only if the pod serves traffic)
pup fleet tracers list --filter "service:<SERVICE_NAME>"

kubectl init 容器检查是重启后最权威的信号——该 init 容器一出现,Pod 就已注入。tracers list 源自遥测数据,存在延迟,因此不要把重启后立即出现的空结果理解为“未发生注入”。

命名空间是否带有 Admission Controller 的启用标签? 当 Admission Controller 以 mutateUnlabelled: false 运行时,只有明确带有 admission.datadoghq.com/mutate-pods=true 标签的命名空间才会发生注入。缺少此标签的命名空间会导致其中每个 Pod 都跳过 SSI,集群中的大多数服务都已完成检测,但某个命名空间中的服务没有检测,这是一个常见原因。

kubectl get namespace <APP_NAMESPACE> -o jsonpath='{.metadata.labels}'
kubectl get namespace <APP_NAMESPACE> --show-labels

修复:为命名空间添加标签,然后重启受影响的 Deployment,以便 AC 在 Pod 重新创建时对其进行变更。

kubectl label namespace <APP_NAMESPACE> admission.datadoghq.com/mutate-pods=true

命名空间目标是否将该 Pod 过滤掉了?

kubectl get datadogagent datadog -n <AGENT_NAMESPACE> -o yaml | grep -A 15 instrumentation

修复:更新 datadog-agent.yaml 中的 enabledNamespaces。

Claude runs
kubectl apply -f datadog-agent.yaml

podSelector 目标是否将该 Pod 过滤掉了? 如果配置了带有 podSelector 的 targets,则只有标签与选择器匹配的 Pod 才会进行检测。检查应用 Pod 的标签是否与任何目标匹配:

kubectl get datadogagent datadog -n <AGENT_NAMESPACE> -o yaml | grep -A 20 targets
kubectl get pod <POD_NAME> -n <APP_NAMESPACE> --show-labels

修复:在 Pod 模板中添加匹配的标签,或放宽 podSelector,然后应用更改并重启。

Pod 注解是否选择了退出,或者缺少 AC 的注入成功注解? 请检查以下两个注解:

  • admission.datadoghq.com/enabled: "false" — 明确选择退出,AC 会跳过该 Pod。
  • admission.datadoghq.com/status: injected — AC 成功变更 Pod 后会设置此注解;运行中的 Pod 缺少此注解,有力表明 AC 从未变更该 Pod。
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

修复:从 Deployment 的 Pod 模板中移除选择退出注解,然后应用更改并重启。

运行中的 Pod 是否包含预期的 DD_* 环境变量? SSI 变更 Pod 时,会将 DD_SERVICE、DD_ENV、DD_VERSION、DD_TRACE_* 和 LD_PRELOAD 注入容器环境变量。缺少这些变量可确认变更未执行;如果变量存在但值不符合预期,则可能是 UST 标签不匹配或 ddTraceConfigs 配置有问题。

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 runs
kubectl apply -f <your-app-deployment.yaml>

重启前请先征得用户同意。 告诉用户:“我需要重启 <DEPLOYMENT_NAME>(位于 <APP_NAMESPACE>),此更改才能生效。是否继续?”等待用户确认。

Claude runs
kubectl rollout restart deployment/<DEPLOYMENT_NAME> -n <APP_NAMESPACE>

应用是否已有自定义检测? SSI 检测到现有 tracer 代码时会静默禁用自身。请扫描源文件,查找以下内容:

  • 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\

同时检查依赖清单:requirements.txt、package.json、Gemfile、pom.xml。

修复:移除导入项或依赖包,重新构建镜像,将其加载到集群中,然后重启 Pod。

基础镜像是否为 Alpine(musl libc)? K8s SSI 会将 LD_PRELOAD 作为环境变量注入 Pod,不依赖 /etc/ld.so.preload,因此支持 musl/Alpine 镜像。这不会妨碍 Kubernetes SSI。

运行时版本是否受支持?

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

请参阅 SSI 兼容性矩阵 进行验证。

Admission Webhook 是否已注册?

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

注入是否产生错误? 先获取节点主机名,然后在 Datadog 中查询注入错误:

kubectl get pod <POD_NAME> -n <APP_NAMESPACE> -o jsonpath='{.spec.nodeName}'
pup apm troubleshooting list --hostname <NODE_HOSTNAME> --timeframe 1h

Agent 是否正在向 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"

Datadog 侧的调查工具

Tracer 是否正在上报?

pup fleet tracers list --filter "service:<SERVICE_NAME>"

APM 是否识别该服务?

pup apm services list --env <ENV>

该服务使用的 SDK 配置是什么? 显示 tracer 配置使用的环境变量(例如 DD_TRACE_ENABLED、DD_SERVICE、DD_ENV、采样规则)。如果未在 enable-ssi 中设置 ddTraceConfigs,则预期输出为空;如果输出有内容但与配置不符,则表示更改未生效。

pup apm service-library-config get --service-name <SERVICE_NAME> --env <ENV>

是否有 trace 到达?

pup traces search --query "service:<SERVICE_NAME>" --from 1h --limit 10

Tracer 连接的是哪个 Agent? 如果怀疑 tracer 与 Agent 之间的连接存在问题,请使用此项。

pup fleet agents list --filter "hostname:<NODE_HOSTNAME>"
pup fleet agents tracers <AGENT_KEY> --filter "service:<SERVICE_NAME>"

第 4 步:得出结论前先反思

应用任何修复之前,请回答:

  1. 有什么证据能证实我的假设?
  2. 有什么证据会与之矛盾——我是否已检查过?
  3. 是否存在我尚未考虑的更简单解释?

如果结论经不起推敲,请带着新的假设返回第 2 步。持续迭代,直到你能针对这三个问题为结论辩护。


第 5 步:修复

针对已确认的根本原因应用修复。如果修复需要更改代码或 Dockerfile,请重新构建并重新加载:

Claude 运行
docker build -f <DOCKERFILE_PATH> -t <IMAGE_NAME> <BUILD_CONTEXT>

[决策:集群类型]

  • kind(本地):将镜像加载到集群中
Claude 运行
kind load docker-image <IMAGE_NAME> --name <CLUSTER_NAME>
  • 基于 Registry:跳过——镜像将在下次部署时拉取

重启前请先与用户确认。 告知用户:“我需要重启 <DEPLOYMENT_NAME>(位于 <APP_NAMESPACE>)以应用修复。是否可以继续?”等待确认。

Claude 运行
kubectl rollout restart deployment/<DEPLOYMENT_NAME> -n <APP_NAMESPACE>
kubectl wait --for=condition=Ready pod -l app=<APP_LABEL> -n <APP_NAMESPACE> --timeout=120s

第 6 步:验证

重新运行排查流程,确认修复是否生效:

Claude 运行
pup traces search --query "service:<SERVICE_NAME>" --from 1h --limit 5
pup fleet tracers list --filter "service:<SERVICE_NAME>"

如果 trace 正在到达——问题已解决(服务可能需要一分钟才会重新出现在 pup fleet tracers list 中;重启后立即看到 tracer 列表为空属于预期的遥测延迟,并非故障)。现在自动继续执行 onboarding-summary——无需征求用户许可。

错误:没有 trace 到达——带着新的排查数据返回第 2 步,并提出更新后的假设。


安全约束

  • 切勿将原始 API 密钥写入任何文件或聊天消息
  • 未经用户确认,切勿运行 kubectl delete
  • 切勿直接修改 admissionController 设置
  • 向 Registry 执行 docker push 始终需要用户确认

评论

支持 Markdown