简介

Node Problem Detector(NPD)是 Kubernetes 集群中一个重要的监控插件,它的作用是监控节点的健康状况并检测可能出现的问题。NPD 通过在每个节点上运行的检测器来工作,能够发现基础设施、容器运行时、硬件和内核等问题,并将这些问题报告给集群中的上层控制面。

NPD 只是作为一个问题检测和报告程序运行,需要配合自愈程序才能完成节点问题的自动处理,默认的集群控制面组件并不会响应 NPD 报告的问题。NPD 可以检测的问题如下:

  • 基础设施问题: NTP 服务关闭;
  • 硬件问题:损坏的处理器 、内存或者磁盘;
  • 内核问题:内核死锁或者文件系统损坏;
  • 容器运行时问题:CRI 守护进程无响应;
  • ...

NPD 以 DaemoSet 或独立进程的方式运行,支持多个 exporter 作为通知渠道,其中 Kubernetes exporter 向 APIServer 报告以下两类节点问题:

  • Event ,对 Pod 影响有限但值得关注的问题;
  • NodeCondition , 可以导致 Pod 无法在节点运行的持久性问题;

实际上,两类问题都会产生 K8s Event ,只不过 NodeCondition 会作为一个不可自动恢复的状态持久存在于 Node 的描述信息中,除非主动重置或者重启 NPD Pod。考虑到 NodeCondition 需要作为自愈系统的输入,这是一种合理的设计,让自愈行为能够实现串行操作,有利于在自愈过程中保持一致性。

架构方面,目前, NPD 作为守护进程以 goroutine 方式运行各类问题检测器,支持用户以各种语言扩展,例如编写 check_xxx.sh 脚本并配置为 NPD 插件, temporarypermanent 类型的规则分别为 APIServer 上报 EventNodeCondition ,未来, NPD 和 问题检测器的架构可能发生变更,部分问题检测器以主机进程的方式运行,以避免检测行为受到被检测对象干扰,导致事件丢失。

NPD 支持的检测器类型有:

问题检测器类型 NodeCondition 描述
SystemLogMonitor <li>KernelDeadlock (内核死锁)<br><li>ReadonlyFilesystem (文件系统只读)<br><li>FrequentKubeletRestart ( Kubelet 频繁重启)<br><li>FrequentDockerRestart ( Docker 频繁重启)<br><li>FrequentContainerdRestart ( Containerd 频繁重启) 根据预定义规则监控系统日志,报告问题和指标,可禁用。
SystemStatMonitor 根据预定义规则监控系统健康相关的状态,报告问题和指标,可禁用。
CustomPluginMonitor NTPProblem ( NTP 问题) 调用用户自定义的问题检测器,仅包含 NTP 检测器作为示例,可禁用。
HealthChecker <li>KubeletUnhealthy ( Kubelet 非健康状态)<br><li>ContainerRuntimeUnhealthy (容器运行时非健康状态) 检查 Kubelet 和容器运行时( Docker 和 Containerd )健康状态,不支持禁用。

NPD 支持多种类型的导出器,可将节点事件导出为 Kubernetes 事件或者 Prometheus 指标等,通过采集以上渠道的数据可实现对节点事件的观测。相对来说,通过 Kubernetes Events 获取节点事件是一个更加优雅的方案,观测方能够通过事件流获得更丰富的上下文。

观测云采集器 Datakit 支持自动采集 Kubernetes 事件,配置日志检测监控器可向用户主动报告节点问题。使用云服务时,建议启用云厂商提供的 NPD 插件,将提供更强大的节点问题检测能力。

操作步骤

部署 DataKit

登录[观测云控制台],点击「集成」 -「DataKit」 - 「Kubernetes」,下载 datakit.yaml,拷贝第 3 步中 ENV_DATAWAY 键的值:

图片

编辑 datakit.yaml,修改 DaemonSet 环境变量:

  • 修改 ENV_DATAWAY 的值为上一步中拷贝的值;
  • 修改 ENV_CLUSTER_NAME_K8S 的值为集群名称;
  • 新增 ENV_NAMESPACE,值为集群名称;

执行以下命令部署 Datakit 并验证:

kubectl apply -f datakit.yaml
kubectl get pods -n datakit

部署成功后 Datakit 将自动采集集群事件并上报至数据来源为 kubernetes_events 的日志,无需额外配置,点击日志条目可查看阔扩展信息:

图片

开启 NPD 插件

对于云 Kubernetes 服务,推荐启用官方 NPD 插件,对于自建 Kubernetes 服务,可前往 NPD 官方仓库下载相关资源文件并部署:

注意:

  • 官方默认配置仅启用从操作系统、进程管理器日志检查节点问题的插件,启用其他插件可能需要为官方镜像集成命令行工具,例如 systemctl、crictl 等;
  • 官方镜像无法拉取时,可为镜像增加前缀 k8s.m.daocloud.io/

日志(事件)

观测云中,Kubernetes 事件描述如下:

