1. kubelet
kubelet 是 Kubernetes 集群中在每个工作节点上运行的代理。它是 Kubernetes 的“节点代理”,是 Master 节点(控制平面)与 Node 节点(工作节点)之间通信的桥梁,也是维护 Pod 生命周期最核心、最直接的组件。
kubelet 的主要作用:
- Pod 生命周期管理:这是 kubelet 最核心的职责。它通过监听 API Server 或本地静态 Pod 配置文件来获取分配给当前节点的 Pod 清单,并确保这些 Pod 都处于期望的状态(“期望状态”由 API Server 中的 Pod 定义决定)。
- 创建 Pod: 当有新的 Pod 被调度到该节点时,kubelet 会执行一系列操作:
- 向容器运行时(如 containerd, CRI-O)发起请求,拉取所需的容器镜像。
- 根据 Pod 定义(
spec.containers
)配置容器(如挂载卷、设置网络命名空间、设置资源限制等)。 - 启动容器。
- 维护 Pod: 持续监控运行中容器的状态,确保它们健康运行。如果容器崩溃,kubelet 会根据 Pod 的
restartPolicy
重启它。 - 终止 Pod: 当 Pod 被从 API Server 中删除(例如,由于副本数减少或节点被驱逐),kubelet 会接收到通知,并优雅地终止 Pod 中的容器,释放资源。
- 创建 Pod: 当有新的 Pod 被调度到该节点时,kubelet 会执行一系列操作:
- 与容器运行时交互:kubelet 不直接操作容器,而是通过 CRI 与容器运行时进行交互。
- CRI: 容器运行时接口。这是一个插件接口,它使得 kubelet 能够使用不同的容器运行时,而无需重新编译。kubelet 通过 gRPC 协议与 CRI 实现(即容器运行时)通信,执行诸如创建/停止容器、拉取镜像等操作。
- 容器健康检查:kubelet 负责执行 Pod 中定义的探针,并根据结果采取行动。
- 存活探针: 检测容器应用是否还在运行。如果失败,kubelet 会重启容器。
- 就绪探针: 检测容器应用是否已准备好接收流量。如果失败,kubelet 会将该 Pod 从关联的 Service 的 Endpoints 中移除,停止向其发送流量。
- 启动探针: 用于保护慢启动容器。在启动探针成功之前,其他探针都不会启动。
- 资源监控与报告
- 节点状态上报: 定期向 API Server 报告当前节点的状态,包括:
- Node Condition:
Ready
,MemoryPressure
,DiskPressure
,PIDPressure
等。 - 资源容量: CPU、内存、可分配 Pod 数量的上限。
- 节点信息: 内核版本、容器运行时版本、OS 类型等。
- Node Condition:
- Pod 状态上报: 定期报告节点上每个 Pod 的状态(
Pending
,Running
,Succeeded
,Failed
等)和事件。
- 节点状态上报: 定期向 API Server 报告当前节点的状态,包括:
- 管理容器网络:kubelet 不直接配置网络,但它负责在 Pod 启动前为其创建网络命名空间(
netns
),并调用 CNI 插件来为这个netns
配置网络(分配 IP、设置路由等)。- CNI: 容器网络接口。和 CRI 类似,也是一个标准接口,kubelet 通过调用配置好的 CNI 插件(如 Calico, Flannel, Cilium 等)来管理 Pod 网络。
- 管理存储:kubelet 负责按照 Pod 定义,在容器启动前将指定的存储卷(Volume)挂载到容器中。
- 它支持多种类型的 Volume:
emptyDir
,hostPath
,configMap
,secret
,persistentVolumeClaim
等。 - 对于
persistentVolumeClaim
,kubelet 会与 CSI 驱动交互,执行实际的挂载(Attach)和格式化/挂载(Mount)操作。
- 它支持多种类型的 Volume:
- 静态 Pod 管理:kubelet 可以独立于 API Server 运行一种特殊的 Pod,称为静态 Pod。
- 来源: 静态 Pod 的配置文件(YAML/JSON)直接存放在节点上的特定目录中(如
/etc/kubernetes/manifests
)。 - 管理方式: kubelet 会监视这个目录,一旦发现有文件,就会自动创建和管理对应的 Pod。
- 典型应用: 用于部署控制平面组件本身,例如
kube-apiserver
,kube-controller-manager
,kube-scheduler
。
- 来源: 静态 Pod 的配置文件(YAML/JSON)直接存放在节点上的特定目录中(如
关键特性与概念:
- 节点自注册: 当 kubelet 启动时,可以通过
--register-node
参数决定是否向 API Server 注册自己。注册时可以提供节点信息(如 IP 地址、资源容量、操作系统等)。 - API Server 交互: kubelet 使用 HTTPS 路径与 API Server 通信(需要有效的客户端证书或令牌进行认证),获取 Pod 清单并上报状态。
- 主控节点高可用: kubelet 可以配置为与多个 API Server 通信,以实现高可用。通过
--kubeconfig
指定包含多个服务器地址的配置文件。 - 驱逐机制: 当节点出现资源压力(如内存不足、磁盘空间不足)时,kubelet 会主动驱逐节点上的 Pod 以保护节点。驱逐策略是可配置的,kubelet 会优先驱逐优先级低且资源使用量超过请求值的 Pod。
- 垃圾回收机制:kubelet 的 GC 机制会负责定期清理工作节点上的镜像以及退出的容器。
- 容器垃圾回收
- 触发机制
- 基于逐出: 当 kubelet 检测到节点的磁盘空间面临压力时(具体是
imagefs
或nodefs
的使用率超过高水位线),它会首先尝试驱逐 Pod 来释放空间。Pod 被驱逐后,其关联的容器就会停止,从而成为容器 GC 的清理目标。 - 基于周期: kubelet 也会定期执行容器清理,无论磁盘压力如何。它会扫描所有容器,并删除那些已退出运行一段时间(可配置)的容器。
- 基于逐出: 当 kubelet 检测到节点的磁盘空间面临压力时(具体是
- 核心配置参数:这些参数通常在 kubelet 的启动参数中配置(也可以通过 ConfigMap 设置)。
--eviction-hard
/--eviction-soft
: 驱逐阈值。定义何时触发磁盘压力并开始驱逐 Pod。这是触发 GC 的主要驱动力。- 例如:
--eviction-hard=memory.available<100Mi,nodefs.available<10%,imagefs.available<15%
- 例如:
--maximum-dead-containers
: 最大保留的死亡容器数量。默认值为-1
,表示禁用此限制,使用--minimum-container-ttl
。建议设置为一个正数(如1
或2
)以便更直接地控制。--maximum-dead-containers-per-container
: 每个容器实例最大保留的死亡容器数量。例如,一个总是崩溃重启的 Pod,这个设置可以限制它留下的旧容器实例的数量。优先级高于--maximum-dead-containers
。--minimum-container-ttl
: 死亡容器的最小存活时间。一个已停止的容器至少需要存活这么长时间才会被 GC 清理。默认是0s
,意味着一旦死亡就可能被回收。通常与maximum-dead-containers
配合使用。
- 清理策略:Kubelet 会优先清理最老的死亡容器。它会根据容器的创建时间戳进行排序,然后从最老的开始删除,直到满足配置的约束条件(例如,死亡容器数量低于
maximum-dead-containers
)。
- 触发机制
- 镜像垃圾回收
- 触发机制
- 基于逐出: 同样是当
imagefs
的使用率超过高水位线时,kubelet 在驱逐 Pod 的同时,也会触发镜像 GC。 - 基于周期: kubelet 会定期(每 5 分钟)检查
imagefs
的磁盘使用情况,并自动执行镜像清理以尝试将使用率保持在目标百分比以下。
- 基于逐出: 同样是当
- 核心配置参数
--image-gc-high-threshold
: 镜像GC高水位线。imagefs
使用率的百分比阈值。当使用率超过此值时,kubelet 会主动触发镜像垃圾回收。默认值为 85%。--image-gc-low-threshold
: 镜像GC低水位线。镜像垃圾回收的目标。GC 会一直删除镜像,直到imagefs
使用率降低到此阈值。默认值为 80%。
- 清理策略
- 排序: 将所有未被引用的镜像(悬空镜像)按最后被使用的时间戳进行排序。
- 删除: 从最老最久未被使用的镜像开始删除,直到磁盘使用率降到
--image-gc-low-threshold
设定的目标值为止。 - 如果清理悬空镜像后,磁盘使用率仍然高于
low-threshold
,Kubelet 会开始删除正在被使用的镜像(Active Images)。
- 触发机制
- 容器垃圾回收
2. kube-proxy
为了支持集群的水平扩展和高可用,k8s 抽象出了 Service 的概念。Service 是对一组 Pod 的抽象,它会根据访问策略(如负载均衡策略)来访问这组 Pod。但 Service 只是一个概念,真正落实 Service 作用的是它背后的 kube-proxy。简单来说,kube-proxy 的核心职责就是:将发往 Service 的流量(虚拟IP+端口)负载均衡并转发到后端正确的 Pod(真实IP+端口)上。
kube-proxy 监听 API Server 中 Service 和 Endpoint(或 EndpointSlice)的变化,并实时配置本机的网络规则,使得对 ClusterIP:Port
的请求能被透明地转发到实际的 PodIP:Port
。