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.
Le flux de bout en bout est le suivant :
ASM collecte les métriques de requête et les écrit dans Prometheus.
kube-metrics-adapter interroge Prometheus et enregistre les métriques en tant que métriques externes dans Kubernetes.
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 :
Un cluster ACK ou un cluster ACS. Consultez les rubriques Créer un cluster ACK managé ou Créer un cluster ACS.
Une instance ASM. Consultez la rubrique Créer une instance ASM.
Une instance Prometheus et une instance Grafana déployées dans les clusters. Consultez la rubrique Utiliser Prometheus open source pour surveiller un cluster ACK.
Une instance Prometheus configurée pour surveiller l'instance ASM. Consultez la rubrique Surveiller les instances ASM à l'aide d'une instance Prometheus autogérée.
É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.
-
Installez kube-metrics-adapter dans le namespace
kube-systemà l'aide de Helm 3. Définissez le paramètreprometheus.urlavec 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-metricsNom de la release Helm prometheus.urlAdresse 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 -
Vérifiez que l'adaptateur est en cours d'exécution :
-
Vérifiez que le groupe d'API
autoscaling/v2betaest enregistré :kubectl api-versions | grep "autoscaling/v2beta"Résultat attendu :
autoscaling/v2beta -
Vérifiez que le pod de l'adaptateur est en cours d'exécution :
kubectl get po -n kube-system | grep metrics-adapterRésultat attendu :
asm-custom-metrics-kube-metrics-adapter-85c6d5d865-2**** 1/1 Running 0 19s -
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.
Créez le namespace
test. Consultez la rubrique Gérer les namespaces et les quotas de ressources.Activez l'injection automatique du proxy sidecar pour le namespace
test. Consultez la rubrique Activer l'injection automatique du proxy sidecar.-
Déployez l'application podinfo. Créez un fichier nommé
podinfo.yamlavec 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: podinfokubectl apply -n test -f podinfo.yaml -
Déployez le service de test de charge. Créez un fichier nommé
loadtester.yamlavec 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: httpkubectl apply -n test -f loadtester.yaml -
Vérifiez que les deux charges de travail sont en cours d'exécution :
kubectl get pod -n testRé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 -
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:9898Une réponse réussie de l'outil
heyconfirme 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.metricsqui 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
-
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 -
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/podinfoLorsque 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 124mLa valeur
8308mutilise 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. 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.