跳到主要内容

Longhorn

官方文档:

注意: 本文档仅供参考。

Longhorn 是 Kubernetes 上开源分布式块存储,提供持久化卷(PVC)能力,支持 V1(基于 ext4/XFS 文件系统)与 V2(基于 SPDK/NVMe 的高性能引擎)两种数据引擎。

1. 前置条件

以下操作需在所有将承载 Longhorn 卷的节点上执行,命令按发行版分别列出。

1.1 通用要求

  • Kubernetes >= v1.25
  • 容器运行时兼容 Kubernetes(Docker v1.13+、containerd v1.3.7+ 等)
  • 支持 Mount Propagation(Rancher v2.0.7+ 默认开启)
  • Longhorn 组件安装需要以 root 权限运行
  • 主机文件系统支持 file extents 特性(ext4 / XFS)

1.2 节点依赖组件(V1 引擎必需,V2 亦依赖)

1.2.1 安装 open-iscsi

Longhorn 依赖 iscsiadm 向 Kubernetes 提供持久卷,iscsid 守护进程需正常运行。安装命令因发行版而异:

Debian/Ubuntu:

apt-get install -y open-iscsi
modprobe iscsi_tcp
systemctl enable iscsid
systemctl start iscsid

RHEL / CentOS / AmazonLinux2 (EKS Worker AMI):

yum --setopt=tsflags=noscripts install iscsi-initiator-utils
echo "InitiatorName=$(/sbin/iscsi-iname)" > /etc/iscsi/initiatorname.iscsi
systemctl enable iscsid
systemctl start iscsid

InitiatorName 是什么,为什么手动写:

  • InitiatorName 是 iSCSI 发起端(initiator)节点的唯一标识,iSCSI target 通过它识别客户端,保存在 /etc/iscsi/initiatorname.iscsi,格式为 InitiatorName=iqn.1994-05.com.redhat:<随机串>
  • iscsi-iname 是 open-iscsi 自带的命令,用于随机生成一个 IQN(iSCSI Qualified Name)。
  • 命令 --setopt=tsflags=noscripts 让 yum 安装时不执行包自带的 %post 脚本(该脚本本会自动写入默认 InitiatorName),因此文件不会自动生成,需用上面那行 echo 手动补齐。
  • iscsi-iname 现场生成而非用默认值,可避免批量克隆节点时所有节点 IQN 相同,导致 target 无法区分客户端。

SUSE / openSUSE:

zypper install open-iscsi
systemctl enable iscsid
systemctl start iscsid

注意: SUSE / openSUSE 上 iscsi_tcp 模块仅包含在 kernel-default 包中。若系统安装的是 kernel-default-base,需先替换为 kernel-default,否则 iscsid 无法正常工作。

各发行版安装后需确保 iscsi_tcp 模块已加载(通常随包自动加载),确认后再启动 iscsid

modprobe iscsi_tcp
lsmod | grep -E 'iscsi_tcp'

验证:

systemctl is-active iscsid

输出 active 即正常。

1.2.2 安装 NFSv4 客户端

RWX 卷和备份功能需要 NFSv4 客户端。先确认内核已开启 NFSv4 支持:

cat /boot/config-`uname -r` | grep CONFIG_NFS_V4
cat /boot/config-`uname -r` | grep CONFIG_NFS_V4_1
cat /boot/config-`uname -r` | grep CONFIG_NFS_V4_2

安装客户端,命令因发行版而异:

Debian/Ubuntu:

apt-get install -y nfs-common

RHEL / CentOS / AmazonLinux2 (EKS Worker AMI):

yum install -y nfs-utils

SUSE / openSUSE:

zypper install nfs-client

验证实际挂载的 NFS 版本:

nfsstat -m
mount | grep nfs

1.3 V2 数据引擎额外要求

本安装参数已启用 v2DataEngine=true,使用 V2 卷的节点还需满足以下要求。

1.3.1 加载内核模块

要求内核模块:vfio_pciuio_pci_genericnvme-tcp

Debian/Ubuntu:

先安装内核 extra 模块,否则 modprobe 会报找不到模块:

apt-get install -y linux-modules-extra-`uname -r`

RHEL / CentOS / AmazonLinux2 (EKS Worker AMI):

yum install -y kernel-modules-extra

SUSE / openSUSE:

SUSE 默认内核 kernel-default 已包含所需模块,通常无需额外安装;若节点装的是最小化内核 kernel-default-base,需先替换为 kernel-default

zypper install -y kernel-default

各发行版加载模块:

