Tous les produits
Search
Centre de documentation

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

Dernière mise à jour :Aug 24, 2026

Service Mesh (ASM) collecte les données de télémétrie des clusters ACK et ACS de manière non intrusive, en générant des métriques de service basées sur les quatre signaux d'or : la latence, le trafic, les erreurs et la saturation. Cette rubrique explique comment configurer un Horizontal Pod Autoscaler (HPA) qui met à l'échelle les charges de travail en fonction de ces métriques ASM, allant au-delà du CPU et de la mémoire pour s'adapter aux modèles de trafic réels.

Fonctionnement

ASM expose les métriques de service (telles que le nombre de requêtes par seconde) à Prometheus. Un adaptateur de métriques personnalisées, kube-metrics-adapter, enregistre ces métriques Prometheus auprès de la couche d'agrégation Kubernetes, ce qui les rend disponibles pour les HPA via l'API des métriques personnalisées.

image

Le flux de bout en bout est le suivant :

  1. ASM collecte les métriques de requête et les écrit dans Prometheus.

  2. kube-metrics-adapter interroge Prometheus et enregistre les métriques en tant que métriques externes dans Kubernetes.

  3. L'HPA interroge l'API des métriques externes toutes les 30 secondes et ajuste le nombre de réplicas lorsque la valeur de la métrique dépasse le seuil défini.

Pour obtenir la liste complète des métriques générées par ASM, consultez la documentation Istio Standard Metrics.

Prérequis

Avant de commencer, assurez-vous de disposer des éléments suivants :

Étape 1 : Activer la surveillance Prometheus pour l'instance ASM

Suivez les instructions de la rubrique Collecter des métriques vers Managed Service for Prometheus afin d'activer la collecte des métriques Prometheus pour votre instance ASM.

Étape 2 : Déployer l'adaptateur de métriques personnalisées

L'adaptateur de métriques personnalisées (kube-metrics-adapter) fait le lien entre les métriques Prometheus et l'API des métriques externes de Kubernetes, permettant ainsi aux HPA d'interroger directement les métriques ASM.

  1. Installez kube-metrics-adapter dans le namespace kube-system à l'aide de Helm 3. Définissez le paramètre prometheus.url avec l'adresse interne de votre instance Prometheus. Pour obtenir la source du chart, consultez le dépôt kube-metrics-adapter.

    Paramètre Description
    asm-custom-metrics Nom de la release Helm
    prometheus.url Adresse interne de l'instance Prometheus qui collecte les métriques ASM
    helm -n kube-system install asm-custom-metrics ./kube-metrics-adapter \
      --set prometheus.url=http://prometheus.istio-system.svc:9090
  2. Vérifiez que l'adaptateur est en cours d'exécution :

    1. Vérifiez que le groupe d'API autoscaling/v2beta est enregistré :

      kubectl api-versions | grep "autoscaling/v2beta"

      Résultat attendu :

      autoscaling/v2beta
    2. Vérifiez que le pod de l'adaptateur est en cours d'exécution :

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

      Résultat attendu :

      asm-custom-metrics-kube-metrics-adapter-85c6d5d865-2****   1/1   Running   0   19s
    3. Vérifiez que l'API des métriques externes est disponible (aucune métrique n'est encore enregistrée) :

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

      Résultat attendu :

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

Étape 3 : Déployer un exemple d'application

Cette étape déploie une application podinfo et un service de test de charge dans le namespace test afin de pouvoir déclencher et observer la mise à l'échelle automatique ultérieurement.

  1. Créez le namespace test. Consultez la rubrique Gérer les namespaces et les quotas de ressources.

  2. Activez l'injection automatique du proxy sidecar pour le namespace test. Consultez la rubrique Activer l'injection automatique du proxy sidecar.

  3. Déployez l'application podinfo. Créez un fichier nommé podinfo.yaml avec le contenu suivant, puis appliquez-le.

    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. Déployez le service de test de charge. Créez un fichier nommé loadtester.yaml avec le contenu suivant, puis appliquez-le.

    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. Vérifiez que les deux charges de travail sont en cours d'exécution :

    kubectl get pod -n test

    Résultat attendu (les deux pods affichent 2/2 Running, indiquant que le conteneur d'application et le sidecar Istio sont tous deux prêts) :

    NAME                          READY   STATUS    RESTARTS   AGE
    loadtester-64df4846b9-nxhvv   2/2     Running   0          2m8s
    podinfo-6d845cc8fc-26xbq      2/2     Running   0          11m
  6. Envoyez une brève rafale de trafic pour confirmer que la configuration fonctionne de bout en bout :

    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

    Une réponse réussie de l'outil hey confirme que le service podinfo est accessible via le maillage.

Étape 4 : Configurer un HPA utilisant les métriques ASM

Définissez un HPA qui met à l'échelle le déploiement podinfo en fonction du nombre de requêtes entrantes par seconde, mesuré par la métrique istio_requests_total dans Prometheus.

Le HPA utilise conjointement deux constructions Kubernetes :

  • Une annotation qui intègre la requête PromQL et lui attribue un nom (processed-requests-per-second).

  • Une référence de métrique dans spec.metrics qui pointe vers la requête nommée et définit le seuil de mise à l'échelle.

Créez un fichier nommé hpa.yaml avec le contenu suivant, puis appliquez-le :

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

Explication des champs clés :

Champ Valeur Description
Annotation metric-config.external.prometheus-query.prometheus/<query-name> Expression PromQL Définit la requête exécutée par kube-metrics-adapter contre Prometheus. Le suffixe <query-name> doit correspondre au libellé query-name dans spec.metrics.
Libellé query-name processed-requests-per-second Lie l'annotation (la requête PromQL) à la référence de métrique dans spec.metrics.
averageValue "10" Le HPA effectue une mise à l'échelle horizontale lorsque le nombre moyen de requêtes par seconde par réplica dépasse 10.
minReplicas / maxReplicas 1 / 10 Limites du nombre de réplicas.

Après avoir appliqué le HPA, vérifiez que la métrique externe est désormais enregistrée :

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

Résultat attendu :

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

L'entrée prometheus-query dans resources confirme que kube-metrics-adapter a enregistré la métrique et que le HPA est actif.

Vérifier la mise à l'échelle automatique

  1. Ouvrez un terminal et lancez une charge soutenue contre podinfo (5 minutes, 10 utilisateurs simultanés, 5 requêtes/seconde chacun) :

    kubectl -n test exec -it ${loadtester} -c loadtester -- sh
    ~ $ hey -z 5m -c 10 -q 5 http://podinfo.test:9898
  2. Dans un autre terminal, observez la mise à l'échelle du HPA :

    Les métriques sont synchronisées toutes les 30 secondes par défaut. Le HPA impose également une période de refroidissement de 3 à 5 minutes entre les événements de mise à l'échelle pour éviter les oscillations.
    watch kubectl -n test get hpa/podinfo

    Lorsque la charge dépasse le seuil, le HPA effectue une mise à l'échelle horizontale :

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

    La valeur 8308m utilise la notation milli-unité de Kubernetes pour représenter 8,308 requêtes par seconde. Comme le nombre moyen de requêtes par seconde par réplica (8,3) est inférieur au seuil de 10, le HPA s'est stabilisé à 6 réplicas. Si la charge était plus élevée, le HPA continuerait la mise à l'échelle jusqu'à atteindre le maximum de 10 réplicas.

  3. Une fois le test de charge terminé, le taux de requêtes retombe à zéro. Le HPA commence alors la réduction de l'échelle et, en quelques minutes, le nombre de réplicas revient à 1.