4. Longhorn 存储类(StorageClass):自定义参数与默认设置

在 Kubernetes 中,StorageClass 是动态卷供给的核心抽象。Longhorn 通过 CSI 驱动注册了名为 longhorn 的默认 StorageClass,但生产环境往往需要根据工作负载特性(性能、容灾、成本)定制多个 StorageClass。本章深入解析 Longhorn StorageClass 的关键参数:副本数、数据局部性、磁盘选择器,以及如何设置默认 StorageClass。

4.1 Longhorn StorageClass 参数体系

Longhorn 的 StorageClass 通过 parameters 字段控制卷的行为。下表列出最常用的自定义参数:

参数名 类型 默认值 说明
numberOfReplicas int 3 卷的副本数,决定数据冗余级别
dataLocality string disabled 数据局部性策略:disabled / best-effort / strict-local
diskSelector string "" 基于磁盘标签的调度过滤,逗号分隔
nodeSelector string "" 基于节点标签的调度过滤,逗号分隔
replicaAutoBalance string disabled 副本自动平衡:disabled / least-effort / best-effort
staleReplicaTimeout int 30 失效副本保留时间(分钟)
fromBackup string "" 从指定备份创建卷的 BackupURL
encrypted bool false 是否启用卷加密(需配置密钥)
最佳实践: 建议为不同工作负载创建独立的 StorageClass。例如:longhorn-ssd(高 IOPS,副本数=2,磁盘选择 SSD 标签)、longhorn-archive(副本数=1,数据局部性=strict-local,磁盘选择 HDD 标签)。

4.2 副本数(numberOfReplicas)

副本数决定卷的数据冗余级别。每个卷的引擎将数据同步写入所有副本,副本分布在不同的节点上(默认策略)。

  • 副本数=1: 无冗余,单节点故障即丢失数据。仅用于测试或临时卷。
  • 副本数=2: 容忍单副本故障,但无法保证数据一致性恢复(脑裂风险)。
  • 副本数=3: 生产推荐值,容忍单节点故障,支持自动重建。
  • 副本数>3: 用于跨 AZ 或跨数据中心场景,增加写入延迟。
注意: 副本数增加会线性消耗存储空间和网络带宽。例如 100Gi 卷,副本数=3 时实际占用 300Gi 裸容量(未计算快照和日志开销)。

4.3 数据局部性(dataLocality)

数据局部性控制副本与使用该卷的 Pod 之间的物理位置关系,直接影响读写延迟和故障域。

策略 行为 适用场景
disabled 副本可调度到任意节点,不保证与 Pod 同节点 通用场景,平衡负载
best-effort 优先将至少一个副本调度到 Pod 所在节点;若资源不足则回退到 disabled 对延迟敏感但允许偶尔跨节点
strict-local 强制所有副本与 Pod 在同一节点;若无法满足则卷创建失败 极致本地 IO 性能,如数据库本地日志
性能影响: strict-local 模式下,读写完全本地化,无网络开销;但节点故障会导致卷不可用,需配合 Pod 反亲和或节点故障转移策略。

4.4 磁盘选择器(diskSelector)

磁盘选择器允许基于磁盘标签(Disk Tags)过滤副本的放置目标。Longhorn 节点可以挂载多块磁盘,每块磁盘可设置多个标签(如 ssd、nvme、hdd、fast)。

配置示例:

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-ssd
provisioner: driver.longhorn.io
parameters:
  numberOfReplicas: "2"
  dataLocality: "best-effort"
  diskSelector: "ssd,fast"
  nodeSelector: "storage-role=worker"
reclaimPolicy: Delete
volumeBindingMode: Immediate

上述配置要求:

  • 副本仅放置到同时包含 ssd 和 fast 标签的磁盘上。
  • 节点必须具有 storage-role=worker 标签。
  • 若没有满足条件的磁盘,卷创建会进入 Degraded 状态并等待资源。

4.5 默认 StorageClass 设置

Kubernetes 集群中只能有一个默认 StorageClass。Longhorn 安装后会自动将 longhorn 标记为默认。切换默认 StorageClass 的两种方式:

  1. 删除旧默认: 移除原默认 StorageClass 的 storageclass.kubernetes.io/is-default-class: "true" 注解。
  2. 设置新默认: 为目标 StorageClass 添加注解 storageclass.kubernetes.io/is-default-class: "true"。

命令示例:

# 查看当前默认
kubectl get sc -o json | jq '.items[] | select(.metadata.annotations["storageclass.kubernetes.io/is-default-class"]=="true") | .metadata.name'

# 设置 longhorn-ssd 为默认
kubectl annotate sc longhorn-ssd storageclass.kubernetes.io/is-default-class=true --overwrite

# 移除原默认
kubectl annotate sc longhorn storageclass.kubernetes.io/is-default-class-
变更影响: 修改默认 StorageClass 不会影响已创建的 PVC。新创建的 PVC(未指定 storageClassName)将使用新的默认 StorageClass。建议在变更前确认所有工作负载的存储需求。

4.6 StorageClass 参数与卷调度流程

下图展示 Longhorn 根据 StorageClass 参数调度卷副本的完整流程:

Longhorn StorageClass 副本调度流程 Longhorn StorageClass 副本调度流程 PVC 创建请求 读取 StorageClass 参数 replicas / locality / selector 调度引擎决策 节点过滤 → 磁盘过滤 → 局部性匹配 ✅ 满足条件 → 创建卷 ❌ 不满足 → Degraded 副本分布到目标节点/磁盘 引擎 + 副本组启动 等待资源满足条件 自动重试调度 说明:diskSelector 和 nodeSelector 在调度决策阶段同时生效;dataLocality 在节点过滤后做局部性匹配

4.7 多 StorageClass 管理策略

生产环境建议按以下维度划分 StorageClass:

StorageClass 名称 副本数 数据局部性 磁盘选择器 典型用途
longhorn 3 disabled 无 通用生产卷
longhorn-ssd 2 best-effort ssd 数据库、缓存
longhorn-local 1 strict-local nvme 本地日志、临时数据
longhorn-archive 3 disabled hdd,archive 冷数据、备份
变更门禁集成: 在 CI/CD 流水线中,可通过 kubectl diff 或 Longhorn API 对比 StorageClass 参数变更。建议在预发环境验证新 StorageClass 的副本调度是否符合预期,再推送到生产集群。