K8s 之所以能成为云原生的「操作系统」,靠的就是这套可插拔的接口设计。搞懂 CNI、CSI、CRI、LB,你对 K8s 架构的理解会上一个台阶。
一、K8s 的四大核心接口是什么
CNI、CSI、CRI 是 Kubernetes 的三大核心扩展接口,分别定义了网络、存储、运行时的标准。它们的设计哲学一致:K8s 只定义接口,具体实现交给插件。
LB(Load Balancer)则不同------它不是 K8s 的内部接口,而是 Service 的一种对外暴露方式,通常依赖云厂商的负载均衡器或软件实现(如 MetalLB)。
1. 为什么需要这些接口
K8s 作为一个容器编排平台,面临三个必须解决的底层问题:
- 网络:Pod 怎么分配 IP?Pod 之间怎么通信?跨节点怎么路由?
- 存储:Pod 重启后数据怎么保留?怎么对接外部存储系统?
- 运行时:容器由谁来创建、启停、销毁?
如果 K8s 把这些能力硬编码进内核,就会跟特定实现绑死。通过定义标准接口,任何符合规范的插件都能接入------这就是「可插拔架构」的核心价值。
┌─────────────────────────────────────────────────────┐
│ Kubernetes API │
├──────────────┬──────────────┬────────────────────────┤
│ CNI │ CSI │ CRI │
│ (网络接口) │ (存储接口) │ (运行时接口) │
├──────────────┼──────────────┼────────────────────────┤
│ Calico │ Ceph CSI │ containerd │
│ Flannel │ NFS CSI │ CRI-O │
│ Cilium │ 云盘 CSI │ Docker (已废弃) │
└──────────────┴──────────────┴────────────────────────┘
二、CNI --- 容器网络接口
1. 什么是 CNI
CNI(Container Network Interface)定义的是容器网络的标准。它的核心职责:
- 为每个 Pod 分配独立的 IP 地址
- 让同一集群内任意两个 Pod 能够直接通信(无需 NAT)
- 让节点上的 kubelet 能够调用 CNI 插件完成网络配置
没有 CNI,Pod 就只能跟同一节点上的 Pod 通信,跨节点完全不通。
2. 主流 CNI 插件对比
| 插件 | 特点 | 适用场景 |
|---|---|---|
| Flannel | 架构简单,支持 VXLAN/host-gw,性能中等;VXLAN 模式下每次转发都要额外封包/解包 | 测试/小规模集群 |
| Calico | BGP 路由协议实现纯三层路由转发,支持 NetworkPolicy(Pod 级别防火墙),性能优秀 | 生产环境首选 |
| Cilium | 基于 eBPF,高性能,L7 可见性,支持 Service Mesh | 高性能/安全要求高 |
| Weave | 支持加密,配置简单 | 中小型集群 |
| Kube-OVN | 基于 OVN/OVS,企业级 SDN 架构,VPC 多租户、Underlay 能力强,功能最全 | OpenShift / 大型集群 |
各插件一句话总结:
- Flannel:最简单、最轻量,只做网络连通,啥高级功能都没有
- Calico:纯三层路由 + BGP,性能强,NetworkPolicy 强,通用云原生首选
- Cilium:eBPF 加持,性能天花板最高,适合对网络性能和可观测性有极致要求的场景
- Kube-OVN:企业级 SDN 架构,VPC 多租户、Underlay 强、功能最全,灵雀云自家核心 CNI
3. 选型建议
| 场景 | 推荐 |
|---|---|
| 个人实验 / 最小集群 | Flannel |
| 通用生产环境 | Calico |
| 高安全 / 高性能要求 | Cilium |
| 大型企业 / 多租户 / OpenShift | Kube-OVN |
大多数中小团队的生产集群,Calico 是最稳妥的选择------功能完备、社区活跃、排坑资料多。
三、CSI --- 容器存储接口
1. 什么是 CSI
CSI(Container Storage Interface)是 K8s 与外部存储系统之间的标准接口。容器本身是无状态的------Pod 一删,数据就没了。CSI 让 Pod 能以标准化的方式挂载外部持久化存储,保障数据不丢失。
通过 CSI 接口对接第三方存储插件(如 NFS、CephFS、各云厂商云盘),实现存储卷的创建、挂载、卸载、删除。典型场景:数据库 Pod 的数据留存、日志持久化、共享文件存储。
2. 存储流程
一条完整的存储生命周期,涉及四个步骤:
2.1 用户创建 PVC
用户声明存储需求:大小(如 10Gi)、访问模式(ReadWriteOnce / ReadWriteMany)、指定 StorageClass。
2.2 PV Controller 创建 PV 并绑定
PV Controller 通过 StorageClass 调用 CSI 插件创建实际的存储资源(PV),并完成 PVC 与 PV 的绑定。
2.3 kubelet 挂载存储
Pod 被调度后,kubelet 调用 CSI 插件,将存储卷挂载到容器的指定路径。
2.4 Pod 删除时卸载
Pod 删除时,CSI 插件依次执行存储卸载、解绑操作。根据 PV 的回收策略(Retain / Delete / Recycle),决定底层存储是保留还是删除。
用户创建 PVC → PV Controller 调用 CSI 创建 PV → kubelet 挂载到 Pod → Pod 删除时 CSI 卸载
3. PV / PVC / StorageClass 详解
这是 K8s 存储体系里最容易搞混的三个概念,用一句话说清楚:
| 概念 | 角色 | 类比 |
|---|---|---|
| PV(PersistentVolume) | 集群中的实际存储资源 | 停车场的车位 |
| PVC(PersistentVolumeClaim) | 用户对存储的需求声明 | 停车券(我要一个车位) |
| StorageClass | 动态存储分配策略 | 自动泊车系统(按需分配) |
三种模式:
- 静态供给:管理员手动创建 PV,用户创建 PVC 后自动绑定匹配的 PV
- 动态供给:用户只创建 PVC + StorageClass,系统自动创建 PV 并绑定------这是大规模生产环境的标准做法
- StorageClass 的关键参数:provisioner(用哪个 CSI 插件)、reclaimPolicy(删除策略)、parameters(存储类型、IOPS 等)
yaml
# 一个典型的 StorageClass 示例
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: disk.csi.azure.com # ← CSI 插件
parameters:
skuName: Premium_LRS # ← 高性能 SSD
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
四、CRI --- 容器运行时接口
1. 什么是 CRI
CRI(Container Runtime Interface)是 K8s 与容器运行时之间的接口。控制平面(kubelet)通过 CRI 接口向容器运行时发送指令:创建容器、启动容器、停止容器、删除容器。
CNCF 推动了 CRI 的标准化,让 K8s 不再绑死某一种容器运行时。只要实现了 CRI 规范的运行时(containerd、CRI-O 等),都能无缝接入。
2. Docker 与 Containerd 区别
这是很多人搞混的点。K8s 1.20 起正式废弃 dockershim,1.24 起彻底移除。背后发生了什么?
| 对比维度 | Docker | Containerd |
|---|---|---|
| 定位 | 完整的容器工具链(构建、运行、编排) | 专注容器运行时 |
| 组件 | dockerd + containerd + runc | containerd + runc |
| 冗余 | 自带构建、compose、swarm 等 K8s 用不到的功能 | 只有 K8s 需要的运行能力 |
| 与 K8s 对接 | 需要 dockershim 适配层(已废弃) | 直接实现 CRI 接口 |
| 资源占用 | 较高 | 较低 |
| OCI 标准 | 通过 containerd 间接实现 | 原生支持 |
简单说:Docker 是个瑞士军刀,containerd 是那把刀。K8s 只需要刀,不需要军刀上那些开瓶器、剪刀。
生产环境推荐 containerd,理由有三:
- 稳定性更好(少一层 dockerd,少一个故障点)
- 资源占用更低(精简组件、少一个守护进程)
- 集群兼容性更好(所有主流 K8s 发行版默认 containerd)
五、LB --- 负载均衡器
1. 什么是 LB
LB(Load Balancer)不是 K8s 的内部接口,而是 Service 的一种对外暴露方式。它的作用:将外部流量分发到后端的多个 Pod 上,实现高可用和负载均衡。
2. Service 类型对比
K8s 的 Service 有四种类型,分别对应不同的流量暴露方式:
| 类型 | 访问范围 | IP 类型 | 典型场景 |
|---|---|---|---|
| ClusterIP | 集群内部 | 虚拟 IP | 微服务间调用 |
| NodePort | 节点 IP + 固定端口 | 节点 IP:30000-32767 | 测试/临时暴露 |
| LoadBalancer | 外部,通过云 LB | 云厂商分配公网/内网 IP | 生产环境对外服务 |
| ExternalName | DNS CNAME 映射 | 无独立 IP | 外部服务映射 |
3. LoadBalancer 的工作原理
LoadBalancer 类型的 Service 创建后,K8s 会调用云厂商的 Cloud Controller Manager(CCM),向云平台申请一个负载均衡器实例。云 LB 将流量转发到各节点的 NodePort 端口,再分发到 Pod。
自建集群怎么办?
如果集群不在公有云上(比如裸金属或自己搭的集群),没有云 LB 可用,就需要部署软件 LB:
- MetalLB:最常用的开源方案,支持 Layer2 和 BGP 模式
- OpenELB:青云开源的替代方案
- Traefik / Nginx Ingress:七层负载,适合 HTTP/HTTPS 流量
yaml
# 云环境下的 LoadBalancer Service
apiVersion: v1
kind: Service
metadata:
name: my-app
spec:
type: LoadBalancer # ← 云厂商会自动创建 LB
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
六、总结
把四者的关系放在一起看:
| 接口 | 解决什么问题 | 如果没有它 |
|---|---|---|
| CNI | Pod 网络:IP 分配、跨节点通信 | Pod 孤立,只能同节点通信 |
| CSI | 持久化存储:数据不随 Pod 销毁而丢失 | 数据库 Pod 重启数据全丢 |
| CRI | 容器管理:创建、启停、销毁容器 | K8s 不知道上哪跑容器 |
| LB | 流量入口:把外部流量均匀分给 Pod | 外面的人根本访问不到你的服务 |
一句话总结:
CNI 管网络,CSI 管存储,CRI 管容器,LB 管入口。搞懂这四个,K8s 的底层架构你就摸清了七成。