Enable APM on Kubernetes via Single Step Instrumentation Before doing anything else: Fully resolve all variables in . Do not begin Step 0 until every variable has a concrete value. --- Silent failure — check this before any other step: If the application has , , or any OpenTelemetry SDK in its dependency manifest ( , , , , ) — even with no import statements in code — SSI will silently disable itself at runtime. The failure is invisible: init containers run and complete, the pod starts healthy, no errors appear in or , but no traces arrive. The injector detects the user-installed tracer and ex…

` — instrument all non-system namespaces, or use the namespace(s) the user mentioned |\n| `TARGET_LANGUAGES` | Run `kubectl get pods -A -o jsonpath='{.items[*].spec.containers[*].image}'` and infer language from image names, or check Dockerfiles/manifests in the workspace. If uncertain, enable all languages. |\n| `DEPLOYMENT_NAME` | Run `kubectl get deployments -A --no-headers` — identify application deployments (exclude system components) |\n| `APP_LABEL` | Check `spec.selector.matchLabels` in the Deployment manifest via `kubectl get deployment \u003cDEPLOYMENT_NAME> -n \u003cAPP_NAMESPACE> -o yaml` |\n| `CLUSTER_NAME` | Check `spec.global.clusterName` in `datadog-agent.yaml`, or `kubectl config current-context` — needed for kind clusters in Step 0 |\n| `ENV` | Use `apm-evals` if running in an eval cluster (kind cluster names contain \"evalya\"). Otherwise use `production` unless the user specifies otherwise. |\n| `SERVICE_NAME` | Use the deployment name (e.g. `python-app` → service `python-app`). Do not ask the user. |\n| `VERSION` | Use `1.0.0` as the default. Do not ask the user. |\n\n---\n\n## Step 0 (Only if existing instrumentation detected): Remove Manual Instrumentation\n\nScan all source files for: `import ddtrace`, `from ddtrace`, `require 'ddtrace'`, `require(\"dd-trace\")`, `opentelemetry`, `tracer.trace(`\n\nAlso check dependency manifests for `ddtrace` / `dd-trace` / OTel SDK packages.\n\nIf found — remove the import/package, then rebuild and reload:\n\n### Claude runs\n\n```bash\ndocker build -f \u003cDOCKERFILE_PATH> -t \u003cIMAGE_NAME> \u003cBUILD_CONTEXT>\n```\n\n[DECISION: how does this cluster get local images?]\n\nCheck the repo's setup script (e.g. `create.sh`, `Makefile`, `justfile`) for how images are loaded — do not guess from the cluster name or context. Common patterns:\n\n| What you find in the setup script | Load command |\n|---|---|\n| `minikube image load` or `minikube cache add` | `minikube -p \u003cPROFILE> image load \u003cIMAGE_NAME>` — profile is the `-p` flag value in the script, NOT necessarily the kubectl context name |\n| `kind load docker-image` | `kind load docker-image \u003cIMAGE_NAME> --name \u003cCLUSTER_NAME>` |\n| `docker push` to a registry | Push the new image; the cluster will pull on restart — skip local load |\n| `k3d image import` | `k3d image import \u003cIMAGE_NAME> -c \u003cCLUSTER_NAME>` |\n| No image load step (cloud cluster, always pulls from registry) | Skip — image will be pulled on next deployment |\n\nIf the setup script is ambiguous, run the load command it uses exactly as written.\n\n- Registry-based: skip — image will be pulled on next deployment\n\n> **Confirm with the user before restarting.** Tell the user: \"I need to restart `\u003cDEPLOYMENT_NAME>` in `\u003cAPP_NAMESPACE>` to pick up the rebuilt image. Ready to proceed?\" Wait for confirmation.\n\n### Claude runs\n\n```bash\nkubectl rollout restart deployment/\u003cDEPLOYMENT_NAME> -n \u003cAPP_NAMESPACE>\nkubectl wait --for=condition=Ready pod \\\n -l app=\u003cAPP_LABEL> \\\n -n \u003cAPP_NAMESPACE> \\\n --timeout=120s\n```\n\n---\n\n## Step 1: Extend the DatadogAgent Manifest with APM\n\nSSI is configured on the existing `DatadogAgent` resource — do not create a separate manifest.\n\n**Choose targeting scope based on what the user asked for:**\n- User asked to instrument **all applications** or didn't specify scope → **use Option A (cluster-wide)**\n- User asked for specific namespaces only → use Option B\n- User asked to exclude namespaces from cluster-wide → use Option C\n- User asked for specific pods/workloads → use Option D\n\n> **Default is cluster-wide (Option A).** If the user said \"all my applications\", \"my whole cluster\", or didn't restrict scope, use Option A with no `enabledNamespaces` or `targets`.\n\nRecommended `ddTraceVersions`: `java: \"1\"`, `python: \"2\"`, `js: \"5\"`, `dotnet: \"3\"`, `ruby: \"2\"`, `php: \"1\"`\n\n**Option A — Cluster-wide (default):**\n```yaml\nfeatures:\n apm:\n instrumentation:\n enabled: true\n```\n\n**Option B — Specific namespaces only:**\n```yaml\nfeatures:\n apm:\n instrumentation:\n enabled: true\n enabledNamespaces:\n - \u003cAPP_NAMESPACE>\n```\n\n**Option C — Cluster-wide with exclusions:**\n```yaml\nfeatures:\n apm:\n instrumentation:\n enabled: true\n disabledNamespaces:\n - jenkins\n - kube-system\n```\n\n**Option D — Target specific workloads:**\n```yaml\nfeatures:\n apm:\n instrumentation:\n enabled: true\n targets:\n - name: \u003cTARGET_NAME>\n namespaceSelector:\n matchNames:\n - \u003cAPP_NAMESPACE>\n ddTraceVersions:\n \u003cLANGUAGE>: \"\u003cMAJOR_VERSION>\"\n```\n\n> **Note:** `ddTraceVersions` only applies inside a `targets[]` entry (Option D). It is not valid alongside `enabledNamespaces` or at the `instrumentation` level directly.\n\n### Claude runs\n\n```bash\nkubectl apply -f datadog-agent.yaml\n```\n\nIf `datadogagent.datadoghq.com/datadog configured` — continue to Step 2.\n\nERROR: Validation error — check YAML. `enabledNamespaces` and `disabledNamespaces` cannot both be set.\n\n---\n\n## Step 2: Inform the User About Unified Service Tags\n\n> **Do NOT modify application Deployments without explicit user confirmation.** Applying labels to existing application workloads is a change to customer-managed resources.\n\nInform the user that adding Unified Service Tags (UST) to their Deployments will enable proper service/env/version tagging in Datadog. This is optional for SSI to work but recommended for full observability:\n\n```yaml\n# Add to both metadata.labels and spec.template.metadata.labels\ntags.datadoghq.com/env: \"\u003cENV>\"\ntags.datadoghq.com/service: \"\u003cSERVICE_NAME>\"\ntags.datadoghq.com/version: \"\u003cVERSION>\"\n```\n\nIf the user wants you to apply these, get their confirmation first. UST labels are not required for APM traces to flow — SSI works without them.\n\n---\n\n## Step 3: Restart Application Pods\n\n> **Confirm with the user before restarting.** Tell the user: \"I need to restart `\u003cDEPLOYMENT_NAME>` in `\u003cAPP_NAMESPACE>` for SSI to inject into the pods. This will cause a brief outage. Ready to proceed?\" Wait for confirmation.\n\n### Claude runs\n\n```bash\nkubectl rollout restart deployment/\u003cDEPLOYMENT_NAME> -n \u003cAPP_NAMESPACE>\n\nkubectl wait --for=condition=Ready pod \\\n -l app=\u003cAPP_LABEL> \\\n -n \u003cAPP_NAMESPACE> \\\n --timeout=120s\n```\n\nIf pods restart cleanly, init containers named `datadog-lib-\u003clanguage>-init` will be visible in the pod spec.\n\nERROR: Pods crash-looping — check for existing custom instrumentation. See `troubleshoot-ssi`.\n\n---\n\n## Done\n\nExit when ALL of the following are true:\n- [ ] `features.apm.instrumentation` is present in the applied `DatadogAgent` manifest\n- [ ] User has been informed that they need to restart their application pods\n- [ ] User has been informed about Unified Service Tags (UST) and how to apply them if desired\n- [ ] Scope confirmed: which workloads are instrumented, which were skipped and why\n\nAutomatically proceed to `verify-ssi` now — do not ask the user for permission.\n\n---\n\n## Security constraints\n\n- Never write a raw API key into any file or chat message\n- Never use namespace `default` for Datadog resources\n- Never modify `admissionController` settings directly — SSI manages this via the Operator\n- Do not add APM config to application manifests — configure only via `DatadogAgent`\n- Exception: UST labels (`tags.datadoghq.com/*`) on application Deployments are required and intentional\n- Never run `kubectl delete` without user confirmation\n- `docker push` to a registry always requires user confirmation\n- **Never use `kubectl patch` to apply UST labels or any Deployment changes.** Always edit the Deployment YAML file and `kubectl apply -f`. Changes made with `kubectl patch` are transient and will be overwritten on the next rollout.\n---","attachment_filenames":[],"attachments":[],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Enable APM on Kubernetes via Single Step Instrumentation","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Before doing anything else:","type":"text","marks":[{"type":"strong"}]},{"text":" Fully resolve all variables in ","type":"text"},{"text":"## Context to resolve before acting","type":"text","marks":[{"type":"code_inline"}]},{"text":". Do not begin Step 0 until every variable has a concrete value.","type":"text"}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Silent failure — check this before any other step:","type":"text","marks":[{"type":"strong"}]}]},{"type":"paragraph","content":[{"text":"If the application has ","type":"text"},{"text":"ddtrace","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"dd-trace","type":"text","marks":[{"type":"code_inline"}]},{"text":", or any OpenTelemetry SDK in its ","type":"text"},{"text":"dependency manifest","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"requirements.txt","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"package.json","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"Gemfile","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"go.mod","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"pom.xml","type":"text","marks":[{"type":"code_inline"}]},{"text":") — even with no import statements in code — SSI will silently disable itself at runtime.","type":"text"}]},{"type":"paragraph","content":[{"text":"The failure is invisible: init containers run and complete, the pod starts healthy, no errors appear in ","type":"text"},{"text":"kubectl","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"pup","type":"text","marks":[{"type":"code_inline"}]},{"text":", but no traces arrive. The injector detects the user-installed tracer and exits cleanly without logging anything.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Claude runs","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"grep -rE \"ddtrace|dd-trace|opentelemetry\" \\\n requirements.txt package.json Gemfile go.mod pom.xml 2>/dev/null \\\n || echo \"No tracer dependency found\"","type":"text"}]},{"type":"paragraph","content":[{"text":"If any match — ","type":"text"},{"text":"stop","type":"text","marks":[{"type":"strong"}]},{"text":". Remove the package entirely (not just the import), rebuild the image, reload it into the cluster, and restart the pod before continuing. A package present in the manifest is enough to trigger this even if it is never imported.","type":"text"}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Triggers","type":"text"}]},{"type":"paragraph","content":[{"text":"Invoke this skill when the user expresses intent to:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Enable APM on a Kubernetes cluster","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Instrument Kubernetes applications with Datadog tracing","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Set up Single Step Instrumentation (SSI)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Do NOT invoke this skill if:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"The Datadog Agent is not yet installed — run ","type":"text"},{"text":"agent-install","type":"text","marks":[{"type":"code_inline"}]},{"text":" first","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"The user wants to verify SSI after setup — use ","type":"text"},{"text":"verify-ssi","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"The user wants to enable Profiler, AppSec, or Data Streams — use ","type":"text"},{"text":"dd-apm-k8s-sdk-features","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Prerequisites","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"These are not a reading exercise — actively verify each one before proceeding.","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"paragraph","content":[{"text":"Environment","type":"text","marks":[{"type":"strong"}]}]},{"type":"checkbox_list","attrs":{"id":null},"content":[{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Datadog Agent is installed and healthy — ","type":"text"},{"text":"agent-install","type":"text","marks":[{"type":"code_inline"}]},{"text":" complete","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Kubernetes v1.20+","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Linux node pools only — Windows pods require explicit namespace exclusion","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Cluster is not ECS Fargate — unsupported","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Not a hardened SELinux environment — unsupported","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Not a very small VM instance (e.g. t2.micro) — SSI can hit init timeouts","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"No PodSecurity baseline or restricted policy enforced","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Language and runtime","type":"text","marks":[{"type":"strong"}]}]},{"type":"checkbox_list","attrs":{"id":null},"content":[{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Application language is one of: Java, Python, Ruby, Node.js, .NET, PHP","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Runtime version is within SSI's supported range — verify against the ","type":"text"},{"text":"SSI compatibility matrix","type":"text","marks":[{"type":"link","attrs":{"href":"https://docs.datadoghq.com/tracing/trace_collection/automatic_instrumentation/single-step-apm/compatibility/","title":null}}]}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Node.js app is not using ESM — SSI does not support ESM","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Java app is not already using a ","type":"text"},{"text":"-javaagent","type":"text","marks":[{"type":"code_inline"}]},{"text":" JVM flag","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Existing instrumentation","type":"text","marks":[{"type":"strong"}]},{"text":" — confirmed clean by the check at the top of this skill. If you skipped that check, go back and run it now.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Context to resolve before acting","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Discover from the cluster — do not ask the user for information you can find yourself.","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Variable","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"How to resolve","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"AGENT_NAMESPACE","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Same namespace used in ","type":"text"},{"text":"agent-install","type":"text","marks":[{"type":"code_inline"}]},{"text":" (e.g. ","type":"text"},{"text":"datadog","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"APP_NAMESPACE","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"kubectl get namespaces --no-headers | awk '{print $1}' | grep -vE '^(kube-system|kube-public|kube-node-lease|datadog|local-path-storage)

Enable APM on Kubernetes via Single Step Instrumentation Before doing anything else: Fully resolve all variables in . Do not begin Step 0 until every variable has a concrete value. --- Silent failure — check this before any other step: If the application has , , or any OpenTelemetry SDK in its dependency manifest ( , , , , ) — even with no import statements in code — SSI will silently disable itself at runtime. The failure is invisible: init containers run and complete, the pod starts healthy, no errors appear in or , but no traces arrive. The injector detects the user-installed tracer and ex…

","type":"text","marks":[{"type":"code_inline"}]},{"text":" — instrument all non-system namespaces, or use the namespace(s) the user mentioned","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"TARGET_LANGUAGES","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"kubectl get pods -A -o jsonpath='{.items[*].spec.containers[*].image}'","type":"text","marks":[{"type":"code_inline"}]},{"text":" and infer language from image names, or check Dockerfiles/manifests in the workspace. If uncertain, enable all languages.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"DEPLOYMENT_NAME","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"kubectl get deployments -A --no-headers","type":"text","marks":[{"type":"code_inline"}]},{"text":" — identify application deployments (exclude system components)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"APP_LABEL","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Check ","type":"text"},{"text":"spec.selector.matchLabels","type":"text","marks":[{"type":"code_inline"}]},{"text":" in the Deployment manifest via ","type":"text"},{"text":"kubectl get deployment \u003cDEPLOYMENT_NAME> -n \u003cAPP_NAMESPACE> -o yaml","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"CLUSTER_NAME","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Check ","type":"text"},{"text":"spec.global.clusterName","type":"text","marks":[{"type":"code_inline"}]},{"text":" in ","type":"text"},{"text":"datadog-agent.yaml","type":"text","marks":[{"type":"code_inline"}]},{"text":", or ","type":"text"},{"text":"kubectl config current-context","type":"text","marks":[{"type":"code_inline"}]},{"text":" — needed for kind clusters in Step 0","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"ENV","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"apm-evals","type":"text","marks":[{"type":"code_inline"}]},{"text":" if running in an eval cluster (kind cluster names contain \"evalya\"). Otherwise use ","type":"text"},{"text":"production","type":"text","marks":[{"type":"code_inline"}]},{"text":" unless the user specifies otherwise.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"SERVICE_NAME","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use the deployment name (e.g. ","type":"text"},{"text":"python-app","type":"text","marks":[{"type":"code_inline"}]},{"text":" → service ","type":"text"},{"text":"python-app","type":"text","marks":[{"type":"code_inline"}]},{"text":"). Do not ask the user.","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"VERSION","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"1.0.0","type":"text","marks":[{"type":"code_inline"}]},{"text":" as the default. Do not ask the user.","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Step 0 (Only if existing instrumentation detected): Remove Manual Instrumentation","type":"text"}]},{"type":"paragraph","content":[{"text":"Scan all source files for: ","type":"text"},{"text":"import ddtrace","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"from ddtrace","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"require 'ddtrace'","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"require(\"dd-trace\")","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"opentelemetry","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"tracer.trace(","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Also check dependency manifests for ","type":"text"},{"text":"ddtrace","type":"text","marks":[{"type":"code_inline"}]},{"text":" / ","type":"text"},{"text":"dd-trace","type":"text","marks":[{"type":"code_inline"}]},{"text":" / OTel SDK packages.","type":"text"}]},{"type":"paragraph","content":[{"text":"If found — remove the import/package, then rebuild and reload:","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Claude runs","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"docker build -f \u003cDOCKERFILE_PATH> -t \u003cIMAGE_NAME> \u003cBUILD_CONTEXT>","type":"text"}]},{"type":"paragraph","content":[{"text":"[DECISION: how does this cluster get local images?]","type":"text"}]},{"type":"paragraph","content":[{"text":"Check the repo's setup script (e.g. ","type":"text"},{"text":"create.sh","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"Makefile","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"justfile","type":"text","marks":[{"type":"code_inline"}]},{"text":") for how images are loaded — do not guess from the cluster name or context. Common patterns:","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"What you find in the setup script","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Load command","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"minikube image load","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"minikube cache add","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"minikube -p \u003cPROFILE> image load \u003cIMAGE_NAME>","type":"text","marks":[{"type":"code_inline"}]},{"text":" — profile is the ","type":"text"},{"text":"-p","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag value in the script, NOT necessarily the kubectl context name","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"kind load docker-image","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"kind load docker-image \u003cIMAGE_NAME> --name \u003cCLUSTER_NAME>","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"docker push","type":"text","marks":[{"type":"code_inline"}]},{"text":" to a registry","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Push the new image; the cluster will pull on restart — skip local load","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"k3d image import","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"k3d image import \u003cIMAGE_NAME> -c \u003cCLUSTER_NAME>","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"No image load step (cloud cluster, always pulls from registry)","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skip — image will be pulled on next deployment","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"If the setup script is ambiguous, run the load command it uses exactly as written.","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Registry-based: skip — image will be pulled on next deployment","type":"text"}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Confirm with the user before restarting.","type":"text","marks":[{"type":"strong"}]},{"text":" Tell the user: \"I need to restart ","type":"text"},{"text":"\u003cDEPLOYMENT_NAME>","type":"text","marks":[{"type":"code_inline"}]},{"text":" in ","type":"text"},{"text":"\u003cAPP_NAMESPACE>","type":"text","marks":[{"type":"code_inline"}]},{"text":" to pick up the rebuilt image. Ready to proceed?\" Wait for confirmation.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Claude runs","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"kubectl rollout restart deployment/\u003cDEPLOYMENT_NAME> -n \u003cAPP_NAMESPACE>\nkubectl wait --for=condition=Ready pod \\\n -l app=\u003cAPP_LABEL> \\\n -n \u003cAPP_NAMESPACE> \\\n --timeout=120s","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Step 1: Extend the DatadogAgent Manifest with APM","type":"text"}]},{"type":"paragraph","content":[{"text":"SSI is configured on the existing ","type":"text"},{"text":"DatadogAgent","type":"text","marks":[{"type":"code_inline"}]},{"text":" resource — do not create a separate manifest.","type":"text"}]},{"type":"paragraph","content":[{"text":"Choose targeting scope based on what the user asked for:","type":"text","marks":[{"type":"strong"}]}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User asked to instrument ","type":"text"},{"text":"all applications","type":"text","marks":[{"type":"strong"}]},{"text":" or didn't specify scope → ","type":"text"},{"text":"use Option A (cluster-wide)","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User asked for specific namespaces only → use Option B","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User asked to exclude namespaces from cluster-wide → use Option C","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"User asked for specific pods/workloads → use Option D","type":"text"}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Default is cluster-wide (Option A).","type":"text","marks":[{"type":"strong"}]},{"text":" If the user said \"all my applications\", \"my whole cluster\", or didn't restrict scope, use Option A with no ","type":"text"},{"text":"enabledNamespaces","type":"text","marks":[{"type":"code_inline"}]},{"text":" or ","type":"text"},{"text":"targets","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]}]},{"type":"paragraph","content":[{"text":"Recommended ","type":"text"},{"text":"ddTraceVersions","type":"text","marks":[{"type":"code_inline"}]},{"text":": ","type":"text"},{"text":"java: \"1\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"python: \"2\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"js: \"5\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"dotnet: \"3\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"ruby: \"2\"","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"php: \"1\"","type":"text","marks":[{"type":"code_inline"}]}]},{"type":"paragraph","content":[{"text":"Option A — Cluster-wide (default):","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"features:\n apm:\n instrumentation:\n enabled: true","type":"text"}]},{"type":"paragraph","content":[{"text":"Option B — Specific namespaces only:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"features:\n apm:\n instrumentation:\n enabled: true\n enabledNamespaces:\n - \u003cAPP_NAMESPACE>","type":"text"}]},{"type":"paragraph","content":[{"text":"Option C — Cluster-wide with exclusions:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"features:\n apm:\n instrumentation:\n enabled: true\n disabledNamespaces:\n - jenkins\n - kube-system","type":"text"}]},{"type":"paragraph","content":[{"text":"Option D — Target specific workloads:","type":"text","marks":[{"type":"strong"}]}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"features:\n apm:\n instrumentation:\n enabled: true\n targets:\n - name: \u003cTARGET_NAME>\n namespaceSelector:\n matchNames:\n - \u003cAPP_NAMESPACE>\n ddTraceVersions:\n \u003cLANGUAGE>: \"\u003cMAJOR_VERSION>\"","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Note:","type":"text","marks":[{"type":"strong"}]},{"text":" ","type":"text"},{"text":"ddTraceVersions","type":"text","marks":[{"type":"code_inline"}]},{"text":" only applies inside a ","type":"text"},{"text":"targets[]","type":"text","marks":[{"type":"code_inline"}]},{"text":" entry (Option D). It is not valid alongside ","type":"text"},{"text":"enabledNamespaces","type":"text","marks":[{"type":"code_inline"}]},{"text":" or at the ","type":"text"},{"text":"instrumentation","type":"text","marks":[{"type":"code_inline"}]},{"text":" level directly.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Claude runs","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"kubectl apply -f datadog-agent.yaml","type":"text"}]},{"type":"paragraph","content":[{"text":"If ","type":"text"},{"text":"datadogagent.datadoghq.com/datadog configured","type":"text","marks":[{"type":"code_inline"}]},{"text":" — continue to Step 2.","type":"text"}]},{"type":"paragraph","content":[{"text":"ERROR: Validation error — check YAML. ","type":"text"},{"text":"enabledNamespaces","type":"text","marks":[{"type":"code_inline"}]},{"text":" and ","type":"text"},{"text":"disabledNamespaces","type":"text","marks":[{"type":"code_inline"}]},{"text":" cannot both be set.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Step 2: Inform the User About Unified Service Tags","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Do NOT modify application Deployments without explicit user confirmation.","type":"text","marks":[{"type":"strong"}]},{"text":" Applying labels to existing application workloads is a change to customer-managed resources.","type":"text"}]}]},{"type":"paragraph","content":[{"text":"Inform the user that adding Unified Service Tags (UST) to their Deployments will enable proper service/env/version tagging in Datadog. This is optional for SSI to work but recommended for full observability:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"yaml"},"content":[{"text":"# Add to both metadata.labels and spec.template.metadata.labels\ntags.datadoghq.com/env: \"\u003cENV>\"\ntags.datadoghq.com/service: \"\u003cSERVICE_NAME>\"\ntags.datadoghq.com/version: \"\u003cVERSION>\"","type":"text"}]},{"type":"paragraph","content":[{"text":"If the user wants you to apply these, get their confirmation first. UST labels are not required for APM traces to flow — SSI works without them.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Step 3: Restart Application Pods","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Confirm with the user before restarting.","type":"text","marks":[{"type":"strong"}]},{"text":" Tell the user: \"I need to restart ","type":"text"},{"text":"\u003cDEPLOYMENT_NAME>","type":"text","marks":[{"type":"code_inline"}]},{"text":" in ","type":"text"},{"text":"\u003cAPP_NAMESPACE>","type":"text","marks":[{"type":"code_inline"}]},{"text":" for SSI to inject into the pods. This will cause a brief outage. Ready to proceed?\" Wait for confirmation.","type":"text"}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Claude runs","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"kubectl rollout restart deployment/\u003cDEPLOYMENT_NAME> -n \u003cAPP_NAMESPACE>\n\nkubectl wait --for=condition=Ready pod \\\n -l app=\u003cAPP_LABEL> \\\n -n \u003cAPP_NAMESPACE> \\\n --timeout=120s","type":"text"}]},{"type":"paragraph","content":[{"text":"If pods restart cleanly, init containers named ","type":"text"},{"text":"datadog-lib-\u003clanguage>-init","type":"text","marks":[{"type":"code_inline"}]},{"text":" will be visible in the pod spec.","type":"text"}]},{"type":"paragraph","content":[{"text":"ERROR: Pods crash-looping — check for existing custom instrumentation. See ","type":"text"},{"text":"troubleshoot-ssi","type":"text","marks":[{"type":"code_inline"}]},{"text":".","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Done","type":"text"}]},{"type":"paragraph","content":[{"text":"Exit when ALL of the following are true:","type":"text"}]},{"type":"checkbox_list","attrs":{"id":null},"content":[{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"features.apm.instrumentation","type":"text","marks":[{"type":"code_inline"}]},{"text":" is present in the applied ","type":"text"},{"text":"DatadogAgent","type":"text","marks":[{"type":"code_inline"}]},{"text":" manifest","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"User has been informed that they need to restart their application pods","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"User has been informed about Unified Service Tags (UST) and how to apply them if desired","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Scope confirmed: which workloads are instrumented, which were skipped and why","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Automatically proceed to ","type":"text"},{"text":"verify-ssi","type":"text","marks":[{"type":"code_inline"}]},{"text":" now — do not ask the user for permission.","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Security constraints","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never write a raw API key into any file or chat message","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never use namespace ","type":"text"},{"text":"default","type":"text","marks":[{"type":"code_inline"}]},{"text":" for Datadog resources","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never modify ","type":"text"},{"text":"admissionController","type":"text","marks":[{"type":"code_inline"}]},{"text":" settings directly — SSI manages this via the Operator","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Do not add APM config to application manifests — configure only via ","type":"text"},{"text":"DatadogAgent","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Exception: UST labels (","type":"text"},{"text":"tags.datadoghq.com/*","type":"text","marks":[{"type":"code_inline"}]},{"text":") on application Deployments are required and intentional","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never run ","type":"text"},{"text":"kubectl delete","type":"text","marks":[{"type":"code_inline"}]},{"text":" without user confirmation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"docker push","type":"text","marks":[{"type":"code_inline"}]},{"text":" to a registry always requires user confirmation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Never use ","type":"text","marks":[{"type":"strong"}]},{"text":"kubectl patch","type":"text","marks":[{"type":"code_inline"},{"type":"strong"}]},{"text":" to apply UST labels or any Deployment changes.","type":"text","marks":[{"type":"strong"}]},{"text":" Always edit the Deployment YAML file and ","type":"text"},{"text":"kubectl apply -f","type":"text","marks":[{"type":"code_inline"}]},{"text":". Changes made with ","type":"text"},{"text":"kubectl patch","type":"text","marks":[{"type":"code_inline"}]},{"text":" are transient and will be overwritten on the next rollout.","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"enable-ssi","author":"@skillopedia","source":{"stars":125,"repo_name":"agent-skills","origin_url":"https://github.com/datadog-labs/agent-skills/blob/HEAD/dd-apm/k8s-ssi/enable-ssi/SKILL.md","repo_owner":"datadog-labs","body_sha256":"c96aa879b392f67b7f2c1da53995ccbf65b04df6787f74ab4a542d438347b0cd","cluster_key":"97ef95c5a641b9ec207397f5f17c95b7865d6f1ae84b1aab4f0b204b2e96db44","clean_bundle":{"format":"clean-skill-bundle-v1","source":"datadog-labs/agent-skills/dd-apm/k8s-ssi/enable-ssi/SKILL.md","bundle_sha256":"7d9cd0a2bccb233c10379bafb89a59d057fdaf15bee9cb187c3c2ebb61a3de42","attachment_count":0,"text_attachments":0,"binary_attachments":0},"cluster_size":1,"skill_md_path":"dd-apm/k8s-ssi/enable-ssi/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"devops-infrastructure","category_label":"DevOps"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"devops-infrastructure","metadata":{"tags":"datadog,apm,kubernetes,ssi,instrumentation,single-step","author":"datadog-labs","version":"1.0.0","repository":"https://github.com/datadog-labs/agent-skills","alwaysApply":"false"},"import_tag":"clean-skills-v1","description":"Enable Single Step Instrumentation (SSI) on Kubernetes — automatically instruments applications for APM without code changes. Only use if the Datadog Agent is already running on the cluster — if not, use agent-install first."}},"renderedAt":1782980330648}

Enable APM on Kubernetes via Single Step Instrumentation Before doing anything else: Fully resolve all variables in . Do not begin Step 0 until every variable has a concrete value. --- Silent failure — check this before any other step: If the application has , , or any OpenTelemetry SDK in its dependency manifest ( , , , , ) — even with no import statements in code — SSI will silently disable itself at runtime. The failure is invisible: init containers run and complete, the pod starts healthy, no errors appear in or , but no traces arrive. The injector detects the user-installed tracer and ex…