跳到主要内容

Kubernetes/监控 生产部署台账:K8s 集群如何接入 Prometheus(Node Exporter 与 DaemonSet 实战)

01 前置理论与核心机制​

1. Kubernetes 已经能管理节点,为什么还需要 Node Exporter?​

Kubernetes 可以管理 Pod、调度工作负载,但日常运维还需要知道每台节点的 CPU、内存、磁盘和网络使用情况。比如:某台节点内存持续升高、磁盘空间不足,或者网卡流量突然增加。

这类操作系统指标可以通过 Node Exporter + Prometheus 采集:

  • Node Exporter:运行在 Linux 节点上,通过 HTTP 接口暴露主机指标。
  • Prometheus:定期访问采集接口,把指标保存下来,供查询、看板和告警使用。
  • Grafana(可选):连接 Prometheus,把已经采集的指标展示成图表。

核心流程:在节点上部署采集器 → 配置 Prometheus 抓取地址 → 确认 Targets 状态为 up。

2. 为什么选 DaemonSet?​

Node Exporter 默认通过 9100 端口提供 /metrics 接口。

如果逐台安装,节点一多就要重复操作。使用 Kubernetes 的 DaemonSet 更方便:

  • 在每个符合条件的节点上运行一个采集器 Pod。
  • 新节点加入集群后,可以自动在新节点上创建采集器。
  • 如果控制平面节点有污点,可以通过 tolerations 允许采集器调度过去。

部署文件里还会用到 hostNetwork: true,让 Node Exporter 使用节点网络,通过 节点IP:9100 提供指标。为了读取宿主机相关信息,还要挂载宿主机文件系统。

要注意,DaemonSet 负责部署采集器,不负责把采集目标自动注册到 Prometheus。 本文先用容易理解的静态地址配置完成接入,后面也会说明节点较多时如何扩展。

3. Prometheus 怎么知道采集成功了?​

Prometheus 的 scrape_configs 中,每个 job_name 表示一组采集目标,例如:

- job_name: 'k8s-node-exporter'
static_configs:
- targets: ['192.168.10.11:9100', '192.168.10.12:9100', '192.168.10.13:9100']

这些地址只是示例,需要换成自己的节点 IP。节点数量不必固定为三台,按实际情况填写即可。

Prometheus 会定期请求每个地址的 /metrics 接口。抓取成功时 up=1,抓取失败时 up=0。在 Targets 页面或 API 中,分别显示为 up 和 down。

up=1 只能说明指标抓取成功,不等于这台节点上的所有业务都正常。


02 部署接入与验证闭环 SOP​

步骤一:确认 Kubernetes 节点状态​

在能使用 kubectl 的管理节点上执行:

kubectl get nodes -o wide

重点看 STATUS、ROLES 和 INTERNAL-IP:

  • STATUS 应为 Ready。
  • ROLES 用来区分控制平面节点和工作节点。
  • INTERNAL-IP 是后续配置 Prometheus 采集地址时需要确认的信息。

先把要监控的 Linux 节点 IP 确认好,避免后面填写错地址。

步骤二:部署 Node Exporter​

在当前工作目录准备 node-exporter.yaml,完整文件放在第 07 章。它包含 monitoring 命名空间和 Node Exporter DaemonSet,可以直接参考使用。

先查看配置:

cat node-exporter.yaml

重点关注 DaemonSet、hostNetwork、宿主机目录挂载,以及控制平面节点的 tolerations。

执行部署:

kubectl apply -f node-exporter.yaml

查看 Pod 分布:

kubectl get pods -n monitoring -o wide

再看 DaemonSet 的期望数量和就绪数量:

kubectl get daemonset -n monitoring

正常情况下,每个符合条件的 Linux 节点都有一个 Node Exporter Pod。READY 数量与 DESIRED 一致,Pod 处于 Running,说明部署基本正常。

步骤三:验证 Node Exporter 是否返回指标​

在已运行 Node Exporter 的 Linux 节点上执行:

curl -s localhost:9100/metrics

