4. kubelet 与 CRI shim 交互原理:kubelet 内部架构、CRI 请求路由、Streaming API 机制

kubelet 是 Kubernetes 节点上最核心的代理组件,负责管理 Pod 生命周期、容器健康检查、资源监控与上报。在容器运行时治理控制面中,kubelet 通过 CRI(Container Runtime Interface)与各类运行时 shim 交互,实现容器创建、启动、停止、删除等操作。本章深入剖析 kubelet 内部架构、CRI 请求在 kubelet 中的路由路径,以及 Streaming API 的建立与数据流转机制。

4.1 kubelet 内部架构概览

kubelet 内部采用模块化设计,核心模块包括 Pod 管理、容器运行时管理、卷管理、网络管理、状态上报等。与 CRI shim 交互的关键模块是 Container Runtime Manager 和 CRI Client。

架构要点: kubelet 不直接调用容器运行时(如 containerd、CRI-O),而是通过 gRPC 客户端调用 CRI shim 暴露的 Unix Socket 或 TCP 端口。这种解耦设计使得 kubelet 无需关心底层运行时实现细节。
kubelet 内部架构与 CRI 交互模块 kubelet 主进程 Pod Manager Volume Manager Network Manager Container Runtime Manager Status Manager PLEG (Pod Lifecycle Event Generator) CRI Client gRPC 客户端 Unix Socket / TCP RuntimeService ImageService CRI shim containerd / CRI-O / Docker Shim gRPC Server Runtime Service Image Service 说明 • Container Runtime Manager 是 kubelet 内部调用 CRI 的入口模块 • CRI Client 封装 gRPC 连接,负责序列化/反序列化 CRI 请求 • CRI shim 运行在独立进程中,通过 Unix Socket 与 kubelet 通信

4.2 CRI 请求路由路径

当 kubelet 需要创建或管理容器时,请求经过以下路由路径:

  1. Pod Manager 从 API Server 接收到 Pod 更新事件,触发 SyncPod 流程。
  2. Container Runtime Manager 调用 RuntimeServiceClient 的对应方法(如 RunPodSandbox、CreateContainer、StartContainer)。
  3. CRI Client 将请求序列化为 Protocol Buffers 格式,通过 gRPC 发送到 CRI shim 的 Unix Socket。
  4. CRI shim 的 gRPC Server 接收请求,反序列化后调用底层运行时接口执行实际操作。
  5. 响应沿原路径返回,最终更新 kubelet 内部状态。
CRI 核心请求路由对照表
CRI 方法 kubelet 调用模块 CRI shim 处理模块 底层操作
RunPodSandbox Container Runtime Manager Runtime Service 创建 Pod 网络命名空间、cgroup 等
CreateContainer Container Runtime Manager Runtime Service 准备容器镜像、配置容器 spec
StartContainer Container Runtime Manager Runtime Service 启动容器进程
ExecSync Container Runtime Manager Runtime Service 在容器内同步执行命令
PullImage Image Manager Image Service 拉取容器镜像
ListImages Image Manager Image Service 列出本地镜像列表
关键设计: CRI 请求路由采用同步阻塞模型。kubelet 在发送 CRI 请求后会等待 gRPC 响应,超时时间由 --runtime-request-timeout 参数控制(默认 2 分钟)。对于长时间操作(如镜像拉取),CRI shim 应在超时前返回进度信息。

4.3 Streaming API 机制

CRI 定义了 Streaming API 用于处理需要流式数据传输的场景,包括 Exec、Attach、PortForward。这些操作不适合通过标准的 gRPC 单向调用实现,因为需要双向实时数据流。

4.3.1 Streaming API 架构

Streaming API 采用 分离式架构:kubelet 通过 CRI 获取流式会话的 URL,然后 kubelet 或 kube-apiserver 直接与该 URL 建立 WebSocket 连接,数据不经过 CRI shim 的 gRPC 通道。

Streaming API 架构与数据流 kubelet CRI Client Streaming 代理 CRI shim Streaming Server (独立 HTTP 服务) 容器运行时 容器进程 stdin/stdout/stderr kubectl / 用户 WebSocket gRPC: Exec/Attach 进程 I/O 直接 WebSocket 数据流

