使用ASM指標(biāo)實(shí)現(xiàn)工作負(fù)載的自動(dòng)彈性伸縮
服務(wù)網(wǎng)格ASM為ACK集群內(nèi)的服務(wù)通信提供了一種非侵入式的生成遙測(cè)數(shù)據(jù)的能力。這種遙測(cè)功能提供了服務(wù)行為的可觀測(cè)性,可以幫助運(yùn)維人員對(duì)應(yīng)用程序進(jìn)行故障排除、維護(hù)和優(yōu)化,而不會(huì)帶來(lái)任何額外負(fù)擔(dān)。根據(jù)監(jiān)控的四個(gè)黃金指標(biāo)維度(延遲、流量、錯(cuò)誤和飽和度),服務(wù)網(wǎng)格ASM為管理的服務(wù)生成一系列指標(biāo)。本文介紹如何使用ASM指標(biāo)實(shí)現(xiàn)工作負(fù)載的自動(dòng)彈性伸縮。
前提條件
已創(chuàng)建ACK集群。更多信息,請(qǐng)參見(jiàn)創(chuàng)建Kubernetes托管版集群。
已創(chuàng)建ASM實(shí)例。更多信息,請(qǐng)參見(jiàn)創(chuàng)建ASM實(shí)例。
已在ACK集群中創(chuàng)建Prometheus實(shí)例和Grafana示例。更多信息,請(qǐng)參見(jiàn)開(kāi)源Prometheus監(jiān)控。
已集成Prometheus實(shí)現(xiàn)網(wǎng)格監(jiān)控。更多信息,請(qǐng)參見(jiàn)集成自建Prometheus實(shí)現(xiàn)網(wǎng)格監(jiān)控。
背景信息
服務(wù)網(wǎng)格ASM為管理的服務(wù)生成一系列指標(biāo)。更多信息,請(qǐng)參見(jiàn)Istio標(biāo)準(zhǔn)指標(biāo)。
自動(dòng)伸縮是一種根據(jù)資源使用情況進(jìn)行自動(dòng)擴(kuò)縮工作負(fù)載的方法。Kubernetes中的自動(dòng)伸縮具有以下兩個(gè)維度:
集群自動(dòng)伸縮器CA(Cluster Autoscaler):用于處理節(jié)點(diǎn)伸縮操作,可以增加或減少節(jié)點(diǎn)。
水平自動(dòng)伸縮器HPA(Horizontal Pod Autoscaler):用于自動(dòng)伸縮應(yīng)用部署中的Pod,可以調(diào)節(jié)Pod的數(shù)量。
Kubernetes提供的聚合層允許第三方應(yīng)用程序?qū)⒆陨碜?cè)為API Addon組件來(lái)擴(kuò)展Kubernetes API。這樣的Addon組件可以實(shí)現(xiàn)Custom Metrics API,并允許HPA訪問(wèn)任意指標(biāo)。HPA會(huì)定期通過(guò)Resource Metrics API查詢(xún)核心指標(biāo)(例如CPU或內(nèi)存)以及通過(guò)Custom Metrics API獲取特定于應(yīng)用程序的指標(biāo),包括ASM提供的可觀測(cè)性指標(biāo)。
步驟一:開(kāi)啟采集Prometheus監(jiān)控指標(biāo)
具體操作,請(qǐng)參見(jiàn)將監(jiān)控指標(biāo)采集到可觀測(cè)監(jiān)控Prometheus版。
步驟二:部署自定義指標(biāo)API Adapter
執(zhí)行以下命令,下載Adapter安裝包,然后在ACK集群中安裝部署自定義指標(biāo)API Adapter。
關(guān)于Adapter安裝包的更多信息,請(qǐng)參見(jiàn)kube-metrics-adapter。
## 如果使用Helm v3。 helm -n kube-system install asm-custom-metrics ./kube-metrics-adapter --set prometheus.url=http://prometheus.istio-system.svc:9090
安裝完成后,通過(guò)以下方式確認(rèn)kube-metrics-adapter已啟用。
執(zhí)行以下命令,確認(rèn)
autoscaling/v2beta
已存在。kubectl api-versions |grep "autoscaling/v2beta"
預(yù)期輸出:
autoscaling/v2beta
執(zhí)行以下命令,確認(rèn)kube-metrics-adapter Pod狀態(tài)。
kubectl get po -n kube-system |grep metrics-adapter
預(yù)期輸出:
asm-custom-metrics-kube-metrics-adapter-85c6d5d865-2**** 1/1 Running 0 19s
執(zhí)行以下命令,列出Prometheus適配器提供的自定義外部指標(biāo)。
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq .
預(yù)期輸出:
{ "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "external.metrics.k8s.io/v1beta1", "resources": [] }
步驟三:部署示例應(yīng)用
創(chuàng)建test命名空間。具體操作,請(qǐng)參見(jiàn)管理命名空間與配額。
啟用Sidecar自動(dòng)注入。具體操作,請(qǐng)參見(jiàn)啟用自動(dòng)注入。
部署示例應(yīng)用。
使用以下內(nèi)容,創(chuàng)建podinfo.yaml文件。
apiVersion: apps/v1 kind: Deployment metadata: name: podinfo namespace: test labels: app: podinfo spec: minReadySeconds: 5 strategy: rollingUpdate: maxUnavailable: 0 type: RollingUpdate selector: matchLabels: app: podinfo template: metadata: annotations: prometheus.io/scrape: "true" labels: app: podinfo spec: containers: - name: podinfod image: stefanprodan/podinfo:latest imagePullPolicy: IfNotPresent ports: - containerPort: 9898 name: http protocol: TCP command: - ./podinfo - --port=9898 - --level=info livenessProbe: exec: command: - podcli - check - http - localhost:9898/healthz initialDelaySeconds: 5 timeoutSeconds: 5 readinessProbe: exec: command: - podcli - check - http - localhost:9898/readyz initialDelaySeconds: 5 timeoutSeconds: 5 resources: limits: cpu: 2000m memory: 512Mi requests: cpu: 100m memory: 64Mi --- apiVersion: v1 kind: Service metadata: name: podinfo namespace: test labels: app: podinfo spec: type: ClusterIP ports: - name: http port: 9898 targetPort: 9898 protocol: TCP selector: app: podinfo
執(zhí)行以下命令,部署podinfo。
kubectl apply -n test -f podinfo.yaml
為了觸發(fā)自動(dòng)彈性伸縮,需要在命名空間test中部署負(fù)載測(cè)試服務(wù),用于觸發(fā)請(qǐng)求。
使用以下內(nèi)容,創(chuàng)建loadtester.yaml文件。
apiVersion: apps/v1 kind: Deployment metadata: name: loadtester namespace: test labels: app: loadtester spec: selector: matchLabels: app: loadtester template: metadata: labels: app: loadtester annotations: prometheus.io/scrape: "true" spec: containers: - name: loadtester image: weaveworks/flagger-loadtester:0.18.0 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080 command: - ./loadtester - -port=8080 - -log-level=info - -timeout=1h livenessProbe: exec: command: - wget - --quiet - --tries=1 - --timeout=4 - --spider - http://localhost:8080/healthz timeoutSeconds: 5 readinessProbe: exec: command: - wget - --quiet - --tries=1 - --timeout=4 - --spider - http://localhost:8080/healthz timeoutSeconds: 5 resources: limits: memory: "512Mi" cpu: "1000m" requests: memory: "32Mi" cpu: "10m" securityContext: readOnlyRootFilesystem: true runAsUser: 10001 --- apiVersion: v1 kind: Service metadata: name: loadtester namespace: test labels: app: loadtester spec: type: ClusterIP selector: app: loadtester ports: - name: http port: 80 protocol: TCP targetPort: http
執(zhí)行以下命令,部署負(fù)載測(cè)試服務(wù)。
kubectl apply -n test -f loadtester.yaml
驗(yàn)證部署示例應(yīng)用和負(fù)載測(cè)試服務(wù)是否成功。
執(zhí)行以下命令,確認(rèn)Pod狀態(tài)。
kubectl get pod -n test
預(yù)期輸出:
NAME READY STATUS RESTARTS AGE loadtester-64df4846b9-nxhvv 2/2 Running 0 2m8s podinfo-6d845cc8fc-26xbq 2/2 Running 0 11m
執(zhí)行以下命令,進(jìn)入負(fù)載測(cè)試器容器,并使用hey命令生成負(fù)載。
export loadtester=$(kubectl -n test get pod -l "app=loadtester" -o jsonpath='{.items[0].metadata.name}') kubectl -n test exec -it ${loadtester} -c loadtester -- hey -z 5s -c 10 -q 2 http://podinfo.test:9898
返回結(jié)果,生成負(fù)載成功,說(shuō)明示例應(yīng)用和負(fù)載測(cè)試服務(wù)部署成功。
步驟四:使用ASM指標(biāo)配置HPA
定義一個(gè)HPA,該HPA將根據(jù)每秒接收的請(qǐng)求數(shù)來(lái)擴(kuò)縮Podinfo的工作負(fù)載數(shù)量。當(dāng)平均請(qǐng)求流量負(fù)載超過(guò)10 req/sec時(shí),將指示HPA擴(kuò)大部署。
使用以下內(nèi)容,創(chuàng)建hpa.yaml。
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: podinfo namespace: test annotations: metric-config.external.prometheus-query.prometheus/processed-requests-per-second: | sum( rate( istio_requests_total{ destination_workload="podinfo", destination_workload_namespace="test", reporter="destination" }[1m] ) ) spec: maxReplicas: 10 minReplicas: 1 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: podinfo metrics: - type: External external: metric: name: prometheus-query selector: matchLabels: query-name: processed-requests-per-second target: type: AverageValue averageValue: "10"
執(zhí)行以下命令,部署HPA。
kubectl apply -f hpa.yaml
執(zhí)行以下命令,驗(yàn)證HPA是否部署成功。
列出Prometheus適配器提供的自定義外部指標(biāo)。
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq .
預(yù)期輸出:
{ "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "external.metrics.k8s.io/v1beta1", "resources": [ { "name": "prometheus-query", "singularName": "", "namespaced": true, "kind": "ExternalMetricValueList", "verbs": [ "get" ] } ] }
返回結(jié)果中包含自定義的ASM指標(biāo)的資源列表,說(shuō)明HPA部署成功。
驗(yàn)證自動(dòng)彈性伸縮
執(zhí)行以下命令,進(jìn)入測(cè)試器容器,并使用hey命令生成工作負(fù)載請(qǐng)求。
kubectl -n test exec -it ${loadtester} -c loadtester -- sh ~ $ hey -z 5m -c 10 -q 5 http://podinfo.test:9898
執(zhí)行以下命令,查看自動(dòng)伸縮狀況。
說(shuō)明默認(rèn)情況下,指標(biāo)每30秒執(zhí)行一次同步,并且只有在最近3分鐘~5分鐘內(nèi)容器沒(méi)有重新縮放時(shí),才可以進(jìn)行放大或縮小。這樣,HPA可以防止沖突決策的快速執(zhí)行,并為集群自動(dòng)擴(kuò)展程序預(yù)留時(shí)間。
watch kubectl -n test get hpa/podinfo
預(yù)期輸出:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE podinfo Deployment/podinfo 8308m/10 (avg) 1 10 6 124m
一分鐘后,HPA將開(kāi)始擴(kuò)大工作負(fù)載,直到請(qǐng)求/秒降至目標(biāo)值以下。負(fù)載測(cè)試完成后,每秒的請(qǐng)求數(shù)將降為零,并且HPA將開(kāi)始縮減工作負(fù)載Pod數(shù)量,幾分鐘后上述命令返回結(jié)果中的REPLICAS副本數(shù)將恢復(fù)為一個(gè)。