也可以从其他能访问该节点的机器请求 http://节点IP:9100/metrics。

正常会看到大量指标,例如:

# HELP node_memory_MemAvailable_bytes Memory information field MemAvailable_bytes.
# TYPE node_memory_MemAvailable_bytes gauge
node_memory_MemAvailable_bytes 1.23456789e+09

node_memory_MemAvailable_bytes 是系统估算的可用物理内存,单位为字节。除此之外,还会有 CPU、文件系统、磁盘 I/O、网络等相关指标。

能看到 /metrics 数据,说明 Node Exporter 的接口正常;是否已经被 Prometheus 抓取,还需要在 Prometheus 侧确认。

步骤四:配置 Prometheus 采集任务​

找到 Prometheus 使用的 prometheus.yml,在现有的 scrape_configs 列表下添加一个任务:

- job_name: 'k8s-node-exporter'
static_configs:
- targets: ['192.168.10.11:9100', '192.168.10.12:9100', '192.168.10.13:9100']

这里假设有三个节点,实际应替换为 kubectl get nodes -o wide 查到的地址。若有更多节点,继续增加对应的 IP:9100 即可。

几个关键字段:

  • job_name:采集任务名,这里统一叫 k8s-node-exporter。
  • targets:Node Exporter 的访问地址。
  • scrape_interval:抓取间隔;例如在 global 中设置为 15s,表示每 15 秒抓取一次。

已有 Prometheus 配置时,把这个 job 添加到原有列表,不要再写第二个 scrape_configs: 顶层字段,也不要无意覆盖已有任务。 新建配置的完整示例在第 07 章。

步骤五:检查配置并让 Prometheus 重新加载​

下面以 Docker 运行 Prometheus,容器名为 prometheus 为例。若使用 systemd、Kubernetes 等方式部署,只需要改成对应的配置更新和重载方法。

将准备好的完整配置复制进容器:

docker cp prometheus.yml prometheus:/etc/prometheus/prometheus.yml

检查配置语法:

docker exec prometheus promtool check config /etc/prometheus/prometheus.yml

如果返回类似结果:

Checking /etc/prometheus/prometheus.yml
SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax

说明配置格式检查通过。再发送 HUP 信号热加载:

docker kill --signal=HUP prometheus

docker kill 在这里指定的是 HUP 信号,不是停止容器。Prometheus 收到信号后会重新读取配置。若语法检查失败,先修正配置,不要继续热加载。

步骤六:验证 Prometheus Targets​

在 Prometheus 所在服务器上执行:

curl -s localhost:9090/api/v1/targets

返回 JSON 后,重点看 labels.job、labels.instance、health 和 lastError。

例如三个节点接入成功时,状态应类似:

JobInstanceHealth
k8s-node-exporter192.168.10.11:9100up
k8s-node-exporter192.168.10.12:9100up
k8s-node-exporter192.168.10.13:9100up

也可以在 Prometheus 查询页面执行:

up{job="k8s-node-exporter"}

对应序列返回 1,说明 Prometheus 能正常抓取这些节点的指标。

到这里,节点监控接入就完成了。 后续可以在 Grafana 中使用 Prometheus 数据源查看节点指标,或者进一步配置告警规则。


03 生产故障案例与处理分析(模拟场景)​

案例一:工作节点有 Node Exporter,控制平面节点却没有​

故障现象

集群节点都是 Ready,但部署 DaemonSet 后,工作节点上都有 Node Exporter,控制平面节点却没有相应的 Pod。

排查过程

先确认节点和 Pod 分布:

kubectl get nodes -o wide
kubectl get pods -n monitoring -o wide

再检查 DaemonSet 的状态及事件:

kubectl describe daemonset node-exporter -n monitoring

通过以下命令查看节点污点:

kubectl describe nodes

假设发现控制平面节点存在 node-role.kubernetes.io/control-plane:NoSchedule,而部署文件没有匹配的 tolerations。

原因和处理

