全部產品
Search
文件中心

Alibaba Cloud Service Mesh:使用ASM指標實現工作負載的自動Auto Scaling

更新時間:Dec 21, 2024

Service Mesh (ASM)為ACK叢集和ACS叢集內的服務通訊提供了一種非侵入式的產生遙測資料的能力。這種遙測功能提供了服務行為的可觀測性,可以協助營運人員對應用程式進行故障排除、維護和最佳化,而不會帶來任何額外負擔。根據監控的四個黃金指標維度(延遲、流量、錯誤和飽和度),ASM為管理的服務產生一系列指標。本文介紹如何使用ASM指標實現工作負載的自動Auto Scaling。

前提條件

背景資訊

Service MeshASM為管理的服務產生一系列指標。更多資訊,請參見Istio標準指標

自動調整是一種根據資源使用方式進行自動擴縮工作負載的方法。Kubernetes中的自動調整具有以下兩個維度:

  • 叢集自動調整器CA(Cluster Autoscaler):用於處理節點伸縮操作,可以增加或減少節點。

  • 水平自動調整器HPA(Horizontal Pod Autoscaler):用於自動調整應用部署中的Pod,可以調節Pod的數量。

Kubernetes提供的彙總層允許第三方應用程式將自身註冊為API Addon組件來擴充Kubernetes API。這樣的Addon組件可以實現Custom Metrics API,並允許HPA訪問任意指標。HPA會定期通過Resource Metrics API查詢核心指標(例如CPU或記憶體)以及通過Custom Metrics API擷取特定於應用程式的指標,包括ASM提供的可觀測性指標。

步驟一:開啟採集Prometheus監控指標

具體操作,請參見將監控指標採集到可觀測監控Prometheus版

步驟二:部署自訂指標API Adapter

  1. 執行以下命令,下載Adapter安裝包,然後在叢集中安裝部署自訂指標API Adapter。

    關於Adapter安裝包的更多資訊,請參見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
  2. 安裝完成後,通過以下方式確認kube-metrics-adapter已啟用。

    • 執行以下命令,確認autoscaling/v2beta已存在。

      kubectl api-versions |grep "autoscaling/v2beta"

      預期輸出:

      autoscaling/v2beta
    • 執行以下命令,確認kube-metrics-adapter Pod狀態。

      kubectl get po -n kube-system |grep metrics-adapter

      預期輸出:

      asm-custom-metrics-kube-metrics-adapter-85c6d5d865-2****          1/1     Running   0          19s
    • 執行以下命令,列出Prometheus適配器提供的自訂外部指標。

      kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1" | jq .

      預期輸出:

      {
        "kind": "APIResourceList",
        "apiVersion": "v1",
        "groupVersion": "external.metrics.k8s.io/v1beta1",
        "resources": []
      }

步驟三:部署樣本應用

  1. 建立test命名空間。具體操作,請參見管理命名空間與配額

  2. 啟用Sidecar自動注入。具體操作,請參見啟用自動注入

  3. 部署樣本應用。

    1. 使用以下內容,建立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
    2. 執行以下命令,部署podinfo。

      kubectl apply -n test -f podinfo.yaml
  4. 為了觸發自動Auto Scaling,需要在命名空間test中部署負載測試服務,用於觸發請求。

    1. 使用以下內容,建立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
    2. 執行以下命令,部署負載測試服務。

      kubectl apply -n test -f loadtester.yaml
  5. 驗證部署樣本應用和負載測試服務是否成功。

    1. 執行以下命令,確認Pod狀態。

      kubectl get pod -n test

      預期輸出:

      NAME                          READY   STATUS    RESTARTS   AGE
      loadtester-64df4846b9-nxhvv   2/2     Running   0          2m8s
      podinfo-6d845cc8fc-26xbq      2/2     Running   0          11m
    2. 執行以下命令,進入負載測試器容器,並使用hey命令產生負載。

      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

      返回結果,產生負載成功,說明樣本應用和負載測試服務部署成功。

步驟四:使用ASM指標配置HPA

定義一個HPA,該HPA將根據每秒接收的請求數來擴縮Podinfo的工作負載數量。當平均請求流量負載超過10 req/sec時,將指示HPA擴大部署。

  1. 使用以下內容,建立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"
  2. 執行以下命令,部署HPA。

    kubectl apply -f hpa.yaml
  3. 執行以下命令,驗證HPA是否部署成功。

    列出Prometheus適配器提供的自訂外部指標。

    kubectl 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"
          ]
        }
      ]
    }

    返回結果中包含自訂的ASM指標的資源清單,說明HPA部署成功。

驗證自動Auto Scaling

  1. 執行以下命令,進入測試器容器,並使用hey命令產生工作負載請求。

    kubectl -n test exec -it ${loadtester} -c loadtester -- sh
    ~ $ hey -z 5m -c 10 -q 5 http://podinfo.test:9898
  2. 執行以下命令,查看自動調整狀況。

    說明

    預設情況下,指標每30秒執行一次同步,並且只有在最近3分鐘~5分鐘內容器沒有重新縮放時,才可以進行放大或縮小。這樣,HPA可以防止衝突決策的快速執行,並為叢集自動擴充程式預留時間。

    watch kubectl -n test get hpa/podinfo

    預期輸出:

    NAME      REFERENCE            TARGETS          MINPODS   MAXPODS   REPLICAS   AGE
    podinfo   Deployment/podinfo   8308m/10 (avg)   1         10        6          124m

    一分鐘後,HPA將開始擴大工作負載,直到請求/秒降至目標值以下。負載測試完成後,每秒的請求數將降為零,並且HPA將開始縮減工作負載Pod數量,幾分鐘後上述命令返回結果中的REPLICAS副本數將恢複為一個。