ข้ามไปยังเนื้อหา

Worked review 2: Agent บน Kubernetes cluster

Prompt คือ “Deploy Datadog Agent ลง EKS cluster ด้วย Helm — APM, log จากทุก container, Cluster Agent และ Redis integration สำหรับ Deployment cache ขอเวอร์ชัน Operator ด้วย เผื่อจะย้าย” ด้านล่างคือ draft แรก มันมีสาม artifact: Helm values.yaml, manifest DatadogAgent สำหรับ Operator และ Deployment ของ Redis พร้อม Autodiscovery annotation helm lint ผ่านกับอันแรก ส่วนอีกสองอันดูเป็น YAML ที่ reviewer ทั่วไปพยักหน้าให้ผ่าน

ใช้อะไรรีวิว และขีดจำกัดของแต่ละอย่าง:

  • helm template กับ chart จริง datadog/datadog 3.250.3 (Helm v4.3.0) — DaemonSet ที่ render ออกมาคือความจริงว่า values ทำอะไร ไม่ได้ติดตั้งอะไรที่ไหนเลย
  • CRD DatadogAgent ของ Operator จาก chart datadog-operator 2.27.0 (Operator app version 1.30.0, CRD sub-chart 2.24.0) CRD นี้ serve เวอร์ชันเดียวคือ v2alpha1 ถูกแปลงเป็น JSON Schema แบบ strict (additionalProperties: false ทุกที่ที่ CRD ไม่ได้ตั้ง x-kubernetes-preserve-unknown-fields) ซึ่งเลียนแบบสิ่งที่ kubectl apply --validate=strict ขอให้ API server ทำ ไม่ได้รันกับ API server จริง — ไม่มี cluster และโหมด --k8s ของ harness ต้องการ cluster kind ที่ไม่มีอยู่ที่นี่
  • agent configcheck จาก container datadog/agent 7.83.3 จริง (API key ปลอม, start ด้วย --network none เพื่อไม่ให้อะไรออกจาก container ได้, ลบทิ้งภายหลัง) โดย mount template Redis ที่แก้แล้วจากดิสก์
  • JSON schema apps/v1 Deployment ของ Kubernetes 1.37 จากคอร์ส Kubernetes สำหรับ Deployment
# @expect-error as generated -- see the review below (helm lint passes; helm template renders)
datadog:
apiKey: "<your-api-key>"
site: https://api.datadoghq.com
tags: env:prod
apm:
enabled: true
logs:
enabled: true
collectAll: true
dogstatsd:
port: 8125
agents:
image:
tag: latest
clusterAgent:
enabled: true
# @expect-error the Operator manifest as generated -- v1alpha1-shaped fields under v2alpha1
apiVersion: datadoghq.com/v2alpha1
kind: DatadogAgent
metadata:
name: datadog
namespace: datadog
spec:
credentials:
apiKey: "<your-api-key>"
global:
clusterName: prod-eks-1
site: https://api.datadoghq.com
features:
apm:
enabled: true
logCollection:
enabled: true
containerCollectAll: true
agent:
image:
name: datadog/agent:latest
clusterAgent:
enabled: true
# @expect-error Autodiscovery annotations on the Deployment, keyed to the wrong container name
apiVersion: apps/v1
kind: Deployment
metadata:
name: cache
namespace: shop
annotations:
ad.datadoghq.com/redis.checks: |
{
"redisdb": {
"init_config": {},
"instances": [{ "host": "%%host%%", "port": "6379" }]
}
}
ad.datadoghq.com/redis.logs: '[{"source": "redis", "service": "cache"}]'
spec:
replicas: 1
selector:
matchLabels:
app: cache
template:
metadata:
labels:
app: cache
spec:
containers:
- name: cache
image: redis:latest

ส่วนที่ 1 — Helm values ทุก finding ตรงนี้คือหนึ่งบรรทัดของ DaemonSet ที่ render ออกมา

helm lint ผ่าน (1 chart(s) linted, 0 chart(s) failed) และ helm template exit 0 container agent ที่ render:

DD_SITE = https://api.datadoghq.com

chart ส่งต่อค่าตรงๆ และ Agent ก็เช่นกัน เมื่อ start ด้วยค่านั้น agent status แสดงว่า Agent ประกอบ hostname ของ intake อย่างไร (พฤติกรรมเดียวกับ entry 6 ของ bug catalog รันซ้ำสำหรับรีวิวนี้):

$ docker exec dd-reading-b agent status # DD_SITE=https://api.datadoghq.com
https://process.https://api.datadoghq.com. - API Key ending with:
$ docker exec dd-reading-b agent status # DD_SITE=datadoghq.com
https://process.datadoghq.com. - API Key ending with:

