在 Kubernetes 中实现应用的自动扩缩容,其核心基础是获取准确的资源指标。没有这个前提,一切自动化的弹性能力都是空谈。因此,部署和配置 metrics-server 是开启 HPA 功能的第一步。
核心组件:metrics-server
metrics-server 是 Kubernetes 自动扩缩容的核心基础组件,负责收集集群中的资源使用数据。
原理介绍
其核心原理可以概括为以下几个步骤:
- 数据采集:每个节点上的 kubelet 会暴露一个资源使用情况的接口。
- 数据汇聚:
metrics-server 定期从所有节点的 kubelet 拉取这些指标数据。
- API 聚合:收集到的数据被注册到 API Server。
- 提供服务:最终对外提供一个名为
metrics.k8s.io 的 API,供 Horizontal Pod Autoscaler (HPA) 或 kubectl top 等工具查询。
简单来说,数据的流向是:kubelet -> metrics-server -> API Aggregation -> HPA / kubectl top。
部署 metrics-server
理解了原理,我们开始动手部署。你可以直接从官方仓库下载最新的部署清单。
# 下载资源清单文件
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/high-availability-1.21+.yaml
对于国内环境,通常需要将镜像源替换为国内地址,以加速拉取。
# 编辑下载的 YAML 文件,修改容器镜像
[root@k8s-master01 /data/manifests/add-one/02-Metrics]# vim high-availability-1.21+.yaml
# ...
containers:
- args:
- --kubelet-insecure-tls
# ...
# image: registry.k8s.io/metrics-server/metrics-server:v0.8.1
# 改为阿里云镜像源
image: registry.aliyuncs.com/google_containers/metrics-server:v0.8.1
编辑完成后,使用 kubectl apply 命令创建资源。
# 应用配置清单,部署 metrics-server
[root@k8s-master01 /data/manifests/add-one/02-Metrics]# kubectl apply -f high-availability-1.21+.yaml
[root@k8s-master01 /data/manifests/add-one/02-Metrics]# kubectl get pods -n kube-system |grep metrics-server
metrics-server-68d7bc6495-fqslz 1/1 Running 0 5m4s
metrics-server-68d7bc6495-v87zq 1/1 Running 0 5m4s
看到 metrics-server 的 Pod 处于 Running 状态后,可以通过 kubectl top 命令来验证组件是否工作正常。
# 验证集群节点资源使用情况
[root@k8s-master01 /data/manifests/add-one/02-Metrics]# kubectl top nodes
NAME CPU(cores) CPU(%) MEMORY(bytes) MEMORY(%)
k8s-master01.dinginx.org 99m 4% 1163Mi 63%
k8s-node01.dinginx.org 64m 3% 910Mi 49%
k8s-node02.dinginx.org 111m 5% 3642Mi 46%
# 验证 kube-system 命名空间下 Pod 的资源使用情况
[root@k8s-master01 /data/manifests/add-one/02-Metrics]# kubectl top pod -n kube-system
NAME CPU(cores) MEMORY(bytes)
coredns-7699bffdb6-5crvp 2m 14Mi
coredns-7699bffdb6-zwvkr 2m 61Mi
etcd-k8s-master01.dinginx.org 19m 137Mi
filebeat-jvdzl 1m 35Mi
... (此处省略部分输出)
metrics-server-68d7bc6495-fqslz 3m 20Mi
metrics-server-68d7bc6495-v87zq 3m 18Mi
当你能成功看到节点和 Pod 的 CPU、内存使用率时,说明 metrics-server 已经部署成功,为后续的 Kubernetes HPA 功能提供了数据基础。
Q: metrics-server 和 Prometheus 有什么区别?
简单来说,metrics-server 是一个轻量级的资源 API 聚合器,主要服务于 HPA 等核心调度功能;而 Prometheus 是一个功能完备的监控告警系统,用于更广泛的监控场景。
手动实现 Pod 扩缩容
在进入自动化之前,我们先回顾一下如何手动调整 Deployment 的副本数,这有助于理解 HPA 在背后做了什么。
创建基础 Deployment
首先,我们创建一个用于测试的 Deployment。
# 资源清单:11-scheduler-scale.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dinginx-deploy-podantiaffinity
spec:
replicas: 5 # 初始副本数设为5
selector:
matchLabels:
app: dinginx-deploy-podantiaffinity
template:
metadata:
labels:
app: dinginx-deploy-podantiaffinity
spec:
tolerations:
- key: app
value: dinginx001
effect: NoSchedule
containers:
- name: nginx
image: harbor.dinginx.org/dinginx/nginx:latest
imagePullPolicy: IfNotPresent
# 创建资源
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl apply -f 11-scheduler-scale.yaml
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl get pods
NAME READY STATUS RESTARTS AGE
dinginx-deploy-podantiaffinity-66ccbcc5dc-bqcc9 1/1 Running 0 5s
dinginx-deploy-podantiaffinity-66ccbcc5dc-hbzk9 1/1 Running 0 5s
dinginx-deploy-podantiaffinity-66ccbcc5dc-p46jf 1/1 Running 0 5s
dinginx-deploy-podantiaffinity-66ccbcc5dc-pzw8t 1/1 Running 0 5s
dinginx-deploy-podantiaffinity-66ccbcc5dc-qgzpd 1/1 Running 0 5s
手动扩容与缩容
使用 kubectl scale 命令可以轻松调整副本数量。
# 将副本数从5扩容到7
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl scale --replicas=7 deployment dinginx-deploy-podantiaffinity
deployment.apps/dinginx-deploy-podantiaffinity scaled
# 验证扩容结果
[root@k8s-master01 /data/manifests/pod-scheduler]# kubectl get pods
NAME READY STATUS RESTARTS AGE
... (原有5个Pod)
dinginx-deploy-podantiaffinity-66ccbcc5dc-sdr7x 1/1 Running 0 4s # 新增
dinginx-deploy-podantiaffinity-66ccbcc5dc-vdzws 1/1 Running 0 4s # 新增
# 将副本数从7缩容到2
[root@k8s-master01 /data/manifests/deploy]# kubectl scale --replicas=2 deployment dinginx-deploy-podantiaffinity
deployment.apps/dinginx-deploy-podantiaffinity scaled
# 验证缩容结果
[root@k8s-master01 /data/manifests/deploy]# kubectl get pods
NAME READY STATUS RESTARTS AGE
dinginx-deploy-podantiaffinity-66ccbcc5dc-cjdbl 1/1 Running 0 114s
dinginx-deploy-podantiaffinity-66ccbcc5dc-sfwn9 1/1 Running 0 83s
手动操作虽然简单,但在面对流量波动时,我们需要更智能的自动化方案。
实现 Pod 水平自动扩缩容 (HPA)
现在,我们进入核心环节,配置 HPA 来实现基于 CPU 使用率的自动扩缩容。
创建压力测试 Deployment
为了模拟高负载场景,我们创建一个使用 stress-ng 镜像的 Deployment,并为其设定资源请求和限制。
# 资源清单:06-deploy-stress.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: stress-test
spec:
replicas: 3
selector:
matchLabels:
app: stress
template:
metadata:
labels:
app: stress
spec:
containers:
- name: stress
image: harbor.dinginx.org/dinginx/stress-ng:latest
command:
- /bin/sh
- -c
- "sleep 3600" # 容器启动后先休眠,等待手动触发压力测试
resources:
requests:
cpu: "200m" # 请求200毫核CPU
memory: "100Mi"
limits:
cpu: "500m" # 限制500毫核CPU
memory: "500Mi"
# 创建压力测试 Deployment
[root@k8s-master01 /data/manifests/deploy]# kubectl apply -f 06-deploy-stress.yaml
[root@k8s-master01 /data/manifests/deploy]# kubectl get pods
NAME READY STATUS RESTARTS AGE
stress-test-5787f949d5-4gnrt 1/1 Running 0 5s
stress-test-5787f949d5-clbfz 1/1 Running 0 8s
stress-test-5787f949d5-h692d 1/1 Running 0 4s
配置 HPA 规则
接下来,为这个 Deployment 创建一个 HPA 规则。我们设定当 CPU 使用率超过请求值的 80% 时触发扩容,副本数范围在 2 到 10 之间。
# 创建 HPA,设置CPU利用率阈值为80%,副本数范围2-10
[root@k8s-master01 /data/manifests/deploy]# kubectl autoscale deployment stress-test --max=10 --min=2 --cpu-percent=80
Flag --cpu-percent has been deprecated, Use --cpu with percentage or resource quantity format (e.g., '70%' for utilization or '500m' for milliCPU).
horizontalpodautoscaler.autoscaling/stress-test autoscaled
# 查看创建的HPA,初始时TARGETS可能显示为<unknown>,因为metrics-server需要一点时间收集数据
[root@k8s-master01 /data/manifests/deploy]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
stress-test Deployment/stress-test cpu: <unknown>/80% 2 10 0 11s
触发压力测试并观察 HPA 效果
现在,我们进入一个 Pod 内部,使用 stress-ng 工具制造 CPU 压力。
# 进入其中一个 Pod 执行压力测试命令
[root@k8s-node01 ~]# kubectl exec -it pods/stress-test-5787f949d5-clbfz -- sh
/ # stress-ng --vm 1 --vm-bytes 300M --timeout 60
stress-ng: info: [16] setting to a 1 min, 0 secs run per stressor
... (压力测试输出)
/ #
在另一个终端窗口,持续观察 HPA 的状态变化。你会看到 CPU 使用率飙升,并触发自动扩容。
# 持续观察 HPA 状态变化
[root@k8s-node02 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
stress-test Deployment/stress-test cpu: <unknown>/80% 2 10 3 30m
stress-test Deployment/stress-test cpu: 250%/80% 2 10 3 30m # CPU使用率达到250%,触发扩容
stress-test Deployment/stress-test cpu: 250%/80% 2 10 3 31m
stress-test Deployment/stress-test cpu: 242%/80% 2 10 6 31m # 副本数从3增加到6
stress-test Deployment/stress-test cpu: 215%/80% 2 10 10 31m # 副本数增加到最大值10
同时,检查 Pod 的数量,确认已经扩容到上限。
[root@k8s-master01 /data/manifests/deploy]# kubectl get pods -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
stress-test-5787f949d5-4gnrt 1/1 Running 1 (3m34s ago) 8m17s 10.244.1.73 k8s-node01.dinginx.org <none> <none>
stress-test-5787f949d5-5gtdz 1/1 Running 0 2m49s 10.244.1.77 k8s-node01.dinginx.org <none> <none>
... (共10个Pod)
[root@k8s-master01 /data/manifests/deploy]# kubectl get pods -owide |wc -l
11 # 包含标题行,实际Pod为10个
关于缩容延迟的配置
你可能注意到,即使压力停止,Pod 也不会立刻减少。这是因为 HPA 有一个缩容稳定时间窗口 (--horizontal-pod-autoscaler-downscale-stabilization),默认为 300 秒(5分钟),目的是防止在指标短暂波动时过于频繁地缩容。
为了在测试中更快看到缩容效果,我们可以修改这个参数。
# 编辑 kube-controller-manager 的静态 Pod 清单
[root@k8s-master01 /data/manifests/deploy]# vim /etc/kubernetes/manifests/kube-controller-manager.yaml
#...
spec:
containers:
- command:
- --horizontal-pod-autoscaler-downscale-stabilization=60s # 添加这一行,将缩容稳定窗口改为60秒
文件保存后,kube-controller-manager 会自动重启加载新配置。等待压力测试停止一段时间(超过60秒)后,HPA 就会开始自动缩容,最终将 Pod 数量减少到最小值 2 个。
通过以上从组件部署、手动操作到全自动扩缩容的完整流程,你已经掌握了在 Kubernetes 中利用 HPA 应对流量变化的核心技能。合理配置资源请求、限制以及 HPA 策略,是保障应用弹性与稳定的关键。如果你想与更多同行交流云原生和 容器化 的实践经验,欢迎访问云栈社区。