前面学习了动态PV,确实帮助我们省略了创建和删除的步骤,但是要还是觉得麻烦,先要创建RBAC,再创建NFS的客户端的pod,再创建pvc,最后才能应用到pod里面。能不能更简化一点?今天介绍一款软件 Longhorn 他来帮我们再减轻一些操作。
可能提起Longhorn有些人不熟悉,但是他的出厂公司Rancher则大大有名。帮助了不少同学来学习K8S。Longhorn是一个轻量级且功能强大的云原生Kubernetes分布式存储平台,可以在任意基础设施上运行。Longhorn与Rancher结合使用,将帮助您在Kubernetes环境中轻松、快速和可靠地部署高可用性持久化块存储。
官网地址:Longhorn | 强大的云原生Kubernetes储存平台 | Rancher Longhorn 是由Rancher研发的容器存储解决方案,Longhorn 已作为沙箱(Sandbox)项目加入CNCF社区。Longhorn 提供了一种简单、轻量、极适用于容器和K8S的持久化存储解决方案,Longhorn 同时极大地简化了用户部署、使用和管理的工作。https://www.rancher.cn/products/longhorn/
github地址:https://github.com/longhorn/longhornhttps://github.com/longhorn/longhorn
# 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
# 下载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"
}
如果所有pod都正常启动,正常显示应该如下图,如果发现只在部分节点运行,则查看是否有污染的情况
# kubectl describe nodes | grep Taint
masterIP:30080 记得这里是开启了NodePort,需要做好安全策略,以防入侵
下图可知目前创建了0个卷,2个节点,合计有38G的可用空间。
注意:
在日常使用中,运行数据库的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 | Documentationhttps://longhorn.io/docs/1.8.1/deploy/uninstall/#uninstalling-longhorn-using-kubectl具体步骤如下,记得切换版本号,保持和安装的版本一致
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
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.抽象层级
2.运维复杂度
3.功能扩展性
4.生产建议