基于Nginx Ingress流量指标的多应用弹性伸缩

多实例部署提升了应用的稳定性,但也可能导致资源闲置和集群成本上升。手动调节不仅工作量大,还存在滞后性。使用 Nginx Ingress 对多个应用实施 HPA,可以根据负载动态调整 Pod 副本数量,在确保应用稳定性和响应速度的同时,优化资源使用并降低成本。本文将介绍如何通过 Nginx Ingress 实现多应用 HPA。

Ingress 可将外部请求转发至集群内的 Service,再由 Service 转发至 Pod 处理客户端请求。生产环境中可以基于请求量配置自动扩缩容,通过注册nginx_ingress_controller_requests指标来暴露请求量,基于 Nginx Ingress Controller 自带的指标实现 HPA。ACK 集群的 Nginx Ingress Controller 在社区版基础上进行了功能增强,使用更便捷。

前提条件

通过Nginx Ingress对多个应用进行HPA前,需要将阿里云Prometheus指标转换成HPA可用的指标,需完成如下准备工作。

  • 已部署阿里云Prometheus监控组件,请参见使用阿里云Prometheus监控

  • 部署ack-alibaba-cloud-metrics-adapter组件并完成组件的prometheus.url字段的配置。

    展开查看如何配置prometheus.url

    1. 登录容器服务管理控制台,在左侧导航栏选择集群列表

    2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择应用 > Helm

    3. Helm页面的操作列,单击ack-alibaba-cloud-metrics-adapter对应的更新

    4. 更新发布面板,配置alibabaCloudMetricsAdapter. prometheus. url字段,值为获取的Prometheus数据请求URL,然后单击确定

      关于如何获取Prometheus数据请求URL,请参见如何获取Prometheus数据请求URL
      关于配置文件的详细说明,请参见ack-alibaba-cloud-metrics-adapter组件配置文件详解
  • 已安装压力测试工具Apache Benchmark。

    展开查看示例命令

    • macOS:使用 Homebrew安装

      brew install httpd
    • Windows:访问Apache Lounge,下载 Windows 版本的 Apache,使用cmd命令行执行cd进入解压后的bin目录,运行ab.exe启动程序。

    • UbuntuDebian:

      sudo apt update
      sudo apt install apache2-utils
    • CentOS 8RHEL:

      sudo yum install httpd-tools

    安装完成后,可执行ab -V验证是否安装成功。

本教程将创建两个Deployment及其对应的Service,并通过路由Ingress配置了不同的访问路径,实现对外的流量路由。然后,基于nginx_ingress_controller_requests指标为应用配置了HPA,并通过HPAselector.matchLabels.service字段对指标进行过滤,以实现随着流量的变化为Pod扩缩容的功能。

步骤一:创建应用与服务

使用以下YAML文件创建业务Deployment和对应的Service。

  1. 创建并拷贝以下内容到nginx1.yaml文件。

    展开查看YAML示例

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: test-app
      namespace: default
      labels:
        app: test-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: test-app
      template:
        metadata:
          labels:
            app: test-app
        spec:
          containers:
          - image: registry-cn-hangzhou.ack.aliyuncs.com/acs/sample-app:v1-b070784-aliyun
            name: metrics-provider
            ports:
            - name: http
              containerPort: 8080
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: test-app
      namespace: default
      labels:
        app: test-app
    spec:
      ports:
        - port: 8080
          name: http
          protocol: TCP
          targetPort: 8080
      selector:
        app: test-app
      type: ClusterIP

    执行以下命令,创建应用test-app和对应的Service。

    kubectl apply -f nginx1.yaml
  2. 创建并拷贝以下内容到nginx2.yaml文件。

    展开查看YAML示例

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: sample-app
      namespace: default
      labels:
        app: sample-app
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: sample-app
      template:
        metadata:
          labels:
            app: sample-app
        spec:
          containers:
          - image: registry-cn-hangzhou.ack.aliyuncs.com/acs/sample-app:v1-b070784-aliyun
            name: metrics-provider
            ports:
            - name: http
              containerPort: 8080
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sample-app
      namespace: default
      labels:
        app: sample-app
    spec:
      ports:
        - port: 80
          name: http
          protocol: TCP
          targetPort: 8080
      selector:
        app: sample-app
      type: ClusterIP

    执行以下命令,创建应用sample-app和对应的Service。

    kubectl apply -f nginx2.yaml

步骤二:创建路由

  1. 创建并拷贝以下内容到ingress.yaml文件。

    展开查看YAML示例

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: test-ingress
      namespace: default
    spec:
      ingressClassName: nginx
      rules:
        - host: test.example.com
          http:
            paths:
              - backend:
                  service:
                    name: sample-app
                    port:
                      number: 80
                path: /
                pathType: ImplementationSpecific
              - backend:
                  service:
                    name: test-app
                    port:
                      number: 8080
                path: /home
                pathType: ImplementationSpecific
    • host:指定服务访问域名。本示例使用test.example.com

    • path:指定访问的URL路径。请求到来之后会根据路由规则匹配相应的Service,然后通过Service访问相应的Pod。

    • backend:由Service名称和Service端口组成,指定当前path转发的Service。

    执行以下命令,部署Ingress资源。

    kubectl apply -f ingress.yaml
  2. 执行以下命令,获取Ingress资源。

    kubectl get ingress -o wide

    预期输出:

    NAME           CLASS   HOSTS              ADDRESS       PORTS   AGE                                                  
    test-ingress   nginx   test.example.com   10.XX.XX.10   80      55s

    部署成功后,可以通过//home两个路径分别访问Host地址。Nginx Ingress Controller会根据上方配置分别访问sample-apptest-app。通过阿里云Prometheus查询指标nginx_ingress_controller_requests,可以获取各应用的请求情况。

