云原生存储与网络方案选型:从 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 方案的收益;第三步,逐步替换,每次只变更一个变量,确保问题可归因。避免一步到位引入全套复杂方案,否则故障排查时无法定位根因。

相关推荐
IT_陈寒1 小时前
Vite的热更新突然不香了,排查三小时差点砸键盘
前端·人工智能·后端
阿里云大数据AI技术3 小时前
构建高转化海外电商搜索:阿里云OpenSearch行业算法版的全链路智能优化策略实战
人工智能·搜索引擎
Awu12273 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
字节跳动视频云技术团队3 小时前
让 Agent 成为音视频工作台:AI MediaKit CLI + Skill 发布
人工智能·音视频开发
魏祖潇3 小时前
framework 整合实战——DDD/TDD/SDD 三件套在 framework 仓的真实落地
人工智能·后端
Token炼金师4 小时前
去噪扩散:从随机噪声到高保真图像的数学之路
人工智能·aigc
这个DBA有点耶4 小时前
AI写的SQL跑崩了生产库,这锅谁背?
数据库·人工智能·程序员
阿里云大数据AI技术4 小时前
阿里云 EMR AI 助手正式发布:从问答工具到全栈智能运维助手
运维·人工智能
Larcher5 小时前
从零搭建 MCP 服务——让 AI 拥有无限扩展能力
人工智能·程序员