Workshop: Cost Optimization โดย Monitor Resource Usage บน Cloud VPS

ค่าใช้จ่ายของ Cloud Infrastructure มักสูงเกินจำเป็นเพราะการตั้ง resource เกินกว่าที่ใช้งานจริง (over-provisioning) หรือปล่อยให้ server/disk/bandwidth ที่ไม่ได้ใช้ทำงานเปล่า ๆ การทำ Cost Optimization ด้วยการ Monitor Resource Usage อย่างเป็นระบบช่วยให้ทีมสามารถปรับขนาด VPS ให้เหมาะกับ workload จริง ลดค่าใช้จ่ายได้ 20-50% โดยไม่กระทบ performance

Workshop นี้จะสอนการตั้ง monitoring stack ที่เน้น cost optimization บน Cloud VPS ตั้งแต่การเก็บ metric การใช้ CPU/RAM/Disk/Network, การคำนวณ right-sizing, การหา idle resources, จนถึงการสร้าง dashboard ที่ตอบโจทย์ทีม finance และ DevOps

ทำไม Cost Optimization ถึงสำคัญ

ในหลายองค์กร ค่าใช้จ่าย Cloud เป็นค่าใช้จ่ายอันดับต้น ๆ ของฝ่าย IT การขาดข้อมูลเรื่อง resource usage ทำให้ทีมเลือกแผน VPS ใหญ่เกินจำเป็น “เผื่อไว้” โดยไม่รู้ว่าจริง ๆ ใช้แค่ 20% ของที่ซื้อมา เมื่อมีระบบ monitor ที่ดีจะเห็นได้ทันทีว่าเครื่องใด over-provisioned และสามารถย่อแผนลง (downsize) ได้โดยไม่เสี่ยง

4 Dimension ของ Resource Cost

  • CPU: ค่าใช้จ่ายหลัก — ควร utilization เฉลี่ย 40-70% (ต่ำกว่า 20% = over-provisioned, สูงกว่า 85% = เสี่ยง)
  • Memory (RAM): ถ้าใช้ประจำต่ำกว่า 50% แสดงว่าใหญ่เกินไป
  • Disk: SSD/NVMe ค่าใช้จ่ายสูง — ต้องรู้ว่าเต็มจริงหรือแค่จอง
  • Network (Bandwidth/Egress): มักเป็น hidden cost — traffic ออกต่างภูมิภาคแพงกว่าใน region เดียวกัน

Step 1: ติดตั้ง node_exporter เก็บ Resource Metrics

เริ่มจากติดตั้ง Prometheus node_exporter บน VPS ทุกเครื่องเพื่อเก็บ metric พื้นฐาน:

wget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gz
tar xvf node_exporter-1.7.0.linux-amd64.tar.gz
sudo mv node_exporter-1.7.0.linux-amd64/node_exporter /usr/local/bin/

sudo tee /etc/systemd/system/node_exporter.service <<EOF
[Unit]
Description=Node Exporter
After=network.target

[Service]
User=prometheus
ExecStart=/usr/local/bin/node_exporter

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter

Step 2: PromQL สำหรับตรวจ Right-Sizing

Query เหล่านี้ช่วยระบุเครื่องที่ over-provisioned (ซื้อใหญ่เกินไป) โดยดู P95 ย้อนหลัง 7 วัน:

# CPU usage P95 ต่อเครื่อง (7 วัน)
quantile_over_time(0.95,
  (1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])))[7d:5m]
)

# Memory usage P95 ต่อเครื่อง (7 วัน)
quantile_over_time(0.95,
  (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)[7d:5m]
)

# เครื่องที่ CPU P95 ต่ำกว่า 25% = over-provisioned
(
  quantile_over_time(0.95,
    (1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])))[7d:5m]
  )
) < 0.25

