Home > Blog > tech

Kubernetes Cost Optimization คืออะไร? ลดค่าใช้จ่าย K8s Cluster โดยไม่กระทบ Performance 2026

kubernetes cost optimization guide
Kubernetes Cost Optimization Guide 2026
2026-04-10 | tech | 3500 words

Kubernetes กลายเป็นมาตรฐานสำหรับ Container Orchestration ในปี 2026 องค์กรจำนวนมากย้ายระบบมาอยู่บน Kubernetes ทั้งบน Cloud (EKS, GKE, AKS) และ On-premise แต่ปัญหาใหญ่ที่หลายทีมพบเจอคือ ค่าใช้จ่ายที่พุ่งสูงขึ้นอย่างควบคุมไม่ได้ จากผลสำรวจพบว่าองค์กรส่วนใหญ่ใช้ทรัพยากร Kubernetes จริงๆ แค่ 30-50% ของที่จ่ายไป ที่เหลือเป็นการสูญเปล่า

บทความนี้จะสอนเทคนิคการลดค่าใช้จ่าย Kubernetes แบบครบวงจร ตั้งแต่การ Right-sizing Pods, Autoscaling, Spot Nodes ไปจนถึง FinOps Practices ที่ช่วยให้คุณลดค่าใช้จ่ายลงได้ 40-70% โดยไม่กระทบ Performance และ Reliability

ทำไมค่าใช้จ่าย Kubernetes ถึงสูงเกินจริง?

มีหลายสาเหตุที่ทำให้ค่าใช้จ่าย K8s พุ่งสูงเกินความจำเป็น:

1. Over-provisioning

Developer มักตั้ง Resource Requests สูงเกินจริง เพราะกลัว Application จะไม่เสถียร เช่น Application ใช้ CPU จริงแค่ 100m แต่ Request ไว้ 500m หรือใช้ Memory จริง 256Mi แต่ Request ไว้ 1Gi ทรัพยากรที่ Request ไว้แต่ไม่ได้ใช้ก็ยังต้องจ่ายเงิน เพราะ Kubernetes จะจองไว้ให้ Pod นั้น

2. Idle Resources

หลาย Application มี Traffic Pattern แบบ Peaks and Valleys เช่น ใช้งานมากตอนกลางวัน แต่แทบไม่มีใครใช้ตอนกลางคืนหรือวันหยุด ถ้าไม่มี Autoscaling ทรัพยากรจะถูกจองไว้ตลอด 24 ชั่วโมง

3. No Resource Limits

Pod ที่ไม่ตั้ง Resource Limits สามารถกิน CPU และ Memory ได้ไม่จำกัด ทำให้ Node ต้องใหญ่กว่าที่ควร และอาจกระทบ Pod อื่นบน Node เดียวกัน

4. Over-sized Nodes

การเลือก Node Type ที่ใหญ่เกินไป เช่น ใช้ m5.4xlarge (16 vCPU, 64GB RAM) ทั้งที่ Workload ต้องการแค่ m5.xlarge (4 vCPU, 16GB RAM) ก็ทำให้เสียเงินโดยไม่จำเป็น

Resource Requests vs Limits: พื้นฐานที่ต้องเข้าใจ

หัวใจของ K8s Cost Optimization คือการเข้าใจ Resource Requests และ Limits:

apiVersion: v1
kind: Pod
metadata:
  name: my-app
spec:
  containers:
  - name: app
    image: my-app:latest
    resources:
      requests:        # ขั้นต่ำที่ต้องการ (Scheduler ใช้ตัดสินใจ)
        cpu: "100m"    # 100 milliCPU = 0.1 CPU
        memory: "256Mi"
      limits:          # สูงสุดที่อนุญาต
        cpu: "500m"
        memory: "512Mi"
Parameterหน้าที่ถ้าไม่ตั้ง
requests.cpuCPU ขั้นต่ำที่ Scheduler จะจองไว้ไม่จอง (Best-effort)
requests.memoryMemory ขั้นต่ำที่ Scheduler จะจองไว้ไม่จอง (เสี่ยง OOMKilled)
limits.cpuCPU สูงสุด (Throttle เมื่อเกิน)ใช้ได้ไม่จำกัด
limits.memoryMemory สูงสุด (OOMKilled เมื่อเกิน)ใช้ได้ไม่จำกัด
กฎ Right-sizing: ตั้ง Request ให้ตรงกับ P95 ของการใช้งานจริง (ดูจาก Monitoring 7-14 วัน) และตั้ง Limit ไว้ 1.5-2 เท่าของ Request เพื่อรองรับ Burst

