引子
为了更好地管理集群,我们打算使用工具监控集群, k8s 首推的是 metric-server; 在其他书籍中我看到的使用 prometheus(普罗米修斯),所以我们对二者都进行一个测试.
metric-server
什么是 metric-server
Metrics Server collects resource metrics from Kubelets and exposes them in Kubernetes apiserver through Metrics API for use by Horizontal Pod Autoscaler and Vertical Pod Autoscaler. Metrics API can also be accessed by kubectl top, making it easier to debug autoscaling pipelines.
它会去与 kubelet 交互,作为 apiserver 的外部 api,向 kubelet 的 /metrics/resource 发起 HTTPS 请求;同时其还支持 HPA 自动扩缩容
可以使用 kubectl get apiservices 查看其 api 状态
NAME SERVICE AVAILABLE AGE
v1beta1.metrics.k8s.io kube-system/metrics-server False (MissingEndpoints) 3d22h
具体操作
首先,metric-server 在其 release 版本中并没有 riscv 的版本,所以我们先要进行适配工作. 不过好在之前的那位大佬也做了相关的支持,所以我们直接使用它的镜像作为我们的私有仓库镜像.
之后写一个 yaml文件 用来部署 metric-server 到 server 上
# metrics-server.yaml
apiVersion: v1
kind: Namespace
metadata:
name: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: metrics-server
namespace: kube-system
labels:
k8s-app: metrics-server
spec:
replicas: 1
selector:
matchLabels:
k8s-app: metrics-server
template:
metadata:
labels:
k8s-app: metrics-server
spec:
containers:
- name: metrics-server
image: jimlt.bfsmlt.top/metrics-server:v0.7.2 # 私有镜像
imagePullPolicy: IfNotPresent
args:
- --cert-dir=/tmp
- --secure-port=4443
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
ports:
- containerPort: 4443
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: metrics-server
namespace: kube-system
labels:
k8s-app: metrics-server
spec:
selector:
k8s-app: metrics-server
ports:
- port: 443
targetPort: 4443
这里包括了 Deployment 和对应的 Service,并且我们作为测试没有用到 tls --kubelet-insecure-tls
写好之后进行部署 kubectl apply -f xxx.yaml
部署结束后,我们进行测试 kubectl top nodes,发现此服务并没有启动成功.
排查问题
我们自然地去查看容器的状态,即 kubectl describe,发现问题所在
Readiness probe failed: Get "https://10.42.0.58:10250/readyz": dial tcp 10.42.0.58:10250: connect: connection refused
这是个什么地址呢?我们先来看看之前 yaml 文件中的这段代码 --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
- InternalIP: 节点 Node 在集群内部网络中的地址
- ExternalIP: 公网 IP,供集群外部访问
- Hostname: 节点的计算机名称
这些与 PodIP 不同,PodIP 是集群使用 CNI 分配的,关于 CNI 在 k3s 中的知识,请看这篇文章.
所以,这个请求其实是发往了我的 server 节点上的一个 Pod,所以这个就很奇怪了,按道理来说应该发往 InternalIP 即192.168.1.198 才对
执行 kubectl get apiservices 可以发现 MissingEndpoints
v1beta1.metrics.k8s.io kube-system/metrics-server False (MissingEndpoints) 3d22h
相关的 issue 可以找到些解决办法,最多的还是添加 - --kubelet-insecure-tls,但是我们已经有了不是吗?
如果现在遇到同样问题的你找到了其他更好的相关问题或者解决方法,请在评论区告知.
我们在 yaml 配置中添加 HostNetwork
spec:
hostNetwork: true # ✅ 添加 hostNetwork,避免 CNI 中 10250 访问失败
dnsPolicy: ClusterFirstWithHostNet # ✅ 搭配 hostNetwork 使用
之后再次查看容器的运行状态:
Readiness probe failed: HTTP probe failed with statuscode: 404
通过查看日志发现:
sudo kubectl logs -n kube-system metrics-server-6b8f575f5d-56jm8
I0518 11:31:43.086131 1 serving.go:374] Generated self-signed cert (/tmp/apiserver.crt, /tmp/apiserver.key)
I0518 11:31:45.510186 1 handler.go:275] Adding GroupVersion metrics.k8s.io v1beta1 to ResourceManager
I0518 11:31:45.658709 1 requestheader_controller.go:169] Starting RequestHeaderAuthRequestController
I0518 11:31:45.658803 1 shared_informer.go:311] Waiting for caches to sync for RequestHeaderAuthRequestController
I0518 11:31:45.659011 1 configmap_cafile_content.go:202] "Starting controller" name="client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file"
I0518 11:31:45.659138 1 shared_informer.go:311] Waiting for caches to sync for client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
I0518 11:31:45.659169 1 configmap_cafile_content.go:202] "Starting controller" name="client-ca::kube-system::extension-apiserver-authentication::client-ca-file"
I0518 11:31:45.659247 1 shared_informer.go:311] Waiting for caches to sync for client-ca::kube-system::extension-apiserver-authentication::client-ca-file
I0518 11:31:45.660929 1 dynamic_serving_content.go:132] "Starting controller" name="serving-cert::/tmp/apiserver.crt::/tmp/apiserver.key"
I0518 11:31:45.662143 1 secure_serving.go:213] Serving securely on [::]:4443
I0518 11:31:45.662329 1 tlsconfig.go:240] "Starting DynamicServingCertificateController"
I0518 11:31:45.759559 1 shared_informer.go:318] Caches are synced for client-ca::kube-system::extension-apiserver-authentication::client-ca-file
I0518 11:31:45.759641 1 shared_informer.go:318] Caches are synced for client-ca::kube-system::extension-apiserver-authentication::requestheader-client-ca-file
I0518 11:31:45.759584 1 shared_informer.go:318] Caches are synced for RequestHeaderAuthRequestController
其并没有直接显示一些访问地址失败的信息.
接着我们尝试 kubectl edit deployment -n kube-system metrics-server修改配置
将 livenessProbe 和 readinessProbe 及其有关配置删除
相关解决方案来自 CSDN
readinessProbe:
httpGet:
path: /readyz
port: 4443
scheme: HTTPS
initialDelaySeconds: 20
periodSeconds: 10
再来看看 Pod 结果如何
kube-system metrics-server-6c8f74f4c4-fktpw 1/1 Running
居然成功了,查看集群信息:
sudo kubectl top no
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
agent197 40m 1% 774Mi 9%
revyos-lpi4a 136m 3% 1502Mi 9%
所以最终我们只需要去掉 readinessProbe即可,不用添加 NetWork 等字段在配置文件中. 这对整体的运行时没有影响的,只是去掉了存活探针检测机制.
Probe及可能原因
这些 Probe 是来自于 k3s 的系统探针
- Readiness Probe:检测某个容器是否就绪(就是我们常见的 Ready 字段),是否可以接受流量,如果没有就不能加入到 Service
- Liveness Probe:判断容器是否“健康”,未通过探针 → 被重启容器。
- Startup Probe:判断容器启动是否完成,配合前两者避免“启动未完成就被探测失败”。
所以结合之前的两种失败报错, https://10.42.0.58:10250/readyz,是 metric-server 访问 kubelet 容器,因为 metrics-server 默认会通过 kubelet API 获取节点、容器、Pod 的资源指标数据
后来返回404:
- 可能metrics-server 镜像中并没有暴露 /readyz 这个 HTTP 路径
- 某些版本只支持 /healthz 或 / 路径
prometheus
prometheus 在 k8s 的集群监控中也是十分常见的工具,可抓取 所有组件、应用、Exporter 的细粒度指标,并且可以做到报警,可视化,长期持久化等功能.
所以我们测试一下在我们的集群中使用情况.
操作流程
与 metric-server 不同的是,prometheus 支持 riscv 架构,所以我们可以直接使用.
在官网下载好安装包传到开发板 server 节点上,进行解压,并将可执行文件和配置文件都放到对应目录中
sudo cp ~/prometheus-2.53.4.linux-riscv64/prometheus /usr/local/bin/prometheus
sudo cp ~/prometheus-2.53.4.linux-riscv64/prometheus.yml /etc/prometheus/prometheus.yml
为其编写 service 文件,交由 systemd 管理
[Unit]
Description=Prometheus Monitoring
Wants=network-online.target
After=network-online.target
[Service]
User=debian
ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/var/lib/prometheus \
--web.listen-address=0.0.0.0:9090 \
--web.enable-lifecycle
Restart=on-failure
[Install]
WantedBy=multi-user.target
这里的 User 可以选择为 prometheus 独立创建一个用户;数据存储在 /var/lib/prometheus 下
同时创建对应的目录并为其赋予对应权限.
sudo mkdir -p /etc/prometheus /var/lib/prometheus
sudo chown -R jimlt:jimlt /etc/prometheus /var/lib/prometheus
重新加载 systemd 并启动
sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable prometheus
sudo systemctl start prometheus
验证其状态:
sudo systemctl status prometheus
#
prometheus.service - Prometheus Monitoring
Loaded: loaded (/etc/systemd/system/prometheus.service; enabled; preset: enabled)
Active: active (running) since Sun 2025-05-18 20:59:08 CST; 12min ago
Invocation: a99f1274a13a4ae89ecb9726ece102a4
Main PID: 5337 (prometheus)
Tasks: 10 (limit: 18020)
Memory: 41.2M (peak: 41.9M)
CPU: 5.667s
CGroup: /system.slice/prometheus.service
└─5337 /usr/local/bin/prometheus --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/var/lib/prometheus --web.listen-address=0.0.0.0:9090 --web.enable->
此时我们就可以去浏览器中输入 localhost:9000 访问其监控页面.
关于其安装部署流程就告一段落了,后续我们可以在其配置文件中添加 job,让其监控集群中的数据,关于其后续的更深入操作,见以后的文章吧!
总结
本文尝试了 k3s 集群中两种监控方案的实现,并解决了 metric-server 运行过程中的探针问题.为后续集群的监控奠定了基础.
这里是LTX,感谢您阅读这篇博客,人生海海,和自己对话,像只蝴蝶纵横四海。