AutoScaling - Custom Pod AutoScaler
在 Kubernetes 中,原生的水平 Pod 自動擴展(HPA)功能通常依賴於 CPU 和記憶體的平均使用量或使用率作為自動擴展的觸發指標。 然而,對於使用 partition 分配機制的應用程式(如 Kafka)來說,這樣的設定可能會導致工作負載分布不均,從而無法有效地擴展資源。
例如,某些 Pod 可能達到其負載上限,但由於整體的平均資源使用率尚未達到閥值,HPA 可能無法及時觸發擴展。
為了解決這個問題,一個有效的策略是使用 KEDA(Kubernetes Event-Driven Autoscaling)。 KEDA 透過監控每個 Pod 的事件處理速度(例如 Kafka 訊息的消費速度)來進行自動擴展,而不僅僅依賴於 Pod 的平均資源使用情況。
這種方法能精確地調整 Pod 數量,有效解決工作負載不均的問題,並優化資源使用,提升整體應用程式的性能與可擴展性。
Kubernetes Event-Driven Autoscaling (KEDA)
Kubernetes Event-Driven Autoscaling (KEDA) 是一種 基於事件的自動擴展 解決方案, 主要用於 自動調整 Kubernetes 工作負載的副本數量,根據 事件驅動 來動態調整應用程式的資源分配, 而不是僅依賴 CPU 或記憶體使用率(如 Horizontal Pod Autoscaler, HPA)。
KEDA 的核心特點
- 事件驅動的自動縮放
- KEDA 允許應用程式根據特定事件來源(如 Kafka、RabbitMQ、Azure Service Bus、Prometheus 等)來決定何時擴展或縮減 Pod 數量。
- 與 HPA(Horizontal Pod Autoscaler)整合
- KEDA 會將事件來源的數據轉換為 Kubernetes 的 HPA 指標,使 HPA 能夠根據這些事件來觸發 Pod 擴展。
- 精細控制 Pod 的擴展
- 當沒有負載時,KEDA 可以將 Pod 縮減為零,以節省資源;當事件出現時,則能夠迅速擴展 Pod。
- 支援多種 Scalers(事件來源)
- KEDA 內建支援 50 多種 Scaler,例如:
- 訊息佇列:Kafka、RabbitMQ、Azure Queue Storage
- 監控系統:Prometheus、Datadog
- 雲端服務:AWS SQS、Google Pub/Sub
- 資料庫:PostgreSQL、MySQL
- KEDA 內建支援 50 多種 Scaler,例如:
KEDA 的應用場景
- 無伺服器架構(Serverless)
- 讓 Kubernetes 上的應用程式具備無伺服器能力,當沒有負載時,Pod 數量可以降到零,避免資源浪費。
- 訊息佇列處理
- 透過 KEDA,系統能夠根據 Kafka、RabbitMQ、SQS 等訊息佇列中的負載動態擴展 Pod,確保即時處理能力。
- 資料庫觸發自動擴展
- 例如,根據 PostgreSQL 的資料變更來觸發 Pod 擴展,適用於高流量的應用程式 。
- 雲端監控與異常響應
- 使用 Prometheus 或 Datadog 作為事件來源,當系統監測到異常時,動態擴展應用程式以應對突發流量。
KEDA 與 HPA 的比較
HPA(水平自動擴展) | KEDA(事件驅動自動擴展) | |
---|---|---|
觸發條件 | 主要依賴 CPU / Memory | 依賴 事件來源(Kafka, RabbitMQ, HTTP 佇列...) |
最低 Pod 數量 | 1 (無法歸零) | 0 (完全釋放資源) |
適用場景 | 長時間運行的應用(如 Web 伺服器) | 需根據負載動態啟動的應用(如背景處理、批次任務) |
擴展速度 | 受 HPA 內部計算影響 | 即時事件驅動 |
KEDA CRD:ScaledObject 與 ScaledJob
在 KEDA 的框架中,ScaledObject
和 ScaledJob
是兩種核心的 自定義資源(Custom Resource Definitions, CRDs),
用來定義如何根據事件來 自動擴展(Scaling)Pod 或 建立短暫的批次工作(Job)。
這兩種 CRD 提供了一種靈活的方式來管理 Kubernetes 應用的 事 件驅動擴展,適用於各種應用場景,如 佇列處理、批次任務、資料庫監控 等。
ScaledObject
ScaledObject
用於 管理長期執行的 Pod(Deployment、StatefulSet、ReplicaSet),並根據事件來源來 動態擴展或縮減 Pod 的副本數。
ScaledObject 主要功能
- 針對 Kubernetes 部署(Deployment, StatefulSet, ReplicaSet)進行擴展
- 當沒有事件時,可以將 Pod 縮減至 0(省資源)
- 可與 HPA(Horizontal Pod Autoscaler)整合
- 支援多種事件來源,如 Kafka、RabbitMQ、Prometheus、AWS SQS 等
ScaledObject YAML 範例
範例:根據 Kafka 訊息數量動態調整 Pod
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: kafka-scaler
namespace: default
spec:
scaleTargetRef:
name: my-kafka-consumer # 指定要擴展的 Deployment
minReplicaCount: 0 # 最小 Pod 數量
maxReplicaCount: 10 # 最大 Pod 數量
idleReplicaCount: 1 # 當無負載時,仍保留 1 個 Pod 避免冷啟動
cooldownPeriod: 30 # 無負載後 30 秒內縮減
pollingInterval: 5 # 每 5 秒檢查一次負載
# 可選:當 KEDA 無法存取事件來源時的回退機制
fallback:
failureThreshold: 5 # 連續 5 次失敗視為無法存取事件來源
replicas: 3 # 無法存取事件來源時,強制維持 3 個 Pod
# 可選:進階擴展行為控制
advanced:
restoreToOriginalReplicaCount: true # 停用 KEDA 時恢復原本的 ReplicaCount
horizontalPodAutoscalerConfig:
behavior:
scaleDown:
stabilizationWindowSeconds: 60 # 60 秒內不進行縮減
policies:
- type: Percent
value: 50
periodSeconds: 15
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 5
triggers:
- type: kafka
metadata:
bootstrapServers: my-kafka-broker:9092
topic: my-topic
consumerGroup: my-group
lagThreshold: '100' # 當 Kafka 訊息積壓超過 100 則觸發擴展
ScaledObject 重要參數
參數 | 作用 |
---|---|
scaleTargetRef.name | 指定要擴展的 Pod(Deployment, StatefulSet, ReplicaSet) |
minReplicaCount | 設定 Pod 的最小數量,可為 0 |
maxReplicaCount | 設定 Pod 的最大數量 |
idleReplicaCount | 當無負載時,仍然保留的 Pod 數量,避免冷啟動(例如 1 表示即使無負載仍保留 1 個 Pod) |
cooldownPeriod | 無負載時等待多久再縮減 Pod |
pollingInterval | 多久檢查一次事件來源(預設 30 秒) |
triggers | 定義 事件來源(Kafka, RabbitMQ, SQS, Prometheus...) |
ScaledObject 可選參數
參數 | 作用 |
---|---|
fallback (可選) | 當 KEDA 無法存取事件來源時,回退到預設副本數 |
fallback.failureThreshold | KEDA 失敗多少次後,啟用回退機制 |
fallback.replicas | 回退機制啟動後,強制維持的 Pod 數量 |
advanced (可選) | 進階自動擴展設定 |
advanced.restoreToOriginalReplicaCount | 停用 KEDA 時,是否恢復原本的 ReplicaCount |
advanced.horizontalPodAutoscalerConfig | 自訂 HPA(水平 Pod 自動擴展)的行為 |
advanced.horizontalPodAutoscalerConfig.behavior | 擴展與縮減的行為控制 |
ScaledJob
ScaledJob
用於 管理短暫執行的批次工作(Jobs),適合一次性或臨時性的計算工作,當事件發生時,KEDA 會 動態啟動 Kubernetes Job,並在工作完成後自動釋放資源。
ScaledJob 主要功能
- 適用於批次任務(Batch Jobs),如影像處理、資料分析
- 當負載增加時,自動啟動多個 Job 處理
- 無負載時,不會產生多餘的 Pod(降低資源消耗)
- 自動管理 Job 的刪除與錯誤處理
ScaledJob YAML 範例
範例:根據 RabbitMQ 訊息數量觸發 Job,並加入進階控制參數
apiVersion: keda.sh/v1alpha1
kind: ScaledJob
metadata:
name: rabbitmq-job-scaler
namespace: default
spec:
jobTargetRef:
parallelism: 2 # 允許最多 2 個 Job 同時運行
completions: 1 # 每個 Job 只需成功執行 1 次
activeDeadlineSeconds: 300 # Job 最長運行時間為 300 秒,超時則終止
backoffLimit: 3 # Job 失敗後最多重試 3 次
template:
spec:
containers:
- name: rabbitmq-client
image: rabbitmq-client:latest
command:
- receive
args:
- '$(RABBITMQ_QUEUE)'
restartPolicy: Never # Job 結束後不自動重啟
minReplicaCount: 0 # 當無負載時,不產生 Job
maxReplicaCount: 20 # 最多允許 20 個 Job 併發
successfulJobsHistoryLimit: 5 # 保留 5 個成功 Job 記錄
failedJobsHistoryLimit: 5 # 保留 5 個失敗 Job 記錄
pollingInterval: 10 # 每 10 秒檢查一次負載
# 可選:從指定 Container 讀取環境變數
envSourceContainerName: rabbitmq-client
# 可選:控制 Job 滾動更新行為
rollout:
strategy: gradual # 逐步滾動更新(可選 "immediate" 或 "gradual")
# 可選:自訂 Job 的擴展策略
scalingStrategy:
strategy: custom # 可選 "default"、"custom" 或 "accurate"
customScalingQueueLengthDeduction: 5 # 每次擴展時,額外扣除 5 個訊息數
customScalingRunningJobPercentage: 50 # 當 50% Job 運行時,停止擴展
triggers:
- type: rabbitmq
metadata:
queueName: my-queue
hostFromEnv: RABBITMQ_HOST
mode: QueueLength
value: '50' # 當佇列訊息超過 50 時觸發 Job