Vertical Pod Autoscaler (VPA)

VPA ช่วยปรับ Resource Requests/Limits ของ Pod อัตโนมัติตามการใช้งานจริง แทนที่คุณจะต้องมานั่งดู Monitoring แล้วปรับเอง VPA จะทำให้อัตโนมัติ:

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: my-app-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  updatePolicy:
    updateMode: "Auto"    # Auto, Recreate, Off
  resourcePolicy:
    containerPolicies:
    - containerName: app
      minAllowed:
        cpu: "50m"
        memory: "128Mi"
      maxAllowed:
        cpu: "2000m"
        memory: "4Gi"
      controlledResources: ["cpu", "memory"]

VPA มี 3 โหมดการทำงาน:

Horizontal Pod Autoscaler (HPA)

HPA เพิ่ม/ลดจำนวน Pod ตามโหลด ช่วยให้ใช้ทรัพยากรตรงกับ Traffic จริง:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70    # Scale เมื่อ CPU > 70%
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300   # รอ 5 นาทีก่อน Scale Down
      policies:
      - type: Percent
        value: 10
        periodSeconds: 60    # ลดได้ไม่เกิน 10% ต่อนาที
    scaleUp:
      stabilizationWindowSeconds: 30
      policies:
      - type: Percent
        value: 100
        periodSeconds: 60    # เพิ่มได้ 100% ต่อนาที
เคล็ดลับ HPA: ตั้ง Scale Down ให้ช้ากว่า Scale Up เสมอ เพื่อป้องกัน Flapping (Scale ขึ้นลงรัวๆ) และตั้ง minReplicas อย่างน้อย 2 สำหรับ Production Workload

KEDA: Event-Driven Autoscaling

KEDA (Kubernetes Event-Driven Autoscaling) ขยายความสามารถของ HPA ให้ Scale ได้ตาม Event Sources ที่หลากหลาย ไม่ใช่แค่ CPU/Memory:

# ติดตั้ง KEDA
helm repo add kedacore https://kedacore.github.io/charts
helm install keda kedacore/keda --namespace keda-system

---
# ScaledObject: Scale ตามจำนวน Messages ใน Queue
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: order-processor
spec:
  scaleTargetRef:
    name: order-processor
  minReplicaCount: 0       # Scale to Zero ได้!
  maxReplicaCount: 50
  triggers:
  - type: rabbitmq
    metadata:
      queueName: orders
      host: amqp://rabbitmq.default.svc
      queueLength: "10"    # 1 Pod ต่อ 10 messages

  - type: prometheus        # Scale ตาม Custom Metrics
    metadata:
      serverAddress: http://prometheus:9090
      metricName: http_requests_total
      threshold: "100"
      query: sum(rate(http_requests_total[2m]))

KEDA สามารถ Scale to Zero ได้ ซึ่งเป็นสิ่งที่ HPA ปกติทำไม่ได้ ทำให้ Workload ที่ไม่มีงาน (เช่น Queue Worker ที่ Queue ว่าง) จะไม่ใช้ทรัพยากรเลย ประหยัดค่าใช้จ่ายได้อย่างมาก

Cluster Autoscaler

Cluster Autoscaler ทำงานระดับ Node โดยจะเพิ่ม/ลด Node ตามความต้องการ:

# ติดตั้งบน AWS EKS
helm install cluster-autoscaler autoscaler/cluster-autoscaler \
  --set autoDiscovery.clusterName=my-cluster \
  --set awsRegion=ap-southeast-1 \
  --set extraArgs.scale-down-delay-after-add=10m \
  --set extraArgs.scale-down-unneeded-time=10m \
  --set extraArgs.skip-nodes-with-local-storage=false

Cluster Autoscaler จะเพิ่ม Node เมื่อมี Pod ที่ Pending (ไม่มี Node ว่างพอ) และลด Node เมื่อ Node มี Utilization ต่ำกว่า Threshold (ปกติ 50%) โดยจะย้าย Pod ไป Node อื่นก่อนลบ Node

Karpenter: ทางเลือกที่ฉลาดกว่า

Karpenter เป็น Node Provisioner จาก AWS ที่ทำงานเร็วกว่า Cluster Autoscaler มาก (30 วินาที vs หลายนาที) และฉลาดกว่าในการเลือก Node Type ที่เหมาะสม:

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  template:
    spec:
      requirements:
      - key: "karpenter.sh/capacity-type"
        operator: In
        values: ["on-demand", "spot"]    # ใช้ Spot ได้
      - key: "node.kubernetes.io/instance-type"
        operator: In
        values: ["m5.large", "m5.xlarge", "m6i.large", "c5.large"]
      - key: "topology.kubernetes.io/zone"
        operator: In
        values: ["ap-southeast-1a", "ap-southeast-1b"]
  limits:
    cpu: "100"
    memory: "400Gi"
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 30s

