云原生存储与网络方案选型:从 CSI 到 CNI 的架构决策与落地实践

云原生存储与网络方案选型:从 CSI 到 CNI 的架构决策与落地实践

一、存储与网络------云原生架构中"看不见的承重墙"

在 Kubernetes 集群中,存储和网络是最容易被忽视的底层基础设施。应用开发者关注 Pod 能不能跑起来、服务能不能访问,却很少追问:PV 挂载的 IOPS 够不够、CNI 的网络策略是否把跨命名空间流量堵死了、存储卷的快照恢复能不能满足 RTO 要求。直到生产环境出现训练任务 I/O 等待、跨节点 Pod 通信延迟飙升、数据卷迁移导致服务中断,这些"承重墙"的问题才会暴露。

存储和网络选型不是"选一个能用的就行"------不同的工作负载对 IOPS、吞吐、延迟、一致性有着截然不同的要求。AI 训练需要高吞吐的并行文件系统,数据库需要低延迟的块存储,日志采集需要弹性扩展的对象存储。网络层面,Service Mesh 的 Sidecar 代理会引入额外延迟,eBPF 方案绕过内核协议栈但调试困难,选择哪个方案直接影响服务间通信的性能上限。

二、存储与网络的底层机制剖析

2.1 CSI 存储架构

graph LR subgraph "Kubernetes 存储架构" PVC[PVC 声明] -->|绑定| PV[PV 持久卷] PV -->|动态供给| SC[StorageClass] SC -->|调用| CSIDriver[CSI Driver] subgraph "CSI Driver 内部" CSIC[CSI Controller] CSIN[CSI Node Plugin] end CSIDriver --> CSIC CSIDriver --> CSIN CSIC -->|CreateVolume| Backend1[Ceph RBD] CSIC -->|CreateVolume| Backend2[Local PV] CSIN -->|Mount| NodeFS[节点文件系统] end

CSI(Container Storage Interface)将存储供给拆分为两个阶段:

Controller 阶段:CSI Controller 负责卷的创建/删除/快照。以 Ceph RBD 为例,Controller 调用 Ceph MON 创建 RBD Image,映射为 Kubernetes PV。这个阶段只处理元数据操作,不涉及数据读写。

Node 阶段 :CSI Node Plugin 运行在每个节点上,负责将卷挂载到 Pod 的文件系统命名空间。对于块存储,Node Plugin 执行 rbd map 将 RBD Image 映射为本地块设备,再 mount 到 Pod 目录。对于文件存储,Node Plugin 直接 mount -t ceph 挂载 CephFS 路径。

关键差异在于:块存储(RBD)经过内核块设备层,支持 fsync 保证数据持久性,但单卷只能被单节点挂载;文件存储(CephFS)支持多节点同时读写,但元数据服务可能成为瓶颈。

2.2 CNI 网络架构

graph TB subgraph "节点网络栈" PodA[Pod A] -->|veth pair| BR[网桥 cni0] PodB[Pod B] -->|veth pair| BR BR -->|路由| ETH[eth0] subgraph "数据包路径" direction LR App[应用程序] -->|syscall| TCP[TCP/IP 栈] TCP -->|iptables| Filter[Netfilter] Filter -->|veth| BR2[网桥] end end subgraph "eBPF 优化路径" PodC[Pod C] -->|BPF 程序| BPFMap[eBPF Map] BPFMap -->|直达| ETH2[eth0] end

传统 CNI(如 Calico iptables 模式)的数据包路径:Pod → veth pair → 网桥 → iptables 规则匹配 → 路由 → 物理网卡。每次跨 Pod 通信都要经过完整的内核协议栈和 iptables 链式匹配,当集群规模超过 1000 节点时,iptables 规则数量膨胀导致匹配延迟显著增加。

eBPF 方案(如 Cilium)绕过 iptables,在 socket 层直接将数据包从源 Pod 的 socket 重定向到目标 Pod 的 socket,跳过中间的协议栈处理。这在同节点 Pod 通信场景下,延迟可降低 30-50%。

三、生产级存储与网络方案实现

3.1 Ceph RBD + CephFS 混合存储方案

