Mengapa Thermal Throttling Menjadi Masalah di Kubernetes

Saat worker node mengalami lonjakan suhu ekstrem, CPU secara otomatis menurunkan clock frequency (dynamic frequency scaling via P-states/T-states) untuk mencegah kerusakan fisik komponen silikon. Di lingkungan Kubernetes bare-metal atau edge computing, fenomena thermal throttling ini memicu penurunan throughput dramatis, lonjakan p99 tail latency, hingga pod status flapping tanpa ada crash log eksplisit pada aplikasi.

Prinsip fisika komputasi berdensitas tinggi menunjukkan bahwa disipasi panas bukan sekadar isu fasilitas, melainkan batasan fundamental arsitektur sistem—analogi serupa dapat dilihat pada tantangan pelepasan panas radiatif di pusat data orbital (IEEE Spectrum: Orbital Data Centers), di mana penumpukan kalor tanpa media konveksi cepat melumpuhkan prosesor. Jika kluster tidak memiliki automasi berbasis metrik termal, scheduler Kubernetes akan terus menjadwalkan workload baru ke node yang performanya terdegradasi parah.

Arsitektur Observabilitas: Metrik Suhu dan Frekuensi CPU

Untuk mendeteksi gejala panas berlebih sebelum kegagalan hardware terjadi, sistem monitoring membutuhkan dua sumber telemetri:

  • Node Exporter: Membaca metrik thermal sysfs Linux melalui kolektor hwmon dan thermal_zone, serta mendeteksi pemangkasan core clock melalui metrik frekuensi CPU.
  • IPMI Exporter: Membaca sensor suhu onboard BMC (Baseboard Management Controller), kecepatan putaran kipas (RPM), dan status PSU out-of-band.

Metrik utama yang dipantau antara lain node_hwmon_temp_celsius dan node_cpu_scaling_frequency_hertz dibandingkan dengan node_cpu_scaling_max_freq_hertz. Jika rasio frekuensi aktual terhadap frekuensi maksimum anjlok di bawah nilai nominal secara terus-menerus sementara utilization 100%, node dipastikan mengalami throttling.

Konfigurasi Prometheus Alerting Rule

Berikut adalah manifest PrometheusRule untuk mendeteksi kondisi suhu kritis atau penurunan clock signifikan akibat power/thermal limit selama 2 menit berturut-turut.

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: hardware-thermal-alerts
  namespace: monitoring
  labels:
    role: alert-rules
spec:
  groups:
  - name: node-hardware.rules
    rules:
    - alert: NodeThermalThrottlingCritical
      expr: |
        (
          node_hwmon_temp_celsius{chip=~"coretemp.*|k10temp.*"} > 85
        ) or (
          (node_cpu_scaling_frequency_hertz / node_cpu_scaling_max_freq_hertz) < 0.65
          and on(instance, cpu) node_cpu_seconds_total{mode!="idle"} > 0
        )
      for: 2m
      labels:
        severity: critical
        action: cordon-drain
      annotations:
        summary: "Thermal throttling terdeteksi pada node {{ $labels.instance }}"
        description: "Temperatur inti CPU > 85C atau frekuensi scaling turun drastis di bawah 65% beban normal."

Otomasi Cordon & Drain: Script Webhook Handler

AlertManager mengirimkan webhook payload ke controller internal atau automasi serverless. Handler mengekstraksi nama node, melakukan cordon agar tidak ada pod baru dijadwalkan, lalu menjalankan drain secara terkontrol agar PodDisruptionBudget (PDB) tetap dihormati.

Alternatif lazier: Gunakan tool open-source kured atau Kubernetes Node Problem Detector bersama drain daemon yang sudah ada jika tidak ingin mengelola webhook custom.

#!/usr/bin/env bash
set -euo pipefail

# Membaca instance/node name dari payload JSON Alertmanager via stdin
NODE_IP=$(jq -r '.alerts[0].labels.instance' | cut -d':' -f1)
NODE_NAME=$(kubectl get nodes -o json | jq -r --arg IP "$NODE_IP" '.items[] | select(.status.addresses[] | .address == $IP) | .metadata.name')

if [[ -z "$NODE_NAME" || "$NODE_NAME" == "null" ]]; then
  echo "Error: Node tidak ditemukan untuk IP $NODE_IP" >&2
  exit 1
fi

echo "[Action] Mengisolasi node bermasalah termal: ${NODE_NAME}"
kubectl cordon "${NODE_NAME}"

echo "[Action] Menjalankan graceful drain dengan timeout 300s..."
kubectl drain "${NODE_NAME}" \
  --ignore-daemonsets \
  --delete-emptydir-data \
  --pod-selector='app.kubernetes.io/criticality!=infra' \
  --grace-period=60 \
  --timeout=300s

# ponytail: uncordon otomatis belum dihandle; pasang cron/remediation controller untuk uncordon saat temp < 65C
echo "Drain selesai. Node ${NODE_NAME} siap masuk maintenance/cooling down."

Strategi Failover ke Cadangan Dingin (Cold Spares)

Saat pod digusur dari node panas, scheduler harus mendistribusikannya ke node yang stabil tanpa memicu efek domino overheating pada node terdekat. Terapkan strategi berikut:

  • Node Taints & Tolerations: Siapkan standby node (cold spare) di zona/rak terpisah dengan taint reserve=cold-spare:NoSchedule. Automasi mengizinkan toleration injeksi ke pod prioritas tinggi saat cluster capacity menyusut.
  • Pod Anti-Affinity: Hindari penumpukan workload CPU-intensive pada satu physical chassis yang sama dengan aturan topologyKey: kubernetes.io/hostname.
  • Dynamic Cooling Window: Terapkan jeda minimum 15-30 menit setelah node mendingin sebelum mengeksekusi kubectl uncordon guna memastikan stabilitas thermal pasta dan cooling fan.

Template Postmortem Insiden Hardware Throttling

Incident Postmortem: Node Hardware Thermal Throttling
Tanggal/Waktu       : 2026-03-31 14:15 UTC
Author              : SRE / Infrastructure Team
Status              : Resolved

1. Ringkasan Eksekutif
Node worker-edge-04 mengalami penurunan clock CPU drastis hingga 800MHz akibat akumulasi debu pada heatsink chassis dan kegagalan sensor fan #2, memicu p99 latency loncat 4x lipat pada pod transaksi payment-service.

2. Kronologi Kejadian
- 14:08 UTC: CPU die temperature mencapai 88C (Threshold: 85C).
- 14:10 UTC: AlertManager menembakkan alert NodeThermalThrottlingCritical.
- 14:11 UTC: Auto-drain script berjalan; 18 application pods terevakuasi ke worker-edge-02.
- 14:14 UTC: payment-service kembali normal di host baru. Node lama di-cordon.

3. Root Cause
Kerusakan mekanis kipas internal chassis yang menyebabkan penumpukan panas statis di socket CPU 1 tanpa ventilasi memadai.

4. Tindakan Korektif & Pencegahan
- Ganti unit kipas chassis dan bersihkan thermal paste (Due: 24 Jam).
- Tambahkan IPMI Fan RPM check pada Prometheus alert rule (Due: 3 Hari).
- Pasang batas Resource Quota CPU burst per pod pada namespace terkait (Done).