Spot/Preemptible Nodes: ประหยัดได้ 60-90%

Spot Instances (AWS) หรือ Preemptible VMs (GCP) มีราคาถูกกว่า On-demand 60-90% แต่อาจถูกเรียกคืนได้ทุกเมื่อ สำหรับ Kubernetes ถ้าจัดการให้ดี Spot Nodes ปลอดภัยมาก:

แยก Node Pool

# On-demand Node Pool สำหรับ Critical Workloads
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
managedNodeGroups:
  - name: on-demand-critical
    instanceType: m5.xlarge
    minSize: 2
    maxSize: 5
    labels:
      workload-type: critical

  # Spot Node Pool สำหรับ Non-critical Workloads
  - name: spot-general
    instanceTypes: ["m5.large", "m5.xlarge", "m6i.large", "c5.large"]
    spot: true
    minSize: 0
    maxSize: 20
    labels:
      workload-type: general

ใช้ Node Affinity + Tolerations

apiVersion: apps/v1
kind: Deployment
metadata:
  name: batch-processor
spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: workload-type
                operator: In
                values: ["general"]
      tolerations:
      - key: "spot"
        operator: "Equal"
        value: "true"
        effect: "NoSchedule"

Pod Disruption Budget (PDB)

# ป้องกันไม่ให้ Spot Eviction ทำให้ Service ล่ม
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 2        # ต้องมี Pod ทำงานอยู่อย่างน้อย 2 ตัวเสมอ
  selector:
    matchLabels:
      app: my-app
แนวทาง Spot ที่ปลอดภัย: ใช้ Spot สำหรับ Stateless Workloads ที่ทนต่อ Interruption ได้ เช่น Web Servers, Queue Workers, Batch Jobs ส่วน Database, StatefulSet หรือ Single-point-of-failure ให้ใช้ On-demand เสมอ

Namespace Resource Quotas และ LimitRanges

ป้องกันไม่ให้ทีมใดทีมหนึ่งใช้ทรัพยากรเกินกว่าที่ควร:

# ResourceQuota: จำกัดทรัพยากรรวมของ Namespace
apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-alpha-quota
  namespace: team-alpha
spec:
  hard:
    requests.cpu: "10"          # รวม CPU Request ไม่เกิน 10 cores
    requests.memory: "20Gi"     # รวม Memory Request ไม่เกิน 20GB
    limits.cpu: "20"
    limits.memory: "40Gi"
    pods: "50"                  # จำนวน Pod ไม่เกิน 50

---
# LimitRange: กำหนดค่า Default สำหรับ Pod ที่ไม่ได้ตั้ง
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: team-alpha
spec:
  limits:
  - default:                    # Default Limits
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:             # Default Requests
      cpu: "100m"
      memory: "128Mi"
    max:                        # Maximum ที่ตั้งได้
      cpu: "4"
      memory: "8Gi"
    min:                        # Minimum ที่ต้องตั้ง
      cpu: "50m"
      memory: "64Mi"
    type: Container

LimitRange สำคัญมาก เพราะถ้า Pod ไหนไม่ได้ตั้ง Resources มันจะใช้ค่า Default ที่คุณกำหนด ป้องกันไม่ให้มี Pod ที่กิน Resource ไม่จำกัด

Cost Monitoring Tools

Kubecost

Kubecost เป็นเครื่องมือ Open Source ที่แสดงค่าใช้จ่ายของ K8s แบบ Real-time แยกตาม Namespace, Deployment, Pod, Label หรือ Team:

# ติดตั้ง Kubecost
helm install kubecost cost-analyzer \
  --repo https://kubecost.github.io/cost-analyzer/ \
  --namespace kubecost --create-namespace \
  --set kubecostToken="YOUR_TOKEN"

# เข้าถึง Dashboard
kubectl port-forward -n kubecost svc/kubecost-cost-analyzer 9090:9090

Kubecost ให้ข้อมูลที่สำคัญ เช่น ค่าใช้จ่ายต่อ Namespace ต่อวัน ทรัพยากรที่ใช้จริง vs ที่ Request ไว้ คำแนะนำ Right-sizing และ Savings Potential ถ้าปรับตามคำแนะนำ

OpenCost

OpenCost เป็นโปรเจกต์ CNCF ที่เป็น Open Source ทั้งหมด ทำงานคล้าย Kubecost แต่ไม่มี Commercial License:

# ติดตั้ง OpenCost
helm install opencost opencost/opencost \
  --namespace opencost --create-namespace

CloudHealth / Spot.io / Datadog Cost Management

สำหรับองค์กรขนาดใหญ่ที่ต้องการ Enterprise Features เช่น Multi-cloud Cost Visibility, Chargeback/Showback, Budget Alerts และ Anomaly Detection เครื่องมือเหล่านี้มี Features ครบกว่า แต่มีค่าใช้จ่ายเพิ่ม

Right-sizing Tools

Goldilocks

Goldilocks จาก Fairwind ช่วย Visualize คำแนะนำ Right-sizing จาก VPA:

# ติดตั้ง Goldilocks
helm install goldilocks fairwinds-stable/goldilocks \
  --namespace goldilocks --create-namespace

# เปิดใช้งานสำหรับ Namespace ที่ต้องการ
kubectl label namespace my-app goldilocks.fairwinds.com/enabled=true

# เข้า Dashboard
kubectl port-forward -n goldilocks svc/goldilocks-dashboard 8080:80

Goldilocks จะสร้าง VPA แบบ Recommendation Mode สำหรับทุก Deployment ใน Namespace ที่ Label ไว้ แล้วแสดงคำแนะนำว่าควรตั้ง Requests/Limits เท่าไหร่ผ่าน Web Dashboard ที่อ่านง่าย

KRR (Kubernetes Resource Recommender)

KRR จาก Robusta เป็น CLI Tool ที่ดึงข้อมูลจาก Prometheus แล้วแนะนำ Right-sizing:

# ติดตั้ง
pip install krr

# Scan ทั้ง Cluster
krr simple

# ผลลัพธ์จะแสดง:
# Deployment     | CPU Req | CPU Rec | Memory Req | Memory Rec | Savings
# my-app         | 500m    | 120m    | 1Gi        | 280Mi      | $45/mo
# api-gateway    | 1000m   | 350m    | 2Gi        | 800Mi      | $78/mo

Multi-tenancy และ Cost Sharing

ในองค์กรที่มีหลายทีมใช้ K8s Cluster ร่วมกัน การแบ่งค่าใช้จ่ายเป็นเรื่องสำคัญ:

Chargeback vs Showback

# ใช้ Labels สำหรับ Cost Allocation
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels:
    team: "platform"
    environment: "production"
    cost-center: "CC-1234"
    project: "user-service"

การใช้ Labels อย่างเป็นระบบช่วยให้ Kubecost หรือ OpenCost สามารถ Aggregate ค่าใช้จ่ายตามทีม ตาม Project หรือตาม Cost Center ได้อัตโนมัติ

Bin-packing และ Cluster Consolidation

Bin-packing คือการจัด Pod ให้อยู่บน Node น้อยที่สุดเท่าที่จะเป็นไปได้ เพื่อลดจำนวน Node ที่ต้องจ่ายเงิน:

Descheduler

Kubernetes Scheduler จัด Pod ลง Node แค่ตอนสร้าง Pod ใหม่ ไม่ได้จัดใหม่เมื่อ Cluster เปลี่ยนแปลง Descheduler ช่วยย้าย Pod ไปรวมกันเพื่อ Consolidation:

apiVersion: descheduler/v1alpha2
kind: DeschedulerPolicy
profiles:
- name: consolidation
  pluginConfig:
  - name: LowNodeUtilization
    args:
      thresholds:
        cpu: 20        # Node ที่ใช้ CPU < 20% ถือว่า Underutilized
        memory: 20
      targetThresholds:
        cpu: 50        # ย้าย Pod ไปจนกว่า Node จะใช้ CPU 50%
        memory: 50
  - name: RemoveDuplicates    # ลบ Pod ซ้ำบน Node เดียวกัน
  plugins:
    balance:
      enabled:
      - LowNodeUtilization
      - RemoveDuplicates

Reserved Instances สำหรับ K8s Nodes

สำหรับ Workload ที่ต้องทำงานตลอด 24 ชั่วโมง (Baseline Capacity) การใช้ Reserved Instances ประหยัดได้มากกว่า On-demand:

ประเภทส่วนลดเหมาะกับ
On-demand0%ทดลอง, Burst Traffic
Spot/Preemptible60-90%Fault-tolerant Workloads
Reserved (1 ปี)30-40%Baseline ที่ใช้ตลอด
Reserved (3 ปี)50-60%Baseline ที่มั่นใจมาก
Savings Plans30-50%ยืดหยุ่นกว่า RI

กลยุทธ์ผสม

