前面学习了动态PV,确实帮助我们省略了创建和删除的步骤,但还是觉得麻烦,先要创建RBAC,再创建NFS的客户端的pod,再创建pvc,最后才能应用到pod里面。能不能更简化一点?今天介绍一款软件 Longhorn 他来帮我们再减轻一些操作。
可能提起Longhorn有些人不熟悉,但是他的出厂公司Rancher则大大有名。帮助了不少同学来学习K8S。Longhorn是一个轻量级且功能强大的云原生Kubernetes分布式存储平台,可以在任意基础设施上运行。
github地址:https://github.com/longhorn/longhornhttps://github.com/longhorn/longhorn
部署longhorn
1.安装插件
# CentOS/RHEL
yum install -y iscsi-initiator-utils
systemctl enable iscsid --now
# Ubuntu/Debian
apt-get install -y open-iscsi
systemctl enable open-iscsi --now
# 验证安装
which iscsiadm # 应输出:/usr/sbin/iscsiadm
2.下载yaml文件并修改
# 下载yaml文件 (202503月最新版)
# wget https://github.com/longhorn/longhorn/releases/download/v1.8.1/longhorn.yaml
# 修改标注内容,开放longhron-ui对外,方便访问管理
---
kind: Service
apiVersion: v1
metadata:
labels:
app: longhorn-ui
name: longhorn-frontend
namespace: longhorn-system
spec:
type: NodePort #这里改为nodeport
selector:
app: longhorn-ui
ports:
- name: http
port: 80
targetPort: http
nodePort: 30080 #修改nodeport对外端口
---
# 修改镜像地址1
# cat longhorn.yaml |grep "image:"
image: longhornio/longhorn-manager:master-head
image: longhornio/longhorn-share-manager:master-head
image: longhornio/longhorn-manager:master-head
image: longhornio/longhorn-manager:master-head
image: longhornio/longhorn-ui:master-head
修改为
image: m.daocloud.io/docker.io/longhornio/longhorn-manager:master-head
image: m.daocloud.io/docker.io/longhornio/longhorn-share-manager:master-head
image: m.daocloud.io/docker.io/longhornio/longhorn-manager:master-head
image: m.daocloud.io/docker.io/longhornio/longhorn-manager:master-head
image: m.daocloud.io/docker.io/longhornio/longhorn-ui:master-head
# 修改镜像地址2
command:
- longhorn-manager
- -d
- daemon
- --engine-image
- "longhornio/longhorn-engine:v1.8.1"
- --instance-manager-image
- "longhornio/longhorn-instance-manager:v1.8.1"
- --share-manager-image
- "longhornio/longhorn-share-manager:v1.8.1"
- --backing-image-manager-image
- "longhornio/backing-image-manager:v1.8.1"
- --support-bundle-manager-image
- "longhornio/support-bundle-kit:v0.0.52"
- --manager-image
- "longhornio/longhorn-manager:v1.8.1"
修改为
command:
- longhorn-manager
- -d
- daemon
- --engine-image
- "m.daocloud.io/docker.io/longhornio/longhorn-engine:v1.8.1"
- --instance-manager-image
- "m.daocloud.io/docker.io/longhornio/longhorn-instance-manager:v1.8.1"
- --share-manager-image
- "m.daocloud.io/docker.io/longhornio/longhorn-share-manager:v1.8.1"
- --backing-image-manager-image
- "m.daocloud.io/docker.io/longhornio/backing-image-manager:v1.8.1"
- --support-bundle-manager-image
- "m.daocloud.io/docker.io/longhornio/support-bundle-kit:v0.0.52"
- --manager-image
- "m.daocloud.io/docker.io/longhornio/longhorn-manager:v1.8.1"
# 修改镜像地址3
- name: CSI_ATTACHER_IMAGE
value: "longhornio/csi-attacher:v4.8.1"
- name: CSI_PROVISIONER_IMAGE
value: "longhornio/csi-provisioner:v5.2.0"
- name: CSI_NODE_DRIVER_REGISTRAR_IMAGE
value: "longhornio/csi-node-driver-registrar:v2.13.0"
- name: CSI_RESIZER_IMAGE
value: "longhornio/csi-resizer:v1.13.2"
- name: CSI_SNAPSHOTTER_IMAGE
value: "longhornio/csi-snapshotter:v8.2.0"
- name: CSI_LIVENESS_PROBE_IMAGE
value: "longhornio/livenessprobe:v2.15.0"
修改为
- name: CSI_ATTACHER_IMAGE
value: "m.daocloud.io/docker.io/longhornio/csi-attacher:v4.8.1"
- name: CSI_PROVISIONER_IMAGE
value: "m.daocloud.io/docker.io/longhornio/csi-provisioner:v5.2.0"
- name: CSI_NODE_DRIVER_REGISTRAR_IMAGE
value: "m.daocloud.io/docker.io/longhornio/csi-node-driver-registrar:v2.13.0"
- name: CSI_RESIZER_IMAGE
value: "m.daocloud.io/docker.io/longhornio/csi-resizer:v1.13.2"
- name: CSI_SNAPSHOTTER_IMAGE
value: "m.daocloud.io/docker.io/longhornio/csi-snapshotter:v8.2.0"
- name: CSI_LIVENESS_PROBE_IMAGE
value: "m.daocloud.io/docker.io/longhornio/livenessprobe:v2.15.0"
2.应用yaml文件
可以看到创建了一个 longhorn-system 的namespace和一大堆的资源
如果使用的是VMware虚拟机,可能会有个报错
# journalctl -u multipathd -f
-- Logs begin at Thu 2025-02-06 18:06:45 CST. --
Mar 28 18:02:54 k8s-master multipathd[741]: sda: failed to get sysfs uid: Invalid argument
Mar 28 18:02:54 k8s-master multipathd[741]: sda: failed to get sgio uid: No such file or directory
Mar 28 18:02:59 k8s-master multipathd[741]: sda: add missing path
Mar 28 18:02:59 k8s-master multipathd[741]: sda: failed to get udev uid: Invalid argument
Mar 28 18:02:59 k8s-master multipathd[741]: sda: failed to get sysfs uid: Invalid argument
Mar 28 18:02:59 k8s-master multipathd[741]: sda: failed to get sgio uid: No such file or directory
Mar 28 18:03:04 k8s-master multipathd[741]: sda: add missing path
# 解决办法 编辑配置文件
sudo vi /etc/multipath.conf
# 添加以下内容
blacklist {
devnode "^sda"
}
3.验证longhorn
pod验证
如果所有pod都正常启动,正常显示应该如下图,如果发现只在部分节点运行,则查看是否有污染的情况
# kubectl describe nodes <node> | grep Taint
web页面验证
masterIP:30080 记得这里是开启了NodePort,需要做好安全策略,以防入侵
下图可知目前创建了0个卷,2个节点,合计有38G的可用空间。
注意:
- longhorn是分布式块存储,与分布式文件系统不同(mfs,lizardfs),不同超过pv设置的存储大小
- 使用dd命令测试(bs=1m,count=1024或者bs=500k,count=2048),发现longhorn的存储性能不及本地磁盘
- longhorn性能要远超nfs-client-provisioner提供的存储性能(2-3倍)
举例验证
在日常使用中,运行数据库的Pod,如果发生故障,相关业务也无法继续,这时你会失去客户、失去订单。在这里,就以一个mysql的pod举例,为它配置一个新的Longhorn持久卷
1.创建pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
labels:
type: longhorn
app: example
spec:
storageClassName: longhorn #类型为longhorn
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
2.创建一个mysql.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-mysql
labels:
app: example
spec:
selector:
matchLabels:
app: example
tier: mysql
strategy:
type: Recreate
template:
metadata:
labels:
app: example
tier: mysql
spec:
containers:
- image: m.daocloud.io/docker.io/mysql:5.6
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: password
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim #对应pvc的名字
应用后查看pod,pv,pvc
通过下图可以看到,pvc已经绑定成功
mysql写入数据后,删除pod
root@k8s-master:~/longhorn# kubectl exec -it my-mysql-7f8f897d85-4zmpx -- /bin/bash
root@my-mysql-7f8f897d85-4zmpx:/# mysql -u root -p mysql
Enter password: #密码为yaml文件中设置的password
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.51 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> create database k8s; #创建一个K8s的数据库
Query OK, 1 row affected (0.00 sec)
mysql> exit
Bye
root@my-mysql-7f8f897d85-4zmpx:/# exit
exit
删除这个mysql pod
root@k8s-master:~/longhorn# kubectl delete pod my-mysql-7f8f897d85-4zmpx
pod "my-mysql-7f8f897d85-4zmpx" deleted
大约一分钟之后,我们将再次寻找新的容器名称,连接到该容器名称,看看我们的数据库是否仍然存在,发现新的pod依然使用了之前的存储卷,并且数据还在。
root@k8s-master:~/longhorn# kubectl get pods | grep mysql
my-mysql-7f8f897d85-hkrp9 1/1 Running 0 27s
root@k8s-master:~/longhorn# kubectl exec -it my-mysql-7f8f897d85-hkrp9 -- /bin/bash
root@my-mysql-7f8f897d85-hkrp9:/# mysql -u root -p mysql
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.51 MySQL Community Server (GPL)
Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> show databases;
+---------------------+
| Database |
+---------------------+
| information_schema |
| k8s |
| #mysql50#lost+found |
| mysql |
| performance_schema |
+---------------------+
5 rows in set (0.00 sec)
mysql>
卸载longhorn
参考官网文档
Longhorn | Documentationhttps://longhorn.io/docs/1.8.1/deploy/uninstall/#uninstalling-longhorn-using-kubectl具体步骤如下,记得切换版本号,保持和安装的版本一致
Uninstalling Longhorn using kubectl
-
Create the uninstallation job to clean up CRDs from the system and wait for success:
kubectl create -f https://raw.githubusercontent.com/longhorn/longhorn/v1.8.1/uninstall/uninstall.yaml kubectl get job/longhorn-uninstall -n longhorn-system -w
Example output:
$ kubectl create -f https://raw.githubusercontent.com/longhorn/longhorn/v1.8.1/uninstall/uninstall.yaml serviceaccount/longhorn-uninstall-service-account created clusterrole.rbac.authorization.k8s.io/longhorn-uninstall-role created clusterrolebinding.rbac.authorization.k8s.io/longhorn-uninstall-bind created job.batch/longhorn-uninstall created $ kubectl get job/longhorn-uninstall -n longhorn-system -w NAME COMPLETIONS DURATION AGE longhorn-uninstall 0/1 3s 3s longhorn-uninstall 1/1 20s 20s
-
Remove remaining components:
kubectl delete -f https://raw.githubusercontent.com/longhorn/longhorn/v1.8.1/deploy/longhorn.yaml kubectl delete -f https://raw.githubusercontent.com/longhorn/longhorn/v1.8.1/uninstall/uninstall.yaml
总结
在安装了longhorn之后,我们就不需要关心底层实现是什么和实现的过程,只需要创建pvc+pod开箱即用,大大方便我们再k8s中使用存储。
以下是通过deepseek生成的 PV、StorageClass 和 Longhorn 的核心区别对比,结合 Kubernetes 存储架构与 Longhorn 的特性整理:
区别对照表:
维度 | PV (PersistentVolume) | StorageClass | Longhorn |
---|---|---|---|
定位 | 集群级别的存储资源实体,如 NFS 卷、云盘等 | 存储策略模板,用于动态生成 PV | 云原生分布式块存储系统,提供存储后端实现 |
核心功能 | 代表实际存储空间,与底层存储系统绑定 | 定义动态 PV 的创建规则(如存储类型、副本策略) | 实现分布式块存储,支持快照、备份、跨集群容灾等 |
创建方式 | 管理员手动创建(静态供应) | 管理员定义模板(如 provisioner 和参数) | 通过 Helm 或 YAML 部署,集成到 Kubernetes 集群 |
生命周期 | 独立于 Pod,可被多个 PVC 绑定(需回收策略支持) | 长期存在,用于动态生成 PV | 与 Kubernetes 集群共存,通过 Operator 管理存储资源 |
动态供应 | 不支持,需预先创建 | 核心动态供应机制,调用存储插件(如 Longhorn)自动生成 PV | 作为 StorageClass 的 provisioner ,提供动态 PV 创建能力 |
访问模式 | 支持 ReadWriteOnce 、ReadOnlyMany 、ReadWriteMany | 通过参数定义 PV 的默认访问模式 | 支持 RWO 和 RWX(需 NFS 或 CSI 插件) |
多租户隔离 | 无原生隔离,依赖存储系统实现 | 通过不同 StorageClass 隔离存储策略(如 SSD/HDD) | 提供多副本隔离,支持跨节点调度(如 nodeSelector ) |
典型使用场景 | 静态分配存储资源(如固定大小的云盘) | 自动化按需分配存储(如开发环境快速创建卷) | 分布式有状态应用(如 MySQL 集群)、跨集群灾备 |
与 Kubernetes 的集成 | 通过 PVC 绑定使用,需手动维护 | 通过 provisioner 字段关联存储插件(如 driver.longhorn.io ) | 提供 CSI 驱动,与 StorageClass 协同实现动态存储供应 |
高可用机制 | 依赖底层存储的高可用(如云盘冗余) | 无直接高可用功能,依赖存储后端实现 | 通过多副本(3 副本默认)和分布式控制器实现跨节点容灾 |
关键差异总结:
1.抽象层级
- PV 是具体的存储资源实体,属于静态资源;StorageClass 是动态资源模板;Longhorn 是底层存储系统的实现。
- 三者关系:StorageClass 动态生成 PV → PVC 绑定 PV → Longhorn 提供底层存储支持。
2.运维复杂度
- PV 需手动维护,适合固定规模场景;StorageClass 通过自动化降低运维成本;Longhorn 提供完整的存储管理界面和运维工具。
3.功能扩展性
- Longhorn 支持高级功能(如增量快照、跨集群备份),而原生 PV/StorageClass 需依赖存储插件实现。
4.生产建议
- 静态场景:直接使用 PV + PVC;
- 动态场景:优先采用 StorageClass + Longhorn 组合,实现弹性扩展和高可用。