🐛 หา bug ในโค้ดนี้

datadog:
site: https://api.datadoghq.com
เฉลย

site คือ site domain ของ Datadog (datadoghq.com, datadoghq.eu, …) ไม่ใช่ API URL; hostname ของ intake ประกอบโดยเอามันไปเป็น prefix (รายการ site: docs.datadoghq.com/getting_started/site/) ทั้ง Helm และ Agent ไม่ validate — ความล้มเหลวคือ Agent ที่รันอยู่และไม่เคยส่งถึง วิธีแก้: site: datadoghq.com

apiKey: "<your-api-key>" — ที่นี่เป็น placeholder แต่รูปแบบคือ key จริงใน ไฟล์ที่อยู่ใน git เมื่อ render chart แปลงมันเป็น Secret ที่ api-key เป็นแค่ base64 ของสตริง:

dd-datadog api-key <your-api-key> (base64-decoded from the rendered Secret)

values.yaml ของ chart เองบอกทางเลือกไว้: datadog.apiKeyExistingSecret — “Use existing Secret which stores API key … The value should be set with the api-key key inside the secret” และ “If set, this parameter takes precedence over apiKey” เมื่อตั้งค่านี้ ผล render ไม่มี object Secret ที่เก็บ key เลย (0 เอกสาร kind: Secret ใน render ที่แก้แล้ว)

🐛 หา bug ในโค้ดนี้

datadog:
apiKey: "<your-api-key>"
เฉลย

key ที่ใช้งานได้ใน values file แปลว่า key อยู่ใน git history, ใน CI log ที่พิมพ์ helm template และในทุก screenshot ของการรีวิว manifest ของ Operator ด้านล่างทำผิดซ้ำในที่ที่ schema อนุญาต วิธีแก้: สร้าง Secret นอกระบบ (kubectl create secret generic datadog-secret --from-literal api-key=...) แล้วอ้างด้วย apiKeyExistingSecret

chart ระบุ datadog.tags เป็น “List of static tags” Helm ไม่บ่นเรื่อง string และ chart ทำ toJson กับอะไรก็ตามที่ได้รับ:

values tags: env:prod -> DD_TAGS = "env:prod" (string, JSON-quoted)
values tags: [env:prod] -> DD_TAGS = ["env:prod"]

สิ่งที่ Agent ทำกับแต่ละแบบ จาก agent config และ agent status ใน container 7.83.3 จริงที่ start ด้วยค่า DD_TAGS สองค่านั้นเป๊ะ:

DD_TAGS='"env:prod"' tags:
- '"env:prod"'
DD_TAGS='["env:prod"]' tags:
- env:prod host tags: env:prod

รูปแบบ scalar สร้าง tag ที่ตัวอักษรมี double quote อยู่ด้วย — มันจะไม่มีวัน match env:prod ใน scope ของ monitor หรือ filter ของ dashboard

🐛 หา bug ในโค้ดนี้

datadog:
tags: env:prod
เฉลย

type ผิดและไม่มีอะไรบังคับ: values.schema.json ของ chart อธิบายแค่ไม่กี่ key (property ระดับบนคือ registryMigrationMode กับ datadog และใต้ datadog มีแค่ instrumentationCrd, networkPath, apm, appsec) ดังนั้น tags ไม่ถูกเช็ก วิธีแก้: YAML list — tags: แล้ว - env:prod ดียิ่งกว่านั้นคือไม่ใส่ env ตรงนี้เลย unified service tagging ตั้งให้ต่อ workload

คำขอคือ “log จากทุก container” container ที่ render:

DD_LOGS_ENABLED = true
DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL = false

key จริงคือ datadog.logs.containerCollectAll (default false; comment ของ chart: “Enable this to allow log collection for all containers”) collectAll ถูกเพิกเฉย หลักฐานคือ diff: render logs: {enabled: true, collectAll: true} เทียบกับ logs: {enabled: true} ได้ ผลเหมือนกันทุกประการ ยกเว้นบรรทัด token, checksum และ install_id ของ Cluster Agent ที่สุ่ม และเพราะ Helm พา key ที่ไม่รู้จักไปเฉยๆ helm lint จึงมองไม่เห็นเช่นกัน

เมื่อ enabled: true ระบบท่อ log อยู่ครบ — DaemonSet ที่ render mount /var/log/pods, /var/log/containers และ pointer directory — ความล้มเหลวจึงแนบเนียน docs (docs.datadoghq.com/containers/kubernetes/log/) บอกกฎ: “When set to false (default), you need to specify Autodiscovery log configurations to enable log collection.” ทุก container ที่ไม่มี logs annotation ของตัวเองถูกข้ามแบบเงียบๆ

