扩展接口(CNI/CSI/CRI)
Kubernetes 的三大扩展接口:容器网络接口(CNI)、容器存储接口(CSI)和容器运行时接口(CRI),是实现 Kubernetes 可扩展性的核心机制。
概述
Kubernetes 通过 CNI(Container Network Interface)、CSI(Container Storage Interface)和 CRI(Container Runtime Interface)三大标准接口实现了插件化的可扩展架构。这些接口将核心控制逻辑与具体实现解耦,使集群可以灵活选择网络、存储和运行时方案。CKA 考试要求理解各接口的作用和常见实现。
1. 三大接口概览
| 接口 | 全称 | 作用 | 解决的问题 |
|---|---|---|---|
| CNI | Container Network Interface | 容器网络 | Pod 网络连通与 IP 分配 |
| CSI | Container Storage Interface | 容器存储 | 持久化存储卷管理 |
| CRI | Container Runtime Interface | 容器运行时 | 容器创建与生命周期管理 |
┌─────────────────────────────────────────────────┐
│ Kubernetes │
│ ┌───────────────────────────────────────────┐ │
│ │ API Server / Controller │ │
│ │ ──────── │ │
│ │ CRI │ CNI CSI │ │
│ │ │ │ │ │ │ │
│ │ ┌────▼────┐ ┌─▼────┐ ┌─▼──────┐ │ │
│ │ │containerd│ │Calico│ │ CSI │ │ │
│ │ │ CRI-O │ │Flannel│ │ Driver │ │ │
│ │ │ │ │Cilium │ │(AWS,EBS│ │ │
│ │ └─────────┘ └──────┘ │ ...) │ │ │
│ └─────────────────────────┴─────────┘ │ │
└─────────────────────────────────────────────────┘
2. CNI -- Container Network Interface
2.1 概述
CNI 定义了容器网络的配置规范。当 Pod 创建时,Kubelet 调用 CNI 插件负责分配 IP 地址,配置网络接口和路由规则,确保 Pod 间网络互通。
2.2 CNI 插件职责
| 功能 | 说明 |
|---|---|
| IP 地址管理(IPAM) | 为 Pod 分配唯一的 IP 地址 |
| 网络连通性 | 确保同一节点和跨节点的 Pod 可以通信 |
| 网络策略 | 实现 NetworkPolicy 访问控制(部分插件) |
| 服务代理 | 部分 CNI 插件集成 kube-proxy 替代方案 |
2.3 常见 CNI 插件对比
| 插件 | 特点 | 网络模式 | 网络策略 | 性能 |
|---|---|---|---|---|
| Calico | 功能全面,支持 BGP | 纯 L3 路由(vxlan/ipip/bgp) | 支持 | 优秀 |
| Flannel | 简单易用,性能尚可 | Overlay(vxlan/host-gw) | 不支持 | 中等 |
| Cilium | eBPF 驱动,高性能 | eBPF(vxlan/direct) | 支持(增强) | 极高 |
| Weave | 简单部署,加密通信 | Overlay(weave mesh) | 支持 | 中等 |
| Multus | 多网络接口 | 附加接口 | 依赖元插件 | -- |
2.4 CNI 配置
# CNI 配置目录
/etc/cni/net.d/
# 查看当前使用的 CNI 插件
ls /etc/cni/net.d/
cat /etc/cni/net.d/10-calico.conflist
cat /etc/cni/net.d/10-flannel.conflist
# CNI 二进制目录
/opt/cni/bin/
ls /opt/cni/bin/
# 常见的 CNI 二进制:
# bridge, host-local, loopback, portmap, bandwidth, tuning
# 加上插件特有的二进制(calico, flannel, cilium 等)
# 查看 CNI 版本
/opt/cni/bin/bridge --version
2.5 CNI 配置示例
{
"cniVersion": "0.3.1",
"name": "k8s-pod-network",
"plugins": [
{
"type": "calico",
"datastore_type": "kubernetes",
"ipam": {
"type": "calico-ipam",
"assign_ipv4": "true",
"assign_ipv6": "false"
},
"policy": {
"type": "k8s"
}
},
{
"type": "portmap",
"capabilities": {"portMappings": true}
},
{
"type": "bandwidth",
"capabilities": {"bandwidth": true}
}
]
}
2.6 CNI 调试命令
# 查看 Pod 网络接口
kubectl exec <pod-name> -- ip addr show
kubectl exec <pod-name> -- ip route
# 查看节点网络接口(通常是 CNI 创建的网桥或路由)
ip link show
ip route show
# 查看 CNI 插件日志
# Calico
kubectl logs -n calico-system -l k8s-app=calico-node
# Flannel
kubectl logs -n kube-flannel -l app=flannel
# Cilium
kubectl logs -n kube-system -l k8s-app=cilium
# 测试 Pod 间连通性
kubectl exec pod-a -- ping <pod-b-ip>
# 查看 IPAM 分配情况
# Calico
calicoctl ipam show
# Cilium
cilium ip list
3. CSI -- Container Storage Interface
3.1 概述
CSI 定义了存储系统的标准接口,允许 Kubernetes 无缝对接各种存储后端。使用 CSI 后,Kubernetes 核心代码无需包含各个云厂商的存储驱动。
3.2 CSI 架构组件
┌──────────────────────────────────────────────┐
│ Kubernetes Node │
│ ┌────────────────┐ ┌─────────────────┐ │
│ │ kubelet │ │ CSI Driver │ │
│ │ ──── │ │ ────────── │ │
│ │ CSI Interface──┼─────┤ CSI Node │ │
│ │ │ │ Service │ │
│ └────────────────┘ └────────┬────────┘ │
└──────────────────────────────────┼────────────┘
│
┌──────────────────────────────────┼────────────┐
│ Control Plane │ │
│ ┌────────────────┐ ┌───────▼────────┐ │
│ │ CSI Controller │ │ External │ │
│ │ Sidecar │ │ Provisioner │ │
│ │ (Attacher, │ │ (Storage │ │
│ │ Resizer, │ │ Backend) │ │
│ │ Snapshotter) │ │ │ │
│ └────────────────┘ └────────────────┘ │
└──────────────────────────────────────────────┘
3.3 CSI 核心组件
| 组件 | Sidecar | 功能 |
|---|---|---|
| Provisioner | csi-provisioner | 监听 PVC,自动创建存储卷 |
| Attacher | csi-attacher | 将存储卷挂载到节点 |
| Resizer | csi-resizer | 在线调整存储卷大小 |
| Snapshotter | csi-snapshotter | 创建和管理卷快照 |
| Driver | 核心驱动 | 实际与存储后端通信(二进制) |
| Node Driver Registrar | node-driver-registrar | 向 kubelet 注册 CSI 驱动 |
3.4 常见 CSI 驱动
| 存储类型 | CSI 驱动 | 适用场景 |
|---|---|---|
| AWS EBS | ebs.csi.aws.com | AWS 块存储 |
| AWS EFS | efs.csi.aws.com | AWS 文件存储 |
| GCE PD | pd.csi.storage.gke.io | Google Cloud 持久化磁盘 |
| Azure Disk | disk.csi.azure.com | Azure 托管磁盘 |
| NFS | nfs.csi.k8s.io | 通用 NFS 共享存储 |
| Ceph/Rook | rook-ceph.cephfs.csi.ceph.com | Ceph 分布式存储 |
| Longhorn | driver.longhorn.io | Rancher 轻量分布式存储 |
| HostPath | 内置(非 CSI) | 本地存储(仅测试用) |
3.5 使用 CSI 的 StorageClass 示例
# StorageClass 使用 CSI 驱动
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: ebs-sc
provisioner: ebs.csi.aws.com
parameters:
type: gp3
fsType: ext4
encrypted: "true"
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
reclaimPolicy: Delete
# 查看集群中的 CSI 驱动
kubectl get csidrivers
# 查看 CSI 驱动的详细信息
kubectl describe csidriver ebs.csi.aws.com
# 查看集群的 StorageClass
kubectl get storageclass
kubectl describe storageclass ebs-sc
# 查看 CSI 控制器 Pod
kubectl get pods -n kube-system | grep csi
# 查看 PV 的驱动信息
kubectl get pv -o yaml | grep -A5 "csi:"
4. CRI -- Container Runtime Interface
4.1 概述
CRI 是 kubelet 与容器运行时之间的接口协议。它使 kubelet 不直接依赖 Docker 或其他特定运行时,而是通过标准 gRPC API 与任何符合 CRI 规范的运行时通信。
4.2 CRI 架构
┌─────────────────────┐
│ kubelet │
│ ────────── │
│ gRPC Client │
│ CRI API │
└────────┬────────────┘
│ gRPC (unix socket)
▼
┌─────────────────────┐
│ CRI Shim/Service │
│ ──────────────── │
│ containerd │
│ CRI-O │
│ Docker via cri-dockerd │
└────────┬────────────┘
│
▼
┌─────────────────────┐
│ Container │
│ (runc / gVisor / │
│ Kata Containers) │
└─────────────────────┘
4.3 CRI 运行时对比
| 运行时 | 特点 | Socket 路径 | 状态 |
|---|---|---|---|
| containerd | 轻量、高性能、Kubernetes 默认 | unix:///var/run/containerd/containerd.sock | 推荐 |
| CRI-O | 专为 Kubernetes 优化 | unix:///var/run/crio/crio.sock | 稳定 |
| Docker (cri-dockerd) | 传统方案,需要适配器 | unix:///var/run/cri-dockerd.sock | 已弃用 |
| gVisor | 沙箱隔离、增强安全 | unix:///var/run/gvisor/gvisor.sock | 特殊场景 |
| Kata Containers | 轻量级 VM 级隔离 | unix:///var/run/kata-containers/kata.sock | 特殊场景 |
4.4 CRI 常用操作命令
# 使用 crictl 管理容器(推荐)
crictl version
crictl info
# 查看容器
crictl ps
crictl ps -a # 包含已停止
crictl ps --name nginx # 按名称过滤
# 查看镜像
crictl images
crictl images -v
# 拉取/删除镜像
crictl pull nginx:latest
crictl rmi nginx:latest
# 查看 Pod
crictl pods
crictl pods --name nginx
# 查看容器日志
crictl logs <container-id>
crictl logs -f <container-id> # 实时日志
# 执行命令
crictl exec -it <container-id> /bin/sh
# 查看容器统计
crictl stats
# 查看容器详细信息
crictl inspect <container-id>
crictl inspectp <pod-id>
# 配置 crictl
cat /etc/crictl.yaml
# runtime-endpoint: unix:///var/run/containerd/containerd.sock
# image-endpoint: unix:///var/run/containerd/containerd.sock
# timeout: 10
# debug: false
4.5 查看 CRI 配置
# 查看 kubelet 使用的 CRI 配置
kubectl get nodes -o json | jq '.items[].status.nodeInfo.containerRuntimeVersion'
# 查看 containerd 配置
cat /etc/containerd/config.toml
# 查看 CRI-O 配置
cat /etc/crio/crio.conf
# 查看 kubelet CRI socket 配置
ps aux | grep kubelet | grep container-runtime-endpoint
# 或
cat /var/lib/kubelet/kubeadm-flags.env
5. 三大接口工作原理总结
Pod 创建流程(涉及三大接口):
1. API Server 创建 Pod
2. Scheduler 调度到节点
3. kubelet 收到 Pod 创建请求
│
├── CRI(容器运行时)
│ └── 通过 containerd/CRI-O 创建容器
│
├── CNI(网络)
│ └── 调用 CNI 插件分配 IP 地址、配置网络
│
└── CSI(存储,如有 PVC)
└── 通过 CSI 驱动挂载存储卷
CKA 考试要点
- CRI:crictl 命令 -- 考试中常用 crictl 替代 docker 命令管理容器
- CRI Socket 配置 -- kubelet 通过
--container-runtime-endpoint指定 socket - CNI 配置目录 --
/etc/cni/net.d/和/opt/cni/bin/两个目录需要了解 - CSI 资源对象 -- StorageClass、PV、PVC、CSIDriver 的关系
- 常见插件名称 -- Calico、Flannel、Cilium(CNI);Ceph/Rook、Longhorn(CSI);containerd、CRI-O(CRI)
🧪 完整操作实例:验证集群的 CNI/CSI/CRI 配置
场景描述
在已运行的集群中检查当前使用的 CNI 网络插件、CSI 存储驱动和 CRI 容器运行时,掌握三大扩展接口的排查方法。
前置条件
- 一个运行中的 Kubernetes 集群
- kubectl 已配置并可正常访问集群
- 节点 sudo 访问权限(可选)
操作步骤
Step 1: 检查 CRI 容器运行时
# 查看节点使用的容器运行时
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.containerRuntimeVersion}'
# containerd://1.7.x
# 查看 kubelet 的 CRI socket 配置
cat /var/lib/kubelet/kubeadm-flags.env
# KUBELET_KUBEADM_ARGS="--container-runtime-endpoint=unix:///var/run/containerd/containerd.sock ..."
# 使用 crictl 查看容器运行时信息
sudo crictl info | grep -E "runtimeName|runtimeVersion"
# "runtimeName": "containerd"
# "runtimeVersion": "1.7.x"
# 查看 crictl 配置
cat /etc/crictl.yaml
# runtime-endpoint: unix:///var/run/containerd/containerd.sock
# image-endpoint: unix:///var/run/containerd/containerd.sock
Step 2: 检查 CNI 网络插件
# 查看 CNI 插件 Pod(不同 CNI 位于不同命名空间)
kubectl get pods --all-namespaces | grep -E "calico|flannel|cilium|weave"
# calico-system calico-node-xxxxx 1/1 Running 0 1h
# calico-system calico-kube-controllers-xxxxx 1/1 Running 0 1h
# 查看 CNI 配置目录
ls /etc/cni/net.d/
# 10-calico.conflist
# 查看 CNI 配置详情
cat /etc/cni/net.d/10-calico.conflist
# {
# "name": "k8s-pod-network",
# "cniVersion": "0.3.1",
# "plugins": [
# { "type": "calico", ... },
# { "type": "portmap", ... }
# ]
# }
# 查看 CNI 二进制文件
ls /opt/cni/bin/
# bandwidth bridge calico calico-ipam flush host-local loopback portmap tuning
Step 3: 检查 CSI 驱动
# 查看已注册的 CSI 驱动
kubectl get csidrivers
# NAME ATTACHREQUIRED PODINFOONMOUNT MODES AGE
# ebs.csi.aws.com true false Persistent 30d
# 查看集群中的 StorageClass
kubectl get storageclass
# NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
# ebs-sc ebs.csi.aws.com Delete WaitForFirstConsumer true 30d
# standard kubernetes.io/gce-pd Delete Immediate false 30d
# 查看 CSI 控制器 Pod
kubectl get pods -n kube-system | grep csi
# ebs-csi-controller-xxxxxxxxx-xxxxx 6/6 Running 0 30d
# ebs-csi-node-xxxxx 3/3 Running 0 30d
# 查看 CSI 驱动详情
kubectl describe csidriver ebs.csi.aws.com
Step 4: 验证 Pod 网络与存储
# 查看 Pod 网络接口
kubectl run net-test --image=busybox --rm -it --restart=Never -- ip addr show
# 1: lo: <LOOPBACK> ...
# 2: eth0@if...: <BROADCAST,MULTICAST,UP,LOWER_UP> ... inet 192.168.1.5/32 <-- CNI 分配的 IP
# 查看 Pod 中是否有 CSI 挂载的卷
kubectl get pod <pod-with-pvc> -o json | jq '.spec.volumes[] | select(.csi != null)'
# {
# "name": "data",
# "csi": {
# "driver": "ebs.csi.aws.com",
# "volumeHandle": "vol-xxxxxxxxx"
# }
# }
验证结果
# 汇总查看三大接口状态
echo "=== CRI Runtime ==="
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.containerRuntimeVersion}'
echo ""
echo "=== CNI Plugins ==="
ls /opt/cni/bin/ | tr '\n' ' '
echo ""
echo "=== CSI Drivers ==="
kubectl get csidrivers -o name
考试提示
- CRI:使用
crictl命令管理容器(类似 docker),crictl ps、crictl images、crictl logs - CNI:配置在
/etc/cni/net.d/(配置文件),二进制在/opt/cni/bin/ - CSI:用
kubectl get csidrivers查看已注册驱动,在 StorageClass 的provisioner字段中引用 - 排查网络问题时先确认 CNI Pod 是否正常运行:
kubectl get pods -n calico-system - 排查存储问题时顺序:StorageClass -> PVC -> PV -> CSI Driver