DaemonSet 虽然会为符合条件的节点安排 Pod,但仍要遵守节点调度约束。为 DaemonSet 增加对应的容忍规则,再执行 kubectl apply 更新资源,并检查 Pod 是否已分布到控制平面节点。

最终结论:DaemonSet 不等于无视节点污点。要采集控制平面节点,就要检查调度条件和容忍规则。

案例二:Pod 已经 Running,Prometheus Targets 却显示 down​

故障现象

Node Exporter Pod 正常运行,在节点本地访问 /metrics 也有数据,但 Prometheus 中某个采集目标显示 down。

排查过程

先看 Pod:

kubectl get pods -n monitoring -o wide

在 Prometheus 所在服务器上,请求异常节点的实际 IP。以示例地址为例:

curl -v --max-time 15 http://192.168.10.12:9100/metrics

如果节点本地可以访问,但从 Prometheus 所在服务器访问超时,就要查路由、防火墙和端口访问策略。若请求正常,再检查采集地址是否填写正确,并看 Targets 里的错误信息:

curl -s localhost:9090/api/v1/targets

必要时查看 Prometheus 日志:

docker logs --since 5m prometheus

原因和处理

假设故障是 Prometheus 到目标节点的 9100 端口被网络策略阻断,调整访问策略后,等待下一个抓取周期,再确认目标是否变为 up。

最终结论:Pod Running 不代表 Prometheus 已经能访问采集接口,排查时一定要从 Prometheus 所在位置验证网络连通性。


04 生产排障速查表(Node Exporter 与 Prometheus)​

排查什么命令看哪里
Kubernetes 节点是否正常kubectl get nodes -o wideReady、角色、节点 IP
采集器分布在哪些节点kubectl get pods -n monitoring -o widePod 状态、NODE
DaemonSet 是否覆盖预期节点kubectl get daemonset -n monitoringDESIRED、READY、AVAILABLE
为什么某个节点没有采集器kubectl describe daemonset node-exporter -n monitoringEvents、调度异常
控制平面节点是否有污点kubectl describe nodesTaints
Node Exporter 是否提供指标curl -s localhost:9100/metrics是否返回 node_ 指标
Prometheus 能否访问节点curl -v --max-time 15 http://192.168.10.12:9100/metrics连接成功、超时或拒绝(替换示例 IP)
Prometheus 配置是否有效docker exec prometheus promtool check config /etc/prometheus/prometheus.ymlSUCCESS 或错误信息
让 Prometheus 重新加载docker kill --signal=HUP prometheus热加载配置
采集目标状态curl -s localhost:9090/api/v1/targetshealth、lastError
Prometheus 最近日志docker logs --since 5m prometheus配置加载和抓取错误

建议按这个顺序排查:先看 DaemonSet/Pod,再看节点 9100 端口,最后检查 Prometheus 的配置、网络和抓取状态。


05 面试应答参考话术​

问题:新搭建了一套 Kubernetes 集群,你会怎么接入 Prometheus 节点监控?

可以这样回答:

我会先用 kubectl get nodes -o wide 检查节点状态和 IP,然后在集群中使用 DaemonSet 部署 Node Exporter,让每个需要监控的 Linux 节点都有一个采集器。如果控制平面节点存在污点,我会检查 DaemonSet 的 tolerations,确保采集器能按预期调度。

部署后,我会访问节点的 9100/metrics 接口,确认 CPU、内存、磁盘和网络等指标已经能够正常返回。接着在 Prometheus 的 scrape_configs 中添加 Node Exporter 的采集任务,检查配置并热加载。

最后通过 Prometheus Targets 或 up 指标确认采集成功。如果某个节点显示 down,就从 Pod 状态、9100 端口连通性和 Prometheus 的错误信息几个方向排查。


06 面试高频追问与应答预案​

Q1:DaemonSet 和 Deployment 有什么区别?​

Deployment 维护指定数量的 Pod 副本,不保证每个节点都有一份;DaemonSet 则在符合条件的节点上运行一个 Pod,适合节点监控、日志采集等场景。