🐛 หา bug ในโค้ดนี้

logs:
enabled: true
collectAll: true
เฉลย

collectAll ดูถูกและถูกเพิกเฉยเงียบๆ key คือ containerCollectAll: true การเปิดมีต้นทุนที่ assistant ไม่ได้บอก: stdout ของ ทุก container รวมถึง sidecar ที่ noisy และตัว Agent เองถูก ingest; ใช้ datadog.containerExcludeLogs ตัดทอน (trade-off อยู่ในหัวข้อด้านล่าง)

Render ได้: registry.datadoghq.com/agent:latest บน container agent, trace-agent, system-probe, init-* และ seccomp-setup ค่า default ของ chart เองเมื่อไม่ตั้ง tag คือ registry.datadoghq.com/agent:7.82.3 ที่ pin ไว้สำหรับ chart 3.250.3 — assistant ทำให้การ deploy ทำซ้ำได้น้อยลง กว่าการไม่ทำอะไร tag เหล่านี้มีอยู่จริงบน Docker Hub (docker manifest inspect datadog/cluster-agent:7.83.3 resolve ได้; tag ของ Agent ถูก pull และรันสำหรับรีวิวนี้) latest เปลี่ยนใต้ DaemonSet ที่กำลังรัน: node ถัดไปที่ pull ได้ Agent ต่างจาก node ข้างเคียง

🐛 หา bug ในโค้ดนี้

agents:
image:
tag: latest
เฉลย

วันนี้ยังไม่พัง - ความเสี่ยงคือไม่มีใครบอกได้ว่า Agent ตัวไหนสร้าง metric หนึ่งๆ และการ restart node กลางสัปดาห์อัปเกรด node หนึ่งแบบเงียบๆ ได้ ให้ pin agents.image.tag และ clusterAgent.image.tag (Cluster Agent มี setting ของ image ตัวเองซึ่ง AI ไม่ได้ตั้ง) แล้วอัปเดตทั้งคู่โดยตั้งใจ วิธีแก้: tag: 7.83.3

clusterAgent.enabled: true โดยไม่มี token และไม่มี tokenExistingSecret comment ของ chart: “autogenerated if empty, needs to be at least 32 characters” helm template สองครั้งติดกันกับ values เดิม:

render 1 dd-datadog-cluster-agent token PIjV... checksum/clusteragent_token: b2b26b5d...
render 2 dd-datadog-cluster-agent token qlPr... checksum/clusteragent_token: 82e66f08...

(แสดงเฉพาะตัวอักษรแรกๆ ของแต่ละ token) token เปลี่ยนทุก render และค่าถูก hash ลงใน annotation ของ pod template ดังนั้น ทุก helm upgrade roll ทั้ง DaemonSet และ Cluster Agent แม้ไม่มีอะไรอื่นเปลี่ยน เมื่อตั้ง tokenExistingSecret ผล render ที่แก้แล้วเหมือนกันทุก byte ระหว่างการรัน ยกเว้น install_id ที่ไม่เกี่ยวข้อง

🐛 หา bug ในโค้ดนี้

clusterAgent:
enabled: true
เฉลย

pre-shared token ระหว่าง node Agent กับ Cluster Agent ต้องคงที่ วิธีแก้: สร้าง Secret ที่มี key token (32+ ตัวอักษร) ครั้งเดียว แล้วตั้ง clusterAgent.tokenExistingSecret นี่คือ bug ประเภทเดียวกับ API key ที่ hard-code แต่ขั้วตรงข้าม: ที่นี่ค่าที่ generate สดเกินไป

DaemonSet ที่ render ไม่มี DD_CLUSTER_NAME เลย (การไม่มีถูกตรวจ ไม่ได้สันนิษฐาน: template ปล่อยมันเฉพาะใน if .Values.datadog.clusterName) comment ของ chart บน key นี้: “Set a unique cluster name to allow scoping hosts and Cluster Checks easily” เอกสาร tag (docs.datadoghq.com/containers/kubernetes/tag/) ระบุ kube_cluster_name โดยมี source “DD_CLUSTER_NAME envvar or cloud provider integration” — ดังนั้นบน cluster ที่ไม่มี cloud integration ตรงกัน ก็ไม่มี tag cluster ให้ scope monitor ไปที่ “prod-eks-1” แทน “cluster ไหนก็ได้”

🐛 หา bug ในโค้ดนี้

datadog:
site: https://api.datadoghq.com
tags: env:prod
เฉลย

