Todos os produtos
Search
Central de documentação

Alibaba Cloud Service Mesh:Use ASM metrics to automatically scale workloads

Última atualização: Jul 05, 2026

O Service Mesh (ASM) coleta dados de telemetria de clusters ACK e ACS de forma não intrusiva e gera métricas de serviço baseadas nos quatro sinais dourados: latência, tráfego, erros e saturação. Este tópico explica como configurar um Horizontal Pod Autoscaler (HPA) para dimensionar cargas de trabalho com base nessas métricas do ASM. Essa abordagem vai além do uso de CPU e memória, permitindo o dimensionamento conforme padrões reais de tráfego.

Como funciona

O ASM expõe métricas de serviço (como requisições por segundo) ao Prometheus. O adaptador de métricas personalizadas kube-metrics-adapter registra essas métricas na camada de agregação do Kubernetes e as disponibiliza para os HPAs por meio da API de métricas personalizadas.

image

Fluxo de ponta a ponta:

  1. O ASM coleta métricas de requisição e as grava no Prometheus.

  2. O kube-metrics-adapter consulta o Prometheus e registra as métricas como métricas externas no Kubernetes.

  3. O HPA consulta a API de métricas externas a cada 30 segundos e ajusta o número de réplicas quando o valor da métrica ultrapassa o limiar.

Para obter a lista completa de métricas geradas pelo ASM, consulte Istio Standard Metrics.

Pré-requisitos

Antes de começar, verifique se você tem:

Etapa 1: Ativar o monitoramento do Prometheus para a instância do ASM

Siga as instruções em Coletar métricas para o Managed Service for Prometheus para ativar a coleta de métricas do Prometheus na sua instância do ASM.

Etapa 2: Implantar o adaptador de métricas personalizadas

O adaptador de métricas personalizadas (kube-metrics-adapter) conecta as métricas do Prometheus à API de métricas externas do Kubernetes, permitindo que os HPAs consultem métricas do ASM diretamente.

  1. Instale o kube-metrics-adapter no namespace kube-system com o Helm 3. Defina prometheus.url como o endereço interno da instância do Prometheus no cluster. Para obter o código-fonte do chart, consulte kube-metrics-adapter.

    Parâmetro

    Descrição

    asm-custom-metrics

    Nome da release do Helm

    prometheus.url

    Endereço interno da instância do Prometheus no cluster que coleta métricas do ASM

    helm -n kube-system install asm-custom-metrics ./kube-metrics-adapter \
      --set prometheus.url=http://prometheus.istio-system.svc:9090
  2. Verifique se o adaptador está em execução:

    1. Confira se o grupo de API autoscaling/v2beta está registrado:

      kubectl api-versions | grep "autoscaling/v2beta"

      Saída esperada:

      autoscaling/v2beta
    2. Valide se o pod do adaptador está em execução:

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

      Saída esperada:

      asm-custom-metrics-kube-metrics-adapter-85c6d5d865-2****   1/1   Running   0   19s
    3. Certifique-se de que a API de métricas externas está disponível (nenhuma métrica registrada ainda):

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

      Saída esperada:

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

Etapa 3: Implantar um aplicativo de exemplo

Esta etapa implanta um aplicativo podinfo e um serviço de teste de carga no namespace test para permitir o acionamento e a observação do dimensionamento automático posteriormente.

  1. Crie o namespace test. Consulte Gerenciar namespaces e cotas de recursos.

  2. Ative a injeção automática de proxy sidecar no namespace test. Consulte Ativar injeção automática de proxy sidecar.

  3. Implante o aplicativo podinfo. Crie um arquivo chamado podinfo.yaml com o conteúdo a seguir e aplique-o.

    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
    kubectl apply -n test -f podinfo.yaml
  4. Implante o serviço de teste de carga. Crie um arquivo chamado loadtester.yaml com o conteúdo a seguir e aplique-o.

    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
    kubectl apply -n test -f loadtester.yaml
  5. Verifique se ambas as cargas de trabalho estão em execução:

    kubectl get pod -n test

    Saída esperada (ambos os pods mostram 2/2 Running, indicando que o contêiner do aplicativo e o sidecar do Istio estão prontos):

    NAME                          READY   STATUS    RESTARTS   AGE
    loadtester-64df4846b9-nxhvv   2/2     Running   0          2m8s
    podinfo-6d845cc8fc-26xbq      2/2     Running   0          11m
  6. Envie um pico curto de tráfego para confirmar o funcionamento completo da configuração:

    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

    Uma resposta bem-sucedida do hey confirma que o serviço podinfo está acessível pela malha.

