Kubernetes核心接口:CRI、CNI、CSI

引言:为什么需要标准化接口?

在 Kubernetes 的设计哲学中,"可插拔架构"是核心原则。CRI(容器运行时接口)、CNI(容器网络接口)、CSI(容器存储接口)三大标准接口实现了 控制平面与基础设施的解耦,使得:

  • 容器运行时可以自由选择(Docker/containerd/CRI-O)
  • 网络方案能够按需切换(Calico/Flannel/Cilium)
  • 存储系统得以灵活扩展(AWS EBS/NFS/分布式存储)

本篇学习k8s核心接口的 工作机制核心组件真实生产场景应用

一、CRI(Container Runtime Interface):容器运行时接口

1.1 CRI 的作用与定位

CRI 是 Kubelet 与容器运行时之间的 通信协议,负责:

  • 容器生命周期管理(创建/启动/停止)
  • 镜像下载与管理
  • 容器监控信息收集
1
2
3
4
+----------------+       gRPC       +-----------------+
| Kubelet | <=============> | CRI Runtime |
| (控制平面组件) | (CRI协议) | (如 containerd) |
+----------------+ +-----------------+

1.2 核心组件解析

  • PodSandbox:Pod 的运行环境(Linux Namespace 隔离)
  • ImageService:镜像拉取、删除、查询接口
  • RuntimeService:容器与沙箱管理接口

1.3 工作流程示例(创建 Pod)

  1. Kubelet 调用 RunPodSandbox 创建沙箱环境
  2. 依次调用 CreateContainer 创建每个容器
  3. 调用 StartContainer 启动容器进程

1.4 主流实现对比

运行时 特点 适用场景
containerd 轻量级,专注核心功能 生产环境首选
CRI-O 专为K8s设计,OCI兼容 OpenShift 默认运行时
Docker 通过dockershim兼容(已废弃) 旧版本兼容方案

二、CNI(Container Network Interface):容器网络接口

2.1 CNI 的核心职责

  • IP 地址分配:为每个 Pod 分配唯一 IP
  • 网络连通性:实现 Pod 间、Pod 与外部网络通信
  • 网络策略实施:通过插件实现网络隔离(如 NetworkPolicy)

2.2 插件工作流程

当 Pod 被创建时:

1
2
3
4
1. Kubelet 调用 CNI 插件                  
2. 插件配置 veth pair 连接容器与主机
3. 调用 IPAM 分配 IP(如 host-local)
4. 设置路由规则与 iptables 策略

2.3 常见插件类型

类型 代表实现 特点
Overlay Flannel VXLAN 跨主机网络,需要封装协议
BGP Calico 高性能,直接路由
eBPF Cilium 可观测性 + 高性能策略

2.4 多网络接口场景

1
2
3
4
5
6
7
8
// 多网络 CNI 配置示例
{
"name": "multi-network",
"plugins": [
{ "type": "macvlan", "master": "eth0" },
{ "type": "vlan", "id": 100 }
]
}

三、CSI(Container Storage Interface):容器存储接口

3.1 CSI 的架构分层

CSI 将存储管理分为三个核心服务:

1
2
3
4
5
6
7
8
+-------------------+       +-----------------------+
| Controller Plugin | <---> | 存储系统(如 Ceph) |
+-------------------+ +-----------------------+
^
| gRPC
+-------------------+
| Node Plugin | ---> 在节点挂载存储卷
+-------------------+

3.2 核心操作流程

  1. Provisioning:创建存储卷(CreateVolume
  2. Attaching:将卷挂载到节点(ControllerPublishVolume
  3. Mounting:将卷挂载到 Pod(NodePublishVolume

3.3 高级特性支持

特性 接口方法 应用场景
动态扩容 ControllerExpandVolume 在线调整存储大小
快照 CreateSnapshot 数据备份与恢复
拓扑感知 GetTopology 区域亲和性调度

3.4 开发 CSI 插件的关键步骤

  1. 实现 CSI Identity/Controller/Node 服务
  2. 部署 Sidecar 组件(external-provisioner、node-driver-registrar)
  3. 创建 StorageClass 定义存储类型

四、三大接口的协同工作

4.1 Pod 创建的全链路流程

1
2
3
4
1. Kubelet 通过 CRI 创建 PodSandbox
2. CNI 插件配置网络命名空间
3. CSI 插件挂载持久化存储卷
4. CRI 创建业务容器并加入沙箱

4.2 生产环境中的典型问题

  • CRI 性能瓶颈:容器启动延迟高 → 优化镜像拉取策略
  • CNI IP 耗尽:Pod 无法分配 IP → 调整 IPAM 配置
  • CSI 挂载失败:存储卷无法附加 → 检查 RBAC 权限

五、开发自定义插件指南

5.1 CRI 开发注意事项

  • 必须实现 CRI proto 定义的所有方法
  • 使用 crictl 工具进行调试
  • 集成 OCI 运行时(如 runc)

5.2 CNI 插件开发要点

1
2
3
4
5
6
7
// CNI 插件必须实现的命令
func cmdAdd(args *skel.CmdArgs) error {
// 1. 解析网络配置
// 2. 创建网络接口
// 3. 调用 IPAM 分配 IP
// 4. 返回 Result JSON
}

5.3 CSI 插件开发实践

  • 使用 CSI 规范仓库 生成代码框架
  • 实现必要的 gRPC 方法(至少 GET_VOLUME_INFO、CREATE_VOLUME)
  • 通过 csc 工具进行端到端测试

总结:构建云原生基础设施的基石

理解 CRI/CNI/CSI 不仅能够帮助运维人员 深度排查集群问题,更是开发者 扩展 Kubernetes 能力 的关键。随着云原生生态的发展,这些接口已成为连接上层应用与底层基础设施的核心纽带。

下一步学习建议

  1. 使用 minikube 实验不同容器运行时
  2. 开发一个简单的 CNI 插件实现固定 IP 分配
  3. 为本地存储实现 CSI 插件支持动态卷供给

延伸阅读

欢迎关注我的其它发布渠道