Metric Server
学习参考:Metric Server
Metrics-Server 概述
我们在使用 Kubernetes 中过程中面临的问题:
-
如何监控 node 计算资源使用情况?
-
如何监控 pod 计算资源使用情况?
-
如何根据 pod 计算资源使用情况,自动扩展?
我们可以使用 Metrics-Server监控:
- node 和 pod 计算资源使用情况。
- Metrics Server 是 Kubernetes 内置自动缩放管道的可扩展、高效的容器资源指标来源。
- Metrics Server 通过 Kubelet 收集资源指标,并通过 Metrics API 将它们公开在 Kubernetes apiserver 中,供 Horizontal Pod Autoscaler 和 Vertical Pod Autoscaler 使用。
- Metrics API 还可以通过 kubectl top 访问,从而更轻松地调试自动缩放管道。
Metrics Server 不适用于非自动缩放目的。 请勿将其用于将指标转发到监控解决方案,或作为监控解决方案指标的来源。 在这种情况下,请直接从 Kubelet /metrics/resource 端点收集指标。
指标服务器提供:
- 适用于大多数集群的单一部署(请参阅要求)。
- 快速自动缩放,每 15 秒收集一次指标。
- 资源效率,集群中每个节点使用 1 mili 核心 CPU 和 2 MB 内存。
- 可扩展支持多达 5,000 个节点集群。
Metrics-Server 部署
bash
# 下载 Metrics-Server
[root@master30 ~]# wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.7.1/components.yaml
# 修改 Metrics-Server,不校验tls
[root@master30 ~]# sed -i '/metric-resolution/a\ - --kubelet-insecure-tls' components.yaml
# 下载镜像
[root@master30 ~]# grep image: components.yaml
image: registry.k8s.io/metrics-server/metrics-server:v0.7.1
# 部署 Metrics-Server
[root@master30 ~]# kubectl apply -f components.yaml
bash
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created
bash
# 查看 Metrics-Server 状态
[root@master30 ~]# kubectl get pods -n kube-system |grep metrics
metrics-server-6556f8cb6c-78mhq 1/1 Running 0 45s
Metrics-Server 使用
查看node状态
bash
[root@master30 ~]# kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
master30.laoma.cloud 97m 4% 1328Mi 35%
worker31.laoma.cloud 49m 2% 912Mi 24%
worker32.laoma.cloud 45m 2% 926Mi 24%
查看 pod 状态
bash
[root@master30 ~]# kubectl top pods -n kube-system
NAME CPU(cores) MEMORY(bytes)
calico-kube-controllers-6dfcd885bf-8rhg2 2m 11Mi
calico-node-crfr7 27m 57Mi
calico-node-sbmjt 22m 57Mi
calico-node-z9dvd 24m 56Mi
coredns-6d56c8448f-nhjpg 3m 12Mi
coredns-6d56c8448f-w2f48 2m 10Mi
etcd-master.laoma.cloud 16m 54Mi
kube-apiserver-master.laoma.cloud 46m 355Mi
kube-controller-manager-master.laoma.cloud 11m 50Mi
kube-proxy-hx566 1m 18Mi
kube-proxy-t2r4x 1m 18Mi
kube-proxy-x6k8h 1m 18Mi
kube-scheduler-master.laoma.cloud 4m 22Mi
metrics-server-6556f8cb6c-78mhq 1m 11Mi
单位:1cpu=1000m
扩容和减容控制
扩容和缩容时间参数
1. 指标采样周期
--horizontal-pod-autoscaler-sync-period duration- 默认:15s,HPA 每 15 秒拉取一次 metrics-server 指标。
2. 启动就绪窗口期
--horizontal-pod-autoscaler-initial-readiness-delay duration- 默认:30s,Pod 刚启动前 30 秒,视为 "启动中",不参与 HPA 计算
3. 缩容稳定窗口期
--horizontal-pod-autoscaler-downscale-stabilization duration- 默认:5m0s(5 分钟),缩容冷却时间。
持续高负载 → 扩容
- 每 15s 采集一次 CPU/内存指标
- Pod 刚启动前 30 秒,视为 "启动中",不参与 HPA 计算。
- 一次扩容动作完成后,再次等待 45s 冷却 才能下一次扩容
👉 结论:K8s 1.30 扩容最小间隔 = 45s
持续低负载 → 缩容
- 同样 15s 采样
- 指标长期低于阈值
- 需要满足 300s(5分钟)稳定低位 才会触发缩容
- 每次缩容后,再次锁定 5 分钟
设置扩容和减容时间参数
扩容和减容pod数量由kube-controller-manager管理,如需调快/调慢,直接修改 controller-manager 启动参数即可。
扩容和缩容pod是有冷却时间的,目的是防止流量抖动、瞬间峰值导致频繁炸裂扩容。
为了演示扩容和缩容效果,这里设置扩容冷却时间为30s(10+20),缩容冷却时间为60秒。
bash
[root@master30 ~]# vim /etc/kubernetes/manifests/kube-controller-manager.yaml
yaml
spec:
containers:
- command:
- kube-controller-manager
- --allocate-node-cidrs=true
......
# 增加下面三行参数
- --horizontal-pod-autoscaler-sync-period=10s
- --horizontal-pod-autoscaler-initial-readiness-delay=20s
- --horizontal-pod-autoscaler-downscale-stabilization=60s
保存退出,静态 Pod 会自动重启生效。
Horizontal Pod Autoscaler
学习参考:hpa
HPA 作用
控制器将从一系列API(metrics.k8s.io、custom.metrics.k8s.io 和 external.metrics.k8s.io)中获取度量值。 metrics.k8s.io API 通常由Metrics Server提供。根据 HPA 中定义的指标动态实现控制器中pod伸缩,支持replication controller、deployment和replicaset。
适用场景
- 流量波动大的无状态服务(nginx、api、网关、微服务)
- 需要提高并发 、削峰填谷
- Deployment/StatefulSet 都支持
核心特点
- 不修改 Pod 配置,只改副本数
- 实时、秒级扩缩
- 最常用、最稳定
支持指标
- CPU 使用率
- 内存使用率
- 自定义指标(Prometheus 对接)
- QPS、延迟等
基于 CPU 使用率伸缩
准备资源
bash
[root@master30 ~]# kubectl create deployment web --image=docker.io/library/nginx
创建 hpa
bash
Usage: kubectl autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS]--max=MAXPODS [--cpu-percent=CPU] [options]
[root@master30 ~]# kubectl autoscale deployment web --max=5 --min=2 --cpu-percent=80
[root@master30 ~]# kubectl get hpa web -o yaml |tee hpa-cpu.yaml
# 省略部分不重要配置
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
maxReplicas: 5
metrics:
- resource:
name: cpu
target:
averageUtilization: 80
type: Utilization
type: Resource
minReplicas: 2
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
bash
[root@master30 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: <unknown>/80% 2 5 2 2m28s
# CPU目标为unknown
# 稍等片刻,创建一个新的pod
[root@master30 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
web-96d5df5c8-4ztct 1/1 Running 0 30s
web-96d5df5c8-fq5kd 1/1 Running 0 41s
要想看到 HPA 的 TARGETS 值必须满足2个条件:
- 安装 metric server。
- 为 pod 设定资源限制。
bash
[root@master30 ~]# kubectl edit deployments.apps web
# 修改spec.template.spec.containers.[N].resources属性,添加limit属性,如下:
resources:
limits:
cpu: 100m
memory: 200Mi
# 再次查看hpa
[root@master30 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 0%/80% 2 5 2 5m3s
[root@master30 ~]# kubectl expose deployment web --port=80 --target-port=80
[root@master30 ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web ClusterIP 10.100.255.92 <none> 80/TCP 2m4s
压力测试
bash
# 打开一个监控窗口
[root@master30 ~]# watch 'kubectl get hpa;echo;kubectl top pods'
# 上 CPU 压力
[root@master30 ~]# apt install -y apache2-utils
[root@master30 ~]# while true ;do ab -n 300000 -c 100 http://10.99.129.137/;sleep 1;done
# -n 300000,总请求数
# -c 100,每次并发数
CPU负载 cpu: 98%
bash
Every 2.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 09:57:22 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 98%/80% 2 5 2 8m32s
NAME CPU(cores) MEMORY(bytes)
web-6dcdc45c94-277r9 99m 3Mi
web-6dcdc45c94-8xdn8 97m 3Mi
超过目标值后,HPA 新建了一个pod
Every 2.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 09:58:04 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 95%/80% 2 5 3 9m14s
NAME CPU(cores) MEMORY(bytes)
web-6dcdc45c94-277r9 99m 3Mi
web-6dcdc45c94-8xdn8 95m 3Mi
web-6dcdc45c94-t4q2p 100m 3Mi
HPA又新建了一个pod
bash
Every 2.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 09:58:59 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 45%/80% 2 5 5 11m
NAME CPU(cores) MEMORY(bytes)
web-6dcdc45c94-277r9 55m 3Mi
web-6dcdc45c94-2zj8s 100m 3Mi
web-6dcdc45c94-8xdn8 98m 3Mi
web-6dcdc45c94-sxvbb 100m 3Mi
HPA又新建了一个pod
bash
Every 2.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 09:59:59 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web cpu: 45%/80% 2 5 5 11m
NAME CPU(cores) MEMORY(bytes)
web-6dcdc45c94-277r9 55m 3Mi
web-6dcdc45c94-2zj8s 100m 3Mi
web-6dcdc45c94-8xdn8 98m 3Mi
web-6dcdc45c94-sxvbb 100m 3Mi
web-6dcdc45c94-t4q2p 100m 3Mi
观察过程:
-
随着pod CPU使用率上升,自动扩展pod数量。
-
即使pod CPU使用率超过阈值,但pod数量不会超过5。
-
压力测试完成后,pod数量逐渐减少为2。
清理资源
bash
# 删除 hpa
[root@master30 ~]# kubectl delete hpa web
# 删除 deployment
[root@master30 ~]# kubectl delete deployment web
# 保留 svc,后续使用
基于 Mem 使用率伸缩
我们仍然以nginx应用实践。想要Nginx 内存涨,要访问会占用内存的页面 。最简单方法:让 Nginx 返回一个超大响应体。
准备资源
bash
# worker节点创建big.img
[root@worker31 ~]# mkdir /www
[root@worker31 ~]# dd if=/dev/zero of=/www/big.img bs=1M count=200
[root@worker32 ~]# mkdir /www
[root@worker32 ~]# dd if=/dev/zero of=/www/big.img bs=1M count=200
[root@master30 ~]# vim deployment-web.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: big-file
mountPath: /usr/share/nginx/html
resources:
limits:
cpu: 100m
memory: 200Mi
volumes:
- name: big-file
hostPath:
path: /www
bash
[root@master30 ~]# kubectl apply -f deployment-web.yaml
创建 hpa
bash
[root@master30 ~]# vim hpa-mem.yaml
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
maxReplicas: 5
metrics:
- resource:
name: memory
target:
type: Utilization
averageUtilization: 60
type: Resource
minReplicas: 2
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
bash
[root@master30 ~]# kubectl apply -f hpa-mem.yaml
[root@master30 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: <unknown>/60% 2 5 1 13m
# 目标值为空
# 稍等片刻,创建一个新的pod
[root@master30 ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
web-6dcdc45c94-2zj8s 1/1 Running 0 13m
web-6dcdc45c94-w62pr 1/1 Running 0 13s
# 稍等一会,再次查看
[root@master30 ~]# kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 1%/60% 2 5 2 53s
压力测试
bash
# 打开一个监控窗口
[root@master30 ~]# watch -n 4 'kubectl get hpa;echo;kubectl top pods'
# 上 MEM 压力
[root@master30 ~]# while true ;do ab -n 300000 -c 100 http://10.99.129.137/big.img;sleep 1;done
负载上来了
bash
Every 4.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 11:13:29 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 86%/60% 2 5 2 16m
NAME CPU(cores) MEMORY(bytes)
web-88cff78bb-2b7vh 15m 174Mi
web-88cff78bb-76pg2 15m 171Mi
新建了一个pods
Every 4.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 11:13:46 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 58%/60% 2 5 3 16m
NAME CPU(cores) MEMORY(bytes)
web-88cff78bb-2b7vh 15m 174Mi
web-88cff78bb-4hcm5 5m 3Mi
web-88cff78bb-76pg2 15m 171Mi
又新建了一个pods
bash
Every 4.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 11:15:46 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 58%/60% 2 5 4 16m
NAME CPU(cores) MEMORY(bytes)
web-88cff78bb-2b7vh 15m 174Mi
web-88cff78bb-4hcm5 5m 3Mi
web-88cff78bb-76pg2 15m 171Mi
web-88cff78bb-ws6t4 1m 3Mi
又新建了一个pods
bash
Every 4.0s: kubectl get hpa;echo;kubectl top pods master30.laoma.cloud: Sun Apr 19 11:17:46 2026
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
web Deployment/web memory: 58%/60% 2 5 5 16m
NAME CPU(cores) MEMORY(bytes)
web-88cff78bb-2b7vh 15m 174Mi
web-88cff78bb-4hcm5 5m 3Mi
web-88cff78bb-76pg2 15m 171Mi
web-88cff78bb-ws6t4 1m 3Mi
web-88cff78bb-t4q2p 100m 3Mi
观察过程:
- 随着pod MEM使用率上升,自动扩展pod数量。
- 即使pod MEM使用率超过阈值,但pod数量不会超过5。
清理资源
bash
# 删除 hpa
[root@master30 ~]# kubectl delete hpa web
# 删除 deployment
[root@master30 ~]# kubectl delete deployment web
# 删除 svc
[root@master30 ~]# kubectl delete svc web
控制扩容和减容
示例:
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web
spec:
###############################
behavior:
# 缩容
scaleDown:
policies:
- periodSeconds: 60
type: Percent
value: 20
- periodSeconds: 60
type: Pods
value: 1
selectPolicy: Min
#每次减容时间,默认值为300
stabilizationWindowSeconds: 30
# 扩容
scaleUp:
policies:
- periodSeconds: 60
type: Percent
value: 50
- periodSeconds: 60
type: Pods
value: 2
selectPolicy: Max
# 每次扩容时间,默认值为0
stabilizationWindowSeconds: 30
############################
maxReplicas: 10
metrics:
- resource:
name: cpu
target:
averageUtilization: 80
type: Utilization
type: Resource
minReplicas: 2
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
Vertical Pod Autoscaler
VPA 使用场景不多,这里不做实践演示。
VPA 作用
控制器将从一系列API(metrics.k8s.io、custom.metrics.k8s.io 和 external.metrics.k8s.io)中获取度量值,metrics.k8s.io API 通常由Metrics Server提供。根据 VPA 中定义的指标动态调整 Pod 的 requests 和 limits。
VPA 适用场景
- 资源配置不合理的服务
- 长期运行、流量稳定的服务
- Java、Go 等内存占用固定的应用
- 不适合频繁扩缩的服务。
VPA 核心特点
- 不改变 Pod 数量
- 自动给 Pod 推荐 / 设置 CPU / 内存
- 生效需要重启 Pod(默认)
- 比 HPA 少用,因为有侵入性
HPA 与 VPA 对比
| 项目 | HPA 横向扩缩容 | VPA 纵向扩缩容 |
|---|---|---|
| 全称 | Horizontal | Vertical |
| 扩缩方式 | 增加 / 减少 Pod 数量 | 调整 CPU / 内存 request/limit |
| 是否重启 Pod | ❌ 不重启 | ✅ 一般需要重启 |
| 适合负载 | 流量波动大 | 资源配置不合理 |
| 生效速度 | 快 | 慢 |
| 稳定性 | 高 | 中 |
| 生产使用 | 非常普遍 | 较少 |
| 能否一起开 | 不能同时开(会冲突) | - |
| 支持资源 | CPU、内存、自定义 | CPU、内存 |