Q2:为什么控制平面节点没有运行 Node Exporter?​

先看节点是否存在 NoSchedule 污点,再检查 DaemonSet 是否配置了对应的 tolerations。还要核对 nodeSelector、资源限制和其他调度条件。

Q3:为什么使用 hostNetwork: true?​

它让采集器使用宿主机网络,外部 Prometheus 可以通过 节点IP:9100 直接访问。要确保端口没有冲突,并且只向允许的监控服务器开放访问。

Q4:Pod Running,为什么 Prometheus 还是 down?​

Pod Running 只能说明容器在运行,并不能证明 Prometheus 抓取成功。我会先请求节点本地 /metrics,再从 Prometheus 所在服务器访问目标地址,最后看 Targets 的 lastError。

Q5:up=1 是否代表服务器没有问题?​

不是。它只代表当前采集成功。CPU、内存、磁盘或应用是否异常,还要看对应指标和业务状态。

Q6:节点越来越多,还要手动写 IP 吗?​

节点数量固定时,static_configs 简单直接;节点经常增加、删除或 IP 经常变化时,可以使用 Prometheus 的 kubernetes_sd_configs 做服务发现。动态发现还需要配置访问 Kubernetes API 的权限,以及正确的目标地址和标签规则,并不是仅改一个字段就能生效。

Q7:Node Exporter 能监控 Pod 状态和容器 CPU 吗?​

Node Exporter 主要采集节点操作系统指标。Pod 状态、Deployment 副本数等 Kubernetes 对象指标通常通过 kube-state-metrics 获取;容器 CPU、内存等使用情况可以通过 kubelet/cAdvisor 获取。接入 Prometheus 的总体思路仍然是配置采集任务并验证指标。

Q8:更新 Prometheus 配置必须重启容器吗?​

不一定。Prometheus 支持 HUP 信号热加载。可以先用 promtool 检查配置,再发送 HUP;也可以在启用了 HTTP 生命周期接口的情况下使用对应的 reload API。


07 完整部署文件与自动化检测脚本​

1. Node Exporter DaemonSet(node-exporter.yaml)​

下面这份文件包含 monitoring 命名空间与 DaemonSet,适用于常见的 Linux 节点。它通过宿主机网络提供 9100 端口,并挂载宿主机根目录供 Node Exporter 读取主机相关信息。

apiVersion: v1
kind: Namespace
metadata:
name: monitoring
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
labels:
app: node-exporter
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
hostNetwork: true
hostPID: true
dnsPolicy: ClusterFirstWithHostNet
nodeSelector:
kubernetes.io/os: linux
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: node-exporter
image: quay.io/prometheus/node-exporter:v1.9.1
imagePullPolicy: IfNotPresent
args:
- --path.rootfs=/host
ports:
- name: metrics
containerPort: 9100
protocol: TCP
securityContext:
runAsNonRoot: true
runAsUser: 65534
readOnlyRootFilesystem: true
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 200m
memory: 128Mi
volumeMounts:
- name: root
mountPath: /host
readOnly: true
mountPropagation: HostToContainer
volumes:
- name: root
hostPath:
path: /
type: Directory

保存为 node-exporter.yaml 后执行:

kubectl apply -f node-exporter.yaml
kubectl get pods -n monitoring -o wide

如果集群启用了较严格的 Pod 安全策略,hostNetwork、hostPID 和宿主机挂载可能受到限制,需要按集群安全要求调整。节点的 9100 端口也不能与其他程序冲突,网络访问权限应限制在必要范围内。

2. Prometheus 采集配置(prometheus.yml)​

下面是一个最小可用的配置示例。将地址换成自己的 Kubernetes 节点 IP,并根据实际节点数量增减目标:

global:
scrape_interval: 15s

scrape_configs:
- job_name: 'k8s-node-exporter'
static_configs:
- targets: ['192.168.10.11:9100', '192.168.10.12:9100', '192.168.10.13:9100']

