引子

为了更好地管理集群,我们打算使用工具监控集群, 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,感谢您阅读这篇博客,人生海海,和自己对话,像只蝴蝶纵横四海。