# Distribution-specific configuration Merge the blocks for the distribution and mode confirmed in SKILL.md Phase 1. Oracle OKE, VMware Tanzu (TKG), and self-managed clusters need no changes; Rancher (RKE2/K3s) only needs `criSocketPath` when the agent can't reach the embedded containerd (see SKILL.md Phase 1). ## Operator path (SKILL.md Phase 3) **GKE Autopilot** (Operator 1.27+) - override the image registry, add the Autopilot annotation to the `DatadogAgent` metadata, and set container resource requests. GKE Autopilot enforces a WorkloadAllowlist through its Warden admission webhook. Warden only admits Agent pods whose image digests appear in the GKE-synchronized allowlist, and that allowlist covers the `gcr.io/datadoghq` images - not `registry.datadoghq.com`. The Phase 3 baseline sets `registry: registry.datadoghq.com`; leaving that in place on Autopilot gets the DaemonSet rejected by Warden with an admission-webhook denial, not a pull failure. Override the registry back to `gcr.io/datadoghq` in `spec.global` (this is a deliberate exception to the baseline default; do not reach for a private mirror or a different image path to work around the rejection): ```yaml spec: global: registry: gcr.io/datadoghq ``` Autopilot's default container limits (50m CPU / 100Mi) are low enough to cause OOMKills, so set resource requests as well. Include only the containers for the products actually enabled: ```yaml metadata: annotations: experimental.agent.datadoghq.com/autopilot: "true" spec: override: nodeAgent: containers: agent: resources: requests: cpu: "200m" memory: "256Mi" trace-agent: resources: requests: cpu: "100m" memory: "200Mi" process-agent: resources: requests: cpu: "100m" memory: "200Mi" system-probe: resources: requests: cpu: "100m" memory: "400Mi" ``` Do not add `spec.global.provider: gke-autopilot`; it is not part of the generated Operator configuration. For Operators older than 1.27, use the Helm path in SKILL.md Phase 4 (with the GKE Autopilot values under *Helm chart path* below) instead. **OpenShift**: OpenShift users usually drive the cluster with `oc`, which is kubectl-compatible. Use the OperatorHub path below and merge the generated distribution settings: ```yaml spec: global: kubelet: tlsVerify: false features: apm: hostPortConfig: enabled: true unixDomainSocketConfig: enabled: false dogstatsd: unixDomainSocketConfig: enabled: false override: clusterAgent: serviceAccountName: datadog-agent-scc nodeAgent: serviceAccountName: datadog-agent-scc hostNetwork: true ``` Keep the security context and control-plane tolerations emitted by the current setup UI. The certified Operator manages the Agent SCCs; verify them with `oc get scc | grep -i datadog`. **EKS Fargate profiles**: Fargate nodes can't schedule the node-agent DaemonSet, so on Fargate the Agent runs as a sidecar injected into workload pods by the admission controller. On a Fargate-only cluster (no EC2 nodes), the Operator and Cluster Agent Pods in `datadog` also run on Fargate, so an active Fargate profile must select the `datadog` namespace (and any Pod labels the profile requires). Check before installing: ```bash REGION=''; CLUSTER='' for fp in $(aws eks list-fargate-profiles --region "$REGION" --cluster-name "$CLUSTER" --query 'fargateProfileNames[]' --output text); do aws eks describe-fargate-profile --region "$REGION" --cluster-name "$CLUSTER" --fargate-profile-name "$fp" \ --query 'fargateProfile.[fargateProfileName,status,selectors]' --output json done ``` If no `ACTIVE` profile selects `datadog`, stop and ask the user to add one through their usual workflow (Terraform, eksctl, or the console). Do not create a Fargate profile yourself without showing the exact change and getting confirmation. Add to `spec.features`: ```yaml admissionController: agentSidecarInjection: enabled: true provider: fargate ``` The injected sidecar authenticates to the Cluster Agent with a shared token, so `datadog-secret` must carry a `token` key alongside `api-key`, and the CR must reference it. The token must be at least 32 alphanumeric characters. An unset `DD_CLUSTER_AGENT_TOKEN` produces an unusable Secret, and an `export` from an earlier command does not survive into a fresh shell, so resolve the token in the same block that writes the Secret. Injected sidecars read `datadog-secret` from their own Pod's namespace, so the block writes the same Secret, with the same token, to `datadog` and to every selected Fargate workload namespace. The block below uses `DD_CLUSTER_AGENT_TOKEN` from the environment or `.env.local` / `.env` if set, otherwise reuses the token already in `datadog-secret`, otherwise generates one with `openssl rand -hex 16`. It generates a token only when `datadog-secret` or its `token` key is confirmed absent; any other read or decode error stops the block, so a transient API failure cannot overwrite a token that running pods already use. If `openssl` is unavailable and no token exists yet, ask the user to add a 32+ character alphanumeric `DD_CLUSTER_AGENT_TOKEN=` line to `.env.local` (not in chat) and re-run. Run this block in place of the API-key-only Secret block (SKILL.md Phase 3 or Phase 4): Set `WORKLOAD_NAMESPACES` to the space-separated Fargate workload namespaces confirmed in SKILL.md Phase 1. ```bash for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY DD_CLUSTER_AGENT_TOKEN; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done : "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}" WORKLOAD_NAMESPACES='' # <- e.g. 'shop payments' case "$WORKLOAD_NAMESPACES" in *'<'*|'') echo "Set WORKLOAD_NAMESPACES to the Fargate workload namespaces - stop"; exit 1;; esac if [ -z "${DD_CLUSTER_AGENT_TOKEN:-}" ]; then EXISTING_TOKEN=$(kubectl get secret datadog-secret -n datadog --ignore-not-found -o jsonpath='{.data.token}') || { echo "Could not read datadog-secret - fix cluster access and re-run"; exit 1; } if [ -n "$EXISTING_TOKEN" ]; then DD_CLUSTER_AGENT_TOKEN=$(printf '%s' "$EXISTING_TOKEN" | base64 --decode) || { echo "Could not decode the token in datadog-secret"; exit 1; } else DD_CLUSTER_AGENT_TOKEN=$(openssl rand -hex 16 2>/dev/null) fi fi case "${DD_CLUSTER_AGENT_TOKEN:-}" in ''|*[!A-Za-z0-9]*) echo "No usable cluster agent token - add DD_CLUSTER_AGENT_TOKEN to .env.local and re-run"; exit 1;; esac [ "${#DD_CLUSTER_AGENT_TOKEN}" -ge 32 ] || { echo "DD_CLUSTER_AGENT_TOKEN must be at least 32 characters"; exit 1; } for ns in datadog $WORKLOAD_NAMESPACES; do kubectl apply -f - < namespace: ``` **Fargate logs.** The baseline `logCollection` settings configure the node Agent, not the injected sidecars. When logs are enabled, require Agent 7.71.0 or later and turn on kubelet log collection for newly injected sidecars on the Cluster Agent. For logs from every container, add a sidecar profile; otherwise rely on per-container Autodiscovery annotations: ```yaml spec: features: admissionController: agentSidecarInjection: profiles: - env: - name: DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL value: "true" override: clusterAgent: env: - name: DD_ADMISSION_CONTROLLER_AGENT_SIDECAR_KUBELET_API_LOGGING_ENABLED value: "true" ``` Label Fargate workload pods with `agent.datadoghq.com/sidecar: fargate`, or configure a deliberate selector. Do not mutate every unlabelled workload by default. On a mixed cluster, keep the DaemonSet for EC2 nodes. On a Fargate-only cluster, disable the node-agent DaemonSet after confirming there are no schedulable EC2 nodes: ```yaml spec: override: nodeAgent: disabled: true ``` **AKS kubelet certificate handling**: inspect `kubernetes.azure.com/kubelet-serving-ca` on the selected cluster's nodes. Prefer the serving CA configuration when it is available. Only disable verification when the user confirms the workaround is required: ```yaml global: kubelet: tlsVerify: false ``` This weakens verification of the kubelet API. Do not apply it preemptively. ## OpenShift-specific install The Operator can be installed via the OperatorHub Bundle instead of Helm. The Datadog Operator is published in the **certified-operators** catalog (not `redhat-operators`, which is Red Hat's own operators), and the certified operator manages the Agent SCCs for you: ```yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: datadog-operator namespace: openshift-operators spec: channel: stable name: datadog-operator source: certified-operators sourceNamespace: openshift-marketplace ``` Show the Subscription and the confirmed context, and apply it with `kubectl apply -f` after confirmation. OLM installs the Operator and its CRD asynchronously, so wait for both before applying the `DatadogAgent`, and stop if they do not become ready: ```bash ok='' for i in $(seq 1 60); do csv=$(kubectl get subscription datadog-operator -n openshift-operators -o jsonpath='{.status.installedCSV}' 2>/dev/null) phase=$([ -n "$csv" ] && kubectl get csv "$csv" -n openshift-operators -o jsonpath='{.status.phase}' 2>/dev/null) [ "$phase" = Failed ] && { echo "Operator install FAILED (CSV $csv) - stop"; exit 1; } if [ "$phase" = Succeeded ] && kubectl wait --for=condition=established crd/datadogagents.datadoghq.com --timeout=10s >/dev/null 2>&1; then ok=1; break; fi sleep 10 done [ -n "$ok" ] || { echo "Operator or DatadogAgent CRD not ready after 10 minutes - stop"; exit 1; } echo "Operator $csv ready" ``` Create the API key secret **and** the `DatadogAgent` resource in the `openshift-operators` namespace - both must live where the operator was deployed so the CR can resolve `datadog-secret` and the operator picks up the CR. The Secret is created only by the Phase 3 heredoc, with its namespace changed; it never goes into `datadog-agent.yaml` or any other saved file (a saved copy holds the literal `${DD_API_KEY}`, and applying it overwrites the real key): ```bash for f in .env.local .env; do [ -f "$f" ] || continue; for k in DD_SITE DD_API_KEY DD_APP_KEY; do eval "[ -n \"\${$k:-}\" ]" && continue; v=$(grep -E "^$k=" "$f" | head -1 | cut -d= -f2- | tr -d '\r' | sed 's/^["'\'']//;s/["'\'']$//'); [ -n "$v" ] && export "$k=$v"; done; done : "${DD_API_KEY:?not set - run dd-account-setup (commercial sites) or supply it directly (government sites)}" kubectl apply -f - < ``` For AKS, enable the provider block. If the user explicitly confirms kubelet TLS verification must be disabled, add: ```yaml providers: aks: enabled: true datadog: kubelet: tlsVerify: false ```