Autoscaling === ###### tags: `SlinkyProject` ###### tags: `Kubernetes`, `k8s`, `app`, `slurm`, `SlinkyProject`, `Autoscaling`, `KEDA`, `HPA`, `VPA`, `Scale out`, `Scale in` <br> [TOC] <br> ## 所需背景知識 - [[應用] keda 部署與測試教學](/iU44zPyST9O5rD7OQYdQYQ) <br> ## Intro - [Autoscaling](https://github.com/SlinkyProject/slurm-operator/blob/main/docs/autoscaling.md) <br> ## 如何填寫 `keda-slurm-compute-e900.yaml` ? - ### `keda-slurm-compute-e900.yaml` ```yaml= apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: scale-e900 namespace: slurm spec: scaleTargetRef: apiVersion: slinky.slurm.net/v1alpha1 kind: NodeSet name: slurm-compute-e900 idleReplicaCount: 0 minReplicaCount: 1 maxReplicaCount: 3 triggers: - type: prometheus metricType: Value metadata: serverAddress: http://monitor-kube-prometheus-st-prometheus.monitor:9090 query: slurm_partition_pending_jobs{partition="radar"} threshold: '5' ``` - ### 確認 `scaleTargetRef` 資訊正確 > ```yaml > scaleTargetRef: > apiVersion: slinky.slurm.net/v1alpha1 > kind: NodeSet > name: slurm-compute-e900 > ``` - ### 確認要縮放的對象存在: 對象:`-n slurm NodeSet/slurm-compute-e900` ```bash $ kubectl -n slurm get NodeSet # 同 $ kubectl -n slurm get nss NAME REPLICAS UPDATED READY AGE slurm-compute-e900 20d slurm-compute-esc8000a 38d slurm-compute-esc8000b 1 1 1 38d $ kubectl -n slurm get NodeSet/slurm-compute-e900 NAME REPLICAS UPDATED READY AGE slurm-compute-e900 20d ``` - ### apiVersion ``` $ kubectl -n slurm get NodeSet/slurm-compute-e900 -o yaml | grep apiVersion: apiVersion: slinky.slurm.net/v1alpha1 ``` - ### 預期的副本數 > ```yaml > idleReplicaCount: 0 > minReplicaCount: 1 > maxReplicaCount: 3 > ``` - **`minReplicaCount` & `minReplicaCount`** 當觸發器上有活動(至少有一個等待中的作業)時,KEDA 會將 NodeSet 的副本數調整為 `minReplicaCount`,然後讓 HPA 負責根據負載自動調整,最高可至 `maxReplicaCount`,或降回 minReplicaCount。 - **`idleReplicaCount`** 當觸發器在設定的時間內沒有偵測到活動時,KEDA 會將 NodeSet 的副本數調整為 `idleReplicaCount`。更多範例請參考 KEDA 官方文件中關於 `idleReplicaCount` 的說明。 - 官方解釋 > When there is activity on the trigger (at least one pending job), KEDA will scale the NodeSet to `minReplicaCount` and then let HPA handle scaling up to `maxReplicaCount` or back down to `minReplicaCount`. When there is no activity on the trigger after a configurable amount of time, KEDA will scale the NodeSet to `idleReplicaCount`. See the [KEDA](https://keda.sh/docs/) documentation on [`idleReplicaCount`](https://keda.sh/docs/concepts/scaling-deployments/#idlereplicacount) for more examples. 當觸發器上有活動(至少有一個等待中的作業)時,KEDA 會將 NodeSet 的副本數調整為 `minReplicaCount`,然後讓 HPA 負責根據負載自動調整,最高可至 `maxReplicaCount`,或降回 `minReplicaCount`。當觸發器在設定的時間內沒有偵測到活動時,KEDA 會將 NodeSet 的副本數調整為 `idleReplicaCount`。更多範例請參考 [KEDA](https://keda.sh/docs/) 官方文件中關於 [`idleReplicaCount`](https://keda.sh/docs/concepts/scaling-deployments/#idlereplicacount) 的說明。 - ### 確認 triggers 資訊 > ```yaml > triggers: > - type: prometheus > metricType: Value > metadata: > serverAddress: http://prometheus-kube-prometheus-prometheus.prometheus:9090 > query: slurm_partition_pending_jobs{partition="radar"} > threshold: '5' > ``` - ### KEDA 使用的 scale object 是 `prometheus` - ### 確認 prometheus service 是否能存取? - ### helm repo 已經有 prometheus ? ``` $ helm repo list | grep -i prometheus prometheus-community https://prometheus-community.github.io/helm-charts ``` - ### prometheus 安裝在哪個 namespace? ``` $ helm list -A | egrep -i "name|prometheus" NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION monitor monitor 1 2025-07-16 07:05:53.714709202 +0000 UTC deployed kube-prometheus-stack-70.7.0 v0.81.0 ``` - ### 查看 prometheus 服務 ``` $ kubectl -n monitor get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 19d monitor-grafana ClusterIP 10.108.0.168 <none> 80/TCP 19d monitor-grafana-headless ClusterIP None <none> 9094/TCP 19d monitor-kube-prometheus-st-alertmanager ClusterIP 10.108.233.120 <none> 9093/TCP,8080/TCP 19d monitor-kube-prometheus-st-operator ClusterIP 10.97.240.59 <none> 443/TCP 19d monitor-kube-prometheus-st-prometheus ClusterIP 10.101.246.225 <none> 9090/TCP,8080/TCP 19d monitor-kube-state-metrics ClusterIP 10.102.45.71 <none> 8080/TCP 19d monitor-prometheus-node-exporter ClusterIP 10.96.132.130 <none> 9100/TCP 19d prometheus-operated ClusterIP None <none> 9090/TCP 19d ``` - **service** - name: `monitor-kube-prometheus-st-prometheus` - port: 9090 or 8080 - **DNS 格式** - **`<service>.<namespace>:<port>`** `monitor-kube-prometheus-st-prometheus.monitor:9090` - **`<service>.<namespace>.svc:<port>`** `monitor-kube-prometheus-st-prometheus.monitor.svc:9090` - **`<service>.<namespace>.svc.cluster.local:<port>`** `monitor-kube-prometheus-st-prometheus.monitor.svc.cluster.local:9090` - **進到 `-n slurm` 的任意 pod,查看 `/etc/resolv.conf` 設定** ``` $ cat /etc/resolv.conf search slurm.svc.cluster.local svc.cluster.local cluster.local nameserver 10.96.0.10 options ndots:5 ``` | domain-name | matched suffix | FQDN | |-------------|--------|------| | `monitor-kube-prometheus-st-prometheus.monitor` | `svc.cluster.local` | `monitor-kube-prometheus-st-prometheus.monitor.svc.cluster.local` | | `monitor-kube-prometheus-st-prometheus.monitor.svc` | `cluster.local` | `monitor-kube-prometheus-st-prometheus.monitor.svc.cluster.local` | | `monitor-kube-prometheus-st-prometheus.monitor.svc.cluster.local` | | `monitor-kube-prometheus-st-prometheus.monitor.svc.cluster.local` | - **確定 service 可以連線?** ```bash # 建立測試用的 pod $ kubectl -n slurm run -it --rm dnstools --image=infoblox/dnstools # 或:進入現有的 pod: $ kubectl -n slurm exec -it pod/dnstools -- sh --- # 進入到 pod $ nslookup monitor-kube-prometheus-st-prometheus.monitor $ curl "http://monitor-kube-prometheus-st-prometheus.monitor:9090" -i HTTP/1.1 302 Found Content-Type: text/html; charset=utf-8 Location: /query Date: Tue, 05 Aug 2025 04:15:10 GMT Content-Length: 29 <a href="/query">Found</a>. --- # 確認可連線後,可進一步進行查詢: # 1. 查詢 Prometheus 自己的時間戳 $ curl "http://monitor-kube-prometheus-st-prometheus.monitor:9090/api/v1/query?query=time()" # 2. 查詢 Prometheus 內建的 up 指標 $ curl "http://monitor-kube-prometheus-st-prometheus.monitor:9090/api/v1/query?query=up" # up 這個指標會顯示每個 target 是否處於「上線」(1=正常,0=異常)。 # 3. 查詢某個 exporter 的 metrics 數量 $ curl "http://monitor-kube-prometheus-st-prometheus.monitor:9090/api/v1/query?query=node_cpu_seconds_total" # 4. 查詢所有 metric 名稱 $ curl "http://monitor-kube-prometheus-st-prometheus.monitor:9090/api/v1/label/__name__/values" ``` - ### 套用並確認 ```bash $ kubectl -n slurm apply -f keda-slurm-compute-e900.yaml ``` ``` $ kubectl -n slurm get all ... NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE horizontalpodautoscaler.autoscaling/keda-hpa-scale-e900 NodeSet/slurm-compute-e900 <unknown>/5 1 3 0 25h ``` - TARGETS 是 `<unknown>`,應該表示還沒有上傳 metrics 到 Prometheus ? ``` $ kubectl -n slurm get scaledobjects NAME SCALETARGETKIND SCALETARGETNAME MIN MAX READY ACTIVE FALLBACK PAUSED TRIGGERS AUTHENTICATIONS AGE scale-e900 slinky.slurm.net/v1alpha1.NodeSet slurm-compute-e900 1 3 True False False Unknown prometheus 25h ``` <br> ## 討論 ### 解釋 HPA 和 VPA - ### Question https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ Horizontal Pod Autoscaling https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler/ Vertical Pod Autoscaler 用簡單的方式解釋 - ### gpt-4.1 (2025/08/05) 當然可以!以下是**Horizontal Pod Autoscaler (HPA)** 和 **Vertical Pod Autoscaler (VPA)** 的簡單說明: --- ### Horizontal Pod Autoscaler (HPA) [官方文件說明連結](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) #### 功能簡介 * **HPA 會根據 CPU 使用率、記憶體用量,或其他自訂指標,自動調整 Pod 的數量。** * 當負載增加時,HPA 會自動擴充(增加)Pod;負載降低時則會縮減(減少)Pod。 #### 適用場景 * 當你的服務在高流量時需要更多實例分攤流量,低流量時節省資源。 #### 流程簡述 1. 設定 HPA,指定監控指標(例如 CPU 使用率)。 2. Kubernetes controller 會持續監控這些指標。 3. 如果指標超過或低於你設定的目標,Kubernetes 會自動調整 Pod 數量。 --- ### Vertical Pod Autoscaler (VPA) [GitHub 連結](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler/) #### 功能簡介 * **VPA 會根據實際的資源使用情況,自動調整 Pod 的「CPU/記憶體配額」大小(不是數量)。** * 負載變大時自動分配更多資源給 Pod;負載小時減少分配,提升資源利用率。 #### 適用場景 * 當你的應用程式的資源需求會隨負載變動,但不想頻繁調整 Deployment 的資源設定時。 #### 流程簡述 1. 部署 VPA 組件並套用 VPA 資源設定。 2. VPA 持續監控每個 Pod 的資源實際用量。 3. 需要時會建議或自動修改 Pod 的資源限制,可能需要重啟 Pod 以套用新設定。 --- ### 小結比較表 | | HPA | VPA | | ------- | ------------------ | ----------------------------- | | 自動調整什麼? | Pod 數量 | Pod 的資源(CPU/記憶體) | | 用途 | 水平擴展(Scale out/in) | 垂直調整(Scale up/down) | | 適合的場景 | 處理流量大起大落的服務 | 資源需求變動大、不想手動調整資源 | | 常見組合 | 可和 VPA 合併用,但有限制 | 可和 HPA 合併用,但 Pod 必須有最小/最大數量限制 | --- 如需範例設定,或想知道兩者能否同時使用,可以再告訴我! <br> --- ### 水平擴展(Scale out / Scale in),哪個數量是增加?哪個數量是減少? - ### gpt-4.1 (2025/08/05) 讓我用最簡單的方式說明:「**Scale out**」和「**Scale in**」這兩個詞的意思: --- ### 水平擴展(Scale out / Scale in) * **Scale out(擴出)**:**增加**資源的「數量」 * 例如:增加更多 Pod、伺服器、主機(通常是同樣規格的機器)。 * 在 Kubernetes HPA 裡,就是**Pod 數量變多**,來應付更大的流量或工作量。 * 中文常說「橫向擴展」。 * **Scale in(縮入)**:**減少**資源的「數量」 * 例如:把多餘的 Pod、伺服器關閉或刪除。 * 在 Kubernetes HPA 裡,就是**Pod 數量變少**,以節省資源。 * 中文常說「橫向縮減」。 --- ### 小口訣 * **out = 增加數量**(數量往「外」擴散出去) * **in = 減少數量**(數量往「內」收縮) --- ### 圖像化舉例 假設原本有 2 個 Pod: * **Scale out** 之後 → 4 個 Pod ``` 原本: PodA, PodB 擴出: PodA, PodB, PodC, PodD ``` * **Scale in** 之後 → 1 個 Pod ``` 原本: PodA, PodB 縮入: PodA ``` --- ### 補充 * **Scale up / Scale down(垂直擴展/縮減)**:是指「**單一台機器(或 Pod)的資源變大/變小**」,比如把 1G RAM 增加到 2G。 --- 如果還不確定,可以告訴我你遇到的情境或是哪裡卡住,我可以用更生活化的例子解釋! <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}