HPA全稱是Horizontal Pod Autoscaler,翻譯成中文是POD水平自動伸縮,如下都會用HPA代替Horizontal Pod Autoscaler,HPA能夠基於CPU利用率對replication controller、deployment和replicaset中的pod數量進行自動擴縮容(除了CPU利用率也能夠基於其餘應程序提供的度量指標custom metrics進行自動擴縮容)。pod自動縮放不適用於沒法縮放的對象,好比DaemonSets。HPA由Kubernetes API資源和控制器實現。資源決定了控制器的行爲。控制器會週期性的獲取平均CPU利用率,並與目標值相比較後來調整replication controller或deployment中的副本數量。php
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/custom-metrics-api.md
https://v1-17.docs.kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
HPA的實現是一個控制循環,由controller manager的--horizontal-pod-autoscaler-sync-period參數指定週期(默認值爲15秒)。每一個週期內,controller manager根據每一個HorizontalPodAutoscaler定義中指定的指標查詢資源利用率。controller manager能夠從resource metrics API(pod 資源指標)和custom metrics API(自定義指標)獲取指標。html
1)對於每一個pod的資源指標(如CPU),控制器從資源指標API中獲取每個 HorizontalPodAutoscaler指定的pod的指標,而後,若是設置了目標使用率,控制器獲取每一個pod中的容器資源使用狀況,並計算資源使用率。若是使用原始值,將直接使用原始數據(再也不計算百分比)。而後,控制器根據平均的資源使用率或原始值計算出縮放的比例,進而計算出目標副本數。須要注意的是,若是pod某些容器不支持資源採集,那麼控制器將不會使用該pod的CPU使用率node
2)若是 pod 使用自定義指標,控制器機制與資源指標相似,區別在於自定義指標只使用原始值,而不是使用率。nginx
3)若是pod 使用對象指標和外部指標(每一個指標描述一個對象信息)。這個指標將直接跟據目標設定值相比較,並生成一個上面提到的縮放比例。在autoscaling/v2beta2版本API中,這個指標也能夠根據pod數量平分後再計算。一般狀況下,控制器將從一系列的聚合API(metrics.k8s.io、custom.metrics.k8s.io和external.metrics.k8s.io)中獲取指標數據。metrics.k8s.io API一般由 metrics-server(須要額外啓動)提供。git
metrics-server是一個集羣範圍內的資源數據集和工具,一樣的,metrics-server也只是顯示數據,並不提供數據存儲服務,主要關注的是資源度量API的實現,好比CPU、文件描述符、內存、請求延時等指標,metric-server收集數據給k8s集羣內使用,如kubectl,hpa,scheduler等github
須要的鏡像是:docker
k8s.gcr.io/metrics-server-amd64:v0.3.6和 k8s.gcr.io/addon-resizer:1.8.4
鏡像所在百度網盤地址以下:apache
連接:https://pan.baidu.com/s/1SKpNaskVr_zQJVQuM_GzIQ 提取碼:24yb 連接:https://pan.baidu.com/s/1KXOSiSJGGGaUXCjdCHoXjQ 提取碼:yab5
若是你們機器不能訪問外部網絡,能夠把鏡像上傳到k8s的各個節點,按以下方法手動解壓api
docker load -i metrics-server-amd64_0_3_1.tar.gz docker load -i addon.tar.gz
cat metrics.yaml服務器
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: metrics-server:system:auth-delegator labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:auth-delegator subjects: - kind: ServiceAccount name: metrics-server namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: metrics-server-auth-reader namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: extension-apiserver-authentication-reader subjects: - kind: ServiceAccount name: metrics-server namespace: kube-system --- apiVersion: v1 kind: ServiceAccount metadata: name: metrics-server namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: system:metrics-server labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile rules: - apiGroups: - "" resources: - pods - nodes - nodes/stats - namespaces verbs: - get - list - watch - apiGroups: - "extensions" resources: - deployments verbs: - get - list - update - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: system:metrics-server labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:metrics-server subjects: - kind: ServiceAccount name: metrics-server namespace: kube-system --- apiVersion: v1 kind: ConfigMap metadata: name: metrics-server-config namespace: kube-system labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: EnsureExists data: NannyConfiguration: |- apiVersion: nannyconfig/v1alpha1 kind: NannyConfiguration --- apiVersion: apps/v1 kind: Deployment metadata: name: metrics-server namespace: kube-system labels: k8s-app: metrics-server kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile version: v0.3.6 spec: selector: matchLabels: k8s-app: metrics-server version: v0.3.6 template: metadata: name: metrics-server labels: k8s-app: metrics-server version: v0.3.6 annotations: scheduler.alpha.kubernetes.io/critical-pod: '' seccomp.security.alpha.kubernetes.io/pod: 'docker/default' spec: priorityClassName: system-cluster-critical serviceAccountName: metrics-server containers: - name: metrics-server image: k8s.gcr.io/metrics-server-amd64:v0.3.6 command: - /metrics-server - --metric-resolution=30s - --kubelet-preferred-address-types=InternalIP - --kubelet-insecure-tls ports: - containerPort: 443 name: https protocol: TCP - name: metrics-server-nanny image: k8s.gcr.io/addon-resizer:1.8.4 resources: limits: cpu: 100m memory: 300Mi requests: cpu: 5m memory: 50Mi env: - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace volumeMounts: - name: metrics-server-config-volume mountPath: /etc/config command: - /pod_nanny - --config-dir=/etc/config - --cpu=300m - --extra-cpu=20m - --memory=200Mi - --extra-memory=10Mi - --threshold=5 - --deployment=metrics-server - --container=metrics-server - --poll-period=300000 - --estimator=exponential - --minClusterSize=2 volumes: - name: metrics-server-config-volume configMap: name: metrics-server-config tolerations: - key: "CriticalAddonsOnly" operator: "Exists" - key: node-role.kubernetes.io/master effect: NoSchedule --- apiVersion: v1 kind: Service metadata: name: metrics-server namespace: kube-system labels: addonmanager.kubernetes.io/mode: Reconcile kubernetes.io/cluster-service: "true" kubernetes.io/name: "Metrics-server" spec: selector: k8s-app: metrics-server ports: - port: 443 protocol: TCP targetPort: https --- apiVersion: apiregistration.k8s.io/v1beta1 kind: APIService metadata: name: v1beta1.metrics.k8s.io labels: kubernetes.io/cluster-service: "true" addonmanager.kubernetes.io/mode: Reconcile spec: service: name: metrics-server namespace: kube-system group: metrics.k8s.io version: v1beta1 insecureSkipTLSVerify: true groupPriorityMinimum: 100 versionPriority: 100
kubectl apply -f metrics.yaml
kubectl get pods -n kube-system
顯示以下running狀態說明啓動成功
metrics-server組件安裝成功以後,就可使用kubectl top命令了
kubectl top nodes
顯示以下:
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% k8s-master 660m 16% 1608Mi 20% k8s-node 348m 8% 1046Mi 28%
kubectl top pods -n kube-system
顯示以下:
NAME CPU(cores) MEMORY(bytes) calico-node-9wkmr 100m 26Mi calico-node-sp5m6 162m 35Mi coredns-6955765f44-j2xrl 8m 8Mi coredns-6955765f44-th2sb 10m 8Mi etcd-k8s-master 48m 44Mi kube-apiserver-k8s-master 128m 286Mi kube-controller-manager-k8s-master 79m 38Mi kube-proxy-9s48h 2m 17Mi kube-proxy-vcx2s 2m 10Mi kube-scheduler-k8s-master 12m 15Mi metrics-server-5cf9669fbf-jmrdx 3m 17Mi
HPA的API有三個版本,經過kubectl api-versions | grep autoscal可看到
autoscaling/v1
autoscaling/v2beta1
autoscaling/v2beta2
autoscaling/v1只支持基於CPU指標的縮放; autoscaling/v2beta1支持Resource Metrics(資源指標,如pod的CPU)和Custom Metrics(自定義指標)的縮放; autoscaling/v2beta2支持Resource Metrics(資源指標,如pod的CPU)和Custom Metrics(自定義指標)和ExternalMetrics(額外指標)的縮放。
與其餘API資源相似,kubectl也支持Pod自動伸縮。咱們能夠經過kubectl create命令建立一個自動伸縮對象,經過kubectl get hpa命令來獲取全部自動伸縮對象,經過kubectl describe hpa命令來查看自動伸縮對象的詳細信息。最後,可使用kubectl delete hpa命令刪除對象。此外,還有個簡便的命令kubectl autoscale來建立自動伸縮對象。例如,命令kubectl autoscale rs foo --min=2 --max=5 --cpu-percent=80將會爲名爲foo的replication set建立一個自動伸縮對象,對象目標的CPU使用率爲80%,副本數量配置爲2到5之間。
在Kubernetes1.6+中支持基於多個指標進行縮放。你可使用autoscaling/v2beta2 API來爲HPA指定多個指標。HPA會跟據每一個指標計算,並生成一個縮放建議。
自Kubernetes1.6起,HPA支持使用自定義指標。你可使用autoscaling/v2beta2 API爲HPA指定用戶自定義指標。Kubernetes會經過用戶自定義指標API來獲取相應的指標。
用Deployment建立一個php-apache服務,而後利用HPA進行自動擴縮容。步驟以下:
使用dockerfile構建一個新的鏡像,在k8s的master節點構建
cat dockerfile
FROM php:5-apache ADD index.php /var/www/html/index.php RUN chmod a+rx index.php
cat index.php
<?php $x = 0.0001; for ($i = 0; $i <= 1000000;$i++) { $x += sqrt($x); } echo "OK!"; ?>
docker build -t k8s.gcr.io/hpa-example:v1 .
docker save -o hpa-example.tar.gz k8s.gcr.io/hpa-example:v1
能夠把鏡像傳到k8s的各個節點,docker load-i hpa-example.tar.gz進行解壓
cat php-apache.yaml
apiVersion:apps/v1 kind:Deployment metadata: name:php-apache spec: selector: matchLabels: run:php-apache replicas:1 template: metadata: labels: run:php-apache spec: containers: -name:php-apache image:k8s.gcr.io/hpa-example:v1 ports: -containerPort:80 resources: limits: cpu:500m requests: cpu:200m --- apiVersion: v1 kind:Service metadata: name:php-apache labels: run:php-apache spec: ports: -port:80 selector: run:php-apache
kubectl apply -f php-apache.yaml
kubectl get pods
顯示以下,說明php服務部署成功了
NAME READY STATUS RESTARTS AGE php-apache-5694767d56-mmr88 1/1 Running 0 66s
php-apache服務正在運行,使用kubectl autoscale建立自動縮放器,實現對php-apache這個deployment建立的pod自動擴縮容,下面的命令將會建立一個HPA,HPA將會根據CPU,內存等資源指標增長或減小副本數,建立一個能夠實現以下目的的hpa:
1)讓副本數維持在1-10個之間(這裏副本數指的是經過deployment部署的pod的副本數) 2)將全部Pod的平均CPU使用率維持在50%(經過kubectlrun運行的每一個pod若是是200毫核,這意味着平均CPU利用率爲100毫核
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
上面命令解釋說明
kubectl autoscale deployment php-apache (php-apache表示deployment的名字) --cpu-percent=50(表示cpu使用率不超過50%) --min=1(最少一個pod) --max=10(最多10個pod)
kubectl get hpa
顯示以下說明建立成功:
注:因爲咱們沒有向服務器發送任何請求,所以當前CPU消耗爲0%(TARGET列顯示了由相應的deployment控制的全部Pod的平均值)。
啓動一個容器,並將無限查詢循環發送到php-apache服務(複製k8s的master節點的終端,也就是打開一個新的終端窗口):
kubectl run v1 -it --image=busybox /bin/sh
登陸到容器以後,執行以下命令
while true; do wget -q -O- http://php-apache.default.svc.cluster.local; done
在一分鐘左右的時間內,咱們經過執行如下命令來看到更高的CPU負載
kubectl get hpa
顯示以下:
上面能夠看到,CPU消耗已經達到256%,每一個pod的目標cpu使用率是50%
,因此,php-apache這個deployment建立的pod副本數將調整爲5個副本,爲何是5個副本,由於256/50=5
kubectl get pod
顯示以下:
NAME READY STATUS RESTARTS AGE php-apache-5694767d56-b2kd7 1/1 Running 0 18s php-apache-5694767d56-f9vzm 1/1 Running 0 2s php-apache-5694767d56-hpgb5 1/1 Running 0 18s php-apache-5694767d56-mmr88 1/1 Running 0 4h13m php-apache-5694767d56-zljkd 1/1 Running 0 18s
kubectl get deployment php-apache
顯示以下:
NAME READY UP-TO-DATE AVAILABLE AGE php-apache 5/5 5 5 2h1m
注意:可能須要幾分鐘來穩定副本數。因爲不以任何方式控制負載量,所以最終副本數可能會與此示例不一樣。
中止向php-apache這個服務發送查詢請求,在busybox鏡像建立容器的終端中,經過<Ctrl>+ C把剛纔while請求中止,而後,咱們將驗證結果狀態(大約一分鐘後):
kubectl get hpa
顯示以下:
kubectl get deployment php-apache
顯示以下:
經過上面能夠看到,CPU利用率降低到0,所以HPA自動將副本數縮減到1。
注意:自動縮放副本可能須要幾分鐘。
cat nginx.yaml
apiVersion:apps/v1 kind: Deployment metadata: name:nginx-hpa spec: selector: matchLabels: app: nginx replicas: 1 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.9.1 ports: - containerPort: 80 name: http protocol: TCP resources: requests: cpu: 0.01 memory: 25Mi limits: cpu: 0.05 memory: 60Mi --- apiVersion: v1 kind: Service metadata: name: nginx labels: app: nginx spec: selector: app: nginx type: NodePort ports: - name: http protocol: TCP port: 80 targetPort: 80 nodePort: 30080
kubectl apply -f nginx.yaml
kubectl get pods
顯示以下,說明nginx的pod正常運行:
NAME READY STATUS RESTARTS AGE nginx-hpa-bb598885d-j4kcp 1/1 Running 0 17m
注意:nginx的pod裏須要有以下字段,不然hpa會採集不到內存指標
resources: requests: cpu: 0.01 memory: 25Mi limits: cpu: 0.05 memory: 60Mi
cat hpa-v1.yaml
apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: nginx-hpa spec: maxReplicas: 10 minReplicas: 1 scaleTargetRef: apiVersion:apps/v1 kind: Deployment name: nginx-hpa metrics: - type: Resource resource: name: memory targetAverageUtilization: 60
kubectl get hpa
顯示以下:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE nginx-hpa Deployment/nginx-hpa 5%/60% 1 10 1 20s
登陸到上面經過pod建立的nginx,並生成一個文件,增長內存
kubectl exec -it nginx-hpa-bb598885d-j4kcp -- /bin/sh
壓測:
dd if=/dev/zero of=/tmp/a
打開新的終端:
kubectl get hpa
顯示以下:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE nginx-hpa Deployment/nginx-hpa 200%/60% 1 10 3 12m
上面的targets列可看到200%/60%,200%表示當前cpu使用率,60%表示全部pod的cpu使用率維持在60%,如今cpu使用率達到200%,因此pod增長到4個
kubectl get deployment
顯示以下:
NAME READY UP-TO-DATE AVAILABLE AGE nginx-hpa 4/4 4 4 25m
kubectl get pods
顯示以下:
NAME READY STATUS RESTARTS AGE nginx-hpa-bb598885d-j4kcp 1/1 Running 0 25m nginx-hpa-bb598885d-rj5hk 1/1 Running 0 63s nginx-hpa-bb598885d-twv9c 1/1 Running 0 18s nginx-hpa-bb598885d-v9ft5 1/1 Running 0 63s
kubectl exec -it nginx-hpa-bb598885d-j4kcp -- /bin/sh
刪除/tmp/a這個文件
rm -rf /tmp/a
kubectl get hpa
顯示以下,可看到內存使用率已經降到5%:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE nginx-hpa Deployment/nginx-hpa 5%/60% 1 10 1 26m
kubectl get deployment
顯示以下,deployment的pod又恢復到1個了:
NAME READY UP-TO-DATE AVAILABLE AGE nginx-hpa 1/1 1 1 38m
能夠經過使用autoscaling/v2beta2 API版原本介紹在自動縮放php-apache這個deployment時使用的其餘度量指標(metrics)。
kubectl get hpa.v2beta2.autoscaling -o yaml > /tmp/hpa-v2.yaml
在編輯器打開文件/tmp/hpa-v2.yaml,刪除掉一些不須要要的字段,可看到以下yaml
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: php-apache namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: php-apache minReplicas: 1 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 50 status: observedGeneration: 1 lastScaleTime: <some-time> currentReplicas: 1 desiredReplicas: 1 currentMetrics: - type: Resource resource: name: cpu current: averageUtilization: 0 averageValue: 0
targetCPUUtilizationPercentage字段由metrics所取代,CPU利用率這個度量指標是一個resource metric(資源度量指標),由於它表示容器上指定資源的百分比。 除CPU外,你還能夠指定其餘資源度量指標。默認狀況下,目前惟一支持的其餘資源度量指標爲內存。只要metrics.k8s.io API存在,這些資源度量指標就是可用的,而且他們不會在不一樣的Kubernetes集羣中改變名稱。你還能夠指定資源度量指標使用絕對數值,而不是百分比,你須要將target類型AverageUtilization替換成AverageValue,同時將target.averageUtilization替換成target.averageValue並設定相應的值。還有兩種其餘類型的度量指標,他們被認爲是custom metrics(自定義度量指標): 即Pod度量指標和對象度量指標(pod metrics and object metrics)。這些度量指標可能具備特定於集羣的名稱,而且須要更高級的集羣監控設置。第一種可選的度量指標類型是Pod度量指標。這些指標從某一方面描述了Pod,在不一樣Pod之間進行平均,並經過與一個目標值比對來肯定副本的數量。它們的工做方式與資源度量指標很是相像,差異是它們僅支持target類型爲AverageValue。
Pod 度量指標經過以下代碼塊定義
type: Pods pods: metric: name: packets-per-second target: type: AverageValue averageValue: 1k
第二種可選的度量指標類型是對象度量指標。相對於描述Pod,這些度量指標用於描述一個在相同名字空間(namespace)中的其餘對象。請注意這些度量指標用於描述這些對象,並不是從對象中獲取。對象度量指標支持的target類型包括Value和AverageValue。若是是Value類型,target值將直接與API返回的度量指標比較,而AverageValue類型,API返回的度量指標將按照Pod數量拆分,而後再與target值比較。下面的YAML文件展現了一個表示requests-per-second的度量指標。
type: Object object: metric: name: requests-per-second describedObject: apiVersion: networking.k8s.io/v1beta1 kind: Ingress name: main-route target: type: Value value: 2k
若是你指定了多個上述類型的度量指標,HorizontalPodAutoscaler將會依次考量各個指標。HorizontalPodAutoscaler將會計算每個指標所提議的副本數量,而後最終選擇一個最高值。好比,若是你的監控系統可以提供網絡流量數據,你能夠經過kubectl edit命令將上述Horizontal Pod Autoscaler的定義更改成:
apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: name: php-apache namespace: default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: php-apache minReplicas: 1 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: type: AverageUtilization averageUtilization: 50 - type: Pods pods: metric: name: packets-per-second targetAverageValue: 1k - type: Object object: metric: name: requests-per-second describedObject: apiVersion: networking.k8s.io/v1beta1 kind: Ingress name: main-route target: kind: Value value: 10k status: observedGeneration: 1 lastScaleTime: <some-time> currentReplicas: 1 desiredReplicas: 1 currentMetrics: - type: Resource resource: name: cpu current: averageUtilization: 0 averageValue: 0 - type: Object object: metric: name: requests-per-second describedObject: apiVersion: networking.k8s.io/v1beta1 kind: Ingress name: main-route current: value: 10k
而後,你的HorizontalPodAutoscaler將會嘗試確保每一個Pod的CPU利用率在50%之內,每秒可以服務1000個數據包請求,並確保全部在Ingress後的Pod每秒可以服務的請求總數達到10000個。
許多度量管道容許你經過名稱或附加的_labels_來描述度量指標。對於全部非資源類型度量指標(pod、object和後面將介紹的external),能夠額外指定一個標籤選擇器。例如,若是你但願收集包含verb標籤的http_requests度量指標, 你能夠在GET請求中指定須要的度量指標,以下所示:
type:Object object: metric: name:`http_requests` selector:`verb=GET`
這個選擇器使用與Kubernetes標籤選擇器相同的語法。若是名稱和標籤選擇器匹配到多個系列,監測管道會決定如何將多個系列合併成單個值。選擇器是附加的,它不會選擇目標之外的對象(類型爲Pods的目標和類型爲Object的目標)。
運行在Kubernetes上的應用程序可能須要基於與Kubernetes集羣中的任何對象沒有明顯關係的度量指標進行自動伸縮,例如那些描述不在Kubernetes任何namespaces服務的度量指標。使用外部的度量指標,須要瞭解你使用的監控系統,相關的設置與使用自定義指標相似。 External metrics可使用你的監控系統的任何指標來自動伸縮你的集羣。你只須要在metric塊中提供name和selector,同時將類型由Object改成External。若是metricSelector匹配到多個度量指標,HorizontalPodAutoscaler將會把它們加和。 External metrics同時支持Value和AverageValue類型,這與Object類型的度量指標相同。例如,若是你的應用程序處理主機上的消息隊列, 爲了讓每30個任務有1個worker,你能夠將下面的內容添加到 HorizontalPodAutoscaler 的配置中。
-type:External
external:
metric:
name:queue_messages_ready
selector:"queue=worker_tasks"
target:
type:AverageValue
averageValue:30
仍是推薦custom metric而不是external metrics,由於這便於讓系統管理員加固custom metrics API。而external metrics API能夠容許訪問全部的度量指標,當暴露這些服務時,系統管理員須要仔細考慮這個問題。
想要了解kubernetes、微服務、DevOps更多知識和生產案例,獲取免費視頻,可按以下方式獲取哈~~~
微信:luckylucky421302