步骤三:验证 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。
例如三个节点接入成功时,状态应类似:
| Job | Instance | Health |
|---|
| k8s-node-exporter | 192.168.10.11:9100 | up |
| k8s-node-exporter | 192.168.10.12:9100 | up |
| k8s-node-exporter | 192.168.10.13:9100 | up |
也可以在 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
通过以下命令查看节点污点:
假设发现控制平面节点存在 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 wide | Ready、角色、节点 IP |
| 采集器分布在哪些节点 | kubectl get pods -n monitoring -o wide | Pod 状态、NODE |
| DaemonSet 是否覆盖预期节点 | kubectl get daemonset -n monitoring | DESIRED、READY、AVAILABLE |
| 为什么某个节点没有采集器 | kubectl describe daemonset node-exporter -n monitoring | Events、调度异常 |
| 控制平面节点是否有污点 | kubectl describe nodes | Taints |
| 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.yml | SUCCESS 或错误信息 |
| 让 Prometheus 重新加载 | docker kill --signal=HUP prometheus | 热加载配置 |
| 采集目标状态 | curl -s localhost:9090/api/v1/targets | health、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 和实际指标完成验证。