Kubernetes中PHP应用的水平扩展:基于自定义指标(如队列长度)的HPA配置

Kubernetes 中 PHP 应用的水平扩展:基于自定义指标(如队列长度)的 HPA 配置

大家好,今天我们来深入探讨 Kubernetes 中 PHP 应用的水平扩展,特别是如何利用自定义指标,比如队列长度,来实现更加智能和高效的自动伸缩。

1. 水平 Pod 自动伸缩 (HPA) 基础

HPA (Horizontal Pod Autoscaler) 是 Kubernetes 中实现 Pod 自动伸缩的核心机制。它会定期监控 Pod 的资源利用率(比如 CPU 和内存),并根据设定的目标值自动调整 Pod 的副本数量,从而保证应用能够应对流量的波动。

HPA 的工作流程大致如下:

  1. 监控指标: HPA 从 Metrics Server 或者 Custom Metrics API 中获取监控数据。
  2. 计算比例: HPA 根据目标指标值和当前指标值,计算出所需的 Pod 副本数量。
  3. 调整副本: HPA 通过 Deployment 或者 ReplicaSet 控制器来调整 Pod 的副本数量。

虽然 HPA 默认支持 CPU 和内存等标准指标,但在实际应用中,往往需要根据业务特性来定义更加精准的伸缩指标,比如队列长度、活跃连接数、请求处理时间等。

2. 为什么需要自定义指标?

仅仅依靠 CPU 和内存利用率进行自动伸缩,在某些情况下可能并不够准确。举例来说:

  • I/O 密集型应用: 应用主要消耗 I/O 资源,CPU 利用率可能不高,但性能已经达到瓶颈。
  • 等待队列积压: 大量请求在队列中等待处理,CPU 利用率可能不高,但用户体验已经受到影响。

使用自定义指标,可以更加准确地反映应用的实际负载情况,从而实现更加精细化的自动伸缩策略。比如,我们可以根据队列长度来判断是否需要增加 Pod 副本,从而及时处理积压的请求。

3. 自定义指标的来源

自定义指标可以来源于多个方面:

  • Prometheus: 一种流行的开源监控解决方案,可以收集和存储各种指标数据。
  • Custom Metrics API: Kubernetes 提供的 API,允许开发者自定义指标数据。
  • External Metrics API: Kubernetes 提供的 API,允许从外部系统获取指标数据。

通常,我们会选择 Prometheus 作为指标收集和存储的工具,然后通过 Prometheus Adapter 将指标暴露给 Kubernetes 的 Custom Metrics API。

4. 队列长度监控方案

假设我们的 PHP 应用使用 Redis 作为消息队列,我们需要监控 Redis 中某个队列的长度,并根据队列长度来调整 Pod 副本数量。

4.1 Prometheus 指标采集

首先,我们需要使用 Prometheus 采集 Redis 队列长度的指标。可以使用 redis_exporter 这个 Prometheus exporter 来实现。

redis_exporter 会定期连接到 Redis 服务器,并采集各种指标数据,包括队列长度。我们需要配置 redis_exporter 来监控我们感兴趣的队列。

假设我们的 Redis 队列名为 my_queueredis_exporter 的配置如下:

# redis_exporter config
redis:
  addr: redis://redis:6379 # Redis Server address
  namespace: redis
  check_keys:
    - my_queue

这个配置指定了 Redis 服务器的地址,以及需要监控的队列名称。

4.2 部署 redis_exporter

我们可以将 redis_exporter 部署到 Kubernetes 集群中,作为一个 Deployment。

# redis_exporter deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-exporter
spec:
  selector:
    matchLabels:
      app: redis-exporter
  replicas: 1
  template:
    metadata:
      labels:
        app: redis-exporter
    spec:
      containers:
      - name: redis-exporter
        image: oliver006/redis_exporter:v1.5.0
        ports:
        - containerPort: 9121
          name: metrics
        env:
        - name: REDIS_ADDR
          value: "redis://redis:6379" # Redis Server address
        - name: REDIS_CHECK_KEYS
          value: "my_queue"

这个 Deployment 创建一个 redis_exporter 的 Pod,并将 Redis 服务器的地址和需要监控的队列名称传递给 redis_exporter

4.3 创建 Service

为了让 Prometheus 能够访问 redis_exporter,我们需要创建一个 Service。

# redis_exporter service.yaml
apiVersion: v1
kind: Service
metadata:
  name: redis-exporter
