Kubernetes 中 PHP 应用的水平扩展:基于自定义指标(如队列长度)的 HPA 配置
大家好,今天我们来深入探讨 Kubernetes 中 PHP 应用的水平扩展,特别是如何利用自定义指标,比如队列长度,来实现更加智能和高效的自动伸缩。
1. 水平 Pod 自动伸缩 (HPA) 基础
HPA (Horizontal Pod Autoscaler) 是 Kubernetes 中实现 Pod 自动伸缩的核心机制。它会定期监控 Pod 的资源利用率(比如 CPU 和内存),并根据设定的目标值自动调整 Pod 的副本数量,从而保证应用能够应对流量的波动。
HPA 的工作流程大致如下:
- 监控指标: HPA 从 Metrics Server 或者 Custom Metrics API 中获取监控数据。
- 计算比例: HPA 根据目标指标值和当前指标值,计算出所需的 Pod 副本数量。
- 调整副本: 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_queue,redis_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.yamlredis_exporter service.yamlprometheus-adapter-config.yamlhpa.yamlphp-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,可以实现更加精准和高效的自动伸缩策略,从而保证应用能够应对流量的波动,并提供更好的用户体验。