背景:有监控node节点pod的CPU等资源,实现自动扩缩容的需要下,需要安装metrics-server
k8s版本:1.30.14(kubadm安装) 对应metrics-server版本:0.8x(本文使用0.8.1)
1、下载部署清单
wget https://github.com/kubernetes-sigs/metrics-server/releases/download/v0.8.1/components.yaml
2、修改components.yaml配置文件
containers: - args: - --cert-dir=/tmp - --secure-port=10250 # ... 可能还有其他参数 ... - --kubelet-insecure-tls # 添加这一行(添加) image: registry.k8s.io/metrics-server/metrics-server:v0.8.1 # 您的镜像地址(修改) name: metrics-server
3、部署与验证
kubectl apply -f components.yaml # 查看 metrics-server Pod 是否运行正常 kubectl get pods -n kube-system -l k8s-app=metrics-server
(最好是kubectl get all -A|grep metrics-server验证)
ubuntu@VM-0-4-ubuntu:~$ kubectl get all -A|grep metrics-server
kube-system pod/metrics-server-588d67bbf8-k8gjm 1/1 Running 0 98m
kube-system service/metrics-server ClusterIP 10.50.168.106 <none> 443/TCP 98m
kube-system deployment.apps/metrics-server 1/1 1 1 98m
kube-system replicaset.apps/metrics-server-588d67bbf8 1 1 1 98m
如果 Pod 状态为 Running,通常表示安装成功。kubectl top nodes会有数据
ubuntu@VM-0-4-ubuntu:~$ kubectl top nodes NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% vm-0-4-ubuntu 81m 2% 2006Mi 55% vm-4-5-ubuntu 57m 2% 1042Mi 56%
5、版本兼容性
不同版本的 metrics-server 对 Kubernetes 集群有兼容性要求。选择版本时,请务必参考官方或云服务商提供的兼容性矩阵。
6、生产环境安全
在上述示例中,我们使用了 --kubelet-insecure-tls 参数来跳过证书验证,这仅在测试环境中推荐使用。在生产环境中,为了安全起见,你应该配置和使用有效的 TLS 证书。
7、重点来了,安装过程中遇到的问题
由于我们是kubadm安装,因此本文不讲二进制安装k8s后再部署metrics-server问题。kubadm安装的k8s,基本不用考虑apiservice链路聚合问题,二进制安装才会考虑,进而修改api配置文件。
先描述下我们遇到的问题:
kubectl get all -A|grep metrics-server检查时,server,pod,deployment都没问题,但是kubectl top nodes报错,这个时候就需要排查metrics-server最重要的一个东西:apiservice v1beta1.metrics.k8s.io,这个api是metrics-server向k8s注册的一个api接口,主要负责的就是通过k8s获取各个节点pod的cpu等资源使用情况,下面展示下排查细节
ubuntu@VM-0-4-ubuntu:~$ kubectl get apiservice v1beta1.metrics.k8s.io NAME SERVICE AVAILABLE AGE v1beta1.metrics.k8s.io kube-system/metrics-server False (FailedDiscoveryCheck) 139m
可以看到api状态False,接着看详细描述
ubuntu@VM-0-4-ubuntu:~$ kubectl describe apiservice v1beta1.metrics.k8s.io Name: v1beta1.metrics.k8s.io Namespace: Labels: k8s-app=metrics-server Annotations: <none> API Version: apiregistration.k8s.io/v1 Kind: APIService Metadata: Creation Timestamp: 2026-08-30T08:09:10Z Resource Version: 38004 UID: ceda4901-435b-425f-ab56-b0abaa5c9348 Spec: Group: metrics.k8s.io Group Priority Minimum: 100 Insecure Skip TLS Verify: true Service: Name: metrics-server Namespace: kube-system Port: 443 Version: v1beta1 Version Priority: 100 Status: Conditions: Last Transition Time: 2026-08-30T10:08:28Z Message: failing or missing response from https://10.50.168.106:443/apis/metrics.k8s.io/v1beta1: Get "https://10.50.168.106:443/apis/metrics.k8s.io/v1beta1": net/http: request canceled (Client.Timeout exceeded while awaiting headers) Reason: FailedDiscoveryCheck Status: False Type: Available Events: <none>
看,报错metrics-server的service ClusterIP 10.50.168.106 443链接超时
vim /etc/kubernetes/manifests/kube-apiserver.yaml 添加 - --tls-private-key-file=/etc/kubernetes/pki/apiserver.key - --enable-aggregator-routing=true(添加该参数) 会临时解决报错443超时(不建议使用)
解释下原理(个人理解):参数解释:--enable-aggregator-routing=true是 Kubernetes API Server 的启动参数,用于启用 API Aggregation 层的路由转发功能,使核心 API Server 能将特定前缀(如/apis/metrics.k8s.io)的请求代理到外部扩展 API Server(如 Metrics Server、Custom Metrics API 等)
参数作用:该参数的作用是允许聚合器将请求直接路由到端点 IP(pod IP) 而非集群 IP(Service IP)
参数要求:部署位置要求:若kube-proxy与kube-apiserver不在同一节点,则必须启用此参数
在k8s 1.30.1中,该参数默认不开启,也就是说加了该参数,api路由就跳过了metrics-server的service IP,直接去访问pod IP了,也就是我们pod IP的10250端口,但是走的网络还是calico的vxlan模式
但是这会引起另一个类似报错是metrics-server的pod 10250超时
ubuntu@VM-0-4-ubuntu:~$ kubectl describe apiservice v1beta1.metrics.k8s.io Name: v1beta1.metrics.k8s.io Namespace: Labels: k8s-app=metrics-server Annotations: <none> API Version: apiregistration.k8s.io/v1 Kind: APIService Metadata: Creation Timestamp: 2026-08-30T08:09:10Z Resource Version: 38004 UID: ceda4901-435b-425f-ab56-b0abaa5c9348 Spec: Group: metrics.k8s.io Group Priority Minimum: 100 Insecure Skip TLS Verify: true Service: Name: metrics-server Namespace: kube-system Port: 443 Version: v1beta1 Version Priority: 100 Status: Conditions: Last Transition Time: 2026-08-30T10:08:28Z Message: failing or missing response from https://10.60.139.19:10250/apis/metrics.k8s.io/v1beta1: Get "https://10.60.139.19:10250/apis/metrics.k8s.io/v1beta1": net/http: request canceled (Client.Timeout exceeded while awaiting headers) Reason: FailedDiscoveryCheck Status: False Type: Available Events: <none>
到现在,我们弄清楚了报错信息,但是还要找原因
先说根本原因:网络不通(不要想什么api聚合问题,就是网络原因)
解释下网络原理(重点):
master节点的metrics-server的api发起访问,走calico网络vxlan(4789端口UDP协议),去node节点的metrics-server pod获取数据(k8s api配置文件未添加- --enable-aggregator-routing=true参数时,走service IP443端口,添加该参数走pod 10250(可自定义)端口)
为什么我笃定是网络原因呢,因此就这个问题我排查了2天,api聚合链路,metrics-server配置文件什么的各种参数,甚至k8s我都重装了一遍,网上也各种搜索,有的文章也说到了是网络问题,但是给出的解决方案安全性不高,基于此才想把该问题分享下
先说下网上的解决方案:
在metrics-server配置文件里加一个参数
serviceAccountName: metrics-server hostNetwork: true #(加的参数) volumes: - emptyDir: {} name: tmp-dir
该参数确实能解决以上我们遇到的问题,但是会增加风险:暴露宿主机网络、端口冲突、安全性下降
解释下网络原理:
hostNetwork: true 是 Kubernetes Pod 规格中的字段,启用后 Pod 直接使用宿主机的网络命名空间(跳过 CNI 网络插件隔离)
导致:IP 行为:Pod IP = 节点 IP;
端口暴露:容器监听端口直接绑定宿主机端口,无需 hostPort(若同时配置 hostPort 会被忽略)
配置了该参数后,容器流量直连宿主机协议栈,不经过 calico 虚拟接口、IPIP/VXLAN 隧道或 Calico 路由表,跨节点通信依赖物理网络路由而非 Calico 通告的 Pod 网段。也就说走的是宿主机网络10250端口的tcp协议(需要云主机防火墙规则放行10250端口TCP协议)。
那么有没有什么更安全的解决方案呢?有的。其实能遇到443,10250链接超时问题的小伙伴,我想大多数应该都是在云主机上搭建的测试环境(或者是本地环境的网络配置有问题)
我的环境就是腾讯云主机的环境,基于此分析,那么为什么我们443,10250会超时就很简单了,就是因为calico vxlan模式使用的是4789端口UDP协议,但是云防火墙该端口协议没开!!!
只要我们在云主机防火墙规则打开4789端口UDP协议就可以,不用其他什么配置

至于本地环境的小伙伴,依据此问题判断,大概率就是路由器规则不允许4789端口UDP协议通行导致的
最后再解释一下网络原理:
(跨节点通信,k8s使用的calico网络vxlan模式,metrics-server的pod在node节点上,存在metrics-server的service,metrics-server部署在非node节点,获取信息属于跨节点)
metrics-server api发起访问,走calico网络vxlan(4789端口UDP协议),去node节点的metrics-server pod获取数据(正常是走metrics-server的service端口获取数据)
当然,这只是本人遇到的443,10250超时的一种情况,若是有其他情况,欢迎补充。
评论 资讯互动
来坐个前排。