# Disk space ที่จองไว้แต่ใช้ไม่ถึง 40%
(node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes < 0.4

Step 3: หา Idle / Zombie Servers

เครื่องที่ยังเปิดอยู่แต่ไม่มี traffic เข้าเลย = “zombie” ต้องสอบถามทีมและปิดถ้าไม่จำเป็น query ต่อไปนี้หา VPS ที่ network activity ต่ำมากใน 24 ชั่วโมงที่ผ่านมา:

# Network traffic เฉลี่ย 24 ชม. (bytes/sec) ต่ำกว่า 10KB/s
avg_over_time(
  rate(node_network_receive_bytes_total{device!~"lo|veth.*"}[5m])[24h:5m]
) < 10240

# Zero load (LoadAvg 1min เฉลี่ย < 0.05) นาน 6 ชม.
avg_over_time(node_load1[6h]) < 0.05

Step 4: สร้าง Grafana Dashboard สำหรับ Cost Review

Dashboard นี้ทีมควรนั่งดูอย่างน้อยเดือนละครั้ง เพื่อหา server ที่ควร downsize หรือปิด มี panel หลัก 5 ตัว:

  • Top 10 Over-Provisioned: ตาราง CPU P95 < 25%
  • Memory Waste: เครื่องที่ใช้ RAM < 50% ต่อเนื่อง
  • Idle Detection: เครื่องที่ network และ load ต่ำมาก
  • Disk Usage %: ดูว่าเครื่องใดยังใช้ disk ต่ำ < 40%
  • Cost Projection: คำนวณการประหยัดถ้า downsize ทั้งหมด

Step 5: Alert สำหรับ Unused Resources

ตั้ง alert ให้ Prometheus เตือนเมื่อพบ resource ที่ไม่ถูกใช้เกิน 7 วันติดต่อกัน:

groups:
  - name: cost-optimization
    rules:
      - alert: OverProvisionedCPU
        expr: |
          quantile_over_time(0.95,
            (1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])))[7d:5m]
          ) < 0.20
        for: 24h
        labels:
          severity: info
          category: cost
        annotations:
          summary: "{{ $labels.instance }} CPU P95 < 20% ติดต่อกัน 7 วัน"
          action: "พิจารณา downsize"

      - alert: IdleServer
        expr: |
          avg_over_time(rate(node_network_receive_bytes_total[5m])[24h:5m]) < 10240
          and avg_over_time(node_load1[6h]) < 0.05
        for: 12h
        labels:
          severity: info
          category: cost
        annotations:
          summary: "{{ $labels.instance }} ไม่มี activity เกิน 12 ชม."

      - alert: UnusedDiskSpace
        expr: |
          (node_filesystem_size_bytes - node_filesystem_used_bytes) / node_filesystem_size_bytes > 0.65
        for: 7d
        labels:
          severity: info
          category: cost
        annotations:
          summary: "{{ $labels.instance }}:{{ $labels.mountpoint }} ใช้ disk ต่ำกว่า 35%"

Step 6: Right-Sizing Decision Framework

เมื่อมีข้อมูลครบแล้ว ให้ใช้ decision table นี้ในการพิจารณาว่าควร downsize หรือไม่:

CPU P95RAM P95Networkคำแนะนำ
< 20%< 50%ต่ำDownsize 2 tier
20-40%< 60%ปกติDownsize 1 tier
40-70%50-75%ปกติเหมาะสมแล้ว
> 70%> 75%สูงUpsize หรือ scale out

Step 7: Automation — Scheduled Right-Sizing Report

สร้าง script Python ที่ดึงข้อมูลจาก Prometheus API และสร้างรายงานอัตโนมัติส่งเข้า Slack ทุกวันจันทร์:

import requests
from datetime import datetime

PROM = "http://prometheus:9090"

def query(q):
    r = requests.get(f"{PROM}/api/v1/query", params={"query": q})
    return r.json()["data"]["result"]

over_cpu = query(
  'quantile_over_time(0.95, '
  '(1 - avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])))[7d:5m]) < 0.25'
)

report = [f"Cost Review — {datetime.now():%Y-%m-%d}"]
report.append(f"\n* Over-provisioned CPU: {len(over_cpu)} เครื่อง")
for m in over_cpu[:10]:
    cpu_pct = float(m["value"][1]) * 100
    report.append(f"  - {m['metric']['instance']} CPU P95 = {cpu_pct:.1f}%")

# ส่งเข้า Slack
requests.post(
    "https://hooks.slack.com/services/XXX/YYY/ZZZ",
    json={"text": "\n".join(report)}
)

Best Practices เพิ่มเติม

  • Tag ทุก VPS: ใส่ label เช่น env=prod/staging, team=backend, project=X เพื่อหา cost center ได้ถูก
  • Review monthly: จัด cost review ทุกเดือนก่อนขึ้นบิล
  • Auto-shutdown non-prod: ปิด staging/dev ตอนกลางคืนและวันหยุดประหยัดได้ 40-60%
  • Retention policy: เก็บ metric ย้อนหลัง 30-90 วันเพื่อดู trend ตามฤดู
  • Budget Alert: ตั้ง alert เมื่อค่าใช้จ่ายเดือนแตะ 80% ของ budget

ข้อควรระวัง

ก่อน downsize ต้องดูข้อมูลย้อนหลังอย่างน้อย 7 วัน เพื่อคลุม workload pattern ทั้งสัปดาห์ บาง service มี burst ช่วงเช้า-เย็น หรือ load สูงในช่วง month-end การดูแค่ 24 ชั่วโมงอาจทำให้ย่อผิดขนาดและกระทบ production

สรุป

Cost Optimization ผ่าน Resource Monitoring ไม่ใช่กิจกรรมครั้งเดียว แต่เป็นกระบวนการต่อเนื่องที่ต้องใช้ข้อมูลในการตัดสินใจ การมี Prometheus + Grafana dashboard ที่ตอบโจทย์ cost และ automation ที่ส่งรายงานสม่ำเสมอจะทำให้ทีมสามารถปรับขนาด resource ได้อย่างมีประสิทธิภาพ ลดค่าใช้จ่ายโดยไม่กระทบ uptime

สิ่งสำคัญคือการสร้าง culture ที่ทีมทุกคน (dev, ops, finance) เห็นข้อมูล cost เดียวกัน และมี review cadence ที่แน่นอน เพื่อไม่ให้ค่าใช้จ่าย cloud บานปลายโดยไม่รู้ตัว