Cuando el tráfico de una API aumenta repentinamente, la aplicación necesita escalar con rapidez. Esta guía explica cómo controlar un Horizontal Pod Autoscaler (HPA) con datos en tiempo real de consultas por segundo (QPS) provenientes de Application Real-Time Monitoring Service (ARMS). De este modo, los pods escalan según la carga real de solicitudes y no solo por CPU o memoria.
Funcionamiento
Después de connect the Java applications in your Container Service for Kubernetes (ACK) cluster to ARMS Application Monitoring, los detalles de acceso de cada API están disponibles en ARMS.
ARMS Application Monitoring instrumenta su aplicación Java y expone el recuento de solicitudes por API como métricas de Prometheus. El complemento ack-alibaba-cloud-metrics-adapter convierte las métricas de Managed Service for Prometheus en métricas externas que el HPA puede usar. Además, las presenta a través de la External Metrics API. El HPA escala su Deployment hacia arriba o hacia abajo según el umbral que configure.
La ruta completa de los datos es la siguiente:
ARMS Application Monitoring recopila el recuento de solicitudes por API desde su aplicación Java → Managed Service for Prometheus almacena las métricas → ack-alibaba-cloud-metrics-adapter convierte los datos de Prometheus al formato de la Kubernetes External Metrics API → Kubernetes HPA lee la métrica y escala su Deployment hacia arriba o hacia abajo.
Esta guía utiliza la aplicación arms-springboot-demo y su endpoint /demo/queryUser/10 como ejemplo práctico en todo el documento.
Requisitos previos
Antes de empezar, compruebe que cuenta con lo siguiente:
Monitoreo de Prometheus de Alibaba Cloud desplegado en su clúster. Consulte Use Alibaba Cloud Prometheus for monitoring.
-
El complemento
ack-alibaba-cloud-metrics-adapterdesplegado en el namespacekube-system, con su campoprometheus.urlconfigurado. Consulte Deploy ack-alibaba-cloud-metrics-adapter. Un namespace creado para la demostración. Esta guía usa
arms-demo. Consulte Manage namespaces and quotas.Un Java Development Kit (JDK) instalado. Para conocer las versiones de JDK compatibles, consulte Application Monitoring network settings.
Procedimiento

