大家好!今天咱们来聊聊 PHP 应用在 Kubernetes 里如何借助 Horizontal Pod Autoscaler (HPA) 和 Custom Metrics 实现真正的弹性伸缩。别害怕,虽然听起来高大上,其实原理很简单,咱们一起一步一步把它拿下。
第一章:HPA 基础 – 伸缩,就是要恰到好处!
HPA,Horizontal Pod Autoscaler,水平 Pod 自动伸缩器。它的作用是根据你的应用负载情况,自动调整 Pod 的数量。想象一下,你开了一家面馆,中午人山人海,晚上门可罗雀。HPA 就像一个聪明的店长,自动增加或减少面馆的座位(Pod),让顾客始终有地方坐,又不会浪费资源。
HPA 默认支持根据 CPU 和内存的使用率进行伸缩。简单来说,就是当你的 Pod 的 CPU 或内存使用率超过了你设定的阈值,HPA 就会自动增加 Pod 的数量;反之,如果使用率过低,就会减少 Pod 的数量。
配置一个基于 CPU 使用率的 HPA
假设你已经有一个部署好的 PHP 应用,并且有一个名为 my-php-app
的 Deployment。现在,我们来创建一个 HPA,让它根据 CPU 使用率自动伸缩。
首先,创建一个 YAML 文件,比如 hpa.yaml
:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: my-php-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-php-app
minReplicas: 1 # 最小 Pod 数量
maxReplicas: 10 # 最大 Pod 数量
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # 目标 CPU 使用率,70%
解释一下:
apiVersion
: API 版本,autoscaling/v2beta2
是推荐的版本。kind
: 资源类型,这里是HorizontalPodAutoscaler
。metadata.name
: HPA 的名称,随便起,但要有意义。spec.scaleTargetRef
: 指向要伸缩的 Deployment。apiVersion
: Deployment 的 API 版本。kind
: 资源类型,这里是Deployment
。name
: Deployment 的名称。
spec.minReplicas
: 最小 Pod 数量,至少要有一个 Pod 运行。spec.maxReplicas
: 最大 Pod 数量,防止 Pod 数量过多,浪费资源。spec.metrics
: 伸缩的指标。type
: 指标类型,这里是Resource
,表示 CPU 或内存等资源。resource
: 资源指标的详细信息。name
: 资源名称,这里是cpu
。target
: 目标值。type
: 目标类型,Utilization
表示平均使用率。averageUtilization
: 目标 CPU 使用率,这里是 70%。
保存好 hpa.yaml
文件后,使用 kubectl
命令创建 HPA:
kubectl apply -f hpa.yaml
查看 HPA 的状态:
kubectl get hpa my-php-app-hpa
如果一切顺利,你应该能看到类似这样的输出:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
my-php-app-hpa Deployment/my-php-app 0%/70% 1 10 1 1m
TARGETS
列显示的是当前的 CPU 使用率和目标 CPU 使用率。REPLICAS
列显示的是当前的 Pod 数量。
测试 HPA
为了验证 HPA 是否正常工作,我们可以模拟高 CPU 负载。可以使用 stress
命令:
kubectl exec -it <pod-name> -- stress --cpu 8 --timeout 60s
其中 <pod-name>
是你的 PHP 应用 Pod 的名称。这条命令会在 Pod 中启动 8 个 CPU 密集型进程,持续 60 秒。
观察 HPA 的状态,你应该能看到 TARGETS
列的 CPU 使用率逐渐升高,REPLICAS
列的 Pod 数量也随之增加。
第二章:Custom Metrics – HPA 的超能力!
默认的 CPU 和内存指标对于某些应用来说可能不够用。例如,你的 PHP 应用可能需要根据请求队列的长度、活跃用户数或者自定义的业务指标进行伸缩。这时,就需要用到 Custom Metrics(自定义指标)。
Custom Metrics 允许你将应用内部的指标暴露给 Kubernetes,然后 HPA 就可以根据这些指标进行伸缩。
Custom Metrics 的架构
Custom Metrics 的实现通常需要以下几个组件:
- 你的 PHP 应用: 负责收集和暴露自定义指标。
- Metrics Server 或 Prometheus: 负责从你的应用收集指标数据。
- Custom Metrics API Server: 负责将 Metrics Server 或 Prometheus 收集到的指标数据暴露给 Kubernetes API。
- HPA: 从 Custom Metrics API Server 获取指标数据,并根据指标值进行伸缩。
第一步:暴露自定义指标 (PHP)
首先,你需要修改你的 PHP 应用,将自定义指标暴露出来。有很多方法可以实现,最常见的是使用 HTTP endpoint。
例如,你可以创建一个名为 /metrics
的 endpoint,返回一个 JSON 格式的指标数据:
<?php
// metrics.php
// 假设你有一个请求队列的长度指标
$queueLength = getQueueLength();
header('Content-Type: application/json');
echo json_encode([
'queue_length' => $queueLength,
]);
function getQueueLength() {
// 从你的消息队列(例如 Redis, RabbitMQ)获取队列长度
// 这里只是一个示例
return rand(0, 100);
}
第二步:部署 Metrics Server 或 Prometheus
Metrics Server 比较轻量级,适合简单的场景。Prometheus 功能更强大,适合复杂的监控需求。这里我们以 Prometheus 为例。
-
安装 Prometheus: 可以使用 Helm 安装 Prometheus。
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update helm install my-prometheus prometheus-community/kube-prometheus-stack
-
配置 Prometheus 抓取 PHP 应用的指标: 你需要创建一个 ServiceMonitor 对象,告诉 Prometheus 如何找到你的 PHP 应用的
/metrics
endpoint。apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: my-php-app-metrics labels: release: my-prometheus # 与你的 Prometheus Helm Release 名称匹配 spec: selector: matchLabels: app: my-php-app # 与你的 PHP 应用 Pod 的 labels 匹配 endpoints: - port: http # 你的 PHP 应用监听的端口名称 path: /metrics # metrics endpoint 路径 interval: 30s # 抓取指标的间隔时间
解释一下:
apiVersion
: ServiceMonitor 的 API 版本。kind
: 资源类型,这里是ServiceMonitor
。metadata.name
: ServiceMonitor 的名称。metadata.labels.release
: 必须与你的 Prometheus Helm Release 名称匹配。spec.selector.matchLabels
: 用于选择要监控的 Service,通常与你的 PHP 应用 Pod 的 labels 匹配。spec.endpoints
: 定义 Prometheus 如何抓取指标。port
: 你的 PHP 应用监听的端口名称。确保你的 Service 定义中包含这个端口。path
:/metrics
endpoint 路径。interval
: 抓取指标的间隔时间。
创建 ServiceMonitor:
kubectl apply -f servicemonitor.yaml
第三步:部署 Custom Metrics API Server
Custom Metrics API Server 负责将 Prometheus 收集到的指标数据暴露给 Kubernetes API。
-
安装
kube-prometheus-adapter
:kube-prometheus-adapter
是一个常用的 Custom Metrics API Server,它可以从 Prometheus 获取指标数据。helm repo add k8s-prometheus-adapter https://kubernetes-sigs.github.io/prometheus-adapter helm repo update helm install my-prometheus-adapter k8s-prometheus-adapter/prometheus-adapter --set prometheus.url="http://my-prometheus-kube-prometheus-prometheus.default.svc" --set prometheus.port=9090 --set mapping.config.name=adapter-config
其中
prometheus.url
和prometheus.port
需要根据你的 Prometheus Service 的地址和端口进行调整。my-prometheus-kube-prometheus-prometheus.default.svc
是我的 prometheus service 的 name。 你要替换成你自己的。 -
配置
kube-prometheus-adapter
: 你需要创建一个 ConfigMap,告诉kube-prometheus-adapter
如何从 Prometheus 获取你的自定义指标。apiVersion: v1 kind: ConfigMap metadata: name: adapter-config namespace: default # 确保与你的 prometheus-adapter 部署的 namespace 相同 data: config.yaml: | rules: - seriesQuery: 'queue_length' # Prometheus 查询语句,用于获取指标数据 resources: overrides: k8s.io/pod.name: resource: pod name: asMatch: "queue_length" # 指标名称,用于 HPA 配置 metricsQuery: sum(queue_length) by (<<.GroupBy>>)
解释一下:
rules.seriesQuery
: Prometheus 查询语句,用于获取指标数据。这里假设你的指标名称是queue_length
。rules.resources.overrides
: 定义如何将指标与 Kubernetes 资源关联起来。这里我们将指标与 Pod 关联起来。rules.name.asMatch
: 指标名称,用于 HPA 配置。
创建 ConfigMap:
kubectl apply -f adapter-config.yaml
第四步:创建基于 Custom Metrics 的 HPA
现在,你可以创建一个 HPA,让它根据你的自定义指标进行伸缩。
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: my-php-app-hpa-custom
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-php-app
minReplicas: 1
maxReplicas: 10
metrics:
- type: External
external:
metric:
name: queue_length # Custom Metrics 的名称,与 adapter-config.yaml 中定义的 name.asMatch 匹配
selector:
matchLabels:
app: my-php-app # 与你的 PHP 应用 Pod 的 labels 匹配
target:
type: AverageValue
averageValue: 20 # 目标队列长度,20
解释一下:
spec.metrics.type
: 指标类型,这里是External
,表示 Custom Metrics。spec.metrics.external
: Custom Metrics 的详细信息。metric.name
: Custom Metrics 的名称,必须与adapter-config.yaml
中定义的name.asMatch
匹配。metric.selector.matchLabels
: 用于选择要监控的资源,通常与你的 PHP 应用 Pod 的 labels 匹配。target.type
: 目标类型,AverageValue
表示平均值。target.averageValue
: 目标队列长度,这里是 20。
创建 HPA:
kubectl apply -f hpa-custom.yaml
查看 HPA 的状态:
kubectl get hpa my-php-app-hpa-custom
如果一切顺利,你应该能看到类似这样的输出:
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
my-php-app-hpa-custom Deployment/my-php-app 10/20 1 10 1 1m
TARGETS
列显示的是当前的队列长度和目标队列长度。REPLICAS
列显示的是当前的 Pod 数量。
测试 HPA (Custom Metrics)
为了验证 HPA 是否正常工作,你可以模拟增加队列长度。修改你的 getQueueLength()
函数,让它返回一个更大的值:
<?php
// metrics.php
$queueLength = getQueueLength();
header('Content-Type: application/json');
echo json_encode([
'queue_length' => $queueLength,
]);
function getQueueLength() {
// 模拟增加队列长度
return rand(50, 150);
}
重新部署你的 PHP 应用,观察 HPA 的状态,你应该能看到 TARGETS
列的队列长度逐渐升高,REPLICAS
列的 Pod 数量也随之增加。
第三章:一些实用技巧和注意事项
- 指标的稳定性: 选择稳定、可靠的指标。如果指标波动太大,HPA 可能会频繁地调整 Pod 数量,造成不必要的资源浪费。
- 伸缩的步长: HPA 默认每次调整 Pod 数量的步长是 1。如果你的应用需要更大的伸缩力度,可以调整 HPA 的算法。
- 冷却时间: HPA 在伸缩后会有一个冷却时间,防止频繁伸缩。可以根据你的应用特性调整冷却时间。
- 监控和告警: 监控 HPA 的状态,并设置告警,以便及时发现问题。
- 资源限制: 为你的 Pod 设置资源限制(CPU 和内存),防止 Pod 占用过多资源,影响其他应用。
- 优雅关闭: 确保你的 PHP 应用能够优雅关闭,避免请求丢失。Kubernetes 会在删除 Pod 之前发送一个
SIGTERM
信号,你的应用应该监听这个信号,并在关闭之前处理完所有请求。 - HPA 版本:
autoscaling/v2beta2
提供了更多的功能和灵活性。
表格总结
步骤 | 描述 | 示例代码/配置 |
---|---|---|
1. 暴露指标 | PHP 应用暴露自定义指标,例如请求队列长度。 | php <?php // metrics.php $queueLength = getQueueLength(); header('Content-Type: application/json'); echo json_encode([ 'queue_length' => $queueLength, ]); function getQueueLength() { // 模拟队列长度 return rand(0, 100); } |
2. 安装 Prometheus | 安装 Prometheus 并配置抓取 PHP 应用的指标。 | bash helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update helm install my-prometheus prometheus-community/kube-prometheus-stack yaml apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: my-php-app-metrics labels: release: my-prometheus # 与你的 Prometheus Helm Release 名称匹配 spec: selector: matchLabels: app: my-php-app # 与你的 PHP 应用 Pod 的 labels 匹配 endpoints: - port: http # 你的 PHP 应用监听的端口名称 path: /metrics # metrics endpoint 路径 interval: 30s # 抓取指标的间隔时间 |
3. 安装 Adapter | 安装 kube-prometheus-adapter 并配置,使其能够从 Prometheus 获取自定义指标。 |
bash helm repo add k8s-prometheus-adapter https://kubernetes-sigs.github.io/prometheus-adapter helm repo update helm install my-prometheus-adapter k8s-prometheus-adapter/prometheus-adapter --set prometheus.url="http://my-prometheus-kube-prometheus-prometheus.default.svc" --set prometheus.port=9090 --set mapping.config.name=adapter-config yaml apiVersion: v1 kind: ConfigMap metadata: name: adapter-config namespace: default # 确保与你的 prometheus-adapter 部署的 namespace 相同 data: config.yaml: | rules: - seriesQuery: 'queue_length' # Prometheus 查询语句,用于获取指标数据 resources: overrides: k8s.io/pod.name: resource: pod name: asMatch: "queue_length" # 指标名称,用于 HPA 配置 metricsQuery: sum(queue_length) by (<<.GroupBy>>) |
4. 创建 HPA | 创建 HPA,并配置其根据 Custom Metrics 进行伸缩。 | yaml apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: my-php-app-hpa-custom spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: my-php-app minReplicas: 1 maxReplicas: 10 metrics: - type: External external: metric: name: queue_length # Custom Metrics 的名称,与 adapter-config.yaml 中定义的 name.asMatch 匹配 selector: matchLabels: app: my-php-app # 与你的 PHP 应用 Pod 的 labels 匹配 target: type: AverageValue averageValue: 20 # 目标队列长度,20 |
总结
今天我们一起学习了如何在 Kubernetes 中使用 HPA 和 Custom Metrics 实现 PHP 应用的弹性伸缩。虽然过程有点复杂,但只要理解了原理,一步一步操作,就能轻松搞定。希望这些知识能帮助你更好地管理你的 PHP 应用,让它们在 Kubernetes 的世界里自由翱翔!
记住,实践是检验真理的唯一标准。多动手,多尝试,你就会发现,Kubernetes 并没有想象中那么可怕! 祝大家编码愉快!