ไม่มีอะไรใน block นี้ตั้งชื่อ cluster draft ของ Operator ตั้ง clusterName ไว้ ซึ่งเป็นเหตุผลที่สอง artifact ขัดกัน วิธีแก้: datadog.clusterName: prod-eks-1 (ตัวพิมพ์เล็ก ตัวเลข และ hyphen; chart เอง fail เมื่อชื่อไม่ถูกต้อง)

port ของ container agent ที่ render:

agent [{'containerPort': 8125, 'name': 'dogstatsdport', 'protocol': 'UDP'}]
trace-agent [{'containerPort': 8126, 'hostPort': 8126, 'name': 'traceport', 'protocol': 'TCP'}]

APM มี hostPort (apm.enabled: true ที่ deprecated ยังเปิดมันอยู่ — ดู Misconceptions); DogStatsD ไม่มี เพราะ port คือ container port และ default ของ chart สำหรับ datadog.dogstatsd.useHostPort คือ false แอปที่ส่ง metric ไป status.hostIP:8125 — pattern เดียวกับ bug 11 ของ รีวิว Node — ไปไม่ถึงอะไรเลย comment ของ chart สำหรับ useHostPort: “Sets the hostPort to the same value of the container port. Needs to be used for sending custom metrics.” เมื่อ useHostPort: true ผล render แสดง 'hostPort': 8125 transport อื่นที่รองรับ ซึ่งเปิดเป็น default คือ Unix socket (useSocketVolume: true) ที่ pod ของแอปต้อง mount

🐛 หา bug ในโค้ดนี้

dogstatsd:
port: 8125
เฉลย

port: 8125 แค่ย้ำค่า default คำถามที่สำคัญคือ แอปเข้าถึง DogStatsD อย่างไร — hostPort หรือ socket volume — และ values file ไม่เคยตอบ วิธีแก้: ตัดสินใจ แล้วตั้ง useHostPort: true (หรือ mount socket ในแอป)

ส่วนที่ 2 — manifest ของ Operator

CRD ใน operator chart 2.27.0 ประกาศเวอร์ชันเดียวเท่านั้น: [('v2alpha1', True, True)] (name, served, storage) ดังนั้น apiVersion: datadoghq.com/v1alpha1 — รูปแบบที่ assistant เรียนจาก tutorial เก่า — ไม่ถูก serve เลย (คำตอบของ API server คือ error ทั่วไป no matches for kind "DatadogAgent" in version; ไม่ได้รันที่นี่) draft นี้ได้ apiVersion ถูกแต่ body ผิด การเช็ก strict schema:

$ python3 vcr.py bad-dda.yaml
apiVersion: datadoghq.com/v2alpha1
/spec -> Additional properties are not allowed ('agent', 'clusterAgent', 'credentials' were unexpected)

