概念
Kubernetes自1.11版本開始引入了名為"HorizontalPodAutoscaler"的控制器用於完成Pod基於CPU使用率進行水平擴展。所謂水平擴展是在Pod中CPU的使用率達到設定的某個值時,HPA告知Pod對應的高層控制器(如Deployment、RS等控制器)。高層控制器隨即創建出多個pod副本平衡負載使Pod的平均CPU使用率低於我們設定的值。當Pod的平均CPU使用率變小時,又能回收多余的Pod以避免資源浪費。
除了CPU使用率這個指標外,還可以采用自定義的指標。通常自定義的指標需要容器以某種方式提供,如URL路徑"/metrics"提供,即http://
HPA控制器配置
目前HPA(HorizontalPodAutoscaler)資源對象處於Kubernetes的API組"autoscaling"中,包括v1、v2beta1及v2beta2三個API版本,其中"autoscaling/v1"僅支持基於CPU的自動擴縮容,而"autoscaling/v2"則支持基於自定義指標類型的數據。
為了使用HPA需要實現部署Metrics-Server。項目地址https://github.com/kubernetes-sigs/metrics-server,由於我本地環境是用Operator部署的Prometheus,部署完自帶metrics-server
,所以不再手動部署。
部署完成metrics-server后稍等一會后就可以使用kubectl top node/pod
命令查看節點或者pod的CPU及內存使用率了。
(1)基於autoscaling/v1版本的HPA配置,僅可以設置CPU使用率
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: php-apache
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: php-apache
miniReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 50
- scaleTargetRef:定義目標作用對象,可以是Deployment、RS
- targetCPUUtilizationPercentage:目標pod的CPU閾值,超過這個值即觸發擴容操作
- miniReplicas及maxReplicas:最小及最大副本數量,HPA會自動在這個范圍內進行Pod的自動伸縮同時維持各個Pod的CPU使用率為50%
(2)基於autoscaling/v2beta2的HPA配置
type=Resource
type=Resource的指標數據由metrics-server采集並提供給HPA控制器
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
name: sample-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sample-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu / memory
target:
type: Utilization
averageUtilization: 50 / averageValue: 200MiB
其中type字段可為:
-
Resource:基於資源的指標值,指標數據可以通過metrics.k8s.io這個API查詢。
-
Pods:基於Pod的指標
-
Object:基於某種資源對象,如ingress或者任意自定義的指標
Pods與Object是自定義指標,需要搭建自定義的Metrics Server和監控工具進行指標采集。指標數據通過custom.metrics.k8s.io進行查詢,必須先啟動自定義的Metrics Server。
type=pods(本次采用的類型)
類型為Pods的類型指標數據來源於Pod對象本身,target指標只能是AverageValue。
metrics:
- type: Pods
pods:
metrics:
name: packet-per-second
target:
type: AverageValue
averageValue: 1k
type=object
type=object的指標數據來自其他資源或者是自定義的指標。target指標為Value或者是AverageValue
#指標名稱為requests-per-second,其值來源於Ingress"main-route"的目標值,即Ingress每秒請求量達到2000時觸發擴容操作
metrics:
- type: Object
object:
metric:
name: requests-per-second
describeObject:
apiVersion: extensions/v1beta1
kind: Ingress
name: main-route
target:
type: Value
value: 2k
#指標名稱為requests-per-second,其值來源於Ingress"main-route"的目標值,即Ingress每秒請求量達到2000時觸發擴容操作
metrics:
- type: Object
object:
metric:
name: 'http_requests'
selector: 'verb=GET'
target:
type: AverageValue
averageValue: 500
基於自定義指標的HPA實戰
整體概述
按照《Kubernetes權威指南(第四版)》所述的架構圖,由Prometheus采集各個pod的指標通過prometheus-adapter這個適配器將數據提交給指標聚合器,並最終注冊到api-server中,以/apis/custom.metrics.k8s.io
的路徑提供指標數據。HPA控制器從該路徑下獲取數據作為水平自動擴縮容的依據。
配置controller-manager
一般而言通過kubeadm部署的k8s集群不需要進行api-server的手動配置,所需要的配置已經默認開啟。我們只需要配置kube-controller-manager的參數即可。
編輯/etc/kubernetes/manifests/kube-controller-manager.yaml
添加上圖所示的啟動參數。為了加快試驗的效果,這里縮短了默認的配置。生產環境推薦以官方默認配置為准。
創建對象pod
該pod會在/metrics路徑下提供名為http_requests_total的指標。
apiVersion: v1
kind: Service
metadata:
name: sample-app
labels:
app: sample-app
spec:
selector:
app: sample-app
ports:
- name: http
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app
labels:
app: sample-app
spec:
replicas: 1
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- image: luxas/autoscale-demo:v0.1.2
name: metrics-provider
ports:
- name: http
containerPort: 8080
創建ServiceMonitor對象,用於監控程序提供的指標
$ cat service-monitor.yaml
kind: ServiceMonitor
apiVersion: monitoring.coreos.com/v1
metadata:
name: sample-app
labels:
app: sample-app
spec:
selector:
matchLabels:
app: sample-app
endpoints:
- port: http
注意:這里的port:http一定要和上面部署的Service對象中port的名稱一致。應用該對象后稍等2~3分鍾打開promethes的頁面,即可發現相應的監控項已經是up狀態:
配置Adapter
以上配置的指標作http_requests_total為一種持續增長的值,不能反映單位時間內的增長量,不能用作HPA的依據。需要進行適當地轉換,打開adapter的配置,添加如下配置並應用:
config.yaml: |
rules:
#sum(rate(http_requests_total{namespace="xx",pod="xx"}[1m])) by pod:1分鍾內全部pod指標http_requests_total的總和的每秒平均值
- metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)
#將metricsQuery計算的結果賦給新的指標`http_requests`並提供給HPA控制器
name:
as: "${1}"
matches: ^(.*)_total$
resources:
template: <<.Resource>>
seriesFilters:
- isNot: .*_seconds_total$
seriesQuery: '{namespace!="",__name__=~"http_requests_.*"}'
應用configmap完成后刪除adapter Pod,使新的配置生效。
自定義API資源
創建名為v1beta1.custom.metrics.k8s.io的自定義聚合API資源
apiVersion: apiregistration.k8s.io/v1beta1
kind: APIService
metadata:
name: v1beta1.custom.metrics.k8s.io
spec:
service:
name: prometheus-adapter
namespace: monitoring
group: custom.metrics.k8s.io
version: v1beta1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100
創建HPA控制器資源
在以上資源創建完成后即可以創建HPA控制器了
kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta2
metadata:
name: sample-app
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sample-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: Pods
pods:
metric:
name: http_requests
target:
type: AverageValue
averageValue: 500m
- type=pods:表示從Pods自身獲取指標
- name=http_requests:即adapter中的配置,有http_requests_total計算而來
- averageValue=500m:即http_requests的目標值為500m。
通過聚合API查詢指標數據,pod指標成功采集
驗證動態擴縮容
在其他終端請求sample-app的地址進行壓測:
$ for i in {1..100000};do wget -q -O- 10.233.38.160 > /dev/null;done
自動擴容成功
停止訪問請求一分鍾后(kube-controller-manager
中設定的參數--horizontal-pod-autoscaler-downscale-stabilization=1min
進行縮容操作)pod數量成功回落到1個
參考
- 《Kubernetes權威指南(第四版)》(p241-p264)