Etapa 4: Configurar um HPA usando métricas do ASM

Defina um HPA para dimensionar o deployment do podinfo com base no número de requisições recebidas por segundo, conforme medido pela métrica istio_requests_total no Prometheus.

O HPA utiliza dois constructos do Kubernetes em conjunto:

  • Uma anotação que incorpora a consulta PromQL e lhe atribui um nome (processed-requests-per-second).

  • Uma referência de métrica em spec.metrics que aponta para a consulta nomeada e define o limiar de dimensionamento.

Crie um arquivo chamado hpa.yaml com o conteúdo a seguir e aplique-o:

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: podinfo
  namespace: test
  annotations:
    # The annotation key format is:
    # metric-config.external.prometheus-query.prometheus/<query-name>
    # The query-name must match the value of the matchLabels selector below.
    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  # matches the annotation key suffix above
        target:
          type: AverageValue
          averageValue: "10"  # scale out when average RPS per replica exceeds 10
kubectl apply -f hpa.yaml

Explicação dos campos principais:

Campo

Valor

Descrição

Anotação metric-config.external.prometheus-query.prometheus/<query-name>

Expressão PromQL

Define a consulta que o kube-metrics-adapter executa no Prometheus. O sufixo <query-name> deve corresponder ao rótulo query-name em spec.metrics.

Rótulo query-name

processed-requests-per-second

Vincula a anotação (consulta PromQL) à referência de métrica em spec.metrics.

averageValue

"10"

O HPA escala horizontalmente quando a média de requisições por segundo por réplica excede 10.

minReplicas / maxReplicas

1 / 10

Limites inferior e superior para o número de réplicas.

Após aplicar o HPA, verifique se a métrica externa foi registrada:

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

Saída esperada:

{
  "kind": "APIResourceList",
  "apiVersion": "v1",
  "groupVersion": "external.metrics.k8s.io/v1beta1",
  "resources": [
    {
      "name": "prometheus-query",
      "singularName": "",
      "namespaced": true,
      "kind": "ExternalMetricValueList",
      "verbs": [
        "get"
      ]
    }
  ]
}

A entrada prometheus-query em resources confirma que o kube-metrics-adapter registrou a métrica e que o HPA está ativo.

Verificar o dimensionamento automático

  1. Abra um terminal e inicie uma carga sustentada no podinfo (5 minutos, 10 usuários simultâneos, 5 requisições/segundo cada):

    kubectl -n test exec -it ${loadtester} -c loadtester -- sh
    ~ $ hey -z 5m -c 10 -q 5 http://podinfo.test:9898
  2. Em outro terminal, acompanhe o aumento de escala do HPA:

    Por padrão, as métricas são sincronizadas a cada 30 segundos. O HPA também aplica um período de resfriamento de 3 a 5 minutos entre eventos de dimensionamento para evitar oscilações excessivas.
    watch kubectl -n test get hpa/podinfo

    À medida que a carga aumenta acima do limiar, o HPA escala horizontalmente:

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

    O valor 8308m usa a notação de miliunidade do Kubernetes para representar 8,308 requisições por segundo. Como a média de RPS por réplica (8,3) está abaixo do limiar de 10, o HPA estabilizou em 6 réplicas. Se a carga fosse maior, o HPA continuaria escalando até o máximo de 10 réplicas.

  3. Ao término do teste de carga, a taxa de requisições cai para zero. O HPA inicia a redução de escala e, em alguns minutos, o número de réplicas retorna a 1.