基于Mixerless Telemetry实现应用扩缩容

服务网格ASM的Mixerless Telemetry技术,为业务容器提供了无侵入式的遥测数据。当您遇到应用性能波动或资源利用不均衡问题时,可以基于Mixerless Telemetry技术实现应用扩缩容。通过使用Prometheus采集关键性能指标,如请求数量、请求延迟、P99分布等,HPA(Horizontal Pod Autoscaler)能够依据这些实时数据自动调整Pod数量,确保应用在负载波动时保持最优性能,实现资源的高效利用。

前提条件

已使用Prometheus采集应用监控指标。具体操作,请参见基于Mixerless Telemetry实现服务网格的可观测性

步骤一:部署metrics-adapter和flagger loadtester

  1. 通过kubectl连接集群。具体操作,请参见获取集群KubeConfig并通过kubectl工具连接集群

  2. 执行以下命令,部署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
  3. 验证metrics-adapter部署情况。

    1. 执行以下命令,查看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
    2. 执行以下命令,查看autoscaling/v2beta的CRD部署情况。

      kubectl --kubeconfig <kubeconfig位置> api-versions | grep "autoscaling/v2beta"

      预期输出:

      autoscaling/v2beta1
      autoscaling/v2beta2
    3. 执行以下命令,查看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": []
      }
  4. 部署flagger loadtester。

    1. 下载flagger loadtester的YAML文件。关于flagger loadtester的YAML文件下载地址,请参见flagger

    2. 执行以下命令,部署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

  1. 创建根据应用请求数量(istio_requests_total)扩缩容的HPA。

    1. 使用以下内容,创建一个名为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会自动扩容。

    2. 执行以下命令,部署HPA。

      kubectl --kubeconfig <kubeconfig位置> apply -f resources_hpa/requests_total_hpa.yaml
    3. 验证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"
            ]
          }
        ]
      }
  2. 使用以下内容,部署根据平均延迟(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会进行自动扩容。

  3. 使用以下内容,部署根据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是否会自动进行扩容。

  1. 执行以下命令,运行了一个持续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:请求并发数。

  2. 执行以下命令,查看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。

  3. 执行以下命令,运行了一个持续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
  4. 执行以下命令,查看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自动进行了缩容。