kubelet 深度解析:节点上的 Pod 管家
1. kubelet 的核心职责
kubelet 是运行在每个 Worker Node 上的节点代理,是 Kubernetes 与容器运行时之间的桥梁:
1 2 3 4 5 6 7 8 9 10 11
| kube-apiserver │ │ Watch Pod 分配 ▼ kubelet │ ├── 通过 CRI 管理容器生命周期 ├── 通过 CNI 配置 Pod 网络 ├── 通过 CSI 挂载存储卷 ├── 上报节点状态和 Pod 状态 └── 执行健康检查(Probe)
|
2. kubelet 架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| ┌─────────────────────────────────────────────────────────┐ │ kubelet │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │ │ PodManager │ │ ProbeManager│ │ StatusManager │ │ │ └─────────────┘ └─────────────┘ └─────────────────┘ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │ │ │VolumeManager│ │ ImageGC │ │ ContainerGC │ │ │ └─────────────┘ └─────────────┘ └─────────────────┘ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ PLEG(Pod Lifecycle Event Generator)│ │ │ └─────────────────────────────────────────────────┘ │ │ │ │ │ CRI gRPC API │ │ │ │ └──────────────────────────┼──────────────────────────────┘ │ ┌──────┴──────┐ │ containerd │ └─────────────┘
|
3. Pod 生命周期管理
3.1 Pod 创建流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| 1. kubelet Watch 到新 Pod 分配到本节点 │ 2. 准备 Pod 沙箱(Sandbox) - 创建 pause 容器(infra container) - 配置网络(调用 CNI) │ 3. 拉取镜像(并行拉取所有容器镜像) │ 4. 启动 Init 容器(按顺序,前一个成功才启动下一个) │ 5. 启动业务容器(并行启动) │ 6. 执行 PostStart Hook(如果配置了) │ 7. 开始健康检查(startupProbe → livenessProbe + readinessProbe) │ 8. Pod 进入 Running 状态
|
3.2 Pod 终止流程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| kubectl delete pod / 驱逐 / 节点关闭 │ 1. Pod 状态变为 Terminating 从 Service Endpoints 中移除(停止接收流量) │ 2. 执行 PreStop Hook(如果配置了) │ 3. 发送 SIGTERM 信号给容器主进程 │ 4. 等待 terminationGracePeriodSeconds(默认 30s) │ 5. 超时后发送 SIGKILL 强制终止 │ 6. 清理网络(调用 CNI DEL) 7. 清理存储卷 8. 删除 Pod 对象
|
3.3 优雅终止最佳实践
1 2 3 4 5 6 7 8 9
| spec: terminationGracePeriodSeconds: 60 containers: - name: app lifecycle: preStop: exec: command: ["/bin/sh", "-c", "sleep 5"]
|
4. PLEG(Pod Lifecycle Event Generator)
PLEG 是 kubelet 的核心组件,负责感知容器状态变化:
1 2 3 4 5 6 7 8 9 10 11
| PLEG 每 1s 轮询一次容器运行时 │ ▼ 对比上次状态,生成事件: - ContainerStarted - ContainerDied - ContainerRemoved - ContainerChanged │ ▼ 触发 Pod 同步(syncPod)
|
PLEG is not healthy
这是 kubelet 最常见的报错之一:
1 2 3 4 5 6 7 8 9 10 11
| PLEG is not healthy: pleg was last seen active 3m0s ago; threshold is 3m0s
1. 容器运行时(containerd/docker)响应慢 2. 节点负载过高,kubelet 无法及时轮询 3. 大量容器同时启停
journalctl -u kubelet -f crictl ps
|
5. CRI(Container Runtime Interface)
CRI 是 kubelet 与容器运行时之间的标准接口(gRPC):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| kubelet │ │ gRPC ▼ CRI Runtime(containerd / CRI-O) │ ├── RuntimeService(管理 Pod 和容器) │ ├── RunPodSandbox │ ├── StopPodSandbox │ ├── CreateContainer │ ├── StartContainer │ ├── StopContainer │ └── ExecSync │ └── ImageService(管理镜像) ├── PullImage ├── ListImages └── RemoveImage
|
containerd 架构
1 2 3 4 5 6 7
| kubelet ──CRI gRPC──▶ containerd │ containerd-shim │ runc(OCI 运行时) │ 容器进程
|
常用 crictl 命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| crictl ps -a
crictl pods
crictl logs <container-id>
crictl exec -it <container-id> sh
crictl images
crictl pull nginx:latest
crictl inspect <container-id>
|
6. 健康检查(Probe)
6.1 三种 Probe
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| spec: containers: - name: app startupProbe: httpGet: path: /healthz port: 8080 failureThreshold: 30 periodSeconds: 10 livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 10 periodSeconds: 10 failureThreshold: 3 timeoutSeconds: 5 readinessProbe: httpGet: path: /ready port: 8080 periodSeconds: 5 failureThreshold: 3
|
6.2 Probe 类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| httpGet: path: /healthz port: 8080 httpHeaders: - name: Authorization value: Bearer token
tcpSocket: port: 3306
exec: command: - cat - /tmp/healthy
grpc: port: 9090 service: liveness
|
6.3 Probe 最佳实践
1 2 3 4 5 6 7 8 9 10 11 12
|
livenessProbe: exec: command: ["pgrep", "myapp"]
readinessProbe: httpGet: path: /ready port: 8080
|
7. 资源管理
7.1 资源请求与限制
1 2 3 4 5 6 7
| resources: requests: cpu: "250m" memory: "256Mi" limits: cpu: "1" memory: "512Mi"
|
7.2 QoS 等级
kubelet 根据资源配置将 Pod 分为三个 QoS 等级:
| QoS 等级 |
条件 |
驱逐优先级 |
| Guaranteed |
requests == limits(所有容器) |
最后驱逐 |
| Burstable |
部分容器设置了 requests/limits |
中间 |
| BestEffort |
没有设置任何 requests/limits |
最先驱逐 |
1 2 3 4 5 6 7 8
| resources: requests: cpu: "1" memory: "1Gi" limits: cpu: "1" memory: "1Gi"
|
7.3 节点资源预留
1 2 3 4
| --kube-reserved=cpu=200m,memory=500Mi,ephemeral-storage=1Gi --system-reserved=cpu=200m,memory=500Mi --eviction-hard=memory.available<100Mi,nodefs.available<10%
|
1 2 3 4 5
| 节点总资源 ├── kube-reserved(K8s 组件预留) ├── system-reserved(OS 预留) ├── eviction-threshold(驱逐阈值) └── Allocatable(可分配给 Pod)
|
7.4 驱逐机制
1 2 3 4 5 6 7 8
| --eviction-soft=memory.available<200Mi --eviction-soft-grace-period=memory.available=1m30s
--eviction-hard=memory.available<100Mi,nodefs.available<5%
|
8. 节点状态上报
kubelet 定期向 apiserver 上报节点状态:
1 2 3 4 5
| --node-status-update-frequency=10s
--node-lease-duration-seconds=40
|
节点条件(Node Conditions)
1 2 3 4 5 6 7
| kubectl describe node <node-name>
|
9. Static Pod
Static Pod 由 kubelet 直接管理,不经过 apiserver:
1 2 3 4 5 6 7 8 9
| /etc/kubernetes/manifests/
ls /etc/kubernetes/manifests/
|
Static Pod 的特点:
- kubelet 直接读取 YAML 文件创建 Pod
- apiserver 中会有对应的 Mirror Pod(只读)
- 节点重启后自动恢复
10. 镜像垃圾回收
1 2 3 4
| --image-gc-high-threshold=85 --image-gc-low-threshold=80 --minimum-image-ttl-duration=2m
|
11. 常见问题排查
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| journalctl -u kubelet -f --since "10 minutes ago"
kubectl describe node <node-name>
kubectl describe pod <pod-name>
systemctl status containerd crictl info
cat /var/lib/kubelet/config.yaml
kubectl top node <node-name>
|
12. 总结
kubelet 是 Kubernetes 节点层面的核心组件:
- Pod 生命周期:从创建到终止的全程管理
- CRI 接口:与容器运行时解耦,支持 containerd/CRI-O
- 健康检查:三种 Probe 保障应用可用性
- 资源管理:QoS 等级、驱逐机制保障节点稳定
- 状态上报:实时向 apiserver 同步节点和 Pod 状态
- Static Pod:控制平面组件的自举机制