modprobe vfio_pci
modprobe uio_pci_generic
modprobe nvme-tcp

验证:

lsmod | grep -E 'vfio_pci|uio_pci_generic|nvme_tcp'

配置开机自动加载:

cat > /etc/modules-load.d/longhorn.conf <<'EOF'
vfio_pci
uio_pci_generic
nvme_tcp
EOF

1.3.2 配置 HugePages

每节点需配置 2 MiB 大页 1024 个(共 2 GiB)。Linux 默认的 hugepage 池大小即 2 MiB,直接通过 sysctl 分配即可,无需修改 GRUB 引导参数。

立即生效:

sysctl -w vm.nr_hugepages=1024

持久化(重启后仍生效):

cat > /etc/sysctl.d/99-longhorn-hugepages.conf <<'EOF'
vm.nr_hugepages = 1024
EOF
sysctl --system

注意: 运行时动态分配大页,在内存碎片严重时可能失败(需为 2 MiB 大页腾出连续物理内存)。若分配不足,可临时调低请求量,或改用内核 cmdline hugepages=1024 在启动早期预留(最稳妥,但需改引导配置)。

验证:

grep Huge /proc/meminfo
# HugePages_Total: 1024
# Hugepagesize: 2048 kB

kubectl describe node <node-name>
# Capacity / Allocatable 中应包含 hugepages-2Mi: 2Gi

1.3.3 添加 block-type 磁盘

V2 卷持久化在 block-type 磁盘上(裸盘/分区,不能是文件系统盘),需在 Longhorn UI 中为节点添加:Node → 选择节点 → Edit Node and Disks → 添加裸盘设备路径。

1.3.4 IOMMU 组隔离

SPDK 通过 vfio-pci 认领设备,VFIO 必须认领整个 IOMMU 组。若 NVMe 设备与父 PCIe bridge 处于同一 IOMMU 组,SPDK 无法初始化该设备,该磁盘只能改用 AIO 模式。

注意: 若 V2 引擎前提未满足,V1 卷仍可正常使用,仅 V2 卷不可用。

2. 添加 Helm 仓库

helm repo add longhorn https://charts.longhorn.io
helm repo update

3. 安装 Longhorn

使用 opencsg 私有镜像仓库(opencsg-registry.cn-beijing.cr.aliyuncs.com/opencsghq)离线安装:

helm upgrade --install longhorn longhorn/longhorn \
--namespace longhorn \
--create-namespace \
--version 1.12.1 \
--set global.imageRegistry=opencsg-registry.cn-beijing.cr.aliyuncs.com/opencsghq \
--set longhornUI.replicas=1 \
--set csi.attacherReplicaCount=1 \
--set csi.provisionerReplicaCount=1 \
--set csi.resizerReplicaCount=1 \
--set csi.snapshotterReplicaCount=1 \
--set persistence.defaultClassReplicaCount=2 \
--set defaultSettings.defaultDataPath=/data/longhorn/ \
--set defaultSettings.storageMinimalAvailablePercentage=10 \
--set defaultSettings.storageOverProvisioningPercentage=150 \
--set defaultSettings.storageReservedPercentageForDefaultDisk=5 \
--set defaultSettings.defaultReplicaCount='{"v1":"2","v2":"2"}' \
--set defaultSettings.v1DataEngine=true \
--set defaultSettings.v2DataEngine=true

3.1 参数说明

