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

Logging และ Metrics

Kubernetes ให้ logging กับ metrics มาแค่พอ debug Pod เดียว ณ ตอนนี้ได้ แต่ไม่มีอะไรที่ aggregate หรือเก็บข้อมูลข้ามทั้ง cluster ให้ นั่นคือ stack แยกที่ต้องเพิ่มเข้าไปเอง

kubectl logs: หน้าต่างของตอนนี้ ไม่ใช่หนังสือประวัติศาสตร์

หัวข้อที่มีชื่อว่า “kubectl logs: หน้าต่างของตอนนี้ ไม่ใช่หนังสือประวัติศาสตร์”

kubectl logs อ่าน stdout/stderr ของ container ตรงจากโหนดที่รันอยู่ เป็นวิธีเร็วที่สุดที่จะดูว่า Pod กำลังทำอะไรอยู่ ณ วินาทีนี้

Terminal window
# Stream logs live as they are written
kubectl logs -f deploy/checkout
# A Pod with more than one container: pick which one
kubectl logs my-pod -c sidecar
# The container just crashed and restarted: see its last words before it died
kubectl logs my-pod --previous

--previous คือ flag ที่คนมักลืมแล้วดันเป็นตัวที่ต้องใช้ที่สุด เวลา container crash-loop log ของ container ตัว ปัจจุบัน จะว่างเปล่าตั้งแต่เริ่ม แต่ --previous จะโชว์ log ของ instance ที่เพิ่ง crash ไป ซึ่งปกติก็ตรงจุดที่มี stack trace อยู่พอดี

ข้อจำกัดสำคัญคือ Kubernetes เองไม่ได้ aggregate หรือเก็บ log พวกนี้ให้ ถ้า Pod ถูกลบ log ของตัวเองก็มักหายไปด้วย ไม่มี “ค้นหา log ข้ามทุก Pod ใน cluster” มาให้ในตัว งานนี้เป็นหน้าที่ของ logging stack แยกต่างหาก โดยทั่วไปจะเป็น node-level agent อย่าง Fluent Bit (หรือ Fluentd/Vector) ที่คอย tail log file ของทุก container แล้วส่งต่อไปยัง backend อย่าง Loki หรือ Elasticsearch ที่ค้นหาและเก็บข้อมูลระยะยาวได้

# A minimal illustration: Fluent Bit runs as a DaemonSet so one agent per node
# tails every container's logs and forwards them to a backend
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit
spec:
selector:
matchLabels:
app: fluent-bit
template:
metadata:
labels:
app: fluent-bit
spec:
containers:
- name: fluent-bit
image: fluent/fluent-bit:3.1
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
hostPath:
path: /var/log

metrics-server เป็น cluster add-on เบา ๆ ที่เก็บ CPU กับ memory usage จากทุก kubelet แล้วเก็บไว้ ในหน่วยความจำเท่านั้น ไม่มีประวัติ ไม่มีการ persist ไม่มี alerting มีไว้เพื่อขับเคลื่อนแค่สองอย่างนี้

Terminal window
kubectl top nodes
kubectl top pods -n checkout

…และ HorizontalPodAutoscaler ที่ poll metrics-server เพื่อตัดสินใจว่าจะ scale Deployment ขึ้นหรือลง

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: checkout
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: checkout
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70

metrics-server ไม่ใช่ monitoring solution ชัดเจน ถ้าถามว่า “CPU usage เมื่อสามชั่วโมงก่อนเป็นยังไง” หรือ “แจ้งเตือนตอน memory เกิน 90%” metrics-server ตอบไม่ได้เลย เพราะรู้แค่ snapshot ปัจจุบันเท่านั้น

สำหรับ observability จริง ๆ ที่ต้องมีข้อมูลย้อนหลัง dashboard และ alerting ตัวมาตรฐานที่ใช้กันคือคู่ Prometheus กับ Grafana

Prometheus ทำงานด้วยการ scrape คือดึง metrics เป็นระยะจาก HTTP endpoint /metrics ที่ workload เปิดไว้ในรูปแบบ text ของ Prometheus เอง แอปและ sidecar หลายตัวเปิด endpoint นี้เอง ส่วนสำหรับสถานะของ object ระดับ cluster (จำนวน replica ของ Deployment, phase ของ Pod, condition ของ node และอื่น ๆ) Prometheus จะ scrape kube-state-metrics ที่เป็น service แยกที่แปลง object ของ Kubernetes API ให้กลายเป็น metrics ของ Prometheus

apiVersion: v1
kind: Pod
metadata:
name: checkout
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
spec:
containers:
- name: checkout
image: checkout:2.3.0
ports:
- containerPort: 9090
Terminal window
# A workload's own /metrics endpoint, in Prometheus text format
curl http://checkout-pod:9090/metrics

Prometheus เก็บข้อมูลที่ scrape มาเป็น time series แล้วประเมินตาม alerting rule ที่ตั้งไว้ Grafana ทำหน้าที่เป็น visualization layer อยู่ด้านบน คือ query ไปที่ Prometheus แล้ว render ออกมาเป็น dashboard เช่นแนวโน้ม CPU/memory, request latency, error rate และใช้ขับเคลื่อนการแจ้งเตือนด้วย

flowchart LR
  subgraph Logs
    stdout["Pod stdout/stderr"] --> agent["Node-level log agent\n(Fluent Bit)"]
    agent --> backend["Log backend\n(Loki / Elasticsearch)"]
  end
  subgraph Metrics
    cadvisor["kubelet cAdvisor"] --> ms["metrics-server\n(in-memory)"]
    ms --> top["kubectl top / HPA"]
    workload["Workload /metrics\n+ kube-state-metrics"] --> prom["Prometheus"]
    prom --> grafana["Grafana dashboards"]
  end
สอง pipeline คู่ขนาน: log ไป log backend และ metrics ไปทั้ง kubectl top/HPA และ Prometheus/Grafana
Kubernetes aggregate และ persist log ของ Pod ข้ามทั้ง cluster ให้โดย default หรือไม่
metrics-server เหมาะกับงานแบบไหนที่สุด
flag ไหนที่โชว์ log ของ container ที่เพิ่ง crash แล้ว restart
Prometheus กับ Grafana สัมพันธ์กับ metrics-server ยังไง