你必知的 Kubernetes 自動縮放
編者按
許多Kubernetes用戶,特別是那些企業級用戶,很快就遇到了對環境自動縮放的需求。幸運的是,Kubernetes Horizontal Pod Autoscaler(HPA)允許您將部署配置爲以多種方式水平擴展。使用Kubernetes Autoscaling的最大優勢之一是您的集羣可以跟蹤現有Pod的負載能力,並計算是否需要更多的Pod。
Kubernetes Autoscaling
通過協調內置的兩層可擴展性,可以充分利用高效的Kubernetes Autoscaling:
- Pod級別的自動縮放:包括Horizontal Pod Autoscaler(HPA)和Vertical Pod Autoscaler(VPA); 兩者都可以擴展容器的可用資源。
- 集羣級別的自動縮放:集羣自動調節器(CA)通過在必要時向上或向下擴展集羣內的節點數來管理這種可擴展性平面。
Kubernetes Autoscaling 詳情
Horizontal Pod Autoscaler(HPA)
HPA會在集羣中縮放Pod副本的數量。該操作由CPU或內存觸發,以根據需要向上或向下擴展。但是,也可以根據各種外部的和自定義指標(metrics.k8s.io,external.metrics.k8s.io和custom.metrics.k8s.io)來配置HPA以擴展Pod。
Vertical Pod Autoscaler(VPA)
VPA主要用於有狀態服務,它可根據需要爲Pod添加CPU或內存——它也適用於無狀態的Pod。爲了應用這些更改,VPA重新啓動Pod以更新新的CPU和內存資源,這些資源可以配置爲響應OOM(內存不足)事件而啓動。重新啓動Pod的時候,VPA始終確保根據Pod分配預算(PDB)確定最小數量,您可以設置該資源分配最大和最小速率。
Cluster Autoscaler(CA)
第二層的自動縮放涉及CA,它在以下情況下自動調整集羣的大小:
- 由於集羣中的容量不足,任何Pod/s都無法運行並進入掛起狀態(在這種情況下,CA將向上擴展)。
- 集羣中的節點在一段時間內未得到充分利用,並且有可能遷移節點上的Pod(在這種情況下,CA將縮小)。
CA進行例行檢查以確定是否有任何pod因等待額外資源處於待定狀態,或者集羣節點是否未得到充分利用。如果需要更多資源,會相應地調整Cluster節點的數量。CA與雲提供商交互以請求其他節點或關閉空閒節點,並確保按比例放大的集羣保持在用戶設置的限制範圍內。它適用於AWS,Azure和GCP。
將HPA和CA與Amazon EKS配合使用的5個步驟
本文提供了通過適用於Kubernetes(Amazon EKS)集羣的Amazon Elastic容器服務,通過HPA和CA安裝和自動擴展的分步指南。以下指南是兩個測試用例示例:
集羣要求
- 滿足EKS集羣要求的Amazon VPC 和 一個安全組。
- 或者,爲免手動創建VPC,AWS提供了創建了VPC和EKS的 CloudFormation模板
- 應用到集羣的 EKS 角色
1.根據 官方指南 創建一個AWS EKS 集羣(控制面板和和工作節點). 一旦你把工作節點以auto scaling group的形式啓動了,它們會自動向EKS集羣註冊,你就可以開始部署k8s應用了。
2.部署度量服務器以便HPA能夠根據API提供的CPU/內存數據自動縮放POD副本的數量。 metrics.k8s.io api 通常由metrics-server(負責從summary api收集cpu和內存度量)提供。
3.把以下策略應用到EKS創建的worker節點的Role上
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "autoscaling:DescribeAutoScalingGroups", "autoscaling:DescribeAutoScalingInstances", "autoscaling:DescribeLaunchConfigurations", "autoscaling:DescribeTags", "autoscaling:SetDesiredCapacity", "autoscaling:TerminateInstanceInAutoScalingGroup" ], "Resource": "*" } ] }
4. 部署k8s CA特性
根據你使用的linux發行版,你可能需要更新部署文件和證書路徑。 例如,如果使用AMI Linux,需要用/etc/ssl/certs/ca-bundle.crt替換/etc/ssl/certs/ca-certificates.crt
5.更新CA的部署YAML文件,找到指定的AWS AG(k8s.io/cluster-autoscaler/< CLUSTER NAME
>應該包含真實的集羣名稱)標籤。
同時更新 AWS_REGION
環境變量。
把以下tag添加到 AWS AG, 以便 k8s 的 cluster autoscaler 能夠自動識別 AWS AG: > k8s.io/cluster-autoscaler/enabled > k8s.io/cluster-autoscaler/
Kubernetes Autoscaling 測試用例 #1
測試k8s hpa 特性和k8s ca 特性同時使用
要求:
- 一個運行中的eks集羣
- 安裝好metric server
- 安裝了k8s cluster autoscaler 特性
1.部署一個測試app,爲app部署創建HPA資源。
2.從不同的地理位置發起請求以增加負載。
3.HPA 應該會隨着負載的增加開始縮放pod的數量。它會根據hpa資源指定的進行縮放的。在某一時刻,新的POD在等待其他資源的時候會是等待狀態。
$ kubectl get nodes -w NAME STATUS ROLES AGE VERSION ip-192-168-189-29.ec2.internal Ready 1h v1.10.3 ip-192-168-200-20.ec2.internal Ready 1h v1.10.3
$ kubectl get Pods -o wide -w NAME READY STATUS RESTARTS AGE IP NODE ip-192-168-200-20.ec2.internal php-apache-8699449574-4mg7w 0/1 Pending 0 17m php-apache-8699449574-64zkm 1/1 Running 0 1h 192.168.210.90 ip-192-168-200-20 php-apache-8699449574-8nqwk 0/1 Pending 0 17m php-apache-8699449574-cl8lj 1/1 Running 0 27m 192.168.172.71 ip-192-168-189-29 php-apache-8699449574-cpzdn 1/1 Running 0 17m 192.168.219.71 ip-192-168-200-20 php-apache-8699449574-dn9tb 0/1 Pending 0 17m ...
4.CA 檢測到因爲容量不足而進入等待狀態的pods,調整AWS 自動縮放組的大小。一個新的節點加入了:
$ kubectl get nodes -w NAME STATUS ROLES AGE VERSION ip-192-168-189-29.ec2.internal Ready 2h v1.10.3 ip-192-168-200-20.ec2.internal Ready 2h v1.10.3 ip-192-168-92-187.ec2.internal Ready 34s v1.10.3
5.HPA能夠把等待狀態的POD調度到新的節點上了。 平均cpu使用率低於指定的目標,沒有必要再調度新的pod了。
$ kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache 40%/50% 2 25 20 1h $ kubectl get Pods -o wide -w
$ kubectl get Pods -o wide -w NAME READY STATUS RESTARTS AGE IP NODE php-apache-8699449574-4mg7w 1/1 Running 0 25m 192.168.74.4 ip-192-168-92-187 php-apache-8699449574-64zkm 1/1 Running 0 1h 192.168.210.90 ip-192-168-200-20 php-apache-8699449574-8nqwk 1/1 Running 0 25m 192.168.127.85 ip-192-168-92-187 php-apache-8699449574-cl8lj 1/1 Running 0 35m 192.168.172.71 ip-192-168-189-29 ...
6.關閉幾個terminal,停掉一些負載
7.CPU平均利用率減小了, 所以HPA開始更改部署裏的pod副本數量並殺掉一些pods
$ kubectl get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE php-apache Deployment/php-apache 47%/50% 2 20 7 1h $ kubectl get Pods -o wide -w NAME READY STATUS RESTARTS AGE IP NODE ... php-apache-8699449574-v5kwf 1/1 Running 0 36m 192.168.250.0 ip-192-168-200-20 php-apache-8699449574-vl4zj 1/1 Running 0 36m 192.168.242.153 ip-192-168-200-20 php-apache-8699449574-8nqwk 1/1 Terminating 0 26m 192.168.127.85 ip-192-168-92-187 php-apache-8699449574-dn9tb 1/1 Terminating 0 26m 192.168.124.108 ip-192-168-92-187 php-apache-8699449574-k5ngv 1/1 Terminating 0 26m 192.168.108.58 ip-192-168-92-187 ...
8.CA 檢測到一個節點未充分使用,正在運行的pod能夠調度到其他節點上。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-192-168-189-29.ec2.internal Ready 2h v1.10.3 ip-192-168-200-20.ec2.internal Ready 2h v1.10.3 ip-192-168-92-187.ec2.internal NotReady 23m v1.10.3 $ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-192-168-189-29.ec2.internal Ready 2h v1.10.3 ip-192-168-200-20.ec2.internal Ready 2h v1.10.3
9.在向下縮放的時候,terminal中應該沒有明顯的timeout
Kubernetes Autoscaling 測試用例 #2
測試在如果沒有足夠的CPU容量調度pod下,CA是否能夠自動調整集羣的大小
要求:
- 一個運行中的aws eks集羣
- Kubernetes ca 特性已安裝
1.創建2個請求小於1vcpu的deployment
$ kubectl run nginx --image=nginx:latest --requests=cpu=200m $ kubectl run nginx2 --image=nginx:latest --requests=cpu=200m
2.創建一個新的deployment,請求比剩餘的cpu更多的資源
$ kubectl run nginx3 --image=nginx:latest --requests=cpu=1
3.新的POD會處於等待狀態,因爲沒有可用的資源:
$ kubectl get Pods -w NAME READY STATUS RESTARTS AGE nginx-5fcb54784c-lcfht 1/1 Running 0 13m nginx2-66667bf959-2fmlr 1/1 Running 0 3m nginx3-564b575974-xcm5t 0/1 Pending 0 41s
描述pod的時候,可能會看到沒有足夠的cpu的事件
$ kubectl describe Pod nginx3-564b575974-xcm5t ….. ….. Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 32s (x7 over 1m) default-scheduler 0/1 nodes are available: 1 Insufficient cpu
4.CA自動調整集羣的大小, 新加了一個節點
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-192-168-142-179.ec2.internal Ready 1m v1.10.3 << ip-192-168-82-136.ec2.internal Ready 1h v1.10.3
5.集羣現在有了足夠的資源以運行pod
$ kubectl get Pods NAME READY STATUS RESTARTS AGE nginx-5fcb54784c-lcfht 1/1 Running 0 48m nginx2-66667bf959-2fmlr 1/1 Running 0 37m nginx3-564b575974-xcm5t 1/1 Running 0 35m
6.兩個部署刪除了。 一段時間後,CA檢測到集羣中的一個節點未被充分利用,運行的pod可以安置到其他存在的節點上。AWS AG 更新,節點數量減1。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-192-168-82-136.ec2.internal Ready 1h v1.10.3 $ kubectl get Pods -o wide NAME READY STATUS RESTARTS AGE IP NODE nginx-5fcb54784c-lcfht 1/1 Running 0 1h 192.168.98.139 ip-192-168-82-136
清除環境的步驟:
- 刪除添加到eks worker節點上Role的自定義策略
- 按照這個 指南 刪除這個集羣
參考
其他的關於kubernetes autoscaling,可以閱讀Stefan Prodan的文章 Kubernetes Horizontal Pod Autoscaler with Prometheus Custom Metrics 。