4.3.2 Streaming API 交互流程

以 kubectl exec 为例,Streaming API 的完整交互流程如下:

  1. kubectl 发起请求: 用户执行 kubectl exec -it <pod> -- /bin/bash,kubectl 向 kube-apiserver 发送子资源请求 /api/v1/namespaces/<ns>/pods/<pod>/exec。
  2. kube-apiserver 转发: API Server 将请求转发到 kubelet 的 /exec 端点(通过 Node 代理或直接连接)。
  3. kubelet 调用 CRI: kubelet 调用 RuntimeService.Exec 方法,传入容器 ID、命令、终端设置等参数。
  4. CRI shim 返回 URL: CRI shim 的 Streaming Server 创建一个会话,返回一个唯一的 WebSocket URL(如 http://<node-ip>:<port>/exec/<session-id>)。
  5. kubelet 升级连接: kubelet 将 HTTP 连接升级为 WebSocket,并将数据流代理到 CRI shim 返回的 URL。
  6. 数据双向传输: 用户输入通过 WebSocket → kubelet → CRI shim → 容器进程 stdin;容器 stdout/stderr 沿反向路径返回。
安全注意事项: Streaming Server 默认监听在 127.0.0.1:0(随机端口),仅允许本地回环地址访问。kubelet 通过 --streaming-connection-idle-timeout 参数控制空闲连接超时(默认 4 小时),防止资源泄漏。生产环境中建议启用 TLS 加密 Streaming 通信。

4.3.3 Streaming API 关键参数

CRI Streaming API 关键配置参数
参数 默认值 说明
StreamServerPort 0(随机分配) Streaming Server 监听端口
StreamIdleTimeout 4h 空闲连接超时时间
StreamServerMaxConcurrentStreams 100 最大并发流数量
EnableTLS false 是否启用 TLS 加密
TLSCertFile "" TLS 证书文件路径
TLSKeyFile "" TLS 私钥文件路径

4.4 CRI 请求超时与重试机制

kubelet 对 CRI 请求实现了完善的超时控制和重试策略:

  • 全局超时: --runtime-request-timeout 控制所有 CRI 请求的超时时间,默认 2 分钟。
  • 操作级超时: 特定操作(如 PullImage)可以设置更长的超时,通过 CRI 请求的 timeout 字段传递。
  • 重试策略: 对于可重试的错误(如网络抖动、临时资源不足),kubelet 使用指数退避算法重试,最大重试次数为 3 次。
  • 背压机制: 当 CRI shim 返回 Unavailable 状态码时,kubelet 会降低请求速率,避免雪崩效应。
// kubelet CRI 客户端重试逻辑示例(简化)
func (c *remoteRuntimeService) exec(ctx context.Context, req *runtimeapi.ExecRequest) (*runtimeapi.ExecResponse, error) {
    var resp *runtimeapi.ExecResponse
    err := retry.OnError(retry.DefaultBackoff, func(err error) bool {
        return grpcStatus.Code(err) == codes.Unavailable
    }, func() error {
        var err error
        resp, err = c.runtimeClient.Exec(ctx, req)
        return err
    })
    return resp, err
}

4.5 性能与调优建议

生产环境调优要点:
  • gRPC 连接复用: kubelet 与 CRI shim 之间保持长连接,避免频繁建立/断开连接的开销。
  • Streaming 端口范围: 如果使用防火墙策略,需要开放 Streaming Server 的动态端口范围(通常 10250-10255)。
  • 超时设置: 对于大规模集群,适当增加 --runtime-request-timeout 到 3-5 分钟,避免大规模镜像拉取超时。
  • 监控指标: 关注 kubelet 暴露的 kubelet_runtime_operations_duration_seconds 指标,识别慢操作。

通过理解 kubelet 内部架构、CRI 请求路由路径和 Streaming API 机制,运维人员可以更有效地诊断容器运行时相关问题,优化集群性能,并确保生产环境的稳定性。