步骤三:将Prometheus指标转换为HPA可用指标

修改adapter-config文件

  1. 登录容器服务管理控制台,在左侧导航栏选择集群列表

  2. 集群列表页面,单击目标集群名称,然后在左侧导航栏,选择应用 > Helm

  3. Helm列表,单击ack-alibaba-cloud-metrics-adapter,在资源区域,单击adapter-config,然后单击页面右上角的YAML 编辑

  4. 用以下代码中的值替换代码中对应字段的值,然后单击页面下方的确定

    关于配置项详解,请参见基于阿里云Prometheus指标的容器水平伸缩
    rules:
    - metricsQuery: sum(rate(<<.Series>>{<<.LabelMatchers>>}[2m]))
      name:
        as: ${1}_per_second
        matches: ^(.*)_requests
      resources:
        namespaced: false  
      seriesQuery: nginx_ingress_controller_requests

    image

查看指标输出

执行以下命令,查看指标输出。

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

查询指标结果如下:

{
  "kind": "ExternalMetricValueList",
  "apiVersion": "external.metrics.k8s.io/v1beta1",
  "metadata": {},
  "items": [
    {
      "metricName": "nginx_ingress_controller_per_second",
      "metricLabels": {},
      "timestamp": "2025-07-25T07:56:04Z",
      "value": "0"
    }
  ]
}

步骤四:创建HPA

  1. 创建并拷贝以下内容到hpa.yaml文件。

    展开查看YAML示例

    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: sample-hpa
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: sample-app
      minReplicas: 1
      maxReplicas: 10
      metrics:
        - type: External
          external:
            metric:
              name: nginx_ingress_controller_per_second
              selector:
                matchLabels:
    # 可以通过这个字段对指标进行过滤,这里设置的字段会传入adapter.config中的<<.LabelMatchers>>标签。
                  service: sample-app
    # External指标类型下只支持ValueAverageValue类型的目标值。
            target:
              type: AverageValue
              averageValue: 30
    ---
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: test-hpa
      namespace: default
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: test-app
      minReplicas: 1
      maxReplicas: 10
      metrics:
        - type: External
          external:
            metric:
              name: nginx_ingress_controller_per_second
              selector:
                matchLabels:
    # 可以通过这个字段对指标进行过滤,这里设置的字段会传入adapter.config中的<<.LabelMatchers>>标签。
                  service: test-app
    # External指标类型下只支持ValueAverageValue类型的目标值。
            target:
              type: AverageValue
              averageValue: 30

    执行以下命令,对业务应用sample-apptest-app分别部署HPA。

    kubectl apply -f hpa.yaml
  2. 执行以下命令,查看HPA部署情况。

    kubectl get hpa

    预期输出:

    NAME         REFERENCE               TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
    sample-hpa   Deployment/sample-app   0/30 (avg)   1         10        1          74s
    test-hpa     Deployment/test-app     0/30 (avg)   1         10        1          59m

步骤五:结果验证

HPA部署成功后,使用工具Apache Benchmark进行压测实验,观察业务应用是否会随着请求增大而扩容。

  1. 执行以下命令,对Host下的/home路径进行压测。

    ab -c 50 -n 5000 test.example.com/home
  2. 执行以下命令,查看HPA情况。

    kubectl get hpa

    预期输出:

    NAME         REFERENCE               TARGETS           MINPODS   MAXPODS   REPLICAS   AGE
    sample-hpa   Deployment/sample-app   0/30 (avg)        1         10        1          22m
    test-hpa     Deployment/test-app     22096m/30 (avg)   1         10        3          80m
  3. 执行以下命令,对Host的根路径进行压测。

    ab -c 50 -n 5000 test.example.com/
  4. 执行以下命令,查看HPA情况。

    kubectl get hpa

    预期输出:

    NAME         REFERENCE               TARGETS           MINPODS   MAXPODS   REPLICAS   AGE
    sample-hpa   Deployment/sample-app   27778m/30 (avg)   1         10        2          38m
    test-hpa     Deployment/test-app     0/30 (avg)        1         10        1          96m

    从上述结果可以看到,业务应用在请求量增大超过阈值的情况下成功扩容。

相关文档

  • 多可用区均衡是数据类型业务在高可用场景下常用的部署方式。当业务压力增大时,有多可用区均衡调度策略的应用希望能够自动扩容出多个可用区的实例来满足集群的调度水位。详细信息,请参见实现多可用区同时快速弹性扩容

  • 构建自定义操作系统镜像以提高复杂场景下弹性伸缩的便捷性,请参见弹性优化之自定义镜像