yaml 复制代码
# StorageClass:块存储(数据库、消息队列等低延迟场景)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ceph-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
  clusterID: ceph-cluster-01
  pool: kubernetes-rbd
  imageFormat: "2"
  imageFeatures: layering
  csi.storage.k8s.io/provisioner-secret-name: ceph-secret
  csi.storage.k8s.io/node-stage-secret-name: ceph-secret
reclaimPolicy: Retain  # 生产环境禁止动态删除,防止误操作
allowVolumeExpansion: true  # 支持在线扩容
mountOptions:
  - discard  # 支持 TRIM,自动回收已删除数据的存储空间
---
# StorageClass:文件存储(AI 训练数据共享、日志汇聚等高吞吐场景)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: cephfs-sc
provisioner: cephfs.csi.ceph.com
parameters:
  clusterID: ceph-cluster-01
  fsName: kubernetes-cephfs
  pool: cephfs-data
  csi.storage.k8s.io/provisioner-secret-name: ceph-secret
  csi.storage.k8s.io/node-stage-secret-name: ceph-secret
reclaimPolicy: Retain

3.2 本地 PV 方案:AI 训练的高性能存储选择

go 复制代码
package storage

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// LocalPVManager 管理本地持久卷的创建与清理
// 核心思路:AI训练需要NVMe级别的IOPS,网络存储无法满足
type LocalPVManager struct {
	basePath    string            // 本地存储根目录,如 /mnt/nvme
	nodeName    string            // 当前节点名称
	storageCap  resource.Quantity // 节点可用存储容量
}

// CreateLocalPV 为指定训练任务创建本地PV
// 使用Kubernetes Local Persistent Volume机制,保证卷与节点绑定
func (m *LocalPVManager) CreateLocalPV(ctx context.Context,
	taskID string, size resource.Quantity) (*corev1.PersistentVolume, error) {

	volPath := filepath.Join(m.basePath, taskID)

	// 创建存储目录,设置权限
	if err := os.MkdirAll(volPath, 0755); err != nil {
		return nil, fmt.Errorf("创建存储目录失败: %w", err)
	}

	pv := &corev1.PersistentVolume{
		ObjectMeta: metav1.ObjectMeta{
			Name: fmt.Sprintf("local-pv-%s", taskID),
		},
		Spec: corev1.PersistentVolumeSpec{
			Capacity: corev1.ResourceList{
				corev1.ResourceStorage: size,
			},
			// Local PV必须指定nodeAffinity,确保Pod调度到正确的节点
			NodeAffinity: &corev1.VolumeNodeAffinity{
				Required: &corev1.NodeSelector{
					NodeSelectorTerms: []corev1.NodeSelectorTerm{
						{
							MatchExpressions: []corev1.NodeSelectorRequirement{
								{
									Key:      "kubernetes.io/hostname",
									Operator: corev1.NodeSelectorOpIn,
									Values:   []string{m.nodeName},
								},
							},
						},
					},
				},
			},
			AccessModes: []corev1.PersistentVolumeAccessMode{
				corev1.ReadWriteOnce, // 本地存储仅支持单节点读写
			},
			PersistentVolumeReclaimPolicy: corev1.Retain,
			StorageClassName:              "local-nvme-sc",
			PersistentVolumeSource: corev1.PersistentVolumeSource{
				Local: &corev1.LocalVolumeSource{
					Path: volPath,
					FSType: ptrToString("ext4"),
				},
			},
		},
	}

	return pv, nil
}

func ptrToString(s string) *string { return &s }

3.3 Cilium eBPF 网络策略配置

yaml 复制代码
# CiliumNetworkPolicy:基于身份的细粒度网络隔离
# 相比传统NetworkPolicy,支持L7层规则(HTTP方法、DNS查询等)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: ai-training-egress
  namespace: ai-platform
spec:
  endpointSelector:
    matchLabels:
      app: training-job
  egress:
    # 允许访问Ceph MON节点(存储IO)
    - toEndpoints:
        matchLabels:
          app: ceph-mon
      toPorts:
        - ports:
            - port: "6789"
              protocol: TCP
    # 允许访问外部模型仓库,但限制HTTP方法为GET
    - toFQDNs:
        - matchName: "huggingface.co"
      toPorts:
        - ports:
            - port: "443"
              protocol: TCP
          rules:
            http:
              - method: GET
    # 允许DNS解析
    - toEndpoints:
        matchLabels:
          k8s:io.kubernetes.pod.namespace: kube-system
          k8s-app: kube-dns
      toPorts:
        - ports:
            - port: "53"
              protocol: UDP

