Monitoring DevOps Observability

Monitoring & Observability — รู้ทุกอย่างที่เกิดขึ้นใน System

By Anirach Mingkhwan DevOps & Vibe Coding 2026
DevOps Engineer — dog monitoring dashboards

จากโพสต์ที่แล้วเราเรียนรู้ IaC — ใช้ Terraform สร้าง infrastructure และ Ansible ตั้งค่า server อัตโนมัติ

แต่หลังจาก deploy ขึ้น production แล้ว... จะรู้ได้ยังไงว่า app ทำงานปกติ? Server จะล่มตอนไหน? User กำลังเจอ error อะไร? 🔍

นี่คือที่มาของ Monitoring & Observability — ระบบที่ทำให้เรา "มองเห็น" ทุกอย่างที่เกิดขึ้นข้างใน เหมือน DevOps Engineer ที่นั่งจ้องจอ dashboard ตลอดเวลา 🐕‍🦺📊


Monitoring vs Observability — ต่างกันยังไง?

หลายคนใช้สองคำนี้แทนกัน แต่จริงๆ ต่างกัน — Monitoring คือ "ดูว่าระบบยังทำงานปกติไหม" (CPU สูงไหม? disk เต็มไหม? error rate เพิ่มไหม?) เป็นการถามคำถามที่ "รู้อยู่แล้ว" ส่วน Observability คือ "สามารถเข้าใจได้ว่าระบบเป็นยังไงจากข้อมูลที่ส่งออกมา" — ตอบคำถามที่ "ยังไม่เคยถาม" ได้ เหมาะกับ microservices ที่ complex และ failure modes คาดเดาไม่ได้:

Monitoring Observability
ตอบว่า "มีปัญหามั้ย?" ตอบว่า "ทำไมถึงมีปัญหา?"
ตรวจสิ่งที่เรา รู้ล่วงหน้า หาสิ่งที่เรา ไม่เคยคิดถึง
Dashboard + Alerts Explore + Drill-down + Correlate
CPU สูง → แจ้งเตือน ทำไม CPU สูง? → trace → พบ query ช้า
💡 จำง่ายๆ: Monitoring = ติดกล้องวงจรปิด | Observability = มีนักสืบวิเคราะห์ภาพ

3 Pillars of Observability

ระบบ Observability ที่ดีต้องมีข้อมูล 3 ประเภทที่ทำงานเสริมกัน — Metrics บอกว่า "มีปัญหาไหม" (ตัวเลข), Logs บอกว่า "เกิดอะไรขึ้น" (events), Traces บอกว่า "ช้าตรงไหน" (request flow) ขาดอันใดอันหนึ่งก็ debug ยาก:

📊
Metrics
ตัวเลขที่วัดได้ เช่น CPU %, memory, request/sec, error rate
📝
Logs
บันทึกเหตุการณ์ เช่น error messages, access logs, debug info
🔗
Traces
ติดตาม request ผ่านทุก service ว่าช้าตรงไหน

Pillar 1: Metrics — ตัวเลขที่ต้องจับตา

Metrics คือตัวเลขที่วัดได้ตามเวลา (time-series data) — CPU usage 72%, response time 230ms, error rate 0.5% เหมาะกับ alerting (แจ้งเตือนเมื่อเกินเกณฑ์) และ trending (ดู pattern ระยะยาว) Metrics แบ่งเป็น 3 ระดับ:

System Metrics

System metrics วัดสุขภาพของ infrastructure — CPU, Memory, Disk, Network ทุก server ต้องมี เป็นตัวบอกว่า "เครื่องจะล่มเมื่อไร":

Application Metrics (RED Method)

RED Method (Rate, Errors, Duration) คือ metrics ที่วัดจากมุมผู้ใช้ — request มาเท่าไร? error กี่ %? ตอบช้าแค่ไหน? สำคัญกว่า system metrics เพราะบอกได้ว่า "user experience ดีไหม":

Business Metrics