spec:
  selector:
    app: redis-exporter
  ports:
  - protocol: TCP
    port: 9121
    targetPort: 9121

这个 Service 将 redis_exporter 的 9121 端口暴露给 Prometheus。

4.4 配置 Prometheus

接下来,我们需要配置 Prometheus 来抓取 redis_exporter 的指标数据。需要在 Prometheus 的配置文件中添加如下配置:

# prometheus.yml
scrape_configs:
  - job_name: 'redis'
    static_configs:
      - targets: ['redis-exporter:9121']

这个配置指定了 Prometheus 需要抓取 redis-exporter 的指标数据。

4.5 验证指标数据

配置完成后,重启 Prometheus,并访问 Prometheus 的 Web 界面,查看是否能够抓取到 Redis 队列长度的指标数据。

应该能够在 Prometheus 中看到类似于 redis_key_length{key="my_queue"} 的指标。

5. 使用 Custom Metrics API

我们需要将 Prometheus 采集到的 Redis 队列长度指标暴露给 Kubernetes 的 Custom Metrics API,以便 HPA 可以使用。

5.1 部署 Prometheus Adapter

Prometheus Adapter 是一个 Kubernetes 组件,它可以将 Prometheus 的指标数据转换为 Custom Metrics API 可以使用的格式。

可以使用 Helm 来安装 Prometheus Adapter:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus-adapter prometheus-community/prometheus-adapter

5.2 配置 Prometheus Adapter

安装完成后,需要配置 Prometheus Adapter,告诉它如何从 Prometheus 中获取 Redis 队列长度的指标数据。

创建一个 ConfigMap,用于配置 Prometheus Adapter:

# prometheus-adapter-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-adapter-config
  namespace: kube-system
data:
  config.yaml: |
    rules:
    - seriesQuery: 'redis_key_length{key="my_queue"}'
      resources:
        template: <<.Resource>>
      name:
        asMatch: "queue_length"
      metricsQuery: sum(redis_key_length{key="my_queue"})

这个 ConfigMap 定义了一个规则,告诉 Prometheus Adapter 从 Prometheus 中获取 redis_key_length{key="my_queue"} 指标,并将其转换为名为 queue_length 的 Custom Metrics API 指标。

然后,需要修改 Prometheus Adapter 的 Deployment,将 ConfigMap 挂载到 Pod 中。

# prometheus-adapter deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: prometheus-adapter
  namespace: kube-system
spec:
  template:
    spec:
      containers:
      - name: prometheus-adapter
        image: prometheus-community/prometheus-adapter:v2.5.0
        args:
        - --config=/etc/adapter/config.yaml
        volumeMounts:
        - name: config
          mountPath: /etc/adapter
      volumes:
      - name: config
        configMap:
          name: prometheus-adapter-config

5.3 验证 Custom Metrics API

配置完成后,重启 Prometheus Adapter,并使用 kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1 命令来验证 Custom Metrics API 是否能够获取到 Redis 队列长度的指标数据。

应该能够看到类似于如下的输出:

{
  "kind": "APIResourceList",
  "apiVersion": "v1",
  "groupVersion": "custom.metrics.k8s.io/v1beta1",
  "resources": [
    {
      "name": "pods/queue_length",
      "singularName": "",
      "namespaced": true,
      "kind": "MetricValueList",
      "verbs": [
        "get"
      ]
    },
    {
      "name": "namespaces/queue_length",
      "singularName": "",
      "namespaced": false,
      "kind": "MetricValueList",
      "verbs": [
        "get"
      ]
    }
  ]
}

这表明 Custom Metrics API 已经成功获取到 Redis 队列长度的指标数据。

6. 配置 HPA

现在,我们可以配置 HPA 来根据 Redis 队列长度自动伸缩 PHP 应用的 Pod 副本数量。

# hpa.yaml
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: php-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-app
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: queue_length
        selector: {}
      target:
        type: AverageValue
        averageValue: 10

这个 HPA 配置指定了:

  • scaleTargetRef: 需要伸缩的目标对象,这里是名为 php-app 的 Deployment。
  • minReplicas: 最小 Pod 副本数量。
  • maxReplicas: 最大 Pod 副本数量。
  • metrics: 伸缩指标,这里是 queue_length,目标平均值为 10。也就是说,当每个 Pod 的平均队列长度超过 10 时,HPA 会自动增加 Pod 副本数量,直到达到 maxReplicas

7. 部署 HPA

使用 kubectl apply -f hpa.yaml 命令部署 HPA。

8. 测试 HPA