四、方案选型的 Trade-offs 分析

存储选型对比:

维度 Ceph RBD CephFS Local PV
IOPS 中等(网络开销) 低(元数据瓶颈) 极高(本地NVMe)
多节点共享 不支持 支持 不支持
数据持久性 副本冗余 副本冗余 单点(依赖节点可靠性)
运维复杂度 高(Ceph集群维护) 高 低
适用场景 数据库、消息队列 训练数据共享 AI训练临时数据

网络选型对比:

维度 Calico iptables Calico eBPF Cilium eBPF
规则匹配延迟 高(O(n)链式匹配) 低(eBPF Map查找) 低(eBPF Map查找)
L7 策略支持 不支持 不支持 支持(HTTP/gRPC/DNS)
可观测性 依赖 tcpdump 基础指标 Hubble 全景可观测
内核版本要求 无特殊要求 ≥ 4.18 ≥ 4.19(部分特性需 5.x)
运维复杂度 低 中 高

关键边界条件:

  • Local PV 的 Pod 调度被绑定到特定节点,当该节点故障时数据不可恢复。因此 Local PV 仅适用于可重建的临时数据(如训练 checkpoint),不适用于持久化业务数据
  • Ceph 集群的 PG(Placement Group)数量直接影响 IOPS 分布。PG 数量过少导致数据倾斜,过多增加 MON 负载。经验公式:每个 OSD 约 100-200 个 PG
  • Cilium 的 eBPF 程序在内核态执行,调试困难。当网络策略导致流量异常时,缺乏传统 iptables 的 --log 机制,需要依赖 Hubble 可观测平台排查

五、总结

云原生存储与网络的选型,本质上是在性能、可靠性和运维成本之间做权衡。存储层面,核心决策路径是:需要多节点共享选 CephFS,需要低延迟选 Ceph RBD,需要极致 IOPS 选 Local PV。网络层面,小规模集群用 Calico iptables 足够,大规模集群或需要 L7 策略时切换到 Cilium eBPF。

落地建议分三步推进:第一步,先用最简方案(Calico + Ceph RBD)跑通业务;第二步,根据监控数据定位瓶颈------如果是存储 I/O 瓶颈,评估是否需要 Local PV 加速;如果是网络延迟瓶颈,评估 eBPF 方案的收益;第三步,逐步替换,每次只变更一个变量,确保问题可归因。避免一步到位引入全套复杂方案,否则故障排查时无法定位根因。

相关推荐
天远API9 小时前
零信任架构实战:基于天远租凭分期报告构建自动化智慧租房免押分期履约评估网关
运维·人工智能·架构·自动化
我要见SA姐19 小时前
Chrome 扩展安全攻防实录:从权限滥用到供应链投毒
运维·人工智能·python·机器学习·自动化
路上有只喵9 小时前
认识元器件 · 单片机(MCU/MPU/SOC) · 实战篇9
人工智能·语音识别
奈落249 小时前
Codex 并进 ChatGPT 之后,“编程智能体“是变浅了还是变顺了:从官方概览页的功能分工到五家公司开发者反馈,读一次产品化合并的得与失
人工智能·chatgpt·工作流·ai 编程
qq_25294131689 小时前
伊蚊检测数据集 | 伊蚊检测 病媒生物 公共卫生 目标检测9304期
人工智能·yolo·目标检测·计算机视觉·蚊子·尹蚊
程序员柒叔10 小时前
Diagram Design 解构:45 种图型如何用语义路由与 SVG 质量门交付
人工智能·github·agent·skills
QXWZ_IA10 小时前
无人机自主巡检从半自动到全闭环的阶段划分与定位要求
人工智能·安全·无人机
YYYing.10 小时前
【Agent系列 (十一) 】上下文工程
人工智能·python·ai·agent·上下文工程
计算机毕业编程指导师10 小时前
基于深度学习的光伏组件红外图像缺陷识别系统设计与实现
人工智能·python·深度学习·目标检测·毕业设计·课程设计·光伏
m4Rk_10 小时前
【论文阅读】Agent 记忆机制(119):EvoLife——让具身 Agent 把主动问到的答案沉淀为可复用的空间经验
论文阅读·人工智能·学习·开源·github