Kubelet 核心架构与启动流程超深度分析
基于 Kubernetes 源码解析,覆盖 cmd/kubelet、pkg/kubelet 核心代码路径
一、模块定位
1.1 Kubelet 业务职责
Kubelet 是 Kubernetes 集群中运行在每个 Node 上的核心代理(Node Agent),它是将"声明式 API 世界"映射到"容器运行时现实"的关键桥梁。其核心职责可归纳为:
| 职责域 | 具体内容 |
|---|---|
| Pod 生命周期管理 | 接收 PodSpec,驱动容器创建/启动/停止/删除,实现期望状态收敛 |
| 节点状态上报 | 周期性向 API Server 报告 Node Status(Capacity、Allocatable、Conditions、Addresses、Images) |
| 容器健康探测 | 执行 Liveness、Readiness、Startup 三种探针,根据结果决策重启/流量/状态 |
| 资源驱逐(Eviction) | 监控节点资源压力(Memory、Disk、PID),按策略驱逐低优先级 Pod |
| 卷管理(Volume) | 协调 Volume Attach/Mount/Unmount/Detach,确保 Pod 存储就绪 |
| 镜像垃圾回收 | 按磁盘使用率阈值回收未使用镜像,保障节点磁盘空间 |
| 容器垃圾回收 | 清理已终止容器,防止磁盘泄漏 |
| Cgroup 资源管理 | 按 QoS 等级创建/维护 Cgroup 层级,实施资源限制 |
| 静态 Pod 管理 | 监控本地文件/HTTP URL 上的 PodSpec,自动创建 Mirror Pod |
| 证书轮转 | 支持客户端/服务端证书自动轮转,保障集群安全通信 |
| 节点优雅关闭 | 监听系统关机信号,按策略优雅终止 Pod |
| 设备管理 | 通过 Device Plugin 框架管理 GPU/FPGA/RDMA 等扩展资源 |
| 动态配置 | 从 API Server 动态获取并应用 Kubelet 配置变更 |
1.2 在 Kubernetes 架构中的位置
┌─────────────────────────────────────────────────────────────┐
│ Control Plane │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
│ │ API Server│ │ Scheduler│ │Ctrl Mgr │ │ Cloud Ctrl │ │
│ └────┬──────┘ └──────────┘ └──────────┘ └────────────────┘ │
│ │ Watch/REST │
└───────┼──────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────┐
│ Node │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Kubelet │ │
│ │ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌──────────────┐ │ │
│ │ │PodConfig│ │SyncLoop │ │PLEG │ │StatusManager │ │ │
│ │ └─────────┘ └──────────┘ └─────────┘ └──────────────┘ │ │
│ │ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌──────────────┐ │ │
│ │ │VolumeMgr│ │Eviction │ │Prober │ │ContainerMgr │ │ │
│ │ └─────────┘ └──────────┘ └─────────┘ └──────────────┘ │ │
│ │ │ │ │
│ │ ▼ CRI │ │
│ │ ┌──────────────────────────────────────────────────────┐│ │
│ │ │ Container Runtime ││ │
│ │ │ (dockershim / containerd / CRI-O / ...) ││ │
│ │ └──────────────────────────────────────────────────────┘│ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌────────┐ ┌──────────┐ ┌──────────────────────┐ │
│ │ kubelet│ │ kube- │ │ Linux Kernel │ │
│ │ proxy │ │ proxy │ │ (cgroup/net/iptables)│ │
│ └────────┘ └──────────┘ └──────────────────────┘ │
└───────────────────────────────────────────────────────────────┘
Kubelet 处于控制面与数据面的交汇点------它既是控制面的"执行者"(接收调度结果、执行 Pod 创建/删除),也是数据面的"观察者"(采集节点状态、容器状态、资源指标)。
二、模块整体结构
2.1 Kubelet Struct 字段详解
Kubelet 结构体是整个 Kubelet 的核心实体,位于 pkg/kubelet/kubelet.go,拥有超过 80 个字段,按功能域分类如下:
go
type Kubelet struct {
// ====== 身份与基础配置 ======
kubeletConfiguration kubeletconfiginternal.KubeletConfiguration // 运行时配置(可动态更新)
hostname string // 检测到或被覆盖的主机名
hostnameOverridden bool // 主机名是否被覆盖
nodeName types.NodeName // 节点名(可能由云提供商确定)
rootDirectory string // 根目录(默认 /var/lib/kubelet)
nodeIPs []net.IP // 节点 IP(支持双栈)
providerID string // 外部数据库中的节点唯一标识
// ====== 客户端连接 ======
kubeClient clientset.Interface // 与 API Server 通信的主客户端
heartbeatClient clientset.Interface // 专用于心跳的客户端(独立限流)
onRepeatedHeartbeatFailure func() // 心跳持续失败回调(关闭所有连接)
// ====== Pod 管理 ======
podManager kubepod.Manager // Pod 真实来源的统一门面(API+Static+Mirror)
podWorkers PodWorkers // Per-Pod 异步同步工作器
workQueue queue.WorkQueue // 触发 Pod Worker 的工作队列
podCache kubecontainer.Cache // Pod 运行时状态缓存
podKiller PodKiller // 处理需要被杀死的 Pod
// ====== 状态管理 ======
statusManager status.Manager // Pod 状态与 API Server 同步
reasonCache *ReasonCache // 容器创建失败原因缓存
lastContainerStartedTime *timeCache // 每Pod最后一次容器启动时间
// ====== 容器运行时 ======
containerRuntime kubecontainer.Runtime // 容器运行时抽象接口
containerRuntimeName string // 运行时名称(docker/remote)
runtimeService internalapi.RuntimeService // CRI RuntimeService 客户端
runtimeCache kubecontainer.RuntimeCache // 运行时状态缓存
streamingRuntime kubecontainer.StreamingRuntime // 流式操作接口(exec/attach/port-forward)
runner kubecontainer.CommandRunner // 命令执行器
containerLogManager logs.ContainerLogManager // 容器日志管理器
dockerLegacyService legacy.DockerLegacyService // Docker 遗留服务
// ====== 运行时状态 ======
runtimeState *runtimeState // 运行时健康状态(网络/存储/运行时错误)
oneTimeInitializer sync.Once // 运行时依赖模块的一次性初始化
// ====== 探针 ======
probeManager prober.Manager // 探针管理器(Liveness/Readiness/Startup)
livenessManager proberesults.Manager // Liveness 探针结果
readinessManager proberesults.Manager // Readiness 探针结果
startupManager proberesults.Manager // Startup 探针结果
// ====== 垃圾回收 ======
containerGC kubecontainer.GC // 容器 GC
imageManager images.ImageGCManager // 镜像 GC
containerDeletor *podContainerDeletor // Pod 内容器删除器
// ====== 资源管理 ======
containerManager cm.ContainerManager // Cgroup/设备/拓扑管理器
cgroupsPerQOS bool // 是否启用 QoS Cgroup 层级
cgroupRoot string // Cgroup 根路径
evictionManager eviction.Manager // 驱逐管理器
// ====== 卷与存储 ======
volumePluginMgr *volume.VolumePluginMgr // 卷插件管理器
volumeManager volumemanager.VolumeManager // 卷 Attach/Mount 协调器
mounter mount.Interface // 文件系统挂载接口
hostutil hostutil.HostUtils // 宿主文件系统工具
subpather subpath.Interface // 子路径处理
// ====== 网络 ======
dnsConfigurer *dns.Configurer // DNS 解析配置器
makeIPTablesUtilChains bool // 是否创建 iptables 工具链
iptablesMasqueradeBit int // SNAT 标记位
iptablesDropBit int // DROP 标记位
// ====== 云提供商 ======
cloud cloudprovider.Interface // 云提供商接口
cloudResourceSyncManager cloudresource.SyncManager // 云资源同步管理器
externalCloudProvider bool // 是否使用外部云控制器
// ====== 节点注册与状态 ======
registerNode bool // 是否自动注册节点
registerWithTaints []api.Taint // 注册时添加的 Taint
registrationCompleted bool // 注册是否完成
nodeStatusUpdateFrequency time.Duration // 节点状态更新频率
nodeStatusReportFrequency time.Duration // 节点状态上报频率(启用 Lease 时)
lastStatusReportTime time.Time // 最后上报时间
nodeLeaseController lease.Controller // 节点 Lease 控制器
nodeRef *v1.ObjectReference // 节点对象引用(用于事件)
nodeLabels map[string]string // 注册时的节点标签
nodeLister corelisters.NodeLister // 节点列表器
nodeHasSynced cache.InformerSynced // 节点 Informer 同步状态
daemonEndpoints *v1.NodeDaemonEndpoints // Daemon 端口信息
nodeStatusMaxImages int32 // 节点状态中最大镜像数
// ====== 服务发现 ======
serviceLister serviceLister // Service 列表器
serviceHasSynced cache.InformerSynced // Service 同步状态
masterServiceNamespace string // Master Service 命名空间
// ====== 配置与密钥 ======
secretManager secret.Manager // Secret 管理器
configMapManager configmap.Manager // ConfigMap 管理器
// ====== 准入与生命周期钩子 ======
admitHandlers lifecycle.PodAdmitHandlers // Pod 准入处理器链
softAdmitHandlers lifecycle.PodAdmitHandlers // 软准入处理器链(准入后、运行前)
PodSyncLoopHandlers lifecycle.PodSyncLoopHandlers // SyncLoop 同步钩子
PodSyncHandlers lifecycle.PodSyncHandlers // Sync 同步钩子
// ====== 其他关键模块 ======
cadvisor cadvisor.Interface // cAdvisor 接口
StatsProvider *stats.Provider // 统计数据提供者
resourceAnalyzer serverstats.ResourceAnalyzer // 资源分析器
oomWatcher oomwatcher.Watcher // OOM 事件监听器
pluginManager pluginmanager.PluginManager // 插件管理器(CSI/DevicePlugin)
runtimeClassManager *runtimeclass.Manager // RuntimeClass 管理器
serverCertificateManager certificate.Manager // 服务端证书管理器
appArmorValidator apparmor.Validator // AppArmor 验证器
shutdownManager *nodeshutdown.Manager // 节点关闭管理器
// ====== 同步控制 ======
sourcesReady config.SourcesReady // 配置源就绪状态
resyncInterval time.Duration // 周期性全量同步间隔
syncLoopMonitor atomic.Value // 同步循环监控时间戳
backOff *flowcontrol.Backoff // 容器重启退避
maxPods int // 最大 Pod 数
podsPerCore int // 每核心 Pod 数
// ====== 杂项 ======
os kubecontainer.OSInterface // 系统调用抽象
clock clock.Clock // 时钟(可测试)
logServer http.Handler // 日志 HTTP Handler
recorder record.EventRecorder // 事件记录器
streamingConnectionIdleTimeout time.Duration // 流式连接空闲超时
experimentalHostUserNamespaceDefaulting bool // 实验性 Host 用户命名空间
keepTerminatedPodVolumes bool // 保持已终止 Pod 卷挂载(调试用)
}
2.2 核心接口定义
SyncHandler 接口
SyncHandler 是 Kubelet 实现的核心接口,定义了 SyncLoop 回调方法:
go
type SyncHandler interface {
HandlePodAdditions(pods []*v1.Pod) // Pod 新增
HandlePodUpdates(pods []*v1.Pod) // Pod 更新
HandlePodRemoves(pods []*v1.Pod) // Pod 移除
HandlePodReconcile(pods []*v1.Pod) // Pod 状态调和
HandlePodSyncs(pods []*v1.Pod) // Pod 同步触发
HandlePodCleanups() error // Pod 清理
}
Kubelet 自身实现了该接口,在 syncLoopIteration 中通过 select 多路复用分发事件。
Bootstrap 接口
Bootstrap 接口定义了 Kubelet 的引导协议:
go
type Bootstrap interface {
GetConfiguration() kubeletconfiginternal.KubeletConfiguration
BirthCry()
StartGarbageCollection()
ListenAndServe(kubeCfg, tlsOptions, auth)
ListenAndServeReadOnly(address, port)
ListenAndServePodResources()
Run(updates <-chan kubetypes.PodUpdate)
RunOnce(updates <-chan kubetypes.PodUpdate) ([]RunPodResult, error)
}
PodWorkers 接口
go
type PodWorkers interface {
UpdatePod(options *UpdatePodOptions) // 更新 Pod
ForgetNonExistingPodWorkers(desiredPods map[types.UID]sets.Empty) // 清理不存在的 Pod Worker
ForgetWorker(uid types.UID) // 遗忘特定 Pod Worker
}
2.3 依赖注入 Dependencies
Dependencies 是 Kubelet 的运行时依赖注入容器,由 UnsecuredDependencies 或调用方构建:
go
type Dependencies struct {
Options []Option // 函数式选项
Auth server.AuthInterface // 认证/授权接口
CAdvisorInterface cadvisor.Interface // cAdvisor 接口
Cloud cloudprovider.Interface // 云提供商
ContainerManager cm.ContainerManager // 容器管理器
DockerOptions *DockerOptions // Docker 特定配置
EventClient v1core.EventsGetter // 事件客户端
HeartbeatClient clientset.Interface // 心跳客户端
OnHeartbeatFailure func() // 心跳失败回调
KubeClient clientset.Interface // API Server 客户端
Mounter mount.Interface // 挂载器
HostUtil hostutil.HostUtils // 宿主工具
OOMAdjuster *oom.OOMAdjuster // OOM 调整器
OSInterface kubecontainer.OSInterface // OS 抽象
PodConfig *config.PodConfig // Pod 配置多路复用器
Recorder record.EventRecorder // 事件记录器
Subpather subpath.Interface // 子路径
VolumePlugins []volume.VolumePlugin // 卷插件列表
DynamicPluginProber volume.DynamicPluginProber // 动态插件探测器
TLSOptions *server.TLSOptions // TLS 配置
KubeletConfigController *kubeletconfig.Controller // 动态配置控制器
RemoteRuntimeService internalapi.RuntimeService // CRI Runtime 服务
RemoteImageService internalapi.ImageManagerService // CRI Image 服务
dockerLegacyService legacy.DockerLegacyService // Docker 遗留服务
useLegacyCadvisorStats bool // 是否使用遗留 cAdvisor 统计
}
2.4 核心方法清单
| 方法 | 所属 | 功能 |
|---|---|---|
NewKubeletCommand() |
app | 创建 Cobra 命令入口 |
Run() |
app | 启动 Kubelet 的顶层函数 |
run() |
app | Run 的实际实现 |
RunKubelet() |
app | 创建并启动 Kubelet 实例 |
createAndInitKubelet() |
app | 调用 NewMainKubelet 并初始化 |
startKubelet() |
app | 启动 Kubelet 的 goroutine |
NewMainKubelet() |
kubelet | 构造 Kubelet 对象及其所有子模块 |
Run() |
Kubelet | Kubelet 主运行循环 |
initializeModules() |
Kubelet | 初始化不依赖运行时的模块 |
initializeRuntimeDependentModules() |
Kubelet | 初始化依赖运行时的模块 |
syncLoop() |
Kubelet | 主同步循环(永不返回) |
syncLoopIteration() |
Kubelet | 单次同步迭代 |
syncPod() |
Kubelet | 单 Pod 同步事务脚本 |
HandlePodAdditions() |
Kubelet | 处理 Pod 新增 |
HandlePodUpdates() |
Kubelet | 处理 Pod 更新 |
HandlePodRemoves() |
Kubelet | 处理 Pod 移除 |
HandlePodReconcile() |
Kubelet | 处理 Pod 调和 |
HandlePodSyncs() |
Kubelet | 处理 Pod 同步 |
HandlePodCleanups() |
Kubelet | 处理 Pod 清理 |
canAdmitPod() |
Kubelet | Pod 准入检查 |
canRunPod() |
Kubelet | Pod 运行性检查 |
dispatchWork() |
Kubelet | 分发 Pod 到 Worker |
deletePod() |
Kubelet | 删除 Pod |
updateRuntimeUp() |
Kubelet | 更新运行时状态 |
syncNodeStatus() |
Kubelet | 同步节点状态到 API Server |
2.5 调用关系总图
#mermaid-svg-2VvvArcuwNTVviYy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2VvvArcuwNTVviYy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2VvvArcuwNTVviYy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2VvvArcuwNTVviYy .error-icon{fill:#552222;}#mermaid-svg-2VvvArcuwNTVviYy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2VvvArcuwNTVviYy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2VvvArcuwNTVviYy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2VvvArcuwNTVviYy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2VvvArcuwNTVviYy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2VvvArcuwNTVviYy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2VvvArcuwNTVviYy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2VvvArcuwNTVviYy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2VvvArcuwNTVviYy .marker.cross{stroke:#333333;}#mermaid-svg-2VvvArcuwNTVviYy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2VvvArcuwNTVviYy p{margin:0;}#mermaid-svg-2VvvArcuwNTVviYy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2VvvArcuwNTVviYy .cluster-label text{fill:#333;}#mermaid-svg-2VvvArcuwNTVviYy .cluster-label span{color:#333;}#mermaid-svg-2VvvArcuwNTVviYy .cluster-label span p{background-color:transparent;}#mermaid-svg-2VvvArcuwNTVviYy .label text,#mermaid-svg-2VvvArcuwNTVviYy span{fill:#333;color:#333;}#mermaid-svg-2VvvArcuwNTVviYy .node rect,#mermaid-svg-2VvvArcuwNTVviYy .node circle,#mermaid-svg-2VvvArcuwNTVviYy .node ellipse,#mermaid-svg-2VvvArcuwNTVviYy .node polygon,#mermaid-svg-2VvvArcuwNTVviYy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2VvvArcuwNTVviYy .rough-node .label text,#mermaid-svg-2VvvArcuwNTVviYy .node .label text,#mermaid-svg-2VvvArcuwNTVviYy .image-shape .label,#mermaid-svg-2VvvArcuwNTVviYy .icon-shape .label{text-anchor:middle;}#mermaid-svg-2VvvArcuwNTVviYy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2VvvArcuwNTVviYy .rough-node .label,#mermaid-svg-2VvvArcuwNTVviYy .node .label,#mermaid-svg-2VvvArcuwNTVviYy .image-shape .label,#mermaid-svg-2VvvArcuwNTVviYy .icon-shape .label{text-align:center;}#mermaid-svg-2VvvArcuwNTVviYy .node.clickable{cursor:pointer;}#mermaid-svg-2VvvArcuwNTVviYy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2VvvArcuwNTVviYy .arrowheadPath{fill:#333333;}#mermaid-svg-2VvvArcuwNTVviYy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2VvvArcuwNTVviYy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2VvvArcuwNTVviYy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2VvvArcuwNTVviYy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2VvvArcuwNTVviYy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2VvvArcuwNTVviYy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2VvvArcuwNTVviYy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2VvvArcuwNTVviYy .cluster text{fill:#333;}#mermaid-svg-2VvvArcuwNTVviYy .cluster span{color:#333;}#mermaid-svg-2VvvArcuwNTVviYy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2VvvArcuwNTVviYy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2VvvArcuwNTVviYy rect.text{fill:none;stroke-width:0;}#mermaid-svg-2VvvArcuwNTVviYy .icon-shape,#mermaid-svg-2VvvArcuwNTVviYy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2VvvArcuwNTVviYy .icon-shape p,#mermaid-svg-2VvvArcuwNTVviYy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2VvvArcuwNTVviYy .icon-shape .label rect,#mermaid-svg-2VvvArcuwNTVviYy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2VvvArcuwNTVviYy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2VvvArcuwNTVviYy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2VvvArcuwNTVviYy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} pkg/kubelet
cmd/kubelet
main()
NewKubeletCommand()
Run() (cobra)
app.Run()
app.run()
RunKubelet()
createAndInitKubelet()
startKubelet()
NewMainKubelet()
k.BirthCry()
k.StartGarbageCollection()
k.Run()
k.initializeModules()
k.initializeRuntimeDependentModules()
k.syncLoop()
k.syncLoopIteration()
k.syncPod()
k.HandlePodAdditions()
k.HandlePodUpdates()
k.HandlePodRemoves()
k.HandlePodReconcile()
k.HandlePodSyncs()
k.HandlePodCleanups()
2.6 数据流
#mermaid-svg-wX72ZgC8yxfhSaGf{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-wX72ZgC8yxfhSaGf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-wX72ZgC8yxfhSaGf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-wX72ZgC8yxfhSaGf .error-icon{fill:#552222;}#mermaid-svg-wX72ZgC8yxfhSaGf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-wX72ZgC8yxfhSaGf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-wX72ZgC8yxfhSaGf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-wX72ZgC8yxfhSaGf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-wX72ZgC8yxfhSaGf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-wX72ZgC8yxfhSaGf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-wX72ZgC8yxfhSaGf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-wX72ZgC8yxfhSaGf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-wX72ZgC8yxfhSaGf .marker.cross{stroke:#333333;}#mermaid-svg-wX72ZgC8yxfhSaGf svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-wX72ZgC8yxfhSaGf p{margin:0;}#mermaid-svg-wX72ZgC8yxfhSaGf .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-wX72ZgC8yxfhSaGf .cluster-label text{fill:#333;}#mermaid-svg-wX72ZgC8yxfhSaGf .cluster-label span{color:#333;}#mermaid-svg-wX72ZgC8yxfhSaGf .cluster-label span p{background-color:transparent;}#mermaid-svg-wX72ZgC8yxfhSaGf .label text,#mermaid-svg-wX72ZgC8yxfhSaGf span{fill:#333;color:#333;}#mermaid-svg-wX72ZgC8yxfhSaGf .node rect,#mermaid-svg-wX72ZgC8yxfhSaGf .node circle,#mermaid-svg-wX72ZgC8yxfhSaGf .node ellipse,#mermaid-svg-wX72ZgC8yxfhSaGf .node polygon,#mermaid-svg-wX72ZgC8yxfhSaGf .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-wX72ZgC8yxfhSaGf .rough-node .label text,#mermaid-svg-wX72ZgC8yxfhSaGf .node .label text,#mermaid-svg-wX72ZgC8yxfhSaGf .image-shape .label,#mermaid-svg-wX72ZgC8yxfhSaGf .icon-shape .label{text-anchor:middle;}#mermaid-svg-wX72ZgC8yxfhSaGf .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-wX72ZgC8yxfhSaGf .rough-node .label,#mermaid-svg-wX72ZgC8yxfhSaGf .node .label,#mermaid-svg-wX72ZgC8yxfhSaGf .image-shape .label,#mermaid-svg-wX72ZgC8yxfhSaGf .icon-shape .label{text-align:center;}#mermaid-svg-wX72ZgC8yxfhSaGf .node.clickable{cursor:pointer;}#mermaid-svg-wX72ZgC8yxfhSaGf .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-wX72ZgC8yxfhSaGf .arrowheadPath{fill:#333333;}#mermaid-svg-wX72ZgC8yxfhSaGf .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-wX72ZgC8yxfhSaGf .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-wX72ZgC8yxfhSaGf .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wX72ZgC8yxfhSaGf .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-wX72ZgC8yxfhSaGf .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wX72ZgC8yxfhSaGf .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-wX72ZgC8yxfhSaGf .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-wX72ZgC8yxfhSaGf .cluster text{fill:#333;}#mermaid-svg-wX72ZgC8yxfhSaGf .cluster span{color:#333;}#mermaid-svg-wX72ZgC8yxfhSaGf div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-wX72ZgC8yxfhSaGf .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-wX72ZgC8yxfhSaGf rect.text{fill:none;stroke-width:0;}#mermaid-svg-wX72ZgC8yxfhSaGf .icon-shape,#mermaid-svg-wX72ZgC8yxfhSaGf .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-wX72ZgC8yxfhSaGf .icon-shape p,#mermaid-svg-wX72ZgC8yxfhSaGf .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-wX72ZgC8yxfhSaGf .icon-shape .label rect,#mermaid-svg-wX72ZgC8yxfhSaGf .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-wX72ZgC8yxfhSaGf .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-wX72ZgC8yxfhSaGf .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-wX72ZgC8yxfhSaGf :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Container Runtime
PodWorkers
SyncLoop
PodConfig
配置源
File Source
(Static Pod)
HTTP Source
(URL Manifest)
APIServer Source
(Watch/List)
config.Mux
podStorage
updates chan
syncLoopIteration
SyncHandler
Pod Worker 1
Pod Worker 2
Pod Worker N
CRI RuntimeService
CRI ImageService
三、核心业务逻辑深度解析
3.1 启动完整流程:main() → Run → NewMainKubelet → Run
3.1.1 入口:main()
go
// cmd/kubelet/kubelet.go
func main() {
rand.Seed(time.Now().UnixNano()) // 初始化随机种子
command := app.NewKubeletCommand() // 创建 Cobra 命令
logs.InitLogs() // 初始化日志
defer logs.FlushLogs() // 确保日志刷盘
if err := command.Execute(); err != nil {
os.Exit(1)
}
}
3.1.2 NewKubeletCommand()
go
func NewKubeletCommand() *cobra.Command {
kubeletFlags := options.NewKubeletFlags() // 初始化 Flag 对象
kubeletConfig, err := options.NewKubeletConfiguration() // 初始化配置对象
cmd := &cobra.Command{
Use: "kubelet",
DisableFlagParsing: true, // 禁用 Cobra 解析,手动处理以实现 Flag 优先级
Run: func(cmd *cobra.Command, args []string) {
// 1. 手动解析 Flag
cleanFlagSet.Parse(args)
// 2. 设置 Feature Gates
utilfeature.DefaultMutableFeatureGate.SetFromMap(kubeletConfig.FeatureGates)
// 3. 验证 KubeletFlags
options.ValidateKubeletFlags(kubeletFlags)
// 4. 加载配置文件(如果指定了 --config)
if configFile := kubeletFlags.KubeletConfigFile; len(configFile) > 0 {
kubeletConfig = loadConfigFile(configFile)
// 4.1 重新应用 Flag 优先级
kubeletConfigFlagPrecedence(kubeletConfig, args)
// 4.2 更新 Feature Gates
utilfeature.DefaultMutableFeatureGate.SetFromMap(kubeletConfig.FeatureGates)
}
// 5. 验证 KubeletConfiguration
kubeletconfigvalidation.ValidateKubeletConfiguration(kubeletConfig)
// 6. 动态配置初始化(如果启用)
if dynamicConfigDir := kubeletFlags.DynamicConfigDir.Value(); len(dynamicConfigDir) > 0 {
dynamicKubeletConfig, kubeletConfigController = BootstrapKubeletConfigController(...)
if dynamicKubeletConfig != nil {
kubeletConfig = dynamicKubeletConfig
}
}
// 7. 构建 KubeletServer
kubeletServer := &options.KubeletServer{
KubeletFlags: *kubeletFlags,
KubeletConfiguration: *kubeletConfig,
}
// 8. 构建默认 Dependencies
kubeletDeps = UnsecuredDependencies(kubeletServer, utilfeature.DefaultFeatureGate)
// 9. 设置信号上下文
ctx := genericapiserver.SetupSignalContext()
// 10. 执行 Run
Run(ctx, kubeletServer, kubeletDeps, utilfeature.DefaultFeatureGate)
},
}
// 注册 Flag
kubeletFlags.AddFlags(cleanFlagSet)
options.AddKubeletConfigFlags(cleanFlagSet, kubeletConfig)
return cmd
}
关键设计点------Flag 优先级 :Kubelet 禁用了 Cobra 的自动 Flag 解析,改为手动处理。这是因为需要实现严格的优先级规则:命令行 Flag > 配置文件 > 默认值 。kubeletConfigFlagPrecedence 函数通过重新解析 Flag 覆盖配置文件中的值,确保向后兼容。
3.1.3 Run() → run()
go
func Run(ctx context.Context, s *options.KubeletServer, kubeDeps *kubelet.Dependencies, ...) error {
// 初始化日志格式
logOption.Apply()
klog.InfoS("Kubelet version", "kubeletVersion", version.Get())
// OS 特定初始化
initForOS(s.KubeletFlags.WindowsService, s.KubeletFlags.WindowsPriorityClass)
// 委托给 run()
run(ctx, s, kubeDeps, featureGate)
}
run() 是真正的启动逻辑,执行顺序如下:
1. 设置 Feature Gates
2. 验证 KubeletServer
3. 获取文件锁(flock.Acquire)
4. 注册 /configz 端点
5. 判断 standalone 模式
6. 初始化 Dependencies(如果为 nil)
7. 初始化云提供商
8. 获取 hostname → nodeName
9. 构建 KubeClient / EventClient / HeartbeatClient
10. 构建 Auth 认证器
11. 计算 cgroupRoots
12. 初始化 cAdvisor
13. 设置 EventRecorder
14. 初始化 ContainerManager
15. 应用 OOM Score 调整
16. PreInitRuntimeService(初始化 CRI 运行时)
17. RunKubelet
18. 启动动态配置同步(如果启用)
19. 启动 Healthz Server
20. 通知 systemd READY=1
21. 阻塞等待信号
3.1.4 启动完整流程图
#mermaid-svg-H0E1VfiZHkxPJVbT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-H0E1VfiZHkxPJVbT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-H0E1VfiZHkxPJVbT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-H0E1VfiZHkxPJVbT .error-icon{fill:#552222;}#mermaid-svg-H0E1VfiZHkxPJVbT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-H0E1VfiZHkxPJVbT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-H0E1VfiZHkxPJVbT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-H0E1VfiZHkxPJVbT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-H0E1VfiZHkxPJVbT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-H0E1VfiZHkxPJVbT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-H0E1VfiZHkxPJVbT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-H0E1VfiZHkxPJVbT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-H0E1VfiZHkxPJVbT .marker.cross{stroke:#333333;}#mermaid-svg-H0E1VfiZHkxPJVbT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-H0E1VfiZHkxPJVbT p{margin:0;}#mermaid-svg-H0E1VfiZHkxPJVbT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-H0E1VfiZHkxPJVbT .cluster-label text{fill:#333;}#mermaid-svg-H0E1VfiZHkxPJVbT .cluster-label span{color:#333;}#mermaid-svg-H0E1VfiZHkxPJVbT .cluster-label span p{background-color:transparent;}#mermaid-svg-H0E1VfiZHkxPJVbT .label text,#mermaid-svg-H0E1VfiZHkxPJVbT span{fill:#333;color:#333;}#mermaid-svg-H0E1VfiZHkxPJVbT .node rect,#mermaid-svg-H0E1VfiZHkxPJVbT .node circle,#mermaid-svg-H0E1VfiZHkxPJVbT .node ellipse,#mermaid-svg-H0E1VfiZHkxPJVbT .node polygon,#mermaid-svg-H0E1VfiZHkxPJVbT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-H0E1VfiZHkxPJVbT .rough-node .label text,#mermaid-svg-H0E1VfiZHkxPJVbT .node .label text,#mermaid-svg-H0E1VfiZHkxPJVbT .image-shape .label,#mermaid-svg-H0E1VfiZHkxPJVbT .icon-shape .label{text-anchor:middle;}#mermaid-svg-H0E1VfiZHkxPJVbT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-H0E1VfiZHkxPJVbT .rough-node .label,#mermaid-svg-H0E1VfiZHkxPJVbT .node .label,#mermaid-svg-H0E1VfiZHkxPJVbT .image-shape .label,#mermaid-svg-H0E1VfiZHkxPJVbT .icon-shape .label{text-align:center;}#mermaid-svg-H0E1VfiZHkxPJVbT .node.clickable{cursor:pointer;}#mermaid-svg-H0E1VfiZHkxPJVbT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-H0E1VfiZHkxPJVbT .arrowheadPath{fill:#333333;}#mermaid-svg-H0E1VfiZHkxPJVbT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-H0E1VfiZHkxPJVbT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-H0E1VfiZHkxPJVbT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H0E1VfiZHkxPJVbT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-H0E1VfiZHkxPJVbT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H0E1VfiZHkxPJVbT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-H0E1VfiZHkxPJVbT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-H0E1VfiZHkxPJVbT .cluster text{fill:#333;}#mermaid-svg-H0E1VfiZHkxPJVbT .cluster span{color:#333;}#mermaid-svg-H0E1VfiZHkxPJVbT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-H0E1VfiZHkxPJVbT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-H0E1VfiZHkxPJVbT rect.text{fill:none;stroke-width:0;}#mermaid-svg-H0E1VfiZHkxPJVbT .icon-shape,#mermaid-svg-H0E1VfiZHkxPJVbT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-H0E1VfiZHkxPJVbT .icon-shape p,#mermaid-svg-H0E1VfiZHkxPJVbT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-H0E1VfiZHkxPJVbT .icon-shape .label rect,#mermaid-svg-H0E1VfiZHkxPJVbT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-H0E1VfiZHkxPJVbT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-H0E1VfiZHkxPJVbT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-H0E1VfiZHkxPJVbT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
是
否
否
是
startKubelet()
rand.Seed()
NewKubeletCommand()
command.Execute()
解析命令行 Flags
设置 Feature Gates
验证 KubeletFlags
是否指定 --config?
loadConfigFile()
跳过
kubeletConfigFlagPrecedence()
Flag 覆盖配置文件
更新 Feature Gates
ValidateKubeletConfiguration()
DynamicConfigDir
是否指定?
BootstrapKubeletConfigController()
跳过
构建 KubeletServer
UnsecuredDependencies()
SetupSignalContext()
Run()
初始化日志
initForOS()
run()
设置 Feature Gates
ValidateKubeletServer()
Acquire File Lock
initConfigz()
standalone模式?
buildKubeletClientConfig()
→ KubeClient
→ EventClient
→ HeartbeatClient
所有 Client = nil
BuildAuth()
cAdvisor.New()
makeEventRecorder()
cm.NewContainerManager()
OOMAdjuster.ApplyOOMScoreAdj()
PreInitRuntimeService()
RunKubelet()
createAndInitKubelet()
go k.Run()
阻塞等待信号
NewMainKubelet()
k.BirthCry()
k.StartGarbageCollection()
3.2 NewMainKubelet() ------ 子模块构建全解析
NewMainKubelet 是 Kubelet 最复杂的构造函数,创建 30+ 个子模块。以下是关键步骤:
go
func NewMainKubelet(kubeCfg, kubeDeps, crOptions, containerRuntime, hostname, ...) (*Kubelet, error) {
// ===== 1. 参数校验 =====
if rootDirectory == "" { return nil, fmt.Errorf(...) }
if kubeCfg.SyncFrequency.Duration <= 0 { return nil, fmt.Errorf(...) }
// iptables bit 范围检查
// ===== 2. 创建 Informer =====
if kubeDeps.KubeClient != nil {
kubeInformers := informers.NewSharedInformerFactoryWithOptions(kubeDeps.KubeClient, 0, ...)
nodeLister = kubeInformers.Core().V1().Nodes().Lister()
nodeHasSynced = kubeInformers.Core().V1().Nodes().Informer().HasSynced
kubeInformers.Start(wait.NeverStop)
} else {
// standalone 模式:使用空 Indexer
nodeIndexer := cache.NewIndexer(...)
nodeHasSynced = func() bool { return true }
}
// ===== 3. 创建 PodConfig =====
if kubeDeps.PodConfig == nil {
kubeDeps.PodConfig = makePodSourceConfig(kubeCfg, kubeDeps, nodeName, nodeHasSynced)
}
// ===== 4. 解析驱逐配置 =====
thresholds := eviction.ParseThresholdConfig(...)
evictionConfig := eviction.Config{...}
// ===== 5. 创建 Service Informer =====
if kubeDeps.KubeClient != nil {
kubeInformers := informers.NewSharedInformerFactory(kubeDeps.KubeClient, 0)
serviceLister = kubeInformers.Core().V1().Services().Lister()
}
// ===== 6. 构造 Kubelet 对象 =====
klet := &Kubelet{
hostname: hostname,
nodeName: nodeName,
kubeClient: kubeDeps.KubeClient,
podManager: nil, // 后面设置
statusManager: nil, // 后面设置
// ... 40+ 字段初始化
}
// ===== 7. Secret/ConfigMap Manager =====
switch kubeCfg.ConfigMapAndSecretChangeDetectionStrategy {
case WatchChangeDetectionStrategy:
secretManager = secret.NewWatchingSecretManager(...)
configMapManager = configmap.NewWatchingConfigMapManager(...)
case TTLCacheChangeDetectionStrategy:
secretManager = secret.NewCachingSecretManager(...)
configMapManager = configmap.NewCachingConfigMapManager(...)
case GetChangeDetectionStrategy:
secretManager = secret.NewSimpleSecretManager(...)
configMapManager = configmap.NewSimpleConfigMapManager(...)
}
// ===== 8. MachineInfo =====
machineInfo := klet.cadvisor.MachineInfo()
// ===== 9. 探针管理器 =====
klet.livenessManager = proberesults.NewManager()
klet.readinessManager = proberesults.NewManager()
klet.startupManager = proberesults.NewManager()
// ===== 10. PodManager =====
mirrorPodClient := kubepod.NewBasicMirrorClient(klet.kubeClient, string(nodeName), nodeLister)
klet.podManager = kubepod.NewBasicPodManager(mirrorPodClient, secretManager, configMapManager)
// ===== 11. StatusManager =====
klet.statusManager = status.NewManager(klet.kubeClient, klet.podManager, klet)
// ===== 12. 容器运行时 =====
runtime := kuberuntime.NewKubeGenericRuntimeManager(
kubecontainer.FilterEventRecorder(kubeDeps.Recorder),
klet.livenessManager, klet.readinessManager, klet.startupManager,
seccompProfileRoot, machineInfo, klet, kubeDeps.OSInterface,
klet, httpClient, imageBackOff,
kubeCfg.SerializeImagePulls, kubeCfg.RegistryPullQPS, kubeCfg.RegistryBurst,
imageCredentialProviderConfigFile, imageCredentialProviderBinDir,
kubeCfg.CPUCFSQuota, kubeCfg.CPUCFSQuotaPeriod,
kubeDeps.RemoteRuntimeService, kubeDeps.RemoteImageService,
kubeDeps.ContainerManager.InternalContainerLifecycle(),
kubeDeps.dockerLegacyService, klet.containerLogManager, klet.runtimeClassManager,
)
klet.containerRuntime = runtime
// ===== 13. PLEG =====
klet.pleg = pleg.NewGenericPLEG(klet.containerRuntime, plegChannelCapacity, plegRelistPeriod, klet.podCache, clock.RealClock{})
// ===== 14. 运行时状态 =====
klet.runtimeState = newRuntimeState(maxWaitForContainerRuntime)
klet.runtimeState.addHealthCheck("PLEG", klet.pleg.Healthy)
// ===== 15. 容器 GC / 镜像 GC =====
containerGC := kubecontainer.NewContainerGC(...)
imageManager := images.NewImageGCManager(...)
// ===== 16. 探针管理器 =====
klet.probeManager = prober.NewManager(
klet.statusManager, klet.livenessManager, klet.readinessManager, klet.startupManager,
klet.runner, kubeDeps.Recorder)
// ===== 17. 卷插件 & 卷管理器 =====
klet.volumePluginMgr = NewInitializedVolumePluginMgr(klet, secretManager, configMapManager, ...)
klet.volumeManager = volumemanager.NewVolumeManager(...)
// ===== 18. Pod Workers =====
klet.workQueue = queue.NewBasicWorkQueue(klet.clock)
klet.podWorkers = newPodWorkers(klet.syncPod, kubeDeps.Recorder, klet.workQueue, klet.resyncInterval, backOffPeriod, klet.podCache)
// ===== 19. 驱逐管理器 =====
evictionManager, evictionAdmitHandler := eviction.NewManager(...)
klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
// ===== 20. 准入处理器链 =====
klet.admitHandlers.AddPodAdmitHandler(sysctlsWhitelist)
klet.AddPodSyncLoopHandler(activeDeadlineHandler)
klet.AddPodSyncHandler(activeDeadlineHandler)
klet.admitHandlers.AddPodAdmitHandler(klet.containerManager.GetAllocateResourcesPodAdmitHandler())
criticalPodAdmissionHandler := preemption.NewCriticalPodAdmissionHandler(...)
klet.admitHandlers.AddPodAdmitHandler(lifecycle.NewPredicateAdmitHandler(...))
// 软准入
klet.softAdmitHandlers.AddPodAdmitHandler(lifecycle.NewAppArmorAdmitHandler(...))
klet.softAdmitHandlers.AddPodAdmitHandler(lifecycle.NewNoNewPrivsAdmitHandler(...))
klet.softAdmitHandlers.AddPodAdmitHandler(lifecycle.NewProcMountAdmitHandler(...))
// ===== 21. Lease Controller =====
klet.nodeLeaseController = lease.NewController(...)
// ===== 22. 节点关闭管理器 =====
shutdownManager, shutdownAdmitHandler := nodeshutdown.NewManager(...)
klet.admitHandlers.AddPodAdmitHandler(shutdownAdmitHandler)
// ===== 23. 设置节点状态函数 =====
klet.setNodeStatusFuncs = klet.defaultNodeStatusFuncs()
return klet, nil
}
3.3 依赖注入构建图
#mermaid-svg-8exn2HEe9jCI33QA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8exn2HEe9jCI33QA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8exn2HEe9jCI33QA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8exn2HEe9jCI33QA .error-icon{fill:#552222;}#mermaid-svg-8exn2HEe9jCI33QA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8exn2HEe9jCI33QA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8exn2HEe9jCI33QA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8exn2HEe9jCI33QA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8exn2HEe9jCI33QA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8exn2HEe9jCI33QA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8exn2HEe9jCI33QA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8exn2HEe9jCI33QA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8exn2HEe9jCI33QA .marker.cross{stroke:#333333;}#mermaid-svg-8exn2HEe9jCI33QA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8exn2HEe9jCI33QA p{margin:0;}#mermaid-svg-8exn2HEe9jCI33QA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8exn2HEe9jCI33QA .cluster-label text{fill:#333;}#mermaid-svg-8exn2HEe9jCI33QA .cluster-label span{color:#333;}#mermaid-svg-8exn2HEe9jCI33QA .cluster-label span p{background-color:transparent;}#mermaid-svg-8exn2HEe9jCI33QA .label text,#mermaid-svg-8exn2HEe9jCI33QA span{fill:#333;color:#333;}#mermaid-svg-8exn2HEe9jCI33QA .node rect,#mermaid-svg-8exn2HEe9jCI33QA .node circle,#mermaid-svg-8exn2HEe9jCI33QA .node ellipse,#mermaid-svg-8exn2HEe9jCI33QA .node polygon,#mermaid-svg-8exn2HEe9jCI33QA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8exn2HEe9jCI33QA .rough-node .label text,#mermaid-svg-8exn2HEe9jCI33QA .node .label text,#mermaid-svg-8exn2HEe9jCI33QA .image-shape .label,#mermaid-svg-8exn2HEe9jCI33QA .icon-shape .label{text-anchor:middle;}#mermaid-svg-8exn2HEe9jCI33QA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8exn2HEe9jCI33QA .rough-node .label,#mermaid-svg-8exn2HEe9jCI33QA .node .label,#mermaid-svg-8exn2HEe9jCI33QA .image-shape .label,#mermaid-svg-8exn2HEe9jCI33QA .icon-shape .label{text-align:center;}#mermaid-svg-8exn2HEe9jCI33QA .node.clickable{cursor:pointer;}#mermaid-svg-8exn2HEe9jCI33QA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8exn2HEe9jCI33QA .arrowheadPath{fill:#333333;}#mermaid-svg-8exn2HEe9jCI33QA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8exn2HEe9jCI33QA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8exn2HEe9jCI33QA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8exn2HEe9jCI33QA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8exn2HEe9jCI33QA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8exn2HEe9jCI33QA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8exn2HEe9jCI33QA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8exn2HEe9jCI33QA .cluster text{fill:#333;}#mermaid-svg-8exn2HEe9jCI33QA .cluster span{color:#333;}#mermaid-svg-8exn2HEe9jCI33QA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8exn2HEe9jCI33QA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8exn2HEe9jCI33QA rect.text{fill:none;stroke-width:0;}#mermaid-svg-8exn2HEe9jCI33QA .icon-shape,#mermaid-svg-8exn2HEe9jCI33QA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8exn2HEe9jCI33QA .icon-shape p,#mermaid-svg-8exn2HEe9jCI33QA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8exn2HEe9jCI33QA .icon-shape .label rect,#mermaid-svg-8exn2HEe9jCI33QA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8exn2HEe9jCI33QA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8exn2HEe9jCI33QA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8exn2HEe9jCI33QA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} NewMainKubelet 中构建
run() 中补充构建
UnsecuredDependencies 构建
InitializeTLS()
mount.New()
subpath.New()
hostutil.NewHostUtil()
ProbeVolumePlugins()
GetDynamicPluginProber()
oom.NewOOMAdjuster()
kubecontainer.RealOS{}
cloudprovider.InitCloudProvider()
buildKubeletClientConfig()
→ KubeClient
→ EventClient
→ HeartbeatClient
BuildAuth()
cadvisor.New()
makeEventRecorder()
cm.NewContainerManager()
SharedInformerFactory
makePodSourceConfig()
SecretManager
ConfigMapManager
PodManager
StatusManager
KubeGenericRuntimeManager
GenericPLEG
ContainerGC
ImageGCManager
ProbeManager
VolumeManager
WorkQueue
PodWorkers
EvictionManager
NodeLeaseController
ShutdownManager
Dependencies
Dependencies 补充
Kubelet
3.4 Kubelet.Run() ------ 主运行循环
go
func (kl *Kubelet) Run(updates <-chan kubetypes.PodUpdate) {
// 1. 设置日志服务器
if kl.logServer == nil {
kl.logServer = http.StripPrefix("/logs/", http.FileServer(http.Dir("/var/log/")))
}
// 2. 启动云资源同步管理器
if kl.cloudResourceSyncManager != nil {
go kl.cloudResourceSyncManager.Run(wait.NeverStop)
}
// 3. 初始化不依赖运行时的模块
if err := kl.initializeModules(); err != nil {
os.Exit(1)
}
// 4. 启动卷管理器
go kl.volumeManager.Run(kl.sourcesReady, wait.NeverStop)
// 5. 节点状态同步(如果有 KubeClient)
if kl.kubeClient != nil {
go wait.Until(kl.syncNodeStatus, kl.nodeStatusUpdateFrequency, wait.NeverStop)
go kl.fastStatusUpdateOnce() // 加速首次状态更新
go kl.nodeLeaseController.Run(wait.NeverStop) // 启动 Lease 续约
}
// 6. 运行时状态更新
go wait.Until(kl.updateRuntimeUp, 5*time.Second, wait.NeverStop)
// 7. iptables 规则
if kl.makeIPTablesUtilChains { kl.initNetworkUtil() }
// 8. Pod Killer
go wait.Until(kl.podKiller.PerformPodKillingWork, 1*time.Second, wait.NeverStop)
// 9. StatusManager
kl.statusManager.Start()
// 10. RuntimeClass Manager
if kl.runtimeClassManager != nil { kl.runtimeClassManager.Start(wait.NeverStop) }
// 11. PLEG
kl.pleg.Start()
// 12. 进入主同步循环(永不返回)
kl.syncLoop(updates, kl)
}
3.5 initializeModules() ------ 运行时无关模块初始化
go
func (kl *Kubelet) initializeModules() error {
// 1. 注册 Prometheus 指标
metrics.Register(
collectors.NewVolumeStatsCollector(kl),
collectors.NewLogMetricsCollector(kl.StatsProvider.ListPodStats),
)
metrics.SetNodeName(kl.nodeName)
servermetrics.Register()
// 2. 创建文件系统目录
kl.setupDataDirs() // /var/lib/kubelet, /var/lib/kubelet/pods, /var/lib/kubelet/plugins, ...
// 3. 创建容器日志目录
os.MkdirAll(ContainerLogsDir, 0755) // /var/log/containers
// 4. 启动镜像管理器
kl.imageManager.Start()
// 5. 启动证书管理器
if kl.serverCertificateManager != nil {
kl.serverCertificateManager.Start()
}
// 6. 启动 OOM Watcher
kl.oomWatcher.Start(kl.nodeRef)
// 7. 启动资源分析器
kl.resourceAnalyzer.Start()
return nil
}
3.6 initializeRuntimeDependentModules() ------ 运行时依赖模块
通过 sync.Once 保证只执行一次,在 updateRuntimeUp() 检测到运行时就绪后触发:
go
func (kl *Kubelet) initializeRuntimeDependentModules() {
// 1. 启动 cAdvisor
kl.cadvisor.Start() // 失败则 os.Exit(1)
// 2. 触发一次按需统计收集(为 ephemeral storage 容量信息)
kl.StatsProvider.GetCgroupStats("/", true)
// 3. 启动 ContainerManager(必须在 cAdvisor 之后,因为需要文件系统容量信息)
node := kl.getNodeAnyWay()
kl.containerManager.Start(node, kl.GetActivePods, kl.sourcesReady, kl.statusManager, kl.runtimeService)
// 4. 启动 Eviction Manager(必须在 cAdvisor 之后,因为需要知道 imagefs)
kl.evictionManager.Start(kl.StatsProvider, kl.GetActivePods, kl.podResourcesAreReclaimed, evictionMonitoringPeriod)
// 5. 启动容器日志管理器
kl.containerLogManager.Start()
// 6. 注册 CSI/DevicePlugin Handler 并启动 PluginManager
kl.pluginManager.AddHandler(pluginwatcherapi.CSIPlugin, plugincache.PluginHandler(csi.PluginHandler))
kl.pluginManager.AddHandler(pluginwatcherapi.DevicePlugin, kl.containerManager.GetPluginRegistrationHandler())
go kl.pluginManager.Run(kl.sourcesReady, wait.NeverStop)
// 7. 启动节点关闭管理器
kl.shutdownManager.Start()
}
3.7 Kubelet 核心类图
#mermaid-svg-yGMnDBw88gur3NDH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yGMnDBw88gur3NDH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yGMnDBw88gur3NDH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yGMnDBw88gur3NDH .error-icon{fill:#552222;}#mermaid-svg-yGMnDBw88gur3NDH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yGMnDBw88gur3NDH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yGMnDBw88gur3NDH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yGMnDBw88gur3NDH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yGMnDBw88gur3NDH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yGMnDBw88gur3NDH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yGMnDBw88gur3NDH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yGMnDBw88gur3NDH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yGMnDBw88gur3NDH .marker.cross{stroke:#333333;}#mermaid-svg-yGMnDBw88gur3NDH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yGMnDBw88gur3NDH p{margin:0;}#mermaid-svg-yGMnDBw88gur3NDH g.classGroup text{fill:#9370DB;stroke:none;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-yGMnDBw88gur3NDH g.classGroup text .title{font-weight:bolder;}#mermaid-svg-yGMnDBw88gur3NDH .cluster-label text{fill:#333;}#mermaid-svg-yGMnDBw88gur3NDH .cluster-label span{color:#333;}#mermaid-svg-yGMnDBw88gur3NDH .cluster-label span p{background-color:transparent;}#mermaid-svg-yGMnDBw88gur3NDH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yGMnDBw88gur3NDH .cluster text{fill:#333;}#mermaid-svg-yGMnDBw88gur3NDH .cluster span{color:#333;}#mermaid-svg-yGMnDBw88gur3NDH .nodeLabel,#mermaid-svg-yGMnDBw88gur3NDH .edgeLabel{color:#131300;}#mermaid-svg-yGMnDBw88gur3NDH .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-yGMnDBw88gur3NDH .label text{fill:#131300;}#mermaid-svg-yGMnDBw88gur3NDH .labelBkg{background:#ECECFF;}#mermaid-svg-yGMnDBw88gur3NDH .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-yGMnDBw88gur3NDH .classTitle{font-weight:bolder;}#mermaid-svg-yGMnDBw88gur3NDH .node rect,#mermaid-svg-yGMnDBw88gur3NDH .node circle,#mermaid-svg-yGMnDBw88gur3NDH .node ellipse,#mermaid-svg-yGMnDBw88gur3NDH .node polygon,#mermaid-svg-yGMnDBw88gur3NDH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yGMnDBw88gur3NDH .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH g.clickable{cursor:pointer;}#mermaid-svg-yGMnDBw88gur3NDH g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-yGMnDBw88gur3NDH g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-yGMnDBw88gur3NDH .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-yGMnDBw88gur3NDH .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-yGMnDBw88gur3NDH .dashed-line{stroke-dasharray:3;}#mermaid-svg-yGMnDBw88gur3NDH .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-yGMnDBw88gur3NDH #compositionStart,#mermaid-svg-yGMnDBw88gur3NDH .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH #compositionEnd,#mermaid-svg-yGMnDBw88gur3NDH .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH #dependencyStart,#mermaid-svg-yGMnDBw88gur3NDH .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH #dependencyStart,#mermaid-svg-yGMnDBw88gur3NDH .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH #extensionStart,#mermaid-svg-yGMnDBw88gur3NDH .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH #extensionEnd,#mermaid-svg-yGMnDBw88gur3NDH .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH #aggregationStart,#mermaid-svg-yGMnDBw88gur3NDH .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH #aggregationEnd,#mermaid-svg-yGMnDBw88gur3NDH .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH #lollipopStart,#mermaid-svg-yGMnDBw88gur3NDH .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH #lollipopEnd,#mermaid-svg-yGMnDBw88gur3NDH .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-yGMnDBw88gur3NDH .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-yGMnDBw88gur3NDH .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yGMnDBw88gur3NDH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yGMnDBw88gur3NDH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yGMnDBw88gur3NDH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} implements
implements
uses
constructed from
Kubelet
-kubeletConfiguration KubeletConfiguration
-hostname string
-nodeName types.NodeName
-podManager kubepod.Manager
-podWorkers PodWorkers
-statusManager status.Manager
-containerRuntime kubecontainer.Runtime
-volumeManager volumemanager.VolumeManager
-evictionManager eviction.Manager
-probeManager prober.Manager
-pleg pleg.PodLifecycleEventGenerator
-containerManager cm.ContainerManager
-imageManager images.ImageGCManager
-containerGC kubecontainer.GC
-runtimeState runtimeState
+Run(updates)
+syncLoop(updates, handler)
+syncLoopIteration(configCh, handler, syncCh, housekeepingCh, plegCh)
+syncPod(options) : error
+HandlePodAdditions(pods)
+HandlePodUpdates(pods)
+HandlePodRemoves(pods)
+HandlePodReconcile(pods)
+HandlePodSyncs(pods)
+HandlePodCleanups() : error
+canAdmitPod(pods, pod)(bool, string, string)
+canRunPod(pod) : PodAdmitResult
+dispatchWork(pod, syncType, mirrorPod, start)
+deletePod(pod) : error
+initializeModules() : error
+initializeRuntimeDependentModules()
+updateRuntimeUp()
+StartGarbageCollection()
+BirthCry()
<<interface>>
SyncHandler
+HandlePodAdditions(pods)
+HandlePodUpdates(pods)
+HandlePodRemoves(pods)
+HandlePodReconcile(pods)
+HandlePodSyncs(pods)
+HandlePodCleanups() : error
<<interface>>
Bootstrap
+GetConfiguration() : KubeletConfiguration
+BirthCry()
+StartGarbageCollection()
+ListenAndServe(...)
+Run(updates)
+RunOnce(updates)
<<interface>>
PodWorkers
+UpdatePod(options)
+ForgetNonExistingPodWorkers(desiredPods)
+ForgetWorker(uid)
Dependencies
+Auth server.AuthInterface
+CAdvisorInterface cadvisor.Interface
+Cloud cloudprovider.Interface
+ContainerManager cm.ContainerManager
+KubeClient clientset.Interface
+HeartbeatClient clientset.Interface
+EventClient v1core.EventsGetter
+PodConfig config.PodConfig
+Recorder record.EventRecorder
+VolumePlugins \[\]volume.VolumePlugin
+RemoteRuntimeService internalapi.RuntimeService
+RemoteImageService internalapi.ImageManagerService
3.8 SyncPod 完整逻辑深度解析
syncPod 是 Kubelet 最核心的事务脚本,处理单个 Pod 的状态收敛。以下逐行解析:
go
func (kl *Kubelet) syncPod(o syncPodOptions) error {
pod := o.pod
mirrorPod := o.mirrorPod
podStatus := o.podStatus
updateType := o.updateType
// ========== 步骤 1:Kill 请求处理 ==========
if updateType == kubetypes.SyncPodKill {
killPodOptions := o.killPodOptions
apiPodStatus := killPodOptions.PodStatusFunc(pod, podStatus)
kl.statusManager.SetPodStatus(pod, apiPodStatus)
err := kl.killPod(pod, nil, podStatus, killPodOptions.PodTerminationGracePeriodSecondsOverride)
return err
}
// ========== 步骤 2:优雅终止中检查 ==========
podFullName := kubecontainer.GetPodFullName(pod)
if kl.podKiller.IsPodPendingTerminationByPodName(podFullName) {
return fmt.Errorf("pod %q is pending termination", podFullName)
}
// ========== 步骤 3:记录首次可见时间 ==========
var firstSeenTime time.Time
if firstSeenTimeStr, ok := pod.Annotations[kubetypes.ConfigFirstSeenAnnotationKey]; ok {
firstSeenTime = kubetypes.ConvertToTimestamp(firstSeenTimeStr).Get()
}
// ========== 步骤 4:记录 Pod Worker 启动延迟 ==========
if updateType == kubetypes.SyncPodCreate {
if !firstSeenTime.IsZero() {
metrics.PodWorkerStartDuration.Observe(metrics.SinceInSeconds(firstSeenTime))
}
}
// ========== 步骤 5:生成 API Pod Status ==========
apiPodStatus := kl.generateAPIPodStatus(pod, podStatus)
// 处理 host network 场景下的 Pod IP
podStatus.IPs = make([]string, 0, len(apiPodStatus.PodIPs))
for _, ipInfo := range apiPodStatus.PodIPs {
podStatus.IPs = append(podStatus.IPs, ipInfo.IP)
}
// ========== 步骤 6:记录 Pod 启动延迟 ==========
existingStatus, ok := kl.statusManager.GetPodStatus(pod.UID)
if !ok || existingStatus.Phase == v1.PodPending && apiPodStatus.Phase == v1.PodRunning && !firstSeenTime.IsZero() {
metrics.PodStartDuration.Observe(metrics.SinceInSeconds(firstSeenTime))
}
// ========== 步骤 7:准入检查 ==========
runnable := kl.canRunPod(pod)
if !runnable.Admit {
apiPodStatus.Reason = runnable.Reason
apiPodStatus.Message = runnable.Message
// 设置所有 Waiting 容器原因为 "Blocked"
for _, cs := range apiPodStatus.InitContainerStatuses {
if cs.State.Waiting != nil { cs.State.Waiting.Reason = "Blocked" }
}
for _, cs := range apiPodStatus.ContainerStatuses {
if cs.State.Waiting != nil { cs.State.Waiting.Reason = "Blocked" }
}
}
// ========== 步骤 8:更新 Status Manager ==========
kl.statusManager.SetPodStatus(pod, apiPodStatus)
// ========== 步骤 9:不可运行则 Kill ==========
if !runnable.Admit || pod.DeletionTimestamp != nil || apiPodStatus.Phase == v1.PodFailed {
err := kl.killPod(pod, nil, podStatus, nil)
return syncErr
}
// ========== 步骤 10:网络就绪检查 ==========
if err := kl.runtimeState.networkErrors(); err != nil && !kubecontainer.IsHostNetworkPod(pod) {
kl.recorder.Eventf(pod, v1.EventTypeWarning, events.NetworkNotReady, ...)
return fmt.Errorf("%s: %v", NetworkNotReadyErrorMsg, err)
}
// ========== 步骤 11:Cgroup 管理 ==========
pcm := kl.containerManager.NewPodContainerManager()
if !kl.podIsTerminated(pod) {
firstSync := true
for _, containerStatus := range apiPodStatus.ContainerStatuses {
if containerStatus.State.Running != nil { firstSync = false; break }
}
podKilled := false
if !pcm.Exists(pod) && !firstSync {
kl.killPod(pod, nil, podStatus, nil) // QoS Cgroup 不存在且非首次同步→重建
podKilled = true
}
if !(podKilled && pod.Spec.RestartPolicy == v1.RestartPolicyNever) {
kl.containerManager.UpdateQOSCgroups()
pcm.EnsureExists(pod) // 确保 Pod Cgroup 存在
}
}
// ========== 步骤 12:静态 Pod Mirror Pod 管理 ==========
if kubetypes.IsStaticPod(pod) {
if mirrorPod != nil {
if mirrorPod.DeletionTimestamp != nil || !kl.podManager.IsMirrorPodOf(mirrorPod, pod) {
kl.podManager.DeleteMirrorPod(podFullName, &mirrorPod.ObjectMeta.UID)
}
}
if mirrorPod == nil || deleted {
node, err := kl.GetNode()
if err == nil || node.DeletionTimestamp == nil {
kl.podManager.CreateMirrorPod(pod) // 创建 Mirror Pod
}
}
}
// ========== 步骤 13:创建 Pod 数据目录 ==========
kl.makePodDataDirs(pod)
// ========== 步骤 14:等待卷 Attach/Mount ==========
if !kl.podIsTerminated(pod) {
kl.volumeManager.WaitForAttachAndMount(pod)
}
// ========== 步骤 15:获取 Image Pull Secrets ==========
pullSecrets := kl.getPullSecretsForPod(pod)
// ========== 步骤 16:调用容器运行时 SyncPod ==========
result := kl.containerRuntime.SyncPod(pod, podStatus, pullSecrets, kl.backOff)
kl.reasonCache.Update(pod.UID, result)
if err := result.Error(); err != nil {
// 仅在非 CrashLoopBackOff/ErrImagePullBackOff 时返回错误
for _, r := range result.SyncResults {
if r.Error != kubecontainer.ErrCrashLoopBackOff && r.Error != images.ErrImagePullBackOff {
return err
}
}
return nil
}
return nil
}
3.9 SyncPod 完整流程图
#mermaid-svg-GEu5Z4nXsrOqwq9s{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GEu5Z4nXsrOqwq9s .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GEu5Z4nXsrOqwq9s .error-icon{fill:#552222;}#mermaid-svg-GEu5Z4nXsrOqwq9s .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GEu5Z4nXsrOqwq9s .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GEu5Z4nXsrOqwq9s .marker.cross{stroke:#333333;}#mermaid-svg-GEu5Z4nXsrOqwq9s svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GEu5Z4nXsrOqwq9s p{margin:0;}#mermaid-svg-GEu5Z4nXsrOqwq9s .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-GEu5Z4nXsrOqwq9s .cluster-label text{fill:#333;}#mermaid-svg-GEu5Z4nXsrOqwq9s .cluster-label span{color:#333;}#mermaid-svg-GEu5Z4nXsrOqwq9s .cluster-label span p{background-color:transparent;}#mermaid-svg-GEu5Z4nXsrOqwq9s .label text,#mermaid-svg-GEu5Z4nXsrOqwq9s span{fill:#333;color:#333;}#mermaid-svg-GEu5Z4nXsrOqwq9s .node rect,#mermaid-svg-GEu5Z4nXsrOqwq9s .node circle,#mermaid-svg-GEu5Z4nXsrOqwq9s .node ellipse,#mermaid-svg-GEu5Z4nXsrOqwq9s .node polygon,#mermaid-svg-GEu5Z4nXsrOqwq9s .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-GEu5Z4nXsrOqwq9s .rough-node .label text,#mermaid-svg-GEu5Z4nXsrOqwq9s .node .label text,#mermaid-svg-GEu5Z4nXsrOqwq9s .image-shape .label,#mermaid-svg-GEu5Z4nXsrOqwq9s .icon-shape .label{text-anchor:middle;}#mermaid-svg-GEu5Z4nXsrOqwq9s .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-GEu5Z4nXsrOqwq9s .rough-node .label,#mermaid-svg-GEu5Z4nXsrOqwq9s .node .label,#mermaid-svg-GEu5Z4nXsrOqwq9s .image-shape .label,#mermaid-svg-GEu5Z4nXsrOqwq9s .icon-shape .label{text-align:center;}#mermaid-svg-GEu5Z4nXsrOqwq9s .node.clickable{cursor:pointer;}#mermaid-svg-GEu5Z4nXsrOqwq9s .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-GEu5Z4nXsrOqwq9s .arrowheadPath{fill:#333333;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-GEu5Z4nXsrOqwq9s .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GEu5Z4nXsrOqwq9s .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-GEu5Z4nXsrOqwq9s .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GEu5Z4nXsrOqwq9s .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-GEu5Z4nXsrOqwq9s .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-GEu5Z4nXsrOqwq9s .cluster text{fill:#333;}#mermaid-svg-GEu5Z4nXsrOqwq9s .cluster span{color:#333;}#mermaid-svg-GEu5Z4nXsrOqwq9s div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-GEu5Z4nXsrOqwq9s .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-GEu5Z4nXsrOqwq9s rect.text{fill:none;stroke-width:0;}#mermaid-svg-GEu5Z4nXsrOqwq9s .icon-shape,#mermaid-svg-GEu5Z4nXsrOqwq9s .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-GEu5Z4nXsrOqwq9s .icon-shape p,#mermaid-svg-GEu5Z4nXsrOqwq9s .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-GEu5Z4nXsrOqwq9s .icon-shape .label rect,#mermaid-svg-GEu5Z4nXsrOqwq9s .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-GEu5Z4nXsrOqwq9s .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-GEu5Z4nXsrOqwq9s .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-GEu5Z4nXsrOqwq9s :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SyncPodKill
其他
是
否
是
否
是
否
否
是
是
否
否 & 非HostNetwork
是 或 HostNetwork
否 & 非首次
是 或 首次
否
是
否
是
否
是
否
是 & 仅BackOff
是 & 其他错误
syncPod 入口
updateType?
killPod()
设置 Pod Status → Kill
返回
Pod 正在
优雅终止?
返回: pending termination
获取 firstSeenTime
(annotations)
updateType
== Create?
记录 PodWorkerStart
延迟指标
跳过
generateAPIPodStatus()
设置 podStatus.IPs
Phase 变化
Pending→Running?
记录 PodStart
延迟指标
跳过
canRunPod()
Admit?
设置 Reason=Blocked
更新 Status
statusManager.
SetPodStatus()
不可运行/
DeletionTimestamp/
Phase=Failed?
killPod()
网络就绪?
返回错误
返回 NetworkNotReady
Cgroup 管理
Pod Cgroup
存在?
killPod() 重建
EnsureExists()
UpdateQOSCgroups()
静态 Pod?
makePodDataDirs()
Mirror Pod
存在且匹配?
创建 Mirror Pod
Pod 已终止?
WaitForAttachAndMount()
getPullSecretsForPod()
containerRuntime.
SyncPod()
reasonCache.Update()
SyncResult
有错误?
返回 nil
返回 nil
忽略 BackOff 错误
返回错误
3.10 syncLoop ------ 主同步循环
syncLoop 是 Kubelet 的心跳,永不返回。它从多个事件源接收更新,驱动 Pod 状态收敛。
go
func (kl *Kubelet) syncLoop(updates <-chan kubetypes.PodUpdate, handler SyncHandler) {
klog.InfoS("Starting kubelet main sync loop")
syncTicker := time.NewTicker(time.Second) // 1 秒同步检查
housekeepingTicker := time.NewTicker(housekeepingPeriod) // 2 秒清理检查
plegCh := kl.pleg.Watch() // PLEG 事件通道
// 初始退避参数
const (base = 100*time.Millisecond; max = 5*time.Second; factor = 2)
duration := base
// 检查 resolv.conf 限制
if kl.dnsConfigurer != nil && kl.dnsConfigurer.ResolverConfig != "" {
kl.dnsConfigurer.CheckLimitsForResolvConf()
}
for {
// 运行时错误检查 → 指数退避
if err := kl.runtimeState.runtimeErrors(); err != nil {
time.Sleep(duration)
duration = time.Duration(math.Min(float64(max), factor*float64(duration)))
continue
}
duration = base // 成功则重置退避
kl.syncLoopMonitor.Store(kl.clock.Now())
if !kl.syncLoopIteration(updates, handler, syncTicker.C, housekeepingTicker.C, plegCh) {
break // updates channel 关闭时退出
}
kl.syncLoopMonitor.Store(kl.clock.Now())
}
}
3.11 syncLoopIteration ------ 单次迭代事件分发
go
func (kl *Kubelet) syncLoopIteration(configCh, handler, syncCh, housekeepingCh, plegCh) bool {
select {
// ====== 事件 1:配置源更新 ======
case u, open := <-configCh:
if !open { return false } // 通道关闭 → 退出
switch u.Op {
case kubetypes.ADD: handler.HandlePodAdditions(u.Pods)
case kubetypes.UPDATE: handler.HandlePodUpdates(u.Pods)
case kubetypes.REMOVE: handler.HandlePodRemoves(u.Pods)
case kubetypes.RECONCILE: handler.HandlePodReconcile(u.Pods)
case kubetypes.DELETE: handler.HandlePodUpdates(u.Pods) // DELETE 当 UPDATE 处理
case kubetypes.SET: klog.ErrorS(nil, "Kubelet does not support snapshot update")
}
kl.sourcesReady.AddSource(u.Source)
// ====== 事件 2:PLEG 事件 ======
case e := <-plegCh:
if e.Type == pleg.ContainerStarted {
kl.lastContainerStartedTime.Add(e.ID, time.Now())
}
if isSyncPodWorthy(e) {
if pod, ok := kl.podManager.GetPodByUID(e.ID); ok {
handler.HandlePodSyncs([]*v1.Pod{pod})
}
}
if e.Type == pleg.ContainerDied {
kl.cleanUpContainersInPod(e.ID, containerID)
}
// ====== 事件 3:定时同步 ======
case <-syncCh:
podsToSync := kl.getPodsToSync()
if len(podsToSync) > 0 {
handler.HandlePodSyncs(podsToSync)
}
// ====== 事件 4:Liveness 探针失败 ======
case update := <-kl.livenessManager.Updates():
if update.Result == proberesults.Failure {
handleProbeSync(kl, update, handler, "liveness", "unhealthy")
}
// ====== 事件 5:Readiness 探针更新 ======
case update := <-kl.readinessManager.Updates():
ready := update.Result == proberesults.Success
kl.statusManager.SetContainerReadiness(update.PodUID, update.ContainerID, ready)
handleProbeSync(kl, update, handler, "readiness", ...)
// ====== 事件 6:Startup 探针更新 ======
case update := <-kl.startupManager.Updates():
started := update.Result == proberesults.Success
kl.statusManager.SetContainerStartup(update.PodUID, update.ContainerID, started)
handleProbeSync(kl, update, handler, "startup", ...)
// ====== 事件 7:Housekeeping ======
case <-housekeepingCh:
if kl.sourcesReady.AllReady() {
handler.HandlePodCleanups()
}
}
return true
}
重要细节 :Go 的 select 在多个 case 同时就绪时,会伪随机选择一个执行。这意味着事件处理没有严格的优先级------PLEG 事件可能与 config 更新竞争。
3.12 Pod 同步主循环图
#mermaid-svg-iMbewZAtdbGgLYSi{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iMbewZAtdbGgLYSi .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iMbewZAtdbGgLYSi .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iMbewZAtdbGgLYSi .error-icon{fill:#552222;}#mermaid-svg-iMbewZAtdbGgLYSi .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iMbewZAtdbGgLYSi .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iMbewZAtdbGgLYSi .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iMbewZAtdbGgLYSi .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iMbewZAtdbGgLYSi .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iMbewZAtdbGgLYSi .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iMbewZAtdbGgLYSi .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iMbewZAtdbGgLYSi .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iMbewZAtdbGgLYSi .marker.cross{stroke:#333333;}#mermaid-svg-iMbewZAtdbGgLYSi svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iMbewZAtdbGgLYSi p{margin:0;}#mermaid-svg-iMbewZAtdbGgLYSi .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iMbewZAtdbGgLYSi .cluster-label text{fill:#333;}#mermaid-svg-iMbewZAtdbGgLYSi .cluster-label span{color:#333;}#mermaid-svg-iMbewZAtdbGgLYSi .cluster-label span p{background-color:transparent;}#mermaid-svg-iMbewZAtdbGgLYSi .label text,#mermaid-svg-iMbewZAtdbGgLYSi span{fill:#333;color:#333;}#mermaid-svg-iMbewZAtdbGgLYSi .node rect,#mermaid-svg-iMbewZAtdbGgLYSi .node circle,#mermaid-svg-iMbewZAtdbGgLYSi .node ellipse,#mermaid-svg-iMbewZAtdbGgLYSi .node polygon,#mermaid-svg-iMbewZAtdbGgLYSi .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iMbewZAtdbGgLYSi .rough-node .label text,#mermaid-svg-iMbewZAtdbGgLYSi .node .label text,#mermaid-svg-iMbewZAtdbGgLYSi .image-shape .label,#mermaid-svg-iMbewZAtdbGgLYSi .icon-shape .label{text-anchor:middle;}#mermaid-svg-iMbewZAtdbGgLYSi .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iMbewZAtdbGgLYSi .rough-node .label,#mermaid-svg-iMbewZAtdbGgLYSi .node .label,#mermaid-svg-iMbewZAtdbGgLYSi .image-shape .label,#mermaid-svg-iMbewZAtdbGgLYSi .icon-shape .label{text-align:center;}#mermaid-svg-iMbewZAtdbGgLYSi .node.clickable{cursor:pointer;}#mermaid-svg-iMbewZAtdbGgLYSi .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iMbewZAtdbGgLYSi .arrowheadPath{fill:#333333;}#mermaid-svg-iMbewZAtdbGgLYSi .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iMbewZAtdbGgLYSi .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iMbewZAtdbGgLYSi .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iMbewZAtdbGgLYSi .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iMbewZAtdbGgLYSi .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iMbewZAtdbGgLYSi .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iMbewZAtdbGgLYSi .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iMbewZAtdbGgLYSi .cluster text{fill:#333;}#mermaid-svg-iMbewZAtdbGgLYSi .cluster span{color:#333;}#mermaid-svg-iMbewZAtdbGgLYSi div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iMbewZAtdbGgLYSi .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iMbewZAtdbGgLYSi rect.text{fill:none;stroke-width:0;}#mermaid-svg-iMbewZAtdbGgLYSi .icon-shape,#mermaid-svg-iMbewZAtdbGgLYSi .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iMbewZAtdbGgLYSi .icon-shape p,#mermaid-svg-iMbewZAtdbGgLYSi .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iMbewZAtdbGgLYSi .icon-shape .label rect,#mermaid-svg-iMbewZAtdbGgLYSi .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iMbewZAtdbGgLYSi .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iMbewZAtdbGgLYSi .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iMbewZAtdbGgLYSi :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
syncLoop (永不返回)
runtimeState
有错误?
指数退避
100ms→5s
select 多路复用
configCh
配置源更新
plegCh
PLEG 事件
syncCh
定时同步
(1s)
livenessManager.Updates()
Liveness 探针
readinessManager.Updates()
Readiness 探针
startupManager.Updates()
Startup 探针
housekeepingCh
清理检查
(2s)
HandlePodAdditions
HandlePodUpdates
HandlePodRemoves
HandlePodReconcile
HandlePodUpdates
(DELETE→UPDATE)
ContainerStarted
记录时间
isSyncPodWorthy?
→ HandlePodSyncs
ContainerDied
→ cleanUpContainersInPod
getPodsToSync()
→ HandlePodSyncs
Failure?
→ HandlePodSyncs
SetContainerReadiness
→ HandlePodSyncs
SetContainerStartup
→ HandlePodSyncs
HandlePodCleanups()
dispatchWork()
→ podWorkers.UpdatePod()
Per-Pod Worker
managePodLoop()
syncPod()
containerRuntime.SyncPod()
清理逻辑
→ 删除孤儿 Pod
→ 清理终止 Pod
→ 清理孤立卷
3.13 接口层次图
#mermaid-svg-mJd0iAJ6jL0skS4t{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mJd0iAJ6jL0skS4t .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mJd0iAJ6jL0skS4t .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mJd0iAJ6jL0skS4t .error-icon{fill:#552222;}#mermaid-svg-mJd0iAJ6jL0skS4t .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mJd0iAJ6jL0skS4t .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mJd0iAJ6jL0skS4t .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mJd0iAJ6jL0skS4t .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mJd0iAJ6jL0skS4t .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mJd0iAJ6jL0skS4t .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mJd0iAJ6jL0skS4t .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mJd0iAJ6jL0skS4t .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mJd0iAJ6jL0skS4t .marker.cross{stroke:#333333;}#mermaid-svg-mJd0iAJ6jL0skS4t svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mJd0iAJ6jL0skS4t p{margin:0;}#mermaid-svg-mJd0iAJ6jL0skS4t .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-mJd0iAJ6jL0skS4t .cluster-label text{fill:#333;}#mermaid-svg-mJd0iAJ6jL0skS4t .cluster-label span{color:#333;}#mermaid-svg-mJd0iAJ6jL0skS4t .cluster-label span p{background-color:transparent;}#mermaid-svg-mJd0iAJ6jL0skS4t .label text,#mermaid-svg-mJd0iAJ6jL0skS4t span{fill:#333;color:#333;}#mermaid-svg-mJd0iAJ6jL0skS4t .node rect,#mermaid-svg-mJd0iAJ6jL0skS4t .node circle,#mermaid-svg-mJd0iAJ6jL0skS4t .node ellipse,#mermaid-svg-mJd0iAJ6jL0skS4t .node polygon,#mermaid-svg-mJd0iAJ6jL0skS4t .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-mJd0iAJ6jL0skS4t .rough-node .label text,#mermaid-svg-mJd0iAJ6jL0skS4t .node .label text,#mermaid-svg-mJd0iAJ6jL0skS4t .image-shape .label,#mermaid-svg-mJd0iAJ6jL0skS4t .icon-shape .label{text-anchor:middle;}#mermaid-svg-mJd0iAJ6jL0skS4t .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-mJd0iAJ6jL0skS4t .rough-node .label,#mermaid-svg-mJd0iAJ6jL0skS4t .node .label,#mermaid-svg-mJd0iAJ6jL0skS4t .image-shape .label,#mermaid-svg-mJd0iAJ6jL0skS4t .icon-shape .label{text-align:center;}#mermaid-svg-mJd0iAJ6jL0skS4t .node.clickable{cursor:pointer;}#mermaid-svg-mJd0iAJ6jL0skS4t .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-mJd0iAJ6jL0skS4t .arrowheadPath{fill:#333333;}#mermaid-svg-mJd0iAJ6jL0skS4t .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-mJd0iAJ6jL0skS4t .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-mJd0iAJ6jL0skS4t .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mJd0iAJ6jL0skS4t .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-mJd0iAJ6jL0skS4t .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mJd0iAJ6jL0skS4t .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-mJd0iAJ6jL0skS4t .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-mJd0iAJ6jL0skS4t .cluster text{fill:#333;}#mermaid-svg-mJd0iAJ6jL0skS4t .cluster span{color:#333;}#mermaid-svg-mJd0iAJ6jL0skS4t div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-mJd0iAJ6jL0skS4t .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-mJd0iAJ6jL0skS4t rect.text{fill:none;stroke-width:0;}#mermaid-svg-mJd0iAJ6jL0skS4t .icon-shape,#mermaid-svg-mJd0iAJ6jL0skS4t .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-mJd0iAJ6jL0skS4t .icon-shape p,#mermaid-svg-mJd0iAJ6jL0skS4t .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-mJd0iAJ6jL0skS4t .icon-shape .label rect,#mermaid-svg-mJd0iAJ6jL0skS4t .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-mJd0iAJ6jL0skS4t .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-mJd0iAJ6jL0skS4t .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-mJd0iAJ6jL0skS4t :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 管理器层
运行时层
核心层
应用层
命令层
implements
implements
cobra.Command
(NewKubeletCommand)
app.Run()
app.run()
RunKubelet()
Bootstrap 接口
SyncHandler 接口
PodWorkers 接口
kubecontainer.Runtime 接口
KubeGenericRuntimeManager
RemoteRuntimeService
(CRI)
RemoteImageService
(CRI)
kubepod.Manager
status.Manager
volumemanager.VolumeManager
eviction.Manager
prober.Manager
cm.ContainerManager
images.ImageGCManager
kubecontainer.GC
pleg.PodLifecycleEventGenerator
Kubelet
四、Pod 状态机与生命周期管理
4.1 Pod 状态机转换图
#mermaid-svg-3ci8202c6V799Rnm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3ci8202c6V799Rnm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3ci8202c6V799Rnm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3ci8202c6V799Rnm .error-icon{fill:#552222;}#mermaid-svg-3ci8202c6V799Rnm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3ci8202c6V799Rnm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3ci8202c6V799Rnm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3ci8202c6V799Rnm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3ci8202c6V799Rnm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3ci8202c6V799Rnm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3ci8202c6V799Rnm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3ci8202c6V799Rnm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3ci8202c6V799Rnm .marker.cross{stroke:#333333;}#mermaid-svg-3ci8202c6V799Rnm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3ci8202c6V799Rnm p{margin:0;}#mermaid-svg-3ci8202c6V799Rnm defs #statediagram-barbEnd{fill:#333333;stroke:#333333;}#mermaid-svg-3ci8202c6V799Rnm g.stateGroup text{fill:#9370DB;stroke:none;font-size:10px;}#mermaid-svg-3ci8202c6V799Rnm g.stateGroup text{fill:#333;stroke:none;font-size:10px;}#mermaid-svg-3ci8202c6V799Rnm g.stateGroup .state-title{font-weight:bolder;fill:#131300;}#mermaid-svg-3ci8202c6V799Rnm g.stateGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-3ci8202c6V799Rnm g.stateGroup line{stroke:#333333;stroke-width:1;}#mermaid-svg-3ci8202c6V799Rnm .transition{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-3ci8202c6V799Rnm .stateGroup .composit{fill:white;border-bottom:1px;}#mermaid-svg-3ci8202c6V799Rnm .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px;}#mermaid-svg-3ci8202c6V799Rnm .state-note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-3ci8202c6V799Rnm .state-note text{fill:black;stroke:none;font-size:10px;}#mermaid-svg-3ci8202c6V799Rnm .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-3ci8202c6V799Rnm .edgeLabel .label rect{fill:#ECECFF;opacity:0.5;}#mermaid-svg-3ci8202c6V799Rnm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3ci8202c6V799Rnm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3ci8202c6V799Rnm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3ci8202c6V799Rnm .edgeLabel .label text{fill:#333;}#mermaid-svg-3ci8202c6V799Rnm .label div .edgeLabel{color:#333;}#mermaid-svg-3ci8202c6V799Rnm .stateLabel text{fill:#131300;font-size:10px;font-weight:bold;}#mermaid-svg-3ci8202c6V799Rnm .node circle.state-start{fill:#333333;stroke:#333333;}#mermaid-svg-3ci8202c6V799Rnm .node .fork-join{fill:#333333;stroke:#333333;}#mermaid-svg-3ci8202c6V799Rnm .node circle.state-end{fill:#9370DB;stroke:white;stroke-width:1.5;}#mermaid-svg-3ci8202c6V799Rnm .end-state-inner{fill:white;stroke-width:1.5;}#mermaid-svg-3ci8202c6V799Rnm .node rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3ci8202c6V799Rnm .node polygon{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3ci8202c6V799Rnm #statediagram-barbEnd{fill:#333333;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-cluster rect{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3ci8202c6V799Rnm .cluster-label,#mermaid-svg-3ci8202c6V799Rnm .nodeLabel{color:#131300;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-cluster rect.outer{rx:5px;ry:5px;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-state .divider{stroke:#9370DB;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-state .title-state{rx:5px;ry:5px;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-cluster.statediagram-cluster .inner{fill:white;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-cluster.statediagram-cluster-alt .inner{fill:#f0f0f0;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-cluster .inner{rx:0;ry:0;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-state rect.basic{rx:5px;ry:5px;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#f0f0f0;}#mermaid-svg-3ci8202c6V799Rnm .note-edge{stroke-dasharray:5;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-note rect{fill:#fff5ad;stroke:#aaaa33;stroke-width:1px;rx:0;ry:0;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-note text{fill:black;}#mermaid-svg-3ci8202c6V799Rnm .statediagram-note .nodeLabel{color:black;}#mermaid-svg-3ci8202c6V799Rnm .statediagram .edgeLabel{color:red;}#mermaid-svg-3ci8202c6V799Rnm #dependencyStart,#mermaid-svg-3ci8202c6V799Rnm #dependencyEnd{fill:#333333;stroke:#333333;stroke-width:1;}#mermaid-svg-3ci8202c6V799Rnm .statediagramTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3ci8202c6V799Rnm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} API Server 创建 Pod
等待调度/卷挂载/镜像拉取
所有容器启动成功
准入拒绝/不可运行
Init 容器失败(restartPolicy=Never)
容器重启/探针通过
所有容器正常退出(restartPolicy=Never/OnFailure)
非零退出码(restartPolicy=Never)
Liveness 探针持续失败(restartPolicy=Never)
驱逐/节点关闭
Pending
Running
Failed
Succeeded
Kubelet 侧状态转换:
-
ADD → dispatchWork(SyncPodCreate)
-
syncPod → generateAPIPodStatus
-
canAdmitPod → Admit/Reject
-
containerRuntime.SyncPod
运行中状态维持: -
PLEG 周期性检测容器变化
-
探针持续检查健康状态
-
SyncLoop 定期全量同步
4.2 Pod 配置操作类型
go
const (
SET PodOperation = iota // 全量设置(初始化时)
ADD // 新增 Pod
DELETE // 优雅删除
REMOVE // 直接移除
UPDATE // 更新
RECONCILE // 状态调和
)
4.3 SyncPodType 类型
go
const (
SyncPodSync SyncPodType = iota // 周期性同步
SyncPodUpdate // 配置源更新
SyncPodCreate // 首次创建
SyncPodKill // 内部触发 Kill(驱逐)
)
4.4 Pod 生命周期事件处理图
ProbeManager PLEG StatusManager ContainerRuntime PodWorker SyncLoop PodConfig API Server ProbeManager PLEG StatusManager ContainerRuntime PodWorker SyncLoop PodConfig API Server #mermaid-svg-pq5Ek96tujDz4EA2{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-pq5Ek96tujDz4EA2 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-pq5Ek96tujDz4EA2 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-pq5Ek96tujDz4EA2 .error-icon{fill:#552222;}#mermaid-svg-pq5Ek96tujDz4EA2 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-pq5Ek96tujDz4EA2 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-pq5Ek96tujDz4EA2 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-pq5Ek96tujDz4EA2 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-pq5Ek96tujDz4EA2 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-pq5Ek96tujDz4EA2 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-pq5Ek96tujDz4EA2 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-pq5Ek96tujDz4EA2 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-pq5Ek96tujDz4EA2 .marker.cross{stroke:#333333;}#mermaid-svg-pq5Ek96tujDz4EA2 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-pq5Ek96tujDz4EA2 p{margin:0;}#mermaid-svg-pq5Ek96tujDz4EA2 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-pq5Ek96tujDz4EA2 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-pq5Ek96tujDz4EA2 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-pq5Ek96tujDz4EA2 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-pq5Ek96tujDz4EA2 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-pq5Ek96tujDz4EA2 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-pq5Ek96tujDz4EA2 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-pq5Ek96tujDz4EA2 .sequenceNumber{fill:white;}#mermaid-svg-pq5Ek96tujDz4EA2 #sequencenumber{fill:#333;}#mermaid-svg-pq5Ek96tujDz4EA2 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-pq5Ek96tujDz4EA2 .messageText{fill:#333;stroke:none;}#mermaid-svg-pq5Ek96tujDz4EA2 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-pq5Ek96tujDz4EA2 .labelText,#mermaid-svg-pq5Ek96tujDz4EA2 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-pq5Ek96tujDz4EA2 .loopText,#mermaid-svg-pq5Ek96tujDz4EA2 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-pq5Ek96tujDz4EA2 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-pq5Ek96tujDz4EA2 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-pq5Ek96tujDz4EA2 .noteText,#mermaid-svg-pq5Ek96tujDz4EA2 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-pq5Ek96tujDz4EA2 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-pq5Ek96tujDz4EA2 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-pq5Ek96tujDz4EA2 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-pq5Ek96tujDz4EA2 .actorPopupMenu{position:absolute;}#mermaid-svg-pq5Ek96tujDz4EA2 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-pq5Ek96tujDz4EA2 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-pq5Ek96tujDz4EA2 .actor-man circle,#mermaid-svg-pq5Ek96tujDz4EA2 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-pq5Ek96tujDz4EA2 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} altADDUPDATEDELETEREMOVE Watch 事件 (Pod ADD/UPDATE/DELETE)updates chan → PodUpdate{Op, Pods, Source}syncLoopIteration() selectHandlePodAdditions(pods)podManager.AddPod(pod)canAdmitPod() 准入检查dispatchWork(SyncPodCreate)HandlePodUpdates(pods)podManager.UpdatePod(pod)dispatchWork(SyncPodUpdate)HandlePodUpdates(pods) 当UPDATE处理dispatchWork(SyncPodUpdate)HandlePodRemoves(pods)podManager.DeletePod(pod)deletePod(pod) → podKiller.KillPod()managePodLoop()syncPod() → containerRuntime.SyncPod()SetPodStatus()Patch Pod Status周期性 relist (1s)plegCh → ContainerStarted/ContainerDiedHandlePodSyncs()执行 Liveness/Readiness/StartuplivenessManager.Updates()HandlePodSyncs()SetContainerReadiness/SetContainerStartup
4.5 Pod 准入处理器链
Pod 准入由一系列 PodAdmitHandler 串行执行,任一 Handler 拒绝则 Pod 不被运行:
#mermaid-svg-yCrBMxwBBuV0gX0e{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yCrBMxwBBuV0gX0e .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yCrBMxwBBuV0gX0e .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yCrBMxwBBuV0gX0e .error-icon{fill:#552222;}#mermaid-svg-yCrBMxwBBuV0gX0e .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yCrBMxwBBuV0gX0e .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yCrBMxwBBuV0gX0e .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yCrBMxwBBuV0gX0e .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yCrBMxwBBuV0gX0e .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yCrBMxwBBuV0gX0e .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yCrBMxwBBuV0gX0e .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yCrBMxwBBuV0gX0e .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yCrBMxwBBuV0gX0e .marker.cross{stroke:#333333;}#mermaid-svg-yCrBMxwBBuV0gX0e svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yCrBMxwBBuV0gX0e p{margin:0;}#mermaid-svg-yCrBMxwBBuV0gX0e .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yCrBMxwBBuV0gX0e .cluster-label text{fill:#333;}#mermaid-svg-yCrBMxwBBuV0gX0e .cluster-label span{color:#333;}#mermaid-svg-yCrBMxwBBuV0gX0e .cluster-label span p{background-color:transparent;}#mermaid-svg-yCrBMxwBBuV0gX0e .label text,#mermaid-svg-yCrBMxwBBuV0gX0e span{fill:#333;color:#333;}#mermaid-svg-yCrBMxwBBuV0gX0e .node rect,#mermaid-svg-yCrBMxwBBuV0gX0e .node circle,#mermaid-svg-yCrBMxwBBuV0gX0e .node ellipse,#mermaid-svg-yCrBMxwBBuV0gX0e .node polygon,#mermaid-svg-yCrBMxwBBuV0gX0e .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yCrBMxwBBuV0gX0e .rough-node .label text,#mermaid-svg-yCrBMxwBBuV0gX0e .node .label text,#mermaid-svg-yCrBMxwBBuV0gX0e .image-shape .label,#mermaid-svg-yCrBMxwBBuV0gX0e .icon-shape .label{text-anchor:middle;}#mermaid-svg-yCrBMxwBBuV0gX0e .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yCrBMxwBBuV0gX0e .rough-node .label,#mermaid-svg-yCrBMxwBBuV0gX0e .node .label,#mermaid-svg-yCrBMxwBBuV0gX0e .image-shape .label,#mermaid-svg-yCrBMxwBBuV0gX0e .icon-shape .label{text-align:center;}#mermaid-svg-yCrBMxwBBuV0gX0e .node.clickable{cursor:pointer;}#mermaid-svg-yCrBMxwBBuV0gX0e .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yCrBMxwBBuV0gX0e .arrowheadPath{fill:#333333;}#mermaid-svg-yCrBMxwBBuV0gX0e .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yCrBMxwBBuV0gX0e .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yCrBMxwBBuV0gX0e .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yCrBMxwBBuV0gX0e .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yCrBMxwBBuV0gX0e .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yCrBMxwBBuV0gX0e .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yCrBMxwBBuV0gX0e .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yCrBMxwBBuV0gX0e .cluster text{fill:#333;}#mermaid-svg-yCrBMxwBBuV0gX0e .cluster span{color:#333;}#mermaid-svg-yCrBMxwBBuV0gX0e div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yCrBMxwBBuV0gX0e .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yCrBMxwBBuV0gX0e rect.text{fill:none;stroke-width:0;}#mermaid-svg-yCrBMxwBBuV0gX0e .icon-shape,#mermaid-svg-yCrBMxwBBuV0gX0e .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yCrBMxwBBuV0gX0e .icon-shape p,#mermaid-svg-yCrBMxwBBuV0gX0e .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yCrBMxwBBuV0gX0e .icon-shape .label rect,#mermaid-svg-yCrBMxwBBuV0gX0e .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yCrBMxwBBuV0gX0e .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yCrBMxwBBuV0gX0e .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yCrBMxwBBuV0gX0e :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Admit
Admit
Reject
Reject
Reject
Pod
Eviction AdmitHandler
(资源压力检查)
Sysctl Whitelist
(安全Sysctl检查)
CPU/Memory/Topology
AllocateResourcesAdmitHandler
(资源分配准入)
PredicateAdmitHandler
(节点条件/优先级抢占)
AppArmor AdmitHandler
NoNewPrivs AdmitHandler
ProcMount AdmitHandler
Pod 可以运行
Pod 被阻塞
Reason=Blocked