{
  "time": 1723622964327,
  "time_us": 1723622964327008,
  "__docid": "L_1723622964327_cqu6cdhmc0rcje80ft90",
  "__source": "kubernetes_events",
  "message": "kernel: BUG: unable to handle kernel NULL pointer dereference at TESTING",
  "__isCutMessage": false,
  "__namespace": "logging",
  "source": "kubernetes_events",
  "status": "warn",
  "df_metering_size": 1,
  "message_length": 72,
  "cluster_name_k8s": "default",
  "date_ns": 1723622964327008500,
  "from_node": "lc-ubuntu-k8s-70",
  "index": "default",
  "involved_kind": "Node",
  "involved_name": "lc-ubuntu-k8s-70",
  "involved_namespace": "",
  "involved_uid": "lc-ubuntu-k8s-70",
  "reason": "KernelOops",
  "resource_version": "228175",
  "time_ns": 1723622964327008500,
  "type": "Warning",
  "uid": "32e220e4-e3f1-4e38-a079-4982c4824ca8",
  "__search": 0,
  "__searches": [],
  "__unit": {
    "time": null,
    "time_us": null,
    "__docid": null,
    "__source": null,
    "__namespace": null,
    "source": null,
    "status": null,
    "df_metering_size": null,
    "message_length": null,
    "cluster_name_k8s": null,
    "date_ns": null,
    "from_node": null,
    "index": null,
    "involved_kind": null,
    "involved_name": null,
    "involved_namespace": null,
    "involved_uid": null,
    "reason": null,
    "resource_version": null,
    "time_ns": null,
    "type": null,
    "uid": null
  },
  "__uuid": "a41db1f0-5a14-11ef-bb6b-61e8f09c54b4",
  "__hightlight": false,
  "__is_all_columns_data": true
}

NPD 生成的事件中并不包含标识持久性与临时性问题的字段,需要根据 reason 字段的值配置不同类型的监控器,例如持久性问题监控器和临时性问题监控器,分别匹配对应的 reason,另外,临时性事件频繁发生时可视为持久性事件。

可以通过云厂商官方文档或启用 NPD 后的 ConfigMap 了解能够检测的节点事件:

kubectl get configmap/ack-node-problem-detector-config -n kube-system -o yaml

监控视图

登录观测云控制台,点击「场景」 -「新建仪表板」,输入 “kubernetes”, 选择 “Node Problem Detector 监控视图”,点击 “确定” 即可添加视图:

图片

关键指标

任何持久性问题、频繁出现的非持久性问题均可作为关键指标,例如 Kubetlet 处于非健康状态、CNI 插件问题、Pod 频繁被 OOMKill 等,这些指标其实会作为日志的 tag 存在。

以下列表包含但不限于默认配置下 NPD 能够检测的事件:

原因 持久性 描述
DockerHung Docker 挂起或无响应
ReadonlyFilesystem 文件系统被挂载为只读模式,通常是一种保护机制,在某些情况下防止文件系统损坏
CorruptDockerOverlay2 Overlay2 存储驱动存在问题
ContainerdUnhealthy Containerd 处于非健康状态
KubeletUnhealthy Kubelet 处于非健康状态
DockerUnhealthy Docker 处于非健康状态
OOMKilling Kubernetes 因 OOM 结束 Pod
TaskHung 任务挂起
UnregisterNetDevice 网络接口异常
KernelOops 内核检测到的异常行为,例如:空指针、设备错误
Ext4Error Ext4 文件系统问题
Ext4Warning Ext4 文件系统问题
IOError 缓冲区问题
MemoryReadError 可被修复的内存错误,频繁发生意味着内存硬件可能出现问题
KubeletStart Kubelet 启动,频繁出现意味 Kubelet 频繁重启
DockerStart Docker 启动,频繁出现意味 Kubelet 频繁重启
ContainerdStart Containerd 启动,频繁出现意味 Kubelet 频繁重启
CorruptDockerImage Docker registry 使用的目录不为空
DockerContainerStartupFailure Docker 无法启动
ConntrackFull 网络连接跟踪数满,将影响 NAT、防火墙等网络功能
NTPIsDown NTP时间同步异常

监控器(告警)

持久性问题监控器

配置持久性问题监控器,关注任意节点的指定事件:

图片

图片

频繁出现的非持久性问题监控器

配置频繁出现的非持久性问题监控器,关注某一节点的指定事件出现的次数:

图片

事件模拟

可通过以下命令模拟问题,该操作向 APIServer 同时写入了临时和持久性事件:

sudo sh -c "echo 'kernel: INFO: task docker:20744 blocked for more than 120 seconds.' >> /dev/kmsg"

可看到告警产生:

图片

点击告警可快速查看事件趋势、自定义链接、事件历史、关联仪表盘等信息:

图片

启用观测云监控器时,需要根据所选 NPD 插件报告的事件类型和 reason 调整仪表盘、监控器。

总结

总的来说,NPD 是 Kubernetes 集群可观测性的重要组成部分,它通过检测和报告节点问题,帮助提高集群的稳定性和可靠性,同时结合观测云的平台,可以为用户提供一个全面、自动化的 Kubernetes 节点监控解决方案,帮助用户更好地管理和维护他们的集群。