如果 Prometheus 已有其他监控任务,只需将上面的 k8s-node-exporter 任务合并进已有的 scrape_configs 列表。 无需替换掉现有的采集目标。

使用 Docker 部署 Prometheus 时,配置更新与验证命令为:

docker cp prometheus.yml prometheus:/etc/prometheus/prometheus.yml
docker exec prometheus promtool check config /etc/prometheus/prometheus.yml
docker kill --signal=HUP prometheus
curl -s localhost:9090/api/v1/targets

这四条命令需要依次执行,只有 promtool 检查成功后,才继续热加载。其中容器名、配置路径和访问端口,要按自己的 Prometheus 部署情况修改。长期运行时,可以用 Docker 配置文件挂载或配置管理系统统一维护 prometheus.yml。

3. 自动检查 Node Exporter 采集状态(check_k8s_prometheus.sh)​

节点数量可能是三台、五台,也可能更多。因此脚本不把 IP 和数量写死,而是直接从 Prometheus Targets API 中读取 k8s-node-exporter 任务下的所有目标。

脚本只查询状态,不修改 Kubernetes 或 Prometheus 配置,依赖 curl、python3。

#!/usr/bin/env bash
# check_k8s_prometheus.sh:检查指定 Prometheus job 下的所有 Targets
set -euo pipefail

prom_url="${PROM_URL:-http://localhost:9090}"
job_name="${JOB_NAME:-k8s-node-exporter}"

curl -fsS --max-time 15 "${prom_url%/}/api/v1/targets" | python3 -c '
import json
import sys

data = json.load(sys.stdin)
job = sys.argv[1]
if data.get("status") != "success":
print("ERROR: Prometheus API returned an error")
sys.exit(1)

targets = [t for t in data.get("data", {}).get("activeTargets", [])
if t.get("labels", {}).get("job") == job]

if not targets:
print("FAILED: no targets found for job", job)
sys.exit(1)

failed = False
print("JOB:", job)
for t in targets:
instance = t.get("labels", {}).get("instance", "unknown")
health = t.get("health", "unknown")
print("{:<25} {}".format(instance, health))
if health != "up":
failed = True
if t.get("lastError"):
print(" lastError:", t["lastError"])

print("TOTAL:", len(targets), "FAILED:", sum(t.get("health") != "up" for t in targets))
sys.exit(1 if failed else 0)
' "$job_name"

保存为 check_k8s_prometheus.sh 后运行:

chmod +x check_k8s_prometheus.sh
./check_k8s_prometheus.sh

如果 Prometheus 不在本机,或者采集任务名称不同,可以这样指定:

PROM_URL=http://192.168.10.20:9090 JOB_NAME=k8s-node-exporter ./check_k8s_prometheus.sh

全部正常时会显示类似:

JOB: k8s-node-exporter
192.168.10.11:9100 up
192.168.10.12:9100 up
192.168.10.13:9100 up
TOTAL: 3 FAILED: 0

若有目标为 down,脚本会输出对应的 lastError,并返回非零退出码,方便在自动化巡检中判断失败。这个脚本检查的是 Prometheus 当前已经发现的目标;如果某个节点根本没有添加到采集配置里,还需要结合 kubectl get nodes -o wide 和 Targets 列表检查覆盖范围。

4. 接入完成后重点看什么?​

  • 覆盖范围:DaemonSet 的就绪数与需要监控的 Linux 节点数量是否一致。
  • 采集状态:Prometheus Targets 里每个目标是否为 up。
  • 指标内容:node_cpu_seconds_total、node_memory_MemAvailable_bytes、node_filesystem_avail_bytes、node_network_receive_bytes_total 等指标能否查询到。
  • 后续扩展:节点数量不大时使用 static_configs;节点变化频繁时可以逐步接入 Kubernetes 服务发现。

整套方案的重点就是:DaemonSet 负责在节点上运行采集器,Prometheus 负责抓取指标,最后通过 Targets 和实际指标完成验证。

完整内容已隐藏

请联系作者或在线获取阅读密码。