为了测试 HPA 是否正常工作,我们可以向 Redis 队列中发送大量消息,模拟队列积压的情况。

观察 HPA 的状态,可以看到 HPA 会自动增加 Pod 副本数量,以处理积压的请求。

可以使用 kubectl get hpa php-app-hpa 命令查看 HPA 的状态。

9. 完整示例代码

这里提供一个完整的示例代码,包括:

  • redis_exporter deployment.yaml
  • redis_exporter service.yaml
  • prometheus-adapter-config.yaml
  • hpa.yaml
  • php-app deployment.yaml (假设你的 PHP 应用 Deployment 已经存在)

9.1 redis_exporter deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-exporter
spec:
  selector:
    matchLabels:
      app: redis-exporter
  replicas: 1
  template:
    metadata:
      labels:
        app: redis-exporter
    spec:
      containers:
      - name: redis-exporter
        image: oliver006/redis_exporter:v1.5.0
        ports:
        - containerPort: 9121
          name: metrics
        env:
        - name: REDIS_ADDR
          value: "redis://redis:6379"
        - name: REDIS_CHECK_KEYS
          value: "my_queue"

9.2 redis_exporter service.yaml

apiVersion: v1
kind: Service
metadata:
  name: redis-exporter
spec:
  selector:
    app: redis-exporter
  ports:
  - protocol: TCP
    port: 9121
    targetPort: 9121

9.3 prometheus-adapter-config.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-adapter-config
  namespace: kube-system
data:
  config.yaml: |
    rules:
    - seriesQuery: 'redis_key_length{key="my_queue"}'
      resources:
        template: <<.Resource>>
      name:
        asMatch: "queue_length"
      metricsQuery: sum(redis_key_length{key="my_queue"})

9.4 hpa.yaml

apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
  name: php-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-app
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Pods
    pods:
      metric:
        name: queue_length
        selector: {}
      target:
        type: AverageValue
        averageValue: 10

9.5 php-app deployment.yaml (示例,需要根据你的实际情况修改)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-app
spec:
  selector:
    matchLabels:
      app: php-app
  replicas: 1
  template:
    metadata:
      labels:
        app: php-app
    spec:
      containers:
      - name: php-app
        image: your-php-app-image:latest
        ports:
        - containerPort: 80

10. 注意事项

  • 指标命名: 确保指标名称在 Prometheus 和 Custom Metrics API 中保持一致。
  • 资源限制: 合理设置 Pod 的资源限制(CPU 和内存),避免资源争抢导致性能下降。
  • 测试和监控: 在生产环境中部署 HPA 之前,务必进行充分的测试和监控,确保 HPA 的行为符合预期。
  • Prometheus Adapter 版本: 选择合适的 Prometheus Adapter 版本,并根据官方文档进行配置。
  • Redis 连接: 确保 redis_exporter 能够正常连接到 Redis 服务器。
  • 权限: 确保 Prometheus Adapter 具有足够的权限来访问 Prometheus 和 Custom Metrics API。

11. 其他自定义指标示例

除了队列长度,还可以使用其他自定义指标来实现自动伸缩,比如:

  • 活跃连接数: 监控应用的活跃连接数,当连接数超过阈值时增加 Pod 副本。
  • 请求处理时间: 监控请求处理时间,当处理时间超过阈值时增加 Pod 副本。
  • 错误率: 监控应用的错误率,当错误率超过阈值时减少 Pod 副本。

12. 使用表格总结配置步骤

步骤 操作 说明
1 安装和配置 Redis Exporter 部署 Redis Exporter 采集 Redis 队列长度指标
2 配置 Prometheus 配置 Prometheus 抓取 Redis Exporter 指标
3 安装 Prometheus Adapter 部署 Prometheus Adapter 将 Prometheus 指标暴露给 Custom Metrics API
4 配置 Prometheus Adapter 配置 Prometheus Adapter,使其能够查询 Redis 队列长度指标
5 创建 HPA 创建 HPA,指定伸缩目标和指标,以及目标平均值
6 验证 验证 HPA 是否正常工作

HPA 基于自定义指标的配置流程总结

本文详细介绍了如何在 Kubernetes 中配置 HPA,使其能够基于自定义指标(如 Redis 队列长度)自动伸缩 PHP 应用的 Pod 副本数量。通过使用 Prometheus、Redis Exporter 和 Prometheus Adapter,可以实现更加精准和高效的自动伸缩策略,从而保证应用能够应对流量的波动,并提供更好的用户体验。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注