Business metrics เชื่อม technical data กับ business impact — ยอดสั่งซื้อต่อนาที, signup rate, cart abandonment rate ช่วยตอบคำถามเช่น "ระบบช้าขึ้น 200ms ส่งผลกระทบต่อยอดขายไหม?":

💡 RED Method: ใช้กับ services (Rate, Errors, Duration)
USE Method: ใช้กับ resources (Utilization, Saturation, Errors)

Prometheus + Grafana — Metrics Stack ยอดนิยม

Prometheus เป็น metrics database (TSDB) ที่เก็บข้อมูลแบบ time-series — ใช้ "pull model" คือ Prometheus ดึงข้อมูลจาก targets (servers, apps) ทุก 15 วินาที ส่วน Grafana เป็น dashboard tool ที่แสดง metrics เป็นกราฟสวยๆ ทั้งคู่เป็น open-source, CNCF graduated projects, และเป็น industry standard:

🎯 App
expose /metrics
📦 Prometheus
scrape + store
📊 Grafana
visualize + alert

ตั้งค่า Prometheus

ไฟล์ prometheus.yml:

global:
  scrape_interval: 15s        # ดึง metrics ทุก 15 วินาที

scrape_configs:
  # Monitor ตัว Prometheus เอง
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # Monitor Node (เครื่อง server)
  - job_name: 'node'
    static_configs:
      - targets:
        - 'server1:9100'
        - 'server2:9100'
        - 'server3:9100'

  # Monitor App
  - job_name: 'myapp'
    metrics_path: '/metrics'
    static_configs:
      - targets: ['app:3000']

Docker Compose สำหรับ Monitoring Stack

Setup monitoring stack ได้ง่ายด้วย Docker Compose — Prometheus + Grafana + Node Exporter (system metrics) + cAdvisor (container metrics) พร้อมใช้งานในไม่กี่นาที:

version: '3.8'
services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3001:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=secret
    volumes:
      - grafana_data:/var/lib/grafana

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro

volumes:
  prometheus_data:
  grafana_data:
# รัน monitoring stack
docker compose up -d

# เข้า Prometheus: http://localhost:9090
# เข้า Grafana:    http://localhost:3001 (admin/secret)

PromQL — Query ข้อมูลจาก Prometheus

PromQL คือ query language ของ Prometheus — ใช้คำนวณ metrics ที่ต้องการ เช่น error rate ใน 5 นาที, 95th percentile latency, CPU usage เฉลี่ย เรียนรู้ PromQL เป็นทักษะสำคัญสำหรับ DevOps:

# CPU usage เฉลี่ย 5 นาที
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# Request rate ต่อวินาที
rate(http_requests_total[5m])

# Error rate (%)
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100

# 95th percentile response time
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))

# Memory usage (%)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

Pillar 2: Logs — บันทึกเหตุการณ์

Logs คือบันทึกเหตุการณ์ที่เกิดขึ้นในระบบ — "user X login สำเร็จ", "payment failed: insufficient funds", "database connection timeout" Metrics บอกว่า "มีปัญหา" แต่ Logs บอกว่า "เกิดอะไรขึ้นจริงๆ" สำคัญมากตอน debug

Structured Logging — ดีกว่า plain text!

แทนที่จะ log แบบ plain text ("User john logged in") ให้ใช้ structured logging (JSON format) — ทำให้ search, filter, aggregate ได้ง่าย ถามว่า "error ทั้งหมดของ user X ใน 1 ชั่วโมงที่แล้ว" ตอบได้ทันที:

// ❌ Bad — ยากต่อการ parse
console.log("User login failed for user123");

// ✅ Good — structured JSON
logger.error({
  event: "login_failed",
  userId: "user123",
  reason: "invalid_password",
  ip: "203.0.113.50",
  timestamp: "2026-03-07T09:00:00Z"
});

Log Levels

Log levels ช่วยแยกความสำคัญ — production ควร log แค่ INFO ขึ้นไป (ไม่ต้อง DEBUG เพราะ volume สูงมาก) เมื่อมีปัญหาค่อยเปิด DEBUG ชั่วคราว:

