在Kubernetes 1.27及更早的版本中,如需在Pod啟動並執行過程中臨時修改容器參數,只能更新PodSpec後重新提交,這種方式會觸發Pod的刪除和重建。ACK提供基於Cgroups檔案動態修改Pod資源參數的功能,支援在不重啟Pod的情況下,臨時修改Pod的CPU、記憶體、磁碟IO等單機隔離參數。
本功能僅適用於臨時性的調整,例如當Pod記憶體使用量率逐漸升高,為避免觸發OOM(Out Of Memory)Killer,希望在不重啟Pod的前提下提高記憶體的Limit。對於正式的常規性營運操作,建議您使用啟用CPU Burst效能最佳化策略、啟用CPU拓撲感知調度、資源畫像等功能。
前提條件
已通過kubectl工具串連叢集。具體操作,請參見擷取叢集KubeConfig並通過kubectl工具串連叢集。
已安裝ack-koordinator組件,且組件版本為0.5.0及以上,請參見ack-koordinator(ack-slo-manager)。
費用說明
ack-koordinator組件本身的安裝和使用是免費的,不過需要注意的是,在以下情境中可能產生額外的費用:
修改記憶體Limit
當Pod記憶體使用量率逐漸升高,為避免觸發OOM Killer,您可以通過Cgroups檔案臨時、動態地修改容器的記憶體Limit。本樣本將建立初始記憶體Limit為1 GB的容器,驗證在Pod不重啟的情況下通過Cgroups可以成功修改容器的記憶體Limit。
若您在1.22以上版本的叢集中使用本功能,請確保ack-koordinator組件版本為v1.5.0-ack1.14及以上;其他組件版本僅支援1.22及以下版本的叢集。
對於常規調整CPU Limit的情境,建議您使用CPU Burst效能最佳化策略功能,自動調整Pod的CPU資源彈性,請參見啟用CPU Burst效能最佳化策略。若您仍需要臨時調整CPU Limit的能力,請參見從resource-controller遷移至ack-koordinator中的流程來實現。
使用以下YAML內容,建立pod-demo.yaml檔案。
apiVersion: v1 kind: Pod metadata: name: pod-demo spec: containers: - name: pod-demo image: registry-cn-beijing.ack.aliyuncs.com/acs/stress:v1.0.4 resources: requests: cpu: 1 memory: "50Mi" limits: cpu: 1 memory: "1Gi" # 容器記憶體Limit為1 GB。 command: ["stress"] args: ["--vm", "1", "--vm-bytes", "256M", "-c", "2", "--vm-hang", "1"]
執行以下命令,將pod-demo部署到叢集中。
kubectl apply -f pod-demo.yaml
執行以下命令,查看當前容器的初始記憶體限制值。
# 具體路徑可根據Pod的UID以及Container的ID拼接得到。 cat /sys/fs/cgroup/memory/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podaf44b779_41d8_43d5_a0d8_8a7a0b17****.slice/memory.limit_in_bytes
預期輸出:
# 對應為1 GB,即1*1024*1024*1024=1073741824。 1073741824
預期輸出表明,當前容器的初始記憶體Limit為1 GB,與步驟1的
spec.containers.resources.limits.memory
描述一致。使用以下YAML內容,指定需要動態修改容器的記憶體Limit,建立cgroups-sample.yaml檔案。
apiVersion: resources.alibabacloud.com/v1alpha1 kind: Cgroups metadata: name: cgroups-sample spec: pod: name: pod-demo namespace: default containers: - name: pod-demo memory: 5Gi # 指定Pod的記憶體Limit為5 GB。
執行以下命令,將cgroups-sample.yaml部署到叢集中。
kubectl apply -f cgroups-sample.yaml
執行以下命令,查看修改後容器的記憶體限制值。
# 具體路徑可根據Pod的UID拼接得到。 cat /sys/fs/cgroup/memory/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podaf44b779_41d8_43d5_a0d8_8a7a0b17****.slice/memory.limit_in_bytes
預期輸出:
# 對應為5 GB,即5*1024*1024*1024=5368709120 5368709120
預期輸出表明,容器的記憶體限制值為5 GB,與步驟4的
spec.pod.containers.memory
描述一致,即本次修改成功。執行以下命令,查看Pod運行情況。
kubectl describe pod pod-demo
預期輸出:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 36m default-scheduler Successfully assigned default/pod-demo to cn-hangzhou.192.168.0.50 Normal AllocIPSucceed 36m terway-daemon Alloc IP 192.XX.XX.51/24 took 4.490542543s Normal Pulling 36m kubelet Pulling image "registry-cn-beijing.ack.aliyuncs.com/acs/stress:v1.0.4" Normal Pulled 36m kubelet Successfully pulled image "registry-cn-beijing.ack.aliyuncs.com/acs/stress:v1.0.4" in 2.204s (2.204s including waiting). Image size: 7755078 bytes. Normal Created 36m kubelet Created container pod-demo Normal Started 36m kubelet Started container pod-demo
預期輸出表明,Event列表中不存在Pod重啟的相關資訊,Pod運行正常。
修改CPU綁核範圍
如果您的應用程式對CPU效能要求較高,期望實現更好的資源隔離,您可以修改CPU Core的綁定範圍,指定Pod可使用的CPU編號。
本樣本將建立一個未綁定CPU Core的Pod,驗證在Pod不重啟的情況下通過Cgroups檔案可以成功修改Pod的CPU綁核範圍。
對於常規的CPU綁核情境,更推薦您使用CPU拓撲感知調度功能,為CPU敏感型的工作負載提供更好的效能。更多資訊,請參見啟用CPU拓撲感知調度。
使用以下YAML內容,建立pod-cpuset-demo.yaml。
apiVersion: v1 kind: Pod metadata: name: pod-cpuset-demo spec: containers: - name: pod-cpuset-demo image: registry-cn-beijing.ack.aliyuncs.com/acs/stress:v1.0.4 resources: requests: memory: "50Mi" limits: memory: "1000Mi" cpu: 0.5 command: ["stress"] args: ["--vm", "1", "--vm-bytes", "556M", "-c", "2", "--vm-hang", "1"]
執行以下命令,將pod-cpuset-demo.yaml部署到叢集中。
kubectl apply -f pod-cpuset-demo.yaml
執行以下命令,查看當前容器的CPU核心綁定情況。
# 實際路徑可根據Pod的UID以及Container的ID拼接得到。 cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podf9b79bee_eb2a_4b67_befe_51c270f8****.slice/cri-containerd-aba883f8b3ae696e99c3a920a578e3649fa957c51522f3fb00ca943dc2c7****.scope/cpuset.cpus
預期輸出:
0-31
預期輸出表明,未綁定CPU前,可使用的CPU編號範圍為0~31,表示CPU目前沒有約束。
使用以下YAML內容,指定CPU的綁核資訊,建立cgroups-sample-cpusetpod.yaml檔案。
apiVersion: resources.alibabacloud.com/v1alpha1 kind: Cgroups metadata: name: cgroups-sample-cpusetpod spec: pod: name: pod-cpuset-demo namespace: default containers: - name: pod-cpuset-demo cpuset-cpus: 2-3 # 指定將Pod綁定到CPU2和CPU3上。
執行以下命令,將cgroups-sample-cpusetpod.yaml部署到叢集中。
kubectl apply -f cgroups-sample-cpusetpod.yaml
執行以下命令,查看當前容器修改後的CPU核心綁定情況。
# 實際路徑可根據Pod的UID以及Container的ID拼接得到。 cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-podf9b79bee_eb2a_4b67_befe_51c270f8****.slice/cri-containerd-aba883f8b3ae696e99c3a920a578e3649fa957c51522f3fb00ca943dc2c7****.scope/cpuset.cpus
預期輸出:
2-3
預期輸出表明,容器已成功綁定到CPU2和CPU3上,與步驟4的
spec.pod.containers.cpuset-cpus
描述一致,即本次修改成功。執行以下命令,查看Pod運行情況。
kubectl describe pod pod-cpuset-demo
預期輸出:
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 7m7s default-scheduler Successfully assigned default/pod-cpuset-demo to cn-hangzhou.192.XX.XX.50 Normal AllocIPSucceed 7m5s terway-daemon Alloc IP 192.XX.XX.56/24 took 2.060752512s Normal Pulled 7m5s kubelet Container image "registry-cn-beijing.ack.aliyuncs.com/acs/stress:v1.0.4" already present on machine Normal Created 7m5s kubelet Created container pod-cpuset-demo Normal Started 7m5s kubelet Started container pod-cpuset-demo Normal CPUSetBind 84s koordlet set cpuset 2-3 to container pod-cpuset-demo success
預期輸出表明,Event列表中不存在Pod重啟的相關資訊,Pod運行正常。
修改磁碟IOPS參數
如果您需要控制磁碟IOPS,請使用作業系統為Alibaba Cloud Linux的Worker節點。
本樣本將建立一個IO密集型的測試應用,驗證在Pod不重啟的情況下通過Cgroups檔案可以對Pod的輸送量進行限制,修改容器的磁碟IO限制。
在cgroup v1環境下使用blkio限制時,作業系統核心只會限制容器的Direct I/O,無法限制Buffered I/O。如需對Buffered I/O進行限制,請使用cgroup v2,或在Alibaba Cloud Linux啟用cgroup v1的控制群組回寫(cgroup writeback)功能,請參見開啟cgroup writeback功能。
使用以下YAML,建立一個IO密集型的測試應用。
將宿主機目錄/mnt掛載至Pod內部使用,對應磁碟裝置名稱為/dev/vda1。
apiVersion: apps/v1 kind: Deployment metadata: name: fio-demo labels: app: fio-demo spec: selector: matchLabels: app: fio-demo template: metadata: labels: app: fio-demo spec: containers: - name: fio-demo image: registry.cn-zhangjiakou.aliyuncs.com/acs/fio-for-slo-test:v0.1 command: ["sh", "-c"] # 使用Fio工具對磁碟IOPS進行寫測試。 args: ["fio -filename=/data/test -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=12000 -group_reporting -name=mytest"] volumeMounts: - name: pvc mountPath: /data # 掛載在/data的路徑下。 volumes: - name: pvc hostPath: path: /mnt
執行以下命令,將fio-demo部署到叢集中。
kubectl apply -f fio-demo.yaml
部署控制磁碟IOPS的Cgroups檔案,對Pod的輸送量進行限制。
使用以下YAML,指定裝置/dev/vda1的BPS(Bit Per Second)限制資訊,建立cgroups-sample-fio.yaml檔案。
apiVersion: resources.alibabacloud.com/v1alpha1 kind: Cgroups metadata: name: cgroups-sample-fio spec: deployment: name: fio-demo namespace: default containers: - name: fio-demo blkio: # BPS限制,例如1048576、2097152、3145728。 device_write_bps: [{device: "/dev/vda1", value: "1048576"}]
執行以下命令,查看當前容器修改後的磁碟IO限制情況。
# 實際路徑可根據Pod的UID以及Container的ID拼接得到。 cat /sys/fs/cgroup/blkio/kubepods.slice/kubepods-besteffort.slice/kubepods-besteffort-pod0840adda_bc26_4870_adba_f193cd00****.slice/cri-containerd-9ea6cc97a6de902d941199db2fcda872ddd543485f5f987498e40cd706dc****.scope/blkio.throttle.write_bps_device
預期輸出:
253:0 1048576
預期輸出表明,當前磁碟的限速配置為
1048576
。
查看對應節點的磁碟監控。
如上圖所示,容器的吞吐BPS(File System Write)和步驟3的
device_write_bps
限制一致,且修改過程中Pod沒有被重啟。說明您也可以參見使用阿里雲Prometheus監控啟用阿里雲Prometheus大盤,並在營運管理 > Prometheus 監控的應用監控頁簽下篩選樣本應用,查看其磁碟資料。
在Deployment維度動態修改Pod資源參數
前文介紹的Pod維度資源參數動態修改同樣支援在Deployment維度生效。Pod維度修改通過Cgroups檔案的spec.pod
欄位內容生效;Deployment維度修改通過spec.deployment
欄位內容生效。下文以修改CPU綁核範圍為例,介紹如何在Deployment完成修改。其他情境操作類似。
使用以下YAML內容,建立go-demo.yaml檔案。
Deployment中包含兩個執行個體的壓測程式,每個執行個體使用的資源為0.5個CPU。
apiVersion: apps/v1 kind: Deployment metadata: name: go-demo labels: app: go-demo spec: replicas: 2 selector: matchLabels: app: go-demo template: metadata: labels: app: go-demo spec: containers: - name: go-demo image: polinux/stress command: ["stress"] args: ["--vm", "1", "--vm-bytes", "556M", "-c", "1", "--vm-hang", "1"] imagePullPolicy: Always resources: requests: cpu: 0.5 limits: cpu: 0.5
執行以下命令,將go-demo部署到叢集中。
kubectl apply -f go-demo.yaml
使用以下YAML內容,指定CPU的綁定資訊,建立cgroups-cpuset-sample.yaml檔案。
apiVersion: resources.alibabacloud.com/v1alpha1 kind: Cgroups metadata: name: cgroups-cpuset-sample spec: deployment: # 此處為Deployment。 name: go-demo namespace: default containers: - name: go-demo cpuset-cpus: 2,3 # 將Pod綁定到CPU2和CPU3上。
執行以下命令,將cgroups-cpuset-sample部署到叢集中。
kubectl apply -f cgroups-cpuset-sample.yaml
執行以下命令,查看當前容器修改後的CPU核心綁定情況。
#具體路徑可根據Pod的UID以及Container的ID拼接得到。 cat /sys/fs/cgroup/cpuset/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod06de7408_346a_4d00_ba25_02833b6c****.slice/cri-containerd-733a0dc93480eb47ac6c5abfade5c22ed41639958e3d304ca1f85959edc3****.scope/cpuset.cpus
預期輸出:
2-3
預期輸出表明,容器綁定在CPU2和CPU3上,與Cgroups檔案中的
spec.deployment.containers.cpuset-cpus
描述一致。