spec ใน v2alpha1 มี property สามตัวพอดี: features, global, override credentials ย้ายไป global.credentials; agent.image กลายเป็น override.nodeAgent.image (แยก name กับ tag); การตั้งค่าของ Cluster Agent อยู่ใต้ override.clusterAgent (และ image ของมันใต้ override.clusterAgent.image) docs ของ Kubernetes เองอธิบายว่า API server ทำอะไรกับ field ที่ไม่รู้จัก: “Possible levels of validation are Ignore, Warn (default), and Strict” (kubernetes.io/docs/reference/using-api/api-concepts/#field-validation) และ kubectl apply --help บนเครื่องนี้ (client v1.36.1) ระบุ --validate='strict' เป็น default ด้วยสองระดับแรก field ที่ไม่รู้จักไม่ใช่ error; CRD ที่มี structural schema จะ prune มัน ดังนั้น DatadogAgent ที่เก็บไว้จะขาด block เหล่านั้น (การ prune นี้ไม่ได้รันที่นี่ — ไม่มี API server) และ Agent ที่ไม่มี credentials คือผลตามธรรมชาติ

🐛 หา bug ในโค้ดนี้

spec:
credentials:
apiKey: "<your-api-key>"
agent:
image:
name: datadog/agent:latest
clusterAgent:
enabled: true
เฉลย

block เหล่านั้นเป็น field ที่ถูกต้องของ v1alpha1 ในเอกสาร v2alpha1 การเช็ก strict schema จับได้; การ apply แบบผ่อนปรนทิ้งมันเงียบๆ ซึ่งเป็นผลที่แย่ที่สุด — DatadogAgent ที่ดูสุขภาพดีแต่ไม่มีการตั้งค่าที่ตั้งใจเลย วิธีแก้: spec.global.credentials, spec.override.nodeAgent.image, spec.override.clusterAgent.image

ย้ายสาม block ที่วางผิดที่ไปยังที่ของมันใน v2alpha1 โดยไม่เปลี่ยนอย่างอื่น (site ยังเป็น URL, key ยัง literal, latest ยังอยู่):

$ python3 vcr.py mid-dda.yaml
apiVersion: datadoghq.com/v2alpha1
OK: no schema violations

schema validate โครงสร้างและ type ไม่ใช่ความหมาย CRD ไม่มี pattern ให้ site และ credentials.apiKey เป็น string ที่ถูกต้อง ปัญหาเรื่องค่าสามอย่างจากส่วนที่ 1 — site ที่เป็น URL, key แบบ plaintext, tag ที่ลอย — ผ่านไปได้หมด (negative control แสดงว่า checker ไม่ได้ว่างเปล่า: containerCollectall ให้ Additional properties are not allowed ('containerCollectall' was unexpected) ที่ /spec/features/logCollection และ enabled: "yes" ให้ 'yes' is not of type 'boolean')

🐛 หา bug ในโค้ดนี้

global:
site: https://api.datadoghq.com
credentials:
apiKey: "<your-api-key>"
เฉลย

“มัน validate ผ่าน” เป็นข้อความเกี่ยวกับ schema API key ควรอยู่ใน spec.global.credentials.apiSecret (secretName และ keyName); site คือ datadoghq.com ทั้งสองเป็นรายการรีวิวที่ schema แบบ offline ยกขึ้นมาไม่ได้

ส่วนที่ 3 — Autodiscovery และ Deployment ของ Redis

annotation อยู่บน metadata ของ Deployment เอง Autodiscovery อ่าน annotation ของ pod จาก docs (docs.datadoghq.com/containers/kubernetes/integrations/): “If you define pods indirectly (with deployments, ReplicaSets, or ReplicationControllers) add pod annotations under spec.template.metadata.” pod template คือสิ่งที่ Deployment ใช้สร้าง pod; metadata ของ Deployment เองไม่ถูกคัดลอกไปที่ pod ตรวจสอง manifest ด้วย schema Deployment ของ Kubernetes และ script เล็กๆ:

bad-cache.yaml schema: OK
Deployment.metadata.annotations keys : ['ad.datadoghq.com/redis.checks', 'ad.datadoghq.com/redis.logs']
pod template annotations keys : []
good-cache.yaml schema: OK
Deployment.metadata.annotations keys : []
pod template annotations keys : ['ad.datadoghq.com/cache.checks', 'ad.datadoghq.com/cache.logs']

ทั้งสอง ผ่าน schema kubectl apply ตอบ deployment.apps/cache created ได้ทั้งคู่; ความต่างเห็นได้เฉพาะบน pod ที่รันอยู่ ใน agent configcheck ของ node Agent ขั้นสุดท้ายนั้นต้องมี cluster และไม่ได้รันที่นี่ — ข้อกล่าวอ้างอิงตามการอ้าง docs ข้างบน

🐛 หา bug ในโค้ดนี้

kind: Deployment
metadata:
name: cache
annotations:
ad.datadoghq.com/redis.checks: |
{ ... }
เฉลย

metadata.annotations ของ Deployment เป็นเอกสารสำหรับคนและเครื่องมือ; pod ได้ spec.template.metadata.annotations วิธีแก้: ย้ายทั้งสอง annotation ไปใต้ spec.template.metadata กฎเดียวกันใช้กับ StatefulSet, DaemonSet, Job และ CronJob (spec.jobTemplate.spec.template.metadata สำหรับตัวหลัง)

ad.datadoghq.com/redis.checks — identifier คือชื่อ container ไม่ใช่ชื่อเทคโนโลยี

หัวข้อที่มีชื่อว่า “ad.datadoghq.com/redis.checks — identifier คือชื่อ container ไม่ใช่ชื่อเทคโนโลยี”

แม้อยู่บน pod template key ของ annotation คือ ad.datadoghq.com/<container-name>.checks container ชื่อ cache; annotation เขียน redis docs อธิบาย identifier ในรูปแบบ annotation ว่า “an identifier to match against the names (spec.containers[i].name, not spec.containers[i].image) of the containers that correspond to your integration” script ข้างบนใช้กฎนี้กับทั้งสอง manifest:

deployment: ad.datadoghq.com/redis.checks JSON ok; identifier 'redis' matches a container name: False
pod-template: ad.datadoghq.com/cache.checks JSON ok; identifier 'cache' matches a container name: True

ตัว template เอง รันผ่าน Agent จริงเป็น config Autodiscovery แบบไฟล์ที่มี ad_identifiers: [cache] คือสิ่งที่ annotation ที่แก้แล้วขยายออกมา agent configcheck -v ใน container 7.83.3 แสดงมัน และแสดงรูปแบบ unresolved ที่ node Agent รอ match กับ container ที่รัน:

Auto-discovery IDs: cache
check_name: redisdb
init_config: null
instances:
- host: '%%host%%'
port: "6379"
logs_config: null

รายการนั้น (ใต้ “Collected configs (matched and unmatched)”) พิสูจน์ว่า template parse ได้และถูกลงทะเบียนใต้ identifier cache; มัน ไม่ได้ พิสูจน์ว่ามี pod match — container listener ไม่มี Kubernetes ให้ดูในการรันนี้ ส่วน “Services (matched and unmatched)” ที่มาคู่กันจึงว่าง identifier ที่ผิดอย่าง redis จะถูกลงทะเบียนอย่างเต็มใจเท่ากันและไม่มีวัน match

🐛 หา bug ในโค้ดนี้

ad.datadoghq.com/redis.checks: |
...
containers:
- name: cache
เฉลย

prefix ของ annotation ที่ตั้งชื่อเทคโนโลยีแทน container เป็นความผิดพลาด Autodiscovery ที่พบบ่อยอันดับสอง (รองจากวางผิด object ด้านบน) ความผิดทั้งสองบังกันในการรีวิวเพราะแต่ละอันดูสมเหตุสมผลเมื่ออยู่เดี่ยวๆ วิธีแก้: ad.datadoghq.com/cache.checks และ ad.datadoghq.com/cache.logs บน pod template รูปแบบ v1 สามคีย์ (check_names, init_configs, instances) ยังถูกระบุคู่กับ v2 ในหน้าเดียวกัน จึงไม่ใช่ bug ตรงนี้; v2 (.checks, Agent 7.36+) เป็นแค่รูปแบบ annotation เดียว

helm/values.yaml
datadog:
apiKeyExistingSecret: datadog-secret
site: datadoghq.com
clusterName: prod-eks-1
tags:
- env:prod
apm:
portEnabled: true
dogstatsd:
useHostPort: true
logs:
enabled: true
containerCollectAll: true
agents:
image:
tag: 7.83.3
clusterAgent:
enabled: true
image:
tag: 7.83.3
tokenExistingSecret: datadog-cluster-agent-token
scripts/create-datadog-secrets.sh
kubectl -n datadog create secret generic datadog-secret \
--from-literal api-key=<your-api-key>
kubectl -n datadog create secret generic datadog-cluster-agent-token \
--from-literal token=<random-string-of-32-or-more-characters>

helm lint รายงาน 1 chart(s) linted, 0 chart(s) failed เมื่อ render container agent มี:

DD_API_KEY = secretKeyRef datadog-secret / api-key
DD_CLUSTER_NAME = prod-eks-1
DD_TAGS = ["env:prod"]
DD_SITE = datadoghq.com
DD_CLUSTER_AGENT_AUTH_TOKEN = secretKeyRef datadog-cluster-agent-token / token
DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL = true
agent containerPort 8125 hostPort 8125 (UDP)
trace-agent containerPort 8126 hostPort 8126 (TCP)

และ render สองครั้งติดกันต่างกันแค่ UUID install_id ที่ไม่เกี่ยวข้อง ตัวเทียบเท่าของ Operator ซึ่งผ่านการเช็ก strict v2alpha1 (OK: no schema violations):

k8s/datadog-agent.yaml
apiVersion: datadoghq.com/v2alpha1
kind: DatadogAgent
metadata:
name: datadog
namespace: datadog
spec:
global:
clusterName: prod-eks-1
site: datadoghq.com
credentials:
apiSecret:
secretName: datadog-secret
keyName: api-key
clusterAgentTokenSecret:
secretName: datadog-cluster-agent-token
keyName: token
tags:
- env:prod
features:
apm:
enabled: true
hostPortConfig:
enabled: true
hostPort: 8126
dogstatsd:
hostPortConfig:
enabled: true
hostPort: 8125
logCollection:
enabled: true
containerCollectAll: true
admissionController:
enabled: true
clusterChecks:
enabled: true
useClusterChecksRunners: true
override:
nodeAgent:
image:
name: datadog/agent
tag: 7.83.3
clusterAgent:
image:
name: datadog/cluster-agent
tag: 7.83.3
k8s/cache-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: cache
namespace: shop
spec:
replicas: 1
selector:
matchLabels:
app: cache
template:
metadata:
labels:
app: cache
annotations:
ad.datadoghq.com/cache.checks: |
{
"redisdb": {
"init_config": {},
"instances": [{ "host": "%%host%%", "port": "6379" }]
}
}
ad.datadoghq.com/cache.logs: '[{"source": "redis", "service": "cache"}]'
spec:
containers:
- name: cache
image: redis:7.4
conf.d/redisdb.d/conf.yaml
ad_identifiers:
- cache
init_config:
instances:
- host: "%%host%%"
port: "6379"

fence สุดท้ายเป็นคู่แฝดแบบไฟล์ของ annotation และเป็น fence ที่ถูกเก็บ: harness ของคอร์ส mount มันเข้า Agent container จริงแล้วรัน agent configcheck

#Bugวิธีแก้พิสูจน์ด้วย
1site: https://api.datadoghq.comsite: datadoghq.comDD_SITE ที่ render; URL intake ใน agent status
2apiKey แบบ literal ใน valuesapiKeyExistingSecretSecret ที่ render decode ได้เป็น key; 0 Secret หลังแก้
3tags: env:prod เป็น stringYAML listDD_TAGS = "env:prod"; agent config แสดง tag ที่มี quote
4logs.collectAll (key ที่แต่งขึ้น)logs.containerCollectAllCOLLECT_ALL = false; render เหมือนกันมีหรือไม่มี key
5agents.image.tag: latestpin tag ของ Agent และ Cluster Agentimage ที่ render; default ของ chart คือ 7.82.3
6ไม่มี token ของ Cluster AgenttokenExistingSecrettoken และ checksum/clusteragent_token ต่างกันทุก render
7ไม่มี clusterNamedatadog.clusterNameไม่มี DD_CLUSTER_NAME ที่ render
8DogStatsD port ไม่มี hostPortuseHostPort: true (หรือ socket)port ของ container ที่ render
9field รูปแบบ v1alpha1 ใน v2alpha1global.credentials, override.*strict CRD schema: 3 property ที่ไม่คาดคิด
10ค่าถูก schema แต่ผิดapiSecret, datadoghq.comOK: no schema violations บน manifest ที่ยังผิด
11AD annotation บน Deploymentspec.template.metadata.annotationsคำอ้างจาก docs; ทั้งสอง manifest ผ่าน schema
12prefix annotation redis แต่ container cachead.datadoghq.com/cache.*script + configcheck -v ลงทะเบียน template ใต้ cache

12 finding ไม่มีอันไหนเป็น syntax error — helm lint เขียว และทุก manifest เป็น YAML ที่ถูกต้อง:

  1. Helm values: site คือ domain (datadoghq.com) ไม่ใช่ URL; tags เป็น list; มี API key แบบ literal (ใช้ apiKeyExistingSecret); logs.collectAll ไม่มีอยู่ — key คือ containerCollectAll และวันนี้ DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL render เป็น false
  2. ทำซ้ำได้: pin agents.image.tag และ clusterAgent.image.tag; ตั้ง clusterAgent.tokenExistingSecret — วันนี้ทุก helm upgrade generate token ใหม่และ roll DaemonSet
  3. ขาด: datadog.clusterName และการตัดสินใจว่าแอปเข้าถึง DogStatsD อย่างไร (useHostPort หรือ socket)
  4. manifest ของ Operator: credentials, agent และ clusterAgent เป็น field ของ v1alpha1; ใน v2alpha1 คือ global.credentials, override.nodeAgent และ override.clusterAgent รัน strict schema — และจำไว้ว่า “valid” ยังไม่พูดอะไรเรื่อง key แบบ plaintext หรือ site ที่เป็น URL
  5. Redis Autodiscovery: annotation ไปที่ spec.template.metadata และ prefix ของ key คือชื่อ container (cache) ไม่ใช่ redis
  6. ยังไม่ได้ยืนยันที่นี่ ช่วยเช็กบน cluster จริง: agent configcheck บน node Agent สำหรับ pod cache และว่า log จาก container ที่ไม่มี annotation มาถึงจริง
flowchart TD
  V["values.yaml"] -->|"1, 3, 5, 7: wrong value shape or missing"| R["helm template"]
  V -->|"2: literal key in git"| R
  V -->|"4: invented key ignored"| R
  V -->|"6: token differs per render"| R
  V -->|"8: port without hostPort"| R
  R --> D["DaemonSet + Cluster Agent"]
  O["DatadogAgent manifest"] -->|"9: v1alpha1 fields"| S["v2alpha1 CRD schema"]
  O -->|"10: valid but wrong values"| S
  S --> D
  A["Deployment annotations"] -->|"11: wrong object"| P["pod"]
  A -->|"12: wrong container identifier"| P
  D -->|"node Agent reads pod annotations"| P
แต่ละ bug อยู่ตรงไหนระหว่าง values กับ pod ที่รัน

ดูว่าอะไรจับอะไร helm template ทำให้ bug 1, 3, 4, 5, 6, 7 และ 8 มองเห็นได้เพราะ DaemonSet ที่ render เป็นข้อความธรรมดาที่อ่านได้ — แต่ต้องมองหาสิ่งที่ หายไป (DD_CLUSTER_NAME, hostPort) strict CRD schema จับ 9 ได้ และโดยการออกแบบจับ 10 ไม่ได้ Bug 11 และ 12 มองไม่เห็นด้วย offline tool ทุกตัวในรีวิวนี้: ทั้งสอง manifest validate ผ่าน schema ของ Kubernetes จุดยืนที่ซื่อสัตย์คือตารางที่มีคอลัมน์ชื่อ “ต้องมี cluster”

  • Helm chart vs Operator chart render เป็น manifest ธรรมดาที่ helm template และ diff ใน CI ได้; Operator เปลี่ยน custom resource เล็กๆ เป็น manifest เหล่านั้นตอน runtime ดังนั้น “อะไรจะถูก deploy” ถูกตัดสินภายใน cluster และคุณรีวิวเจตนา ไม่ใช่ผลลัพธ์ strict schema ปกป้องทาง Operator; การ render ปกป้องทาง chart
  • containerCollectAll: true เป็นวิธีเร็วที่สุดของ “log จากทุกอย่าง” และมันส่งทุกอย่าง: sidecar ที่ noisy, chatter ของ health check, log ของ Agent เอง annotation ad.datadoghq.com/<container>.logs ต่อ workload พร้อม exclusion filter ต้องตั้งค่ามากกว่าแต่คุมบิลได้
  • hostPort vs socket สำหรับ APM และ DogStatsD hostPort เข้าถึงได้ด้วย status.hostIP อย่างเดียวโดยไม่ต้อง mount volume แลกกับการเปิด port บนทุก node; Unix socket ต้อง mount hostPath ใน pod ของแอปแต่ไม่มี network hop ทั้งสองรองรับโดย chart และ Operator; หน้าที่ของรีวิวคือต้องมีการเลือกหนึ่งอย่าง
  • “helm lint ผ่าน แปลว่า values ถูก” พิสูจน์แล้วข้างบน: lint ผ่านกับ values file ที่มี URL เป็น site, key logs ที่แต่งขึ้น และ string ในที่ที่ต้องเป็น list
  • “apm.enabled: true เป็น bug เพราะ deprecated” มัน deprecated (comment ของ chart: “DEPRECATED. Use datadog.apm.portEnabled instead”) แต่ใช้ได้: ผล render แสดง DD_APM_ENABLED = true, DD_APM_RECEIVER_PORT = 8126 และ hostPort: 8126 บน container trace-agent เขียนใหม่เพื่ออนาคต แต่อย่าเรียกว่าพัง
  • “ถ้า CRD schema validate ผ่าน DatadogAgent ก็ถูก” พิสูจน์แล้วข้างบน: manifest ที่ยังผิดคืน OK: no schema violations
  • “Autodiscovery annotation วางตรงไหนของ workload ก็ได้” ต้องอยู่บน pod (spec.template.metadata สำหรับ Deployment) และ key ด้วยชื่อ container ทั้งสองแบบผ่าน kubectl apply
  • “annotation v1 (check_names) ถูกถอดแล้ว” หน้า docs ยังแสดง v1 คู่กับ v2; v2 ต้องการ Agent 7.36+ ซึ่ง Agent ปัจจุบันทุกตัวเป็นไปตามนั้น
helm lint รายงาน 0 chart(s) failed สำหรับ values file ที่มี site: https://api.datadoghq.com helm template render อะไร และ Agent ทำอะไรกับมัน?
values file ตั้ง datadog.logs.collectAll: true เทียบผล render มีและไม่มีบรรทัดนั้น ผลเป็นอย่างไร?
helm template รันสองครั้งกับ values เดียวกัน (ไม่มี clusterAgent.token ไม่มี tokenExistingSecret) แสดง annotation checksum/clusteragent_token ต่างกัน ผลต่อ helm upgrade คืออะไร?
DatadogAgent ที่มี apiVersion: datadoghq.com/v2alpha1 มี spec.credentials, spec.agent และ spec.clusterAgent strict CRD schema รายงานอะไร และ apply แบบผ่อนปรนทำอะไร?
หลังย้าย block ที่วางผิดไป spec.global และ spec.override manifest ยังมี site: https://api.datadoghq.com และ apiKey แบบ literal การเช็ก schema พิมพ์อะไร?
Redis Autodiscovery annotation อยู่ที่ metadata.annotations ของ Deployment โดยมี prefix ad.datadoghq.com/redis.; container ชื่อ cache ข้อใดถูกต้อง?