Level ใช้เมื่อ ตัวอย่าง
ERROR เกิดข้อผิดพลาดจริง Database connection failed
WARN อาจมีปัญหาในอนาคต Disk usage > 80%
INFO เหตุการณ์ปกติที่สำคัญ Server started on port 3000
DEBUG รายละเอียดสำหรับ debug Query result: 42 rows

ELK Stack — Centralized Logging

เมื่อมีหลาย servers/containers การ SSH เข้าไปดู log ทีละเครื่องไม่ work — ต้องมี centralized logging ที่รวม logs ทั้งหมดมาที่เดียว ELK Stack (Elasticsearch + Logstash + Kibana) เป็น solution ยอดนิยม:

📱 Apps
ส่ง logs
🚛 Logstash
collect + transform
🔍 Elasticsearch
store + search
📊 Kibana
visualize + explore

ทางเลือกที่เบากว่า: Loki + Promtail + Grafana (ใช้ Grafana เดิมได้เลย!)

# Loki + Promtail Docker Compose
services:
  loki:
    image: grafana/loki:latest
    ports:
      - "3100:3100"

  promtail:
    image: grafana/promtail:latest
    volumes:
      - /var/log:/var/log:ro
      - ./promtail.yml:/etc/promtail/config.yml

Pillar 3: Traces — ติดตาม Request

เมื่อ 1 request ต้องผ่านหลาย services (microservices) เราจะรู้ได้ยังไงว่า ช้าตรงไหน?

🌐 API Gateway
2ms
👤 User Service
15ms
💳 Payment Service
850ms ⚠️
📧 Email Service
45ms

Trace ช่วยให้เห็นว่า Payment Service ใช้เวลา 850ms — นั่นคือ bottleneck!

เครื่องมือ Tracing

เครื่องมือ tracing หลักๆ — Jaeger (CNCF, open-source, ใช้กับ Kubernetes ดี), Zipkin (โดย Twitter, lightweight), OpenTelemetry (มาตรฐานใหม่ที่รวม metrics+logs+traces เป็น vendor-neutral SDK):

// OpenTelemetry ตัวอย่าง (Node.js)
const { trace } = require('@opentelemetry/api');

const tracer = trace.getTracer('my-service');

app.get('/api/checkout', async (req, res) => {
  const span = tracer.startSpan('checkout');

  try {
    // แต่ละขั้นตอนมี child span
    const userSpan = tracer.startSpan('get-user', { parent: span });
    const user = await getUser(req.userId);
    userSpan.end();

    const paySpan = tracer.startSpan('process-payment', { parent: span });
    await processPayment(user, req.amount);
    paySpan.end();

    res.json({ status: 'success' });
  } catch (err) {
    span.setStatus({ code: 2, message: err.message });
    res.status(500).json({ error: err.message });
  } finally {
    span.end();
  }
});

Alerting — แจ้งเตือนก่อนพัง

Dashboard สวยแค่ไหนก็ไม่ช่วย ถ้าไม่มีใครดู — ต้องมี Alert!

Alert Rules (Prometheus)

Alert rules กำหนดว่า "เมื่อ condition X เป็นจริงนาน Y นาที → แจ้งเตือน" สิ่งสำคัญคือ for duration ป้องกัน false alarms จาก spikes ชั่วคราว และ labels/annotations ช่วยให้ on-call team เข้าใจปัญหาเร็ว:

# alert-rules.yml
groups:
  - name: critical
    rules:
      # Server down
      - alert: InstanceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "{{ $labels.instance }} is down!"

      # CPU สูงเกิน 90% นาน 5 นาที
      - alert: HighCPU
        expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU > 90% on {{ $labels.instance }}"

      # Error rate สูงเกิน 5%
      - alert: HighErrorRate
        expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100 > 5
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "Error rate > 5% on {{ $labels.job }}"

      # Disk เหลือน้อยกว่า 10%
      - alert: DiskSpaceLow
        expr: (node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100 < 10
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Disk < 10% on {{ $labels.instance }}"

Alert ส่งไปไหน? (Alertmanager)

Alertmanager รับ alerts จาก Prometheus แล้วส่งต่อไปยัง channels ที่เหมาะสม — Slack, PagerDuty, email, webhook รองรับ grouping (รวม alerts เดียวกัน), silencing (ปิดเสียงชั่วคราว), และ routing (critical → PagerDuty, warning → Slack):

# alertmanager.yml
route:
  receiver: 'team-slack'
  routes:
    - match:
        severity: critical
      receiver: 'pagerduty'     # Critical → ปลุกคนมาแก้!
    - match:
        severity: warning
      receiver: 'team-slack'    # Warning → แจ้งใน Slack

receivers:
  - name: 'team-slack'
    slack_configs:
      - api_url: 'https://hooks.slack.com/services/xxx'
        channel: '#alerts'
        title: '🚨 {{ .GroupLabels.alertname }}'
        text: '{{ .CommonAnnotations.summary }}'

  - name: 'pagerduty'
    pagerduty_configs:
      - service_key: 'your-pagerduty-key'
🐕 Alert Fatigue: อย่าตั้ง alert ทุกอย่าง! ถ้าแจ้งเตือนเยอะเกิน คนจะเพิกเฉย → Critical = ต้อง action ทันที | Warning = ดูภายในวัน | Info = ดูเมื่อว่าง

Monitoring Stack ยอดนิยม

มี monitoring tools มากมาย — ตารางด้านล่างเปรียบเทียบ stack ยอดนิยมทั้ง open-source และ commercial ช่วยเลือกตามความต้องการ (budget, scale, complexity):

Stack ส่วนประกอบ จุดเด่น
PLG Prometheus + Loki + Grafana Open-source, K8s friendly, ครบ 3 pillars
ELK Elasticsearch + Logstash + Kibana Log search ดีมาก, enterprise
TIG Telegraf + InfluxDB + Grafana IoT/time-series ดี
Datadog All-in-one SaaS ง่ายสุด แต่แพง
New Relic All-in-one SaaS APM ดี, free tier

4 Golden Signals (Google SRE)

4 Golden Signals จาก Google SRE Book — ถ้า monitor ได้แค่ 4 อย่าง ให้เลือก 4 ตัวนี้ ครอบคลุม user experience ทั้งหมด Latency บอกประสบการณ์, Traffic บอก demand, Errors บอกคุณภาพ, Saturation บอกขีดจำกัด:

  1. Latency — ใช้เวลาตอบนานแค่ไหน? (p50, p95, p99)
  2. Traffic — มี request เข้ามากี่ครั้ง/วินาที?
  3. Errors — กี่ % ที่ error? (HTTP 5xx)
  4. Saturation — ระบบเต็มแค่ไหน? (CPU, memory, disk, queue)
💡 SLO Tip: กำหนด SLO (Service Level Objective) เช่น "99.9% uptime" หรือ "p95 latency < 200ms" แล้ว monitor ว่าทำได้จริงมั้ย — อันนี้คือ SLI (Service Level Indicator)

สรุป

Monitoring & Observability เป็นสิ่งที่ต้องมี ไม่ใช่ "มีก็ดี" — ถ้าไม่มี ก็เหมือนขับรถโดยไม่มี dashboard ไม่รู้ว่าน้ำมันจะหมดเมื่อไร เครื่องยนต์ร้อนแค่ไหน เริ่มจาก metrics + alerting ก่อน (Prometheus + Grafana) แล้วเพิ่ม logs และ traces เมื่อระบบซับซ้อนขึ้น:

บทความจากซีรีส์ DevOps & Vibe Coding 2026
← Previous
Infrastructure as Code — จัดการ Server ด้วย Terraform & Ansible
Next →
Linux Command Line — คำสั่งพื้นฐานที่ DevOps ต้องรู้