服务网格ASM的Mixerless Telemetry技术,为业务容器提供了无侵入式的遥测数据。当您遇到应用性能波动或资源利用不均衡问题时,可以基于Mixerless Telemetry技术实现应用扩缩容。通过使用Prometheus采集关键性能指标,如请求数量、请求延迟、P99分布等,HPA(Horizontal Pod Autoscaler)能够依据这些实时数据自动调整Pod数量,确保应用在负载波动时保持最优性能,实现资源的高效利用。
前提条件
已使用Prometheus采集应用监控指标。具体操作,请参见基于Mixerless Telemetry实现服务网格的可观测性。
步骤一:部署metrics-adapter和flagger loadtester
通过kubectl连接集群。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群。
执行以下命令,部署metrics-adapter。
说明关于metrics-adapter完整脚本,请参见demo_hpa.sh。
helm --kubeconfig <kubeconfig位置> -n kube-system install asm-custom-metrics $KUBE_METRICS_ADAPTER_SRC/deploy/charts/kube-metrics-adapter --set prometheus.url=http://prometheus.istio-system.svc:9090
验证metrics-adapter部署情况。
执行以下命令,查看metrics-adapter的Pod部署情况。
kubectl --kubeconfig <kubeconfig位置> get po -n kube-system | grep metrics-adapter
预期输出:
asm-custom-metrics-kube-metrics-adapter-6fb4949988-ht8pv 1/1 Running 0 30s
执行以下命令,查看autoscaling/v2beta的CRD部署情况。
kubectl --kubeconfig <kubeconfig位置> api-versions | grep "autoscaling/v2beta"
预期输出:
autoscaling/v2beta1 autoscaling/v2beta2
执行以下命令,查看metrics-adapter部署情况。
kubectl --kubeconfig <kubeconfig位置> get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq .
预期输出:
{ "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "external.metrics.k8s.io/v1beta1", "resources": [] }
部署flagger loadtester。
下载flagger loadtester的YAML文件。关于flagger loadtester的YAML文件下载地址,请参见flagger。
执行以下命令,部署flagger loadtester。
kubectl --kubeconfig <kubeconfig位置> apply -f <flagger的位置>/kustomize/tester/deployment.yaml -n test kubectl --kubeconfig <kubeconfig位置> apply -f <flagger的位置>/kustomize/tester/service.yaml -n test
步骤二:创建HPA
创建根据应用请求数量(istio_requests_total)扩缩容的HPA。
使用以下内容,创建一个名为requests_total_hpa的YAML文件。
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: podinfo-total namespace: test annotations: metric-config.external.prometheus-query.prometheus/processed-requests-per-second: | sum(rate(istio_requests_total{destination_workload_namespace="test",reporter="destination"}[1m])) spec: maxReplicas: 5 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"
annotations:设置应用的Pod会受到应用请求数量(istio_requests_total)影响进行扩缩容。
target:当应用请求数量的平均值大于等于10时,应用的Pod会自动扩容。
执行以下命令,部署HPA。
kubectl --kubeconfig <kubeconfig位置> apply -f resources_hpa/requests_total_hpa.yaml
验证HPA部署情况。
kubectl --kubeconfig <kubeconfig位置> get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq .
预期输出:
{ "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "external.metrics.k8s.io/v1beta1", "resources": [ { "name": "prometheus-query", "singularName": "", "namespaced": true, "kind": "ExternalMetricValueList", "verbs": [ "get" ] } ] }
使用以下内容,部署根据平均延迟(istio_request_duration_milliseconds_sum)扩缩容的HPA。
部署根据平均延迟扩缩容的HPA的具体步骤,请参见上文。
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: podinfo-latency-avg namespace: test annotations: metric-config.external.prometheus-query.prometheus/latency-average: | sum(rate(istio_request_duration_milliseconds_sum{destination_workload_namespace="test",reporter="destination"}[1m])) /sum(rate(istio_request_duration_milliseconds_count{destination_workload_namespace="test",reporter="destination"}[1m])) spec: maxReplicas: 5 minReplicas: 1 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: podinfo metrics: - type: External external: metric: name: prometheus-query selector: matchLabels: query-name: latency-average target: type: AverageValue averageValue: "0.005"
annotations:设置HPA会受到平均延迟(istio_request_duration_milliseconds_sum)影响进行扩缩容。
target:当平均延迟的平均值大于等于0.005s时,应用的Pod会进行自动扩容。
使用以下内容,部署根据P95分布(istio_request_duration_milliseconds_bucket)扩缩容的HPA。
部署根据P95分布扩缩容的HPA的具体步骤,请参见上文。
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: podinfo-p95 namespace: test annotations: metric-config.external.prometheus-query.prometheus/p95-latency: | histogram_quantile(0.95,sum(irate(istio_request_duration_milliseconds_bucket{destination_workload_namespace="test",destination_canonical_service="podinfo"}[5m]))by (le)) spec: maxReplicas: 5 minReplicas: 1 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: podinfo metrics: - type: External external: metric: name: prometheus-query selector: matchLabels: query-name: p95-latency target: type: AverageValue averageValue: "4"
annotations:设置应用的Pod会受到P95分布(istio_request_duration_milliseconds_bucket)影响进行扩缩容。
target:当P95分布的平均值大于等于4时,应用的Pod会自动扩容。
验证应用扩缩容
以下以应用请求数量为例,验证当应用请求数量大于等于10时,应用的Pod是否会自动进行扩容。
执行以下命令,运行了一个持续5分钟、QPS为10、并发数为2的请求。
alias k="kubectl --kubeconfig $USER_CONFIG" loadtester=$(k -n test get pod -l "app=flagger-loadtester" -o jsonpath='{.items..metadata.name}') k -n test exec -it ${loadtester} -c loadtester -- hey -z 5m -c 2 -q 10 http://podinfo:9898
-z
:请求持续时间。-q
:请求数量。-c
:请求并发数。
执行以下命令,查看Pod扩容情况。
watch kubectl --kubeconfig $USER_CONFIG -n test get hpa/podinfo-total
预期输出:
Every 2.0s: kubectl --kubeconfig /Users/han/shop_config/ack_zjk -n test get hpa/podinfo East6C16G: Tue Jan 26 18:01:30 2021 NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE podinfo Deployment/podinfo 10056m/10 (avg) 1 5 2 4m45s
可以看到
REPLICAS
为2,说明当前应用的Pod数量为2。执行以下命令,运行了一个持续5分钟、QPS为15、并发数为2的请求。
alias k="kubectl --kubeconfig $USER_CONFIG" loadtester=$(k -n test get pod -l "app=flagger-loadtester" -o jsonpath='{.items..metadata.name}') k -n test exec -it ${loadtester} -c loadtester -- hey -z 5m -c 2 -q 15 http://podinfo:9898
执行以下命令,查看Pod扩容情况。
watch kubectl --kubeconfig $USER_CONFIG -n test get hpa/podinfo-total
预期输出:
Every 2.0s: kubectl --kubeconfig /Users/han/shop_config/ack_zjk -n test get hpa/podinfo East6C16G: Tue Jan 26 18:01:30 2021 NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE podinfo Deployment/podinfo 10056m/10 (avg) 1 5 3 4m45s
可以看到
REPLICAS
为3,当前应用的Pod数量为3。说明随着请求数增加,应用的Pod自动进行了扩容。减少对应用的请求,可以看到REPLICAS
逐渐变为1。随着请求数减少,应用的Pod自动进行了缩容。