Paso 1: Instalar el complemento ARMS Application Monitoring
Instale el complemento ack-onepilot para conectar su aplicación con ARMS Application Monitoring.
Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.
En la página Clusters, haga clic en el nombre del clúster. En el panel de navegación izquierdo, haga clic en Add-ons.
Busque ack-onepilot, configure sus parámetros y complete la instalación.
Paso 2: Otorgar permisos de acceso a ARMS
La autorización obligatoria depende del tipo de clúster.
Para clústeres ACK Serverless o aplicaciones en clústeres conectados a Elastic Container Instance (ECI):
Complete la autorización en la página RAM Quick Authorization. Después, reinicie todos los pods del complemento ack-onepilot.
Para clústeres ACK estándar:
Compruebe si existe un ARMS Addon Token en el clúster.
-
Si el token existe: ARMS realiza automáticamente la autorización sin contraseña.
Los clústeres administrados de ACK incluyen un ARMS Addon Token de forma predeterminada. Algunos clústeres administrados más antiguos podrían no tenerlo. En ese caso, otorgue los permisos manualmente con los pasos siguientes.
-
Si el token no existe: Otorgue los permisos manualmente.
-
Cree una política personalizada con el contenido siguiente. Consulte Step 1: Create a custom policy.
{ "Action": "arms:*", "Resource": "*", "Effect": "Allow" } Asocie la política personalizada al rol de RAM de worker del clúster. Consulte Step 2: Attach the custom policy to the worker RAM role.
-
Paso 3: Habilitar ARMS Application Monitoring para su aplicación Java
Habilite el monitoreo al agregar etiquetas a la sección spec.template.metadata de su Deployment.
Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.
En la página Clusters, haga clic en el nombre del clúster. En el panel de navegación izquierdo, elija Workloads > Deployments.
En la página Deployments, haga clic en Create from YAML.
-
Seleccione Sample Template y agregue las
labelssiguientes bajospec.template.metadataen la Template (en formato YAML):Habilitar Application Security genera cargos adicionales. Consulte What is Application Security? y Billing .
labels: armsPilotAutoEnable: "on" armsPilotCreateAppName: "<your-deployment-name>" # Required: replace with your application name one-agent.jdk.version: "OpenJDK11" # Required only for JDK 11 armsSecAutoEnable: "on" # Optional: enables Application SecurityLa plantilla YAML de ejemplo siguiente muestra cómo crear una aplicación sin estado (Deployment) con ARMS Application Monitoring habilitado.
-
Compruebe el despliegue. En la página Deployments, el botón ARMS Console aparece en la columna Actions de la aplicación objetivo. Haga clic en ARMS Console para consultar los datos de monitoreo. En el panel de navegación izquierdo, haga clic en API Call para ver los detalles de acceso de las interfaces HTTP. La aplicación de demostración genera llamadas continuas a las interfaces de forma automática.
La página API Call enumera cada API con su tiempo de respuesta, recuento de solicitudes y recuento de errores. Entre los ejemplos se encuentran
/demo/randomRT/{id}(5.0 s),/demo/invokeConponent(1.2 s),/demo/queryUser/{id}(218.07 ms),/demo/queryNotExistDB/{id}(2.5 ms) y/demo/queryException/{id}(1.4 ms). La página también muestra un diagrama de topología de llamadas y gráficas de tendencias para el recuento de solicitudes y el tiempo de respuesta. -
Cree un Service para
arms-springboot-demoy exponga la API de la aplicación mediante Server Load Balancer (SLB).En la página Clusters, haga clic en el nombre del clúster. En el panel de navegación izquierdo, elija Network > Services.
Haga clic en Create para crear un Service para la aplicación asociada y luego haga clic en Create. Para obtener más información sobre los parámetros, consulte Create a Service.
Una vez creado el Service, anote la External IP de
arms-demo-svc(por ejemplo,47.94.XX.XX:8080).-
Acceda al endpoint
/demo/queryUser/10del Service a través del puerto externo:curl http://47.94.XX.XX:8080/demo/queryUser/10Resultado esperado:
{"id":1,"name":"KeyOfSpectator","password":"12****"}Este resultado indica que el endpoint es accesible.
Paso 4: Configurar el adaptador de métricas
Managed Service for Prometheus y el complemento ack-alibaba-cloud-metrics-adapter (desplegado en kube-system) deben estar ejecutándose antes de continuar.
Este paso asigna los datos de recuento de solicitudes de ARMS Application Monitoring a una métrica externa con nombre que el HPA puede consumir. El nombre de la métrica que se usa en hpa.yaml (paso 5) se genera a partir del campo name.as que configure aquí.
4.1 Obtener la URL de Prometheus
Inicie sesión en la consola de ARMS.
En el panel de navegación izquierdo, elija Managed Service for Prometheus > Instance.
Haga clic en el nombre de la instancia objetivo (formato:
arms_metrics_{RegionId}_XXX). En el panel de navegación izquierdo, haga clic en Settings.-
En la parte inferior de la pestaña Settings, consulte y anote la HTTP API Address (Grafana Read Address). Esta es su URL de Prometheus.
La página muestra la HTTP API Address (Grafana Read Address) con las columnas Network y URL:
Public:
https://{RegionId}.arms.aliyuncs.com:9443/api/v1/prometheus/{InstanceID}/{UserID}/{Secret}/cn-beijingInternal:
http://{RegionId}-intranet.arms.aliyuncs.com:9090/api/v1/prometheus/{InstanceID}/{UserID}/{Secret}/cn-beijing
Copie la dirección de red pública como URL de Prometheus para los pasos siguientes.
4.2 Establecer la URL de Prometheus en el adaptador
Inicie sesión en la consola de ACK. En el panel de navegación izquierdo, haga clic en Clusters.
En la página Clusters, haga clic en el nombre del clúster. En el panel de navegación izquierdo, elija Applications > Helm.
En la página Helm, busque ack-alibaba-cloud-metrics-adapter y haga clic en Update dentro de la columna Actions.
-
En el panel Update Release, inserte la URL de Prometheus que anotó en el paso 4.1.
custom: - metricsQuery: sum(sum(container_memory_working_set_bytes)by(pod) * on(pod) group_right sum(<<.Series>>{<<.LabelMatchers>>}) by(pod)) / 1024 / 1024 / 1024 name: as: container_memory_working_total matches: ^(.*)_labels resources: overrides: namespace: resource: namespace pod: resource: pod seriesQuery: kube_pod_labels{namespace!="",pod!=""} default: false enabled: true logLevel: 4 metricsRelistInterval: 1m tls: ca: "" certificate: "" enable: false key: "" url: http://cn-beijing-intranet.arms.aliyuncs.com:9090/api/v1/prometheus/ 8cba801fff65546a3012e9a6843xxx/xxx0538168824xxx xxx a174ae4xxx2xxx xxx xxx xxx ramRoleType: restricted replicas: 1 service: type: ClusterIP serviceAccountName: admin tolerations: [] ConfigReloader: image: repository: registry.aliyuncs.com/acs/configmap-reload tag: v0.0.1
4.3 Agregar una regla de métricas de ARMS a adapter-config
En la página Helm, haga clic en ack-alibaba-cloud-metrics-adapter.
En la pestaña Basic Information, haga clic en adapter-config.
En la esquina superior derecha, haga clic en Edit YAML.
-
Agregue la regla siguiente a
adapter-config:rules: - metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0) # ^^ Replace with your ARMS service name # ^^ Replace with your cluster ID name: as: "${1}_per_second" # Generates the HPA metric name: arms_app_requests_per_second matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc" resources: namespaced: false seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7"} # ^^ Replace with your ARMS service name and cluster IDReemplace
arms-k8s-democon el nombre de su servicio de ARMS ycc13c8725******a9839190b7d1695d7con el identificador de su clúster.A continuación se muestra un ejemplo completo:
4.4 Comprobar que la métrica esté disponible
-
Compruebe que
arms_app_requests_per_secondaparezca en la External Metrics API:kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1"Busque
"name":"arms_app_requests_per_second"en el resultado. -
Compruebe que la métrica devuelva datos en tiempo real:
kubectl get --raw "/apis/external.metrics.k8s.io/v1beta1/namespaces/arms-demo/arms_app_requests_per_second" | jq .Resultado esperado:
{ "kind": "ExternalMetricValueList", "apiVersion": "external.metrics.k8s.io/v1beta1", "metadata": {}, "items": [ { "metricName": "arms_app_requests_per_second", "metricLabels": {}, "timestamp": "2025-02-13T02:51:31Z", "value": "2" } ] }
Paso 5: Crear el HPA
Cree el archivo hpa.yaml con el contenido siguiente.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: test-hpa
namespace: arms-demo
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: arms-springboot-demo
minReplicas: 1
maxReplicas: 10
metrics:
- type: External
external:
metric:
name: arms_app_requests_per_second # Must match the name generated by adapter-config (name.as field in Step 4.3)
target:
type: AverageValue
averageValue: 40 # Scale out when QPS exceeds 40; External metrics support Value and AverageValue only
Aplique el HPA:
kubectl apply -f hpa.yaml
Compruebe que esté recibiendo datos de métricas:
kubectl get hpa -n arms-demo
Resultado esperado:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
test-hpa Deployment/arms-springboot-demo 12/40 (avg) 1 10 1 113s
Un valor distinto de vacío en TARGETS confirma que el HPA lee los datos de métricas correctamente.
Paso 6: Comprobar el escalado elástico con una prueba de estrés
Ejecute una prueba de estrés contra la aplicación de demostración. Reemplace 47.94.XX.XX:8080 con el endpoint externo de arms-demo-svc.
ab -c 50 -n 2000 http://47.94.XX.XX:8080/demo/queryUser/10
Mientras se ejecuta la prueba, supervise el HPA:
kubectl get hpa -n arms-demo
Resultado esperado después del escalado:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
test-hpa Deployment/arms-springboot-demo 47500m/40 (avg) 1 10 10 6m43s
Revise el efecto del escalado desde tres perspectivas:
-
Consola de ARMS: El volumen de solicitudes de la interfaz aumenta drásticamente durante la prueba de estrés.
En la pestaña Overview de ARMS Application Monitoring se observan los cambios siguientes en las métricas durante la prueba de estrés (aproximadamente entre las 10:58 y las 10:59):
Requests per minute: Las solicitudes de entrada HTTP aumentan de casi 0 a unas 1,800.
Response time per minute: El tiempo de respuesta de entrada HTTP fluctúa entre 800 ms y 1.6 s.
Slow calls per minute: El recuento sube a cerca de 6 hacia el final de la prueba.
HTTP status code statistics: La cantidad de códigos de estado 200 aumenta hasta unas 2,400, en sincronía con el recuento de solicitudes. Los demás códigos de estado se mantienen cercanos a 0.
-
Panel de Prometheus: El HPA activa el escalado horizontal cuando los QPS superan el umbral configurado.
En el panel de Grafana, la gráfica de líneas de la métrica
arms_app_requests_countmuestra un pico pronunciado durante la prueba de estrés. El valor alcanza un máximo de aproximadamente 33.5 min y luego desciende a 1.40 min. Las estadísticas del panel son mín. 8s, máx. 33.5 min, prom. 2.61 min y actual 1.40 min. Clúster de ACK: El número de réplicas de pods escala horizontalmente según los QPS de las llamadas a la interfaz.
Para consultar el historial completo de eventos de escalado, ejecute:
kubectl describe hpa test-hpa -n arms-demo
Ejemplos avanzados
Los ejemplos siguientes muestran cómo configurar el adaptador de métricas para escenarios de escalado más específicos. Todos usan sum_over_time_lorc para agregar el recuento de solicitudes en una ventana de 1 minuto.
Escalar varios servicios de forma independiente
Defina una regla por servicio y asigne a cada una un nombre de métrica único. Así, el HPA podrá dirigirlas por separado.
rules:
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
name:
as: "${1}_per_second_arms_k8s_demo"
matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
resources:
namespaced: false
seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",clusterId="cc13c8725******a9839190b7d1695d7"}
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo-subcomponent",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
name:
as: "${1}_per_second_arms_k8s_demo_subcomponent"
matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
resources:
namespaced: false
seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo-subcomponent",clusterId="cc13c8725******a9839190b7d1695d7"}
Escalar según un endpoint RPC específico
Agregue la etiqueta rpc a la consulta para dirigir un solo endpoint, en lugar de todo el tráfico de un servicio.
rules:
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",rpc="/demo/queryUser/{id}",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
name:
as: "${1}_per_second_arms_k8s_demo_queryUser"
matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
resources:
namespaced: false
seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",rpc="/demo/queryUser/{id}",clusterId="cc13c8725******a9839190b7d1695d7"}
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",rpc="/demo/queryException/{id}",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
name:
as: "${1}_per_second__arms_k8s_demo_queryException"
matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
resources:
namespaced: false
seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",rpc="/demo/queryException/{id}",clusterId="cc13c8725******a9839190b7d1695d7"}
- metricsQuery: sum(sum_over_time_lorc(<<.Series>>{service="arms-k8s-demo",rpc="/demo/queryNotExistDB/{id}",clusterId="cc13c8725******a9839190b7d1695d7",serverIp=~".*",callKind=~"http|rpc|custom_entry|server|consumer|schedule",source="apm",<<.LabelMatchers>>}[1m])) or vector(0)
name:
as: "${1}_per_second__arms_k8s_demo_queryNotExistDB"
matches: "^(.*)_count_ign_destid_endpoint_ppid_prpc"
resources:
namespaced: false
seriesQuery: arms_app_requests_count_ign_destid_endpoint_ppid_prpc{service="arms-k8s-demo",rpc="/demo/queryNotExistDB/{id}",clusterId="cc13c8725******a9839190b7d1695d7"}
Referencias
Application Monitoring metrics: lista completa de métricas de ARMS disponibles para usarse en las reglas del adaptador.