# แนวทาง 3-Tier Node Strategy
# 1. Reserved Instances: 40% ของ Capacity (Baseline)
#    - System Pods (kube-system, monitoring)
#    - Database, StatefulSets
#    - Critical Services ที่ต้องทำงานตลอด

# 2. On-demand: 20% ของ Capacity (Buffer)
#    - Critical Workloads ที่ทนต่อ Interruption ไม่ได้
#    - ช่วง Scale Up ก่อนที่ Spot จะพร้อม

# 3. Spot Instances: 40% ของ Capacity (Variable)
#    - Stateless Web Servers
#    - Queue Workers
#    - Batch Processing
#    - CI/CD Runners

FinOps สำหรับ Kubernetes

FinOps (Cloud Financial Operations) เป็นแนวปฏิบัติที่ช่วยให้ทีม Engineering, Finance และ Business ทำงานร่วมกันเพื่อจัดการค่าใช้จ่าย Cloud อย่างมีประสิทธิภาพ:

หลักการ FinOps สำหรับ K8s

  1. Visibility: ทุกคนต้องเห็นค่าใช้จ่ายของทีมตัวเอง (ใช้ Kubecost Dashboard)
  2. Optimization: มี Process Right-sizing เป็นประจำ (ทุกเดือน Review คำแนะนำ VPA)
  3. Governance: ตั้งกฎเกณฑ์ เช่น LimitRanges, ResourceQuotas, Budget Alerts
  4. Accountability: แต่ละทีมรับผิดชอบค่าใช้จ่ายของตัวเอง

Automation สำหรับ FinOps

# ตัวอย่าง: GitHub Actions สำหรับ Right-sizing Review รายเดือน
name: Monthly K8s Cost Review
on:
  schedule:
    - cron: '0 9 1 * *'    # วันที่ 1 ของทุกเดือน เวลา 9:00
jobs:
  cost-review:
    runs-on: ubuntu-latest
    steps:
    - name: Run KRR Scan
      run: |
        pip install krr
        krr simple --format json > krr-report.json

    - name: Generate Report
      run: |
        python generate_cost_report.py

    - name: Send to Slack
      uses: slackapi/slack-github-action@v2
      with:
        payload: |
          {"text": "Monthly K8s Cost Report is ready!"}

Checklist: ลดค่าใช้จ่าย K8s ทันที

เรียงตามผลกระทบจากมากไปน้อย:

  1. ติดตั้ง Cost Monitoring (Kubecost/OpenCost) เพื่อเห็นค่าใช้จ่ายจริง
  2. Right-size Pods ดู Usage จริงแล้วปรับ Requests/Limits ให้ตรง (ประหยัดได้ 20-40%)
  3. เปิด HPA สำหรับทุก Deployment ที่ Traffic ไม่คงที่ (ประหยัดได้ 10-30%)
  4. ใช้ Spot Nodes สำหรับ Stateless Workloads (ประหยัดได้ 40-70%)
  5. ตั้ง LimitRanges ทุก Namespace เพื่อป้องกัน Over-provisioning
  6. ใช้ Cluster Autoscaler/Karpenter เพื่อลด Node ที่ไม่ได้ใช้
  7. ซื้อ Reserved Instances สำหรับ Baseline Capacity
  8. ใช้ KEDA สำหรับ Event-driven Workloads ที่ Scale to Zero ได้
  9. ตั้ง ResourceQuotas สำหรับ Multi-tenant Clusters
  10. Review ค่าใช้จ่ายทุกเดือน เป็น FinOps Practice

สรุป

ค่าใช้จ่าย Kubernetes ไม่จำเป็นต้องสูงเกินจริง ด้วยเทคนิคที่กล่าวมาในบทความนี้ ตั้งแต่การ Right-sizing Pods ด้วย VPA และ Goldilocks การ Autoscaling ด้วย HPA และ KEDA การใช้ Spot Nodes อย่างปลอดภัย ไปจนถึงการสร้างวัฒนธรรม FinOps ในองค์กร คุณสามารถลดค่าใช้จ่ายลงได้ 40-70% โดยไม่กระทบ Performance และ Reliability ของระบบ

เริ่มต้นวันนี้ด้วยการติดตั้ง Kubecost หรือ OpenCost เพื่อเห็นค่าใช้จ่ายจริงของ Cluster ก่อน จากนั้นค่อยๆ ปรับ Right-sizing และเปิด Autoscaling ทีละส่วน ค่าใช้จ่ายที่ประหยัดได้จะทำให้ทั้งทีม Engineering และ Management มีความสุข


Back to Blog | iCafe Forex | SiamLanCard | Siam2R