参数说明
--namespace longhorn安装命名空间为 longhorn(注意不是官方默认的 longhorn-system
global.imageRegistry指定全局镜像仓库,指向 opencsg 私有镜像,支持内网/离线环境拉取
longhornUI.replicasLonghorn UI 副本数,置 1 节省资源
csi.attacherReplicaCount 等 4 项CSI 各组件(attacher / provisioner / resizer / snapshotter)副本数,均置 1,适合小规模集群
persistence.defaultClassReplicaCount默认 StorageClass longhorn 的副本数,置 2
defaultSettings.defaultDataPath节点默认数据目录 /data/longhorn/
defaultSettings.storageMinimalAvailablePercentage磁盘最小可用空间百分比为 10,低于此值该节点磁盘将停止调度新副本
defaultSettings.storageOverProvisioningPercentage存储超用比例 150%
defaultSettings.storageReservedPercentageForDefaultDisk默认磁盘预留 5% 空间用于存储卷元数据
defaultSettings.defaultReplicaCount新卷默认副本数,以 JSON 分别指定 V1/V2 引擎各为 2(该设置默认值为 {"v1":"3","v2":"3"}
defaultSettings.v1DataEngine启用 V1 数据引擎
defaultSettings.v2DataEngine启用 V2 数据引擎(需满足第 1 节 V2 额外前提)

4. 验证安装

查看 Pod 运行状态:

kubectl -n longhorn get pod

确认 longhorn-managerlonghorn-uilonghorn-driver-deployerlonghorn-csi-plugin 及相关 csi-* 组件均为 Running

查看默认 StorageClass:

kubectl get storageclass

输出中应包含 longhorn(默认副本数 2):

NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
longhorn driver.longhorn.io Delete Immediate true 3m

查看节点与磁盘是否已被 Longhorn 纳管:

kubectl -n longhorn get nodes.longhorn.io
kubectl -n longhorn get disks.longhorn.io

确认各节点 Ready/data/longhorn/(V1)与 block-type 磁盘(V2)均已纳入。启用 V2 引擎后应看到 V1/V2 两类 instance-manager

kubectl -n longhorn get instancemanager

创建测试 PVC 验证动态供给:

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: longhorn-test
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 1Gi
EOF
kubectl get pvc longhorn-test

PVC 状态为 Bound 即正常,验证后删除即可。

5. 访问 Longhorn UI

查看 UI 服务:

kubectl -n longhorn get svc longhorn-frontend

方式一:NodePort 访问(默认 30080)

http://<节点 IP>:30080

方式二:端口转发

kubectl -n longhorn port-forward svc/longhorn-frontend 8080:80 --address 0.0.0.0

然后浏览器访问 http://localhost:8080

注意: Longhorn UI 默认不启用认证,生产环境建议通过 Ingress 增加 Basic Auth(参考官方文档 Create an Ingress with Basic Authentication)。

6. Troubleshooting

6.1 获取排查信息

Support Bundle 是最快的切入点,包含 Longhorn 相关配置与日志,点击 Longhorn UI 底部的 Generate Support Bundle 即可下载 zip;仅 dmesg 需要登录各节点自行获取。

查看 manager 与引擎日志(原生 kubectl,多个 manager 时带 --prefix 区分 Pod):

# 实时跟踪所有 longhorn-manager Pod 日志
kubectl -n longhorn logs -l app=longhorn-manager --prefix -f

# 查看指定 Pod 日志
kubectl -n longhorn logs <pod-name> -f

CSI 排查看 csi-attachercsi-provisionerlonghorn-csi-plugin 的日志:

kubectl -n longhorn logs <csi-pod>

6.2 创建卷提示 "v2 data engine is not enabled"

在 Longhorn UI 创建卷时提示该错误,说明 v2-data-engine 设置未开启。虽然安装命令里带了 --set defaultSettings.v2DataEngine=true,但该设置仅在全新安装时写入;若是升级、重复安装或设置被改过,不会自动生效。

依次排查:

# 1. 查看当前 v2-data-engine 设置值,应为 true
kubectl -n longhorn get settings.longhorn.io v2-data-engine -o yaml

若 value 不是 true,在 Longhorn UI Settings → V2 Data Engine 中开启,或直接 patch:

kubectl -n longhorn patch settings.longhorn.io v2-data-engine --type=merge -p '{"value": "true"}'

报错:not enough hugepages-2Mi capacity

patch 开启时可能报如下错误:

The request is invalid: value: failed to validate setting v2-data-engine with invalid value true: not enough hugepages-2Mi capacity for node k3s-master, requested 2Gi, capacity 0

原因: 开启 V2 引擎时 Longhorn 会校验各节点上的 hugepages-2Mi 资源,capacity 0 表示该节点完全没有可用大页。你的安装参数 --set defaultSettings.v2DataEngine=true 只负责写设置,但节点若未按 1.3.2 分配 2 GiB 大页,校验就会失败、拒绝开启。

解决: 先在节点上分配大页(见 1.3.2):

sysctl -w vm.nr_hugepages=1024

确认节点 hugepages-2Mi 容量已上报:

kubectl describe node k3s-master | grep -A2 hugepages
# Capacity / Allocatable 中应包含 hugepages-2Mi: 2Gi

然后再执行上面的 patch 开启 V2 引擎。

开启后实例管理器 Pod 会自动重启。随后确认:

  • 节点满足 V2 前提(见 1.3:内核模块、HugePages、block-type 磁盘、IOMMU)
  • 创建卷时在 Data Engine 下拉中显式选择 v2(仅开启设置并不会自动把新卷都建成 V2)

6.3 Pod 镜像拉取失败(ImagePullBackOff / ErrImagePull)

本安装使用 opencsg 私有镜像仓库,若 Pod 处于 ImagePullBackOff / ErrImagePull,先确认镜像已同步到 opencsg-registry.cn-beijing.cr.aliyuncs.com/opencsghq,并核对 global.imageRegistry 是否正确:

kubectl -n longhorn describe pod <pod>
kubectl -n longhorn get events

6.4 PVC 一直 Pending

依次排查:

kubectl get pvc
kubectl get storageclass
kubectl -n longhorn get nodes.longhorn.io
kubectl -n longhorn get pods
  • StorageClass 是否存在且 provisionerdriver.longhorn.io
  • 节点是否为 Ready,磁盘是否正常、/data/longhorn/ 是否有足够空间
  • 副本数是否超过可用节点数(本安装副本数为 2,需至少 2 个可调度的节点)

6.5 V1 卷无法附加 / 挂载失败

Longhorn V1 卷通过 iSCSI 提供,若卷无法附加,优先检查节点上的 open-iscsi 与 iscsid

systemctl is-active iscsid
lsmod | grep iscsi_tcp

iscsid 未运行或 iscsi_tcp 模块未加载都会导致挂载失败,按 1.2.1 修复后重试。

6.6 V2 引擎问题

6.6.1 实例管理器 Pod 异常 / 启动失败

优先检查大页是否分配成功:

grep Huge /proc/meminfo

HugePages_Total 不足 1024(或为 0)时 SPDK 无法启动,按 1.3.2 重新分配。若为运行时动态分配失败,多为内存碎片导致。

6.6.2 failed to bind NVMe disk / vfio-pci 报错 -22

实例管理器日志出现 failed to bind NVMe diskvfio-pci: probe ... failed with error -22,说明 NVMe 设备与 PCIe bridge 共享 IOMMU 组。

验证:

lspci -t
ls /sys/kernel/iommu_groups/

若两者处于同一 IOMMU 组,该磁盘需在 Longhorn UI 中改用 AIO 模式(参见 1.3.4)。

6.6.3 block-type 磁盘状态报 "Invalid argument"

磁盘状态报 failed to create AIO bdev ... Invalid argument,实例管理器日志提示:

bdev_aio.c: *WARNING*: Specified block size 4096 does not match auto-detected block size 512
bdev_aio.c: *ERROR*: Disk size 100000000000 is not a multiple of block size 4096

说明磁盘大小不是 4096 的整数倍,处理步骤:

  1. 从节点移除该 block-type 磁盘
  2. fdisk 重新分区,确保分区大小是 4096 的整数倍
  3. 将分区作为 block-type 磁盘重新添加到节点

6.6.4 Debian 安装 linux-modules-extra 报 "No installation candidate"

Package 'linux-modules-extra-5.15.0-67-generic' has no installation candidate

uname -r 对应的内核模块包不可用时,可到 pkgs.org 查找可用版本手动指定安装,例如 Ubuntu 22.04:

apt update -y
apt install -y linux-modules-extra-5.15.0-76-generic

6.7 节点 /data/longhorn 目录空间不足

数据目录空间不足时(本安装 storageMinimalAvailablePercentage=10,低于 10% 即停止调度新副本),卷可能一直 Pending:

df -h /data/longhorn/
kubectl -n longhorn get nodes.longhorn.io

7. 卸载 Longhorn

卸载前需先将删除确认标志置为 true,否则卸载任务会失败:

kubectl -n longhorn patch -p '{"value": "true"}' --type=merge lhs deleting-confirmation-flag

lhs 是 Longhorn 设置资源 settings.longhorn.io 的简写。

删除所有使用 Longhorn 卷的工作负载(Deployment、StatefulSet、PVC、PV、StorageClass 等)后执行卸载:

helm uninstall longhorn -n longhorn

helm uninstall 会自动运行 Longhorn 自带的 uninstall job(chart 的 pre-delete 钩子)清理 CRD 与残留资源,等待其完成即可:

kubectl -n longhorn get job -w

若之前曾手动 kubectl apply 过 Longhorn 清单、导致 helm 卸载后仍有 CRD 残留,可再手动创建卸载 job 兜底清理。注意官方 uninstall.yaml 默认部署到 longhorn-system 命名空间,需先改为实际命名空间(本安装为 longhorn)再使用:

kubectl create -f https://raw.githubusercontent.com/longhorn/longhorn/v1.12.1/uninstall/uninstall.yaml
kubectl get job/longhorn-uninstall -w