K8S 部署Longhorn(云原生分布式块存储解决方案)
myluzh 发布于 阅读:23 Kubernetes
0x00 前言
Longhorn 是 Kubernetes 里的分布式块存储,主要用来给 PVC 提供持久化存储。它不需要单独部署 Ceph 这种重型存储集群,直接使用各个 worker 节点上的本地磁盘,然后通过副本机制把数据分散到不同节点上。
我这里选择 Longhorn,主要是因为这几个点:
- 部署简单,直接用官方 YAML 就能跑起来。
- 原生支持 CSI,Pod 里直接挂 PVC。
- 支持卷副本,节点故障时可以从其他副本恢复。
- 支持快照、备份、扩容和 Web UI。
- 对小规模 Kubernetes 集群比较合适,维护成本比 Ceph 低很多。
Longhorn 的核心不是“共享一个目录”,而是“每个卷有多个副本”。比如一个 5Gi 的 PVC,如果副本数是 2,Longhorn 会保存两份数据。最好让这两个副本落在不同节点或者不同磁盘上。
副本数可以简单这样理解:
| 副本数 | 实际占用 | 容错能力 | 适合场景 |
|---|---|---|---|
1 |
PVC 容量 x 1 |
没有节点级容错 | 测试环境 |
2 |
PVC 容量 x 2 |
允许丢一个副本 | 小集群常用 |
3 |
PVC 容量 x 3 |
容错更好 | 节点数和磁盘空间充足时 |
容量按副本数计算:
实际占用容量 = PVC 容量 x 副本数
可用容量约等于 = Longhorn 总磁盘容量 / 副本数
比如两个 worker 节点,每个节点给 Longhorn 准备 500Gi 磁盘:
Longhorn 总容量 = 500Gi x 2 = 1000Gi
副本数 = 2
理论可用容量约等于 1000Gi / 2 = 500Gi
实际可用容量还要扣掉系统保留空间、Longhorn 调度预留空间、快照、备份和临时重建副本需要的空间,所以不要按满盘规划。
副本数不要乱设。两个 worker 节点就不要强行设 3 副本,副本调度不满,卷容易长期处于 Degraded。如果只有一个 worker 节点,那 Longhorn 只能提供本地盘能力,不能提供节点级容错。
还有一个比较重要的点:Longhorn 默认数据路径是:
/var/lib/longhorn
正式用不建议直接拿系统盘跑 Longhorn。最好提前准备一块单独的数据盘,挂载到 /var/lib/longhorn,然后再部署 Longhorn。这样系统盘和存储盘分开,后面排查、扩容、重装系统都更清楚。
0x01 部署前处理
每个需要承载 Longhorn 数据的 worker 节点都先准备好挂载目录:
mkdir -p /var/lib/longhorn
示例:把单独的数据盘挂载到 Longhorn 默认目录:
mount /dev/sdb1 /var/lib/longhorn
再写入 /etc/fstab 固化挂载:
blkid /dev/sdb1
vi /etc/fstab
UUID=这里替换成实际UUID /var/lib/longhorn ext4 defaults,noatime 0 2
确认挂载没问题:
df -h /var/lib/longhorn
如果 Longhorn 已经运行了一段时间,再去移动 /var/lib/longhorn,不要直接复制目录硬搬。应该先在 Longhorn UI 里禁用调度、驱逐副本,等数据迁移完成后再调整磁盘路径。
Longhorn 还依赖节点上的 iSCSI 工具。如果系统是 Debian/Ubuntu,可以先装:
apt install -y open-iscsi nfs-common
systemctl enable --now iscsid
如果系统是 CentOS/RHEL,可以先装:
yum install -y iscsi-initiator-utils nfs-utils
systemctl enable --now iscsid
其中 nfs-common / nfs-utils 主要用于 Longhorn RWX 卷。
0x02 部署
这边采用 kubectl YAML 方式,也可以用 Helm 方式部署。
下载 YAML
wget https://raw.githubusercontent.com/longhorn/longhorn/v1.11.2/deploy/longhorn.yaml
查看依赖镜像,修改成加速地址
grep -oE '[a-zA-Z0-9._-]+/[a-zA-Z0-9._/-]+:[a-zA-Z0-9._-]+' longhorn.yaml | sort -u
docker.io/longhornio/backing-image-manager:v1.11.2
docker.io/longhornio/csi-attacher:v4.11.0-20260428
docker.io/longhornio/csi-node-driver-registrar:v2.16.0-20260428
docker.io/longhornio/csi-provisioner:v5.3.0-20260428
docker.io/longhornio/csi-resizer:v2.1.0-20260428
docker.io/longhornio/csi-snapshotter:v8.5.0-20260428
docker.io/longhornio/livenessprobe:v2.18.0-20260428
docker.io/longhornio/longhorn-engine:v1.11.2
docker.io/longhornio/longhorn-instance-manager:v1.11.2
docker.io/longhornio/longhorn-manager:v1.11.2
docker.io/longhornio/longhorn-share-manager:v1.11.2
docker.io/longhornio/longhorn-ui:v1.11.2
docker.io/longhornio/support-bundle-kit:v0.0.84
替换成加速地址:
sed -i 's|docker\.io/longhornio/\([^: ]*\):\([^ "]*\)|swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/\1:\2-amd64|g' longhorn.yaml
再检查一次:
grep -oE '[a-zA-Z0-9._-]+/[a-zA-Z0-9._/-]+:[a-zA-Z0-9._-]+' longhorn.yaml | sort -u
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/backing-image-manager:v1.11.2-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/csi-attacher:v4.11.0-20260428-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/csi-node-driver-registrar:v2.16.0-20260428-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/csi-provisioner:v5.3.0-20260428-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/csi-resizer:v2.1.0-20260428-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/csi-snapshotter:v8.5.0-20260428-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/livenessprobe:v2.18.0-20260428-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/longhorn-engine:v1.11.2-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/longhorn-instance-manager:v1.11.2-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/longhorn-manager:v1.11.2-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/longhorn-share-manager:v1.11.2-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/longhorn-ui:v1.11.2-amd64
swr.cn-east-3.myhuaweicloud.com/itho/docker.io/longhornio/support-bundle-kit:v0.0.84-amd64
开始部署
kubectl apply -f longhorn.yaml
查看 Pod:
kubectl -n longhorn-system get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE
csi-attacher-79b46ddbb5-8mxpf 1/1 Running 1 (7m11s ago) 11m 10.244.36.206 k8s-worker-01
csi-attacher-79b46ddbb5-bfm5q 1/1 Running 1 (7m11s ago) 11m 10.244.36.207 k8s-worker-01
csi-attacher-79b46ddbb5-zzxz7 1/1 Running 4 (4m ago) 11m 10.244.118.79 k8s-worker-02
csi-provisioner-589b68df94-8jv2l 1/1 Running 4 (3m53s ago) 11m 10.244.118.80 k8s-worker-02
csi-provisioner-589b68df94-m5rp8 1/1 Running 4 (3m54s ago) 11m 10.244.118.81 k8s-worker-02
csi-provisioner-589b68df94-mbg2p 1/1 Running 0 11m 10.244.36.208 k8s-worker-01
csi-resizer-6686cb7b68-5282c 1/1 Running 4 (3m48s ago) 11m 10.244.118.82 k8s-worker-02
csi-resizer-6686cb7b68-7zl5v 1/1 Running 0 11m 10.244.36.210 k8s-worker-01
csi-resizer-6686cb7b68-wb89s 1/1 Running 0 11m 10.244.36.209 k8s-worker-01
csi-snapshotter-567bc6c575-5sn2z 1/1 Running 0 11m 10.244.36.211 k8s-worker-01
csi-snapshotter-567bc6c575-78r9h 1/1 Running 3 (4m33s ago) 11m 10.244.118.84 k8s-worker-02
csi-snapshotter-567bc6c575-jmncl 1/1 Running 3 (4m35s ago) 11m 10.244.118.83 k8s-worker-02
engine-image-ei-89a2d474-5qfkt 1/1 Running 0 12m 10.244.36.203 k8s-worker-01
engine-image-ei-89a2d474-5t482 1/1 Running 0 12m 10.244.118.77 k8s-worker-02
instance-manager-39bcec98d10b689799eff1e45a19367f 1/1 Running 0 11m 10.244.118.78 k8s-worker-02
instance-manager-c25d748ecd3392e94e4597b302d0eeac 1/1 Running 0 11m 10.244.36.204 k8s-worker-01
longhorn-csi-plugin-jgz58 3/3 Running 1 (5m44s ago) 11m 10.244.118.85 k8s-worker-02
longhorn-csi-plugin-n7zj5 3/3 Running 0 11m 10.244.36.212 k8s-worker-01
longhorn-driver-deployer-66dc8cf958-hn22t 1/1 Running 0 13m 10.244.118.75 k8s-worker-02
longhorn-manager-2r4rs 2/2 Running 0 13m 10.244.36.201 k8s-worker-01
longhorn-manager-lmh7c 2/2 Running 0 13m 10.244.118.74 k8s-worker-02
longhorn-ui-66b5b4dc7d-8fl2p 1/1 Running 0 13m 10.244.118.76 k8s-worker-02
longhorn-ui-66b5b4dc7d-9bxzl 1/1 Running 0 13m 10.244.36.202 k8s-worker-01
查看 StorageClass:
kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
csi-s3 ru.yandex.s3.csi Delete Immediate false 17h
longhorn (default) driver.longhorn.io Delete Immediate true 12m
longhorn-static driver.longhorn.io Delete Immediate true 12m
查看 Service:
kubectl get svc -n longhorn-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
longhorn-admission-webhook ClusterIP 10.104.158.115 <none> 9502/TCP 15m
longhorn-backend ClusterIP 10.96.13.116 <none> 9500/TCP 15m
longhorn-frontend ClusterIP 10.104.253.143 <none> 80/TCP 15m
longhorn-recovery-backend ClusterIP 10.97.147.135 <none> 9503/TCP 15m
0x03 暴露 Web UI
这里直接把 longhorn-frontend 改成 NodePort:
kubectl -n longhorn-system patch svc longhorn-frontend \
-p '{"spec":{"type":"NodePort","ports":[{"port":80,"targetPort":8000,"nodePort":30880}]}}'
访问地址:
http://节点IP:30880
如果只是临时看一下,也可以用 port-forward:
kubectl port-forward -n longhorn-system svc/longhorn-frontend 8080:80
然后访问:
http://localhost:8080
0x04 修改默认副本数
方法一:kubectl patch
kubectl -n longhorn-system patch settings.longhorn.io default-replica-count \
--type='merge' \
-p '{"value":"{\"v1\":\"2\",\"v2\":\"2\"}"}'
参数说明:
settings.longhorn.io:Longhorn 的自定义资源类型。default-replica-count:要改的设置项名称。--type='merge':合并更新,只改value字段。-p '...':新的 JSON 值。
方法二:kubectl edit
kubectl -n longhorn-system edit settings.longhorn.io default-replica-count
方法三:Longhorn UI
浏览器打开 Longhorn UI,进入 Settings,找到 Default Replica Count,直接改成 2。
常用查看命令
# 查看某个设置项的值
kubectl -n longhorn-system get settings.longhorn.io default-replica-count -o jsonpath='{.value}'
# 列出所有设置项
kubectl -n longhorn-system get settings.longhorn.io -o wide
Longhorn 的所有配置都是 settings.longhorn.io 资源,名称就是配置项,改 value 字段就行。
0x05 快速使用
直接创建 PVC
写一个 PVC,storageClassName 不填就会用默认的 longhorn:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 5Gi
在 Pod 中使用
apiVersion: v1
kind: Pod
metadata:
name: test-longhorn
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /data
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: my-pvc
在 Deployment 中使用
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: html
volumes:
- name: html
persistentVolumeClaim:
claimName: my-pvc
0x06 常用说明
关键特性
| 功能 | 说明 |
|---|---|
| 默认副本数 | 这里改成 2,数据在两个 worker 间冗余 |
| 扩容 | 支持,PVC 中改 storage 大小即可,allowVolumeExpansion: true |
| 快照/备份 | 通过 Longhorn UI 或 kubectl 操作 |
| UI 面板 | 可以用 NodePort 或 port-forward 访问 |
两个 StorageClass 区别
longhorn:默认 StorageClass,用于动态供给,创建 PVC 后自动创建/删除 PV。longhorn-static:用于预创建 PV 的场景。
几个注意点
- 副本数越高,容错越好,但容量消耗也越高。
- Longhorn 不适合把所有空间都打满,要给副本重建和快照留空间。
- 节点少于副本数时,卷会出现副本调度不满。
- 系统盘不要和 Longhorn 数据盘混用。
/var/lib/longhorn的挂载要在部署前处理好,并且确认重启后还能自动挂载。- 如果使用 RWX 卷,需要确认节点上 NFS 相关工具已经安装。