在 Kubernetes 生产环境中,节点操作系统内核更新和安全补丁安装是维持集群安全性的常规操作。然而,裸机重启节点可能导致服务中断,甚至引发数据不一致问题。Kured(Kubernetes Reboot Daemon)作为 CNCF Sandbox 项目,通过哨兵文件检测与分布式锁机制,为运维团队提供了一种安全、可控的节点滚动重启解决方案。本文将深入剖析其核心工作原理,并给出生产环境的关键配置参数。
哨兵文件检测机制
Kured 的核心设计理念是依赖操作系统层面的信号来判断节点是否需要重启。默认情况下,它会监测节点上的哨兵文件 /var/run/reboot-required,该文件通常由系统包管理器(如 apt、yum)在需要内核更新或关键库升级后自动创建。Kured 以 DaemonSet 形式在每个节点上运行一个 Pod,通过定时轮询机制检测该文件的存在。
这种设计将重启触发逻辑下放至操作系统层面,Kured 本身不需要理解为何需要重启,只需要响应外部信号。运维人员可以通过配置 --sentinel-file 参数自定义哨兵文件路径,以适配不同的 Linux 发行版或容器运行时环境。更灵活的做法是使用 --sentinel-command 参数,指定一个返回值为零的命令脚本,这在使用不支持哨兵文件的操作系统或需要更复杂判断逻辑时尤为有用。例如,可以编写一个脚本同时检查内核版本和安全补丁状态,仅在满足特定条件时返回成功。
默认的检测周期为 60 秒,运维团队可以通过 --period 参数调整轮询频率。考虑到频繁的文件系统操作可能带来性能开销,建议在生产环境中将周期设置为 60 至 120 秒之间,在响应速度和资源消耗之间取得平衡。
基于 API Server 的分布式锁机制
多节点集群环境下,同时重启多个节点将导致服务不可用,因此需要一种协调机制确保节点逐一重启。Kured 利用 Kubernetes API Server 实现了一种轻量级的分布式锁,其核心思想是将锁信息存储在 DaemonSet 资源的注解(Annotation)中。
当某个节点的 Kured 检测到哨兵文件存在时,它会尝试在 kube-system 命名空间中的 Kured DaemonSet 上获取锁。锁的实现方式是更新 DaemonSet 的注解,将 kured.weave.works/locked 键的值设置为当前节点的名称,并记录锁的持有时间戳。其他节点上的 Kured 在尝试获取锁时会读取该注解,如果发现锁已被占用,则进入等待状态并定期重试。
这种基于注解的锁机制避免了引入额外的分布式锁服务(如 etcd 或 Redis),降低了系统复杂度。运维人员可以通过 --lock-annotation、--ds-name 和 --ds-namespace 参数自定义锁注解的名称和 DaemonSet 的标识,以适应多集群环境或与现有 RBAC 策略配合。
值得注意的是,锁的获取采用乐观策略:如果两个节点同时检测到哨兵文件并尝试加锁,后写入的节点将覆盖前一个节点的信息,导致前者释放锁并重新进入等待。这种设计简化了实现,但运维团队需要确保节点名称的唯一性,并在监控系统中关注锁竞争情况。
节点驱逐与安全重启流程
获取锁后,Kured 将执行完整的节点重启流程,确保工作负载安全迁移。首先,节点会被标记为不可调度(Cordon),防止新的 Pod 调度到该节点。随后,Kured 按照可配置的策略驱逐( Drain)节点上的 Pod。驱逐过程涉及向 API Server 发送驱逐请求,触发 Pod 的优雅终止(Graceful Termination)。
驱逐行为可以通过多个参数精细控制。--drain-delay 参数设置获取锁后开始驱逐的等待时间,默认值为 10 秒,给予剩余请求一定的处理缓冲时间。--drain-grace-period 参数指定每个 Pod 的优雅终止期限,Kured 会将该值传递给 Pod 的 terminationGracePeriodSeconds 字段。--drain-timeout 参数则限制整个驱逐操作的总超时时间,默认值为 10 分钟,超时后将强制继续后续流程。
驱逐完成后,Kured 会触发节点重启。在容器化环境中,节点重启通常通过 reboot 命令实现。重启完成后,节点会自动重新加入集群,Kured 会自动解除节点的不可调度状态(Uncordon),并释放锁供下一个节点使用。整个流程确保了工作负载的平滑迁移和服务的持续可用。
生产环境关键配置参数
基于上述机制,运维团队在生产环境中部署 Kured 时需要关注以下关键配置。首先是时间窗口控制:通过 --start-time 和 --end-time 参数可以限制重启操作发生在特定时间段内,例如设置为凌晨 2:00 至 5:00,避免在业务高峰期触发重启。其次是 Pod 过滤:使用 --blocked-pod-selector 参数可以指定不参与驱逐的 Pod 标签,关键的系统组件或有状态服务通常需要配置此项。
对于需要与监控系统集成的场景,Kured 支持在重启前后发送 Prometheus 告警。通过 --notify-url 参数可以配置 Webhook 回调,在锁获取、驱逐开始、重启完成等关键事件发生时通知运维系统。此外,可以设置 --prometheus-alert 参数,在节点重启期间暂停或延迟重启,以避免在系统存在告警时进行冒险操作。
在实际部署中,建议为 Kured 设置适当的资源限制。参考配置包括 CPU 请求 100m、内存请求 64MB,以及 CPU 限制 500m、内存限制 256MB。由于 Kured 主要执行轮询和 API 操作,资源消耗较低,但需要确保在节点压力下不会被驱逐。
监控与运维考量
成功运行 Kured 需要建立完善的监控体系。核心监控指标包括:锁等待时间(从检测到哨兵文件到获取锁的间隔)、驱逐耗时(Pod 优雅终止的总时长)、以及重启次数。建议在 Prometheus 中配置告警,当单个节点的重启流程超过 30 分钟时触发通知,以便运维人员介入排查。
对于大规模集群,需要评估 API Server 的压力。每个节点的 Kured 会持续轮询 DaemonSet 注解,在节点数量超过百台时,API Server 的读操作负载可能成为瓶颈。此时可以考虑启用 Kured 的 Leader Election 模式,通过 --enable-lease 参数激活 Lease 资源进行协调,减少对 DaemonSet 的直接修改。
哨兵文件的正确配置是 Kured 正常工作的前提。在 Ubuntu 系统中,dpkg 包管理器会在需要重启时创建 /var/run/reboot-required 文件;在 Red Hat 系系统中,可能需要安装 needs-restarting 工具并配置自定义哨兵命令。运维团队应定期验证哨兵机制的有效性,可以通过手动创建文件模拟重启需求,观察 Kured 的响应行为。
Kured 通过将操作系统重启信号与 Kubernetes 调度能力相结合,为容器化基础设施的自动化运维提供了可靠方案。理解其哨兵检测机制和分布式锁原理,有助于运维团队在保障服务可用性的前提下,实现安全补丁的及时部署。
资料来源:Kured 官方文档(https://kured.dev/docs/configuration/)、GitHub kubereboot/kured 仓库(https://github.com/kubereboot/kured)