深色模式
静态 Pod 与节点级管理
摘要:本文面向负责节点与控制面运维的 SRE,讲解静态 Pod 如何通过 kubelet 本地清单自管理、mirror Pod 的可见性,以及它与 API 驱动工作负载的边界。覆盖 Kubernetes v1.28+。
适用版本与前提
- Kubernetes:v1.28+(
staticPodPath/staticPodURL为 kubelet 配置字段) - 工具:
kubectl、crictl(节点本地)、SSH/节点访问权限 - 前提:理解 kubelet 角色与 Pod 基础
背景与问题
大多数 Pod 由 API server 接收、调度器调度、各节点 kubelet 执行。但有一类 Pod 完全由节点上的 kubelet 自己“看文件”创建,不经过 API server 的控制器——这就是静态 Pod。为什么需要它?因为控制面组件(kube-apiserver、kube-controller-manager、kube-scheduler)本身就要先于集群“存在”,它们不能依赖一个还不存在的调度器来调度自己。kubeadm 正是用静态 Pod 拉起控制面的。
定义方式
kubelet 通过配置文件(staticPodPath,默认如 /etc/kubernetes/manifests)周期性扫描目录,出现/消失 YAML/JSON 即创建/删除对应 Pod。也可用 staticPodURL 从 HTTP 拉取清单。
yaml
# /etc/kubernetes/manifests/static-web.yaml (在目标节点上)
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
kubelet 配置中指定路径(推荐,替代已废弃的 --pod-manifest-path 命令行参数):
yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
staticPodPath: /etc/kubernetes/manifests1
2
3
2
3
注意
kubelet 会处理该目录下所有不以点开头的文件,不看扩展名。若你 cp kube-apiserver.yaml kube-apiserver.yaml.backup 做备份,kubelet 会同时读两个文件并尝试各建一个 Pod,同名时行为未定义,可能让旧备份的过期 spec 悄悄生效。备份务必放到目录外(如 /etc/kubernetes/backup/)。
Mirror Pod 与可见性
静态 Pod 在 API server 上以 mirror Pod(名字形如 static-web-<节点名>)的形式可见,标签会同步过去,可被 kubectl get pods 看到、可被 Service 通过 selector 选中。但 mirror Pod 只读——对它执行 kubectl delete 只是删了镜像对象,kubelet 会立刻重建静态 Pod。
bash
kubectl get pods
# NAME READY STATUS RESTARTS AGE
# static-web-node1 1/1 Running 0 2m
kubectl delete pod static-web-node1
# pod "static-web-node1" deleted
kubectl get pods
# 仍然 Running —— 因为真正的 Pod 由 kubelet 本地清单管理1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
节点本地可用 crictl 直接看容器与日志:
bash
# 在节点上执行
crictl ps
crictl logs <container_id>1
2
3
2
3
生命周期与自愈
kubelet 启动即创建所配置的全部静态 Pod;动态增删文件即可增删 Pod(轮询扫描,秒级生效)。若容器被手动停止,kubelet 会按重启策略重新拉起——这是静态 Pod 的“自愈”能力。
与 API 驱动工作负载的边界
| 维度 | 静态 Pod | Deployment/DaemonSet 等 |
|---|---|---|
| 创建者 | 节点 kubelet 看本地文件 | API server + 控制器 |
| 调度 | 固定在清单所在节点 | 调度器决定 |
| 自愈 | kubelet 重建容器 | 控制器重建 Pod |
| 能否 kubectl 删除 | 否(删的是 mirror) | 是 |
| 滚动更新 | 改文件后 kubelet 重建 | 控制器滚动 |
| 适用 | 控制面组件、节点基础设施 | 业务与通用工作负载 |
生产危险
静态 Pod 不受 Deployment/DaemonSet 等控制器管理,也没有滚动更新、回滚、PDB 等保障。手动改清单文件会触发 kubelet 重建容器,过程中可能短暂中断(无优雅排水)。修改控制面静态 Pod 清单前务必备份并在维护窗口内进行。
生产实践
- 控制面组件用静态 Pod(kubeadm 默认),因为它们必须先于集群存在;自建集群也应如此。
- 备份放目录外:绝不在
staticPodPath目录内存.backup之类副本,避免被误读。 - 变更走配置管理:静态 Pod 清单应通过 Git/配置管理(如 Ansible)下发,保持节点间一致,避免“幽灵差异”。
- 节点级观测:静态 Pod 的自愈依赖 kubelet 健康;若 kubelet 本身挂了,静态 Pod 也不会重建,需监控 kubelet。
- 不要滥用:普通业务绝不用静态 Pod——你会失去滚动更新、回滚、HPA、PDB 等一切编排能力。
版本相关
通过命令行 --pod-manifest-path 指定路径的方式已被废弃,新集群应使用 kubelet 配置文件的 staticPodPath / staticPodURL。staticPodURL 用于从 HTTP 拉取清单,适合大规模统一下发但需保证该 URL 高可用。
故障排查
| 现象 | 原因 | 处理 |
|---|---|---|
| 静态 Pod 没起来 | 清单不在 staticPodPath 或不以合规名 | 检查路径与文件名(非点开头) |
| 显示旧 spec | 目录内有备份/重复文件 | 清理目录外备份,确认唯一文件 |
kubectl delete 后仍在 | 删的是 mirror Pod | 改本地清单或移走文件 |
| 改了镜像没生效 | kubelet 未扫描/未重启 | 确认路径配置与轮询;必要时重启 kubelet |
常见坑
- 在
staticPodPath目录里留备份文件导致双清单冲突。 - 以为
kubectl delete能删静态 Pod(只能删 mirror)。 - 静态 Pod 不受 PDB 保护,节点维护时仍会被 drain 影响(drain 对静态 Pod 的处理取决于版本与标志,需实测)。
替代方案与权衡
- 节点级常驻基础设施(日志/监控)优先用 DaemonSet,获得滚动更新与 PDB。
- 仅“必须先于集群存在的组件”(控制面)才用静态 Pod;其余场景用 API 驱动工作负载以获得完整编排能力。
FAQ
Q:静态 Pod 能被 Service 选中吗? A:可以。mirror Pod 的标签会同步,标签匹配的 Service 能把它纳入端点。
Q:改了清单文件,Pod 会自动更新吗? A:kubelet 轮询扫描到变化后会重建容器,但这是“重建”而非滚动更新,可能短暂中断。
参考资料
- Create static Pods - Kubernetes 官方文档,访问日期:2026-10-08。
- Static Pods 概念 - Kubernetes 官方文档,访问日期:2026-10-08。
- kubeadm 静态 Pod 清单实现细节 - Kubernetes 官方文档,访问日期:2026-10-08。