在Kubernetes集群中部署有状态服务时,你是否遇到过这样的困境:本地存储无法跨节点共享,导致Pod漂移后数据丢失;使用云厂商提供的块存储,又受限于特定云平台,无法实现多云或混合云部署?之前团队在自建K8s集群部署MySQL时,就因本地存储的局限性,每次节点故障都要手动迁移数据,耗时又容易出错。
Longhorn是由Rancher开源的云原生分布式块存储解决方案,基于Kubernetes CRD(自定义资源)实现,能将集群中节点的本地存储整合成分布式存储池,提供高可用、可扩展的块存储服务。本文从实战出发,讲解Longhorn的核心特性、部署方式及在K8s中使用Longhorn卷的完整流程,帮你解决云原生环境中的有状态服务存储难题。
一、先搞懂:Longhorn 是什么?为什么用它?
在了解部署前,先明确Longhorn的核心价值——它解决了K8s原生存储的哪些痛点:
- 本地存储的局限性:K8s节点的本地存储(
hostPath
、emptyDir
)无法跨节点共享,Pod迁移后数据丢失;Longhorn将多个节点的本地磁盘整合为分布式存储池,Pod在任意节点都能访问数据。 - 云厂商存储的绑定性:AWS EBS、阿里云云盘等块存储依赖特定云平台,无法在自建集群或多云环境中使用;Longhorn完全开源,支持任意K8s集群,无厂商锁定。
- 高可用缺失:单节点存储故障会导致服务中断;Longhorn默认将数据复制到3个节点(可配置副本数),单个节点故障时,自动切换到副本节点,保证数据不丢失。
Longhorn的核心特性包括:
- 支持动态卷供应(通过StorageClass);
- 自动数据备份与恢复;
- 卷快照(Snapshot)与克隆(Clone);
- 跨节点卷迁移;
- 基于UI的可视化管理。
二、环境准备:Longhorn 部署前提
部署Longhorn前,需确保K8s集群满足以下条件:
- K8s版本≥1.21(推荐1.24+,适配最新特性);
- 每个节点已安装
open-iscsi
(Longhorn依赖iSCSI协议挂载卷):
- CentOS/RHEL:
yum install -y iscsi-initiator-utils
- Ubuntu/Debian:
apt install -y open-iscsi
- 每个节点有空闲磁盘(或目录),用于存储Longhorn数据;
- 集群已安装
helm
(推荐3.8+,用于快速部署)。
验证open-iscsi
是否安装成功:
# 检查iscsid服务状态
systemctl status iscsid
# 输出 active (running) 表示正常
三、实战部署:用 Helm 安装 Longhorn
Longhorn官方推荐用Helm部署,步骤简单且便于后续升级。
1. 添加 Longhorn Helm 仓库
# 添加仓库
helm repo add longhorn https://charts.longhorn.io
# 更新仓库索引
helm repo update
2. 部署 Longhorn(默认配置)
# 创建命名空间
kubectl create namespace longhorn-system
# 安装Longhorn(默认配置,适合测试环境)
helm install longhorn longhorn/longhorn \
--namespace longhorn-system \
--version 1.5.1 # 指定版本(推荐使用最新稳定版)
3. 验证部署状态
# 查看Longhorn相关Pod(所有Pod状态应为Running)
kubectl get pods -n longhorn-system
# 查看Longhorn UI Service(获取访问地址)
kubectl get svc longhorn-frontend -n longhorn-system
# 输出示例:
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# longhorn-frontend ClusterIP 10.96.123.45 <none> 80/TCP 5m
4. 访问 Longhorn UI
默认情况下,Longhorn UI是ClusterIP类型,需通过端口转发访问:
# 端口转发(后台运行,可按Ctrl+C停止)
kubectl port-forward svc/longhorn-frontend -n longhorn-system 8080:80 &
# 访问UI:http://localhost:8080
# 默认账号密码:admin/admin(生产环境需修改默认密码)
登录UI后,可看到集群节点列表、存储池状态、卷管理等功能,后续的卷创建、快照、备份等操作都可通过UI或K8s YAML完成。
四、核心操作:在 K8s 中使用 Longhorn 卷
Longhorn部署完成后,通过StorageClass动态创建卷,供有状态服务使用(如MySQL、Redis)。
1. 查看 Longhorn StorageClass
Longhorn部署后会自动创建默认的StorageClass:
# 查看StorageClass,longhorn为默认存储类
kubectl get sc
# 输出示例:
# NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
# longhorn (default) driver.longhorn.io Delete Immediate true 10m
默认StorageClass的配置(可通过UI修改):
- 副本数:3(数据复制到3个节点);
- 备份策略:无(需手动配置备份目标);
- 卷扩缩容:支持(
ALLOWVOLUMEEXPANSION: true
)。
2. 创建 PVC(持久化卷声明)
通过PVC请求Longhorn卷,K8s会自动通过StorageClass创建PV(持久化卷):
# longhorn-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
namespace: default
spec:
accessModes:
- ReadWriteOnce # 读写模式(Longhorn支持ReadWriteOnce、ReadOnlyMany)
resources:
requests:
storage: 10Gi # 请求10GB存储
storageClassName: longhorn # 使用Longhorn StorageClass
创建PVC:
kubectl apply -f longhorn-pvc.yaml
# 查看PVC状态(STATUS为Bound表示创建成功)
kubectl get pvc mysql-pvc
# 输出示例:
# NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
# mysql-pvc Bound pvc-12345678-1234-1234-1234-1234567890ab 10Gi RWO longhorn 2m
3. 部署有状态服务(MySQL)
将PVC挂载到MySQL Pod,实现数据持久化:
# mysql-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-data # 挂载卷到容器内目录
mountPath: /var/lib/mysql # MySQL数据存储目录
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-pvc # 引用之前创建的PVC
部署MySQL:
kubectl apply -f mysql-deployment.yaml
# 查看Pod状态(Running表示部署成功)
kubectl get pods -l app=mysql
4. 验证数据持久化
进入MySQL容器写入测试数据,然后删除Pod,验证数据是否保留:
# 进入MySQL容器
kubectl exec -it $(kubectl get pods -l app=mysql -o jsonpath='{.items[0].metadata.name}') -- bash
# 登录MySQL并创建测试表
mysql -u root -p123456
mysql> create database test_db;
mysql> use test_db;
mysql> create table test_table (id int);
mysql> insert into test_table values (1);
mysql> exit;
exit
# 删除MySQL Pod(Deployment会自动重建新Pod)
kubectl delete pod $(kubectl get pods -l app=mysql -o jsonpath='{.items[0].metadata.name}')
# 等待新Pod启动后,验证数据是否存在
kubectl exec -it $(kubectl get pods -l app=mysql -o jsonpath='{.items[0].metadata.name}') -- mysql -u root -p123456 -e "use test_db; select * from test_table;"
# 输出示例:
# +------+
# | id |
# +------+
# | 1 |
# +------+
结果显示数据依然存在,说明Longhorn卷成功实现了数据持久化,即使Pod重建或迁移到其他节点,数据也不会丢失。
五、进阶功能:卷快照与备份
Longhorn的快照和备份功能是保障数据安全的关键,适合定期备份和误操作后的恢复场景。
1. 创建卷快照(通过 UI)
- 访问Longhorn UI,进入“Volumes”页面,找到
mysql-pvc
对应的卷; - 点击卷名称进入详情页,点击“Take Snapshot”;
- 输入快照名称(如
mysql-snapshot-20240520
),点击“Create”; - 快照创建完成后,在“Snapshots”列表中可查看。
2. 从快照恢复卷(通过 YAML)
如果数据丢失,可通过快照创建新的PVC:
# restore-from-snapshot.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc-restore
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: longhorn
dataSource:
name: mysql-snapshot-20240520 # 快照名称
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io
3. 配置备份目标(持久化备份)
默认快照存储在本地节点,如需异地备份,需配置备份目标(如S3、NFS):
- 进入Longhorn UI,点击“Settings”→“Backup”;
- 设置“Backup Target”(如S3地址:
s3://longhorn-backup@us-east-1/
); - 配置S3访问密钥(
AWS_ACCESS_KEY_ID
、AWS_SECRET_ACCESS_KEY
); - 点击“Save”,后续创建快照时可选择“Backup to Target”。
六、常见问题与解决方案
1. 问题1:Pod挂载Longhorn卷失败,日志显示“iscsi: failed to connect to target”
原因:节点未安装open-iscsi
或服务未启动。
解决:
# CentOS/RHEL
yum install -y iscsi-initiator-utils
systemctl start iscsid
systemctl enable iscsid
# Ubuntu/Debian
apt install -y open-iscsi
systemctl start iscsid
systemctl enable iscsid
2. 问题2:Longhorn卷副本数不足(显示“Degraded”)
原因:集群节点数少于副本数(默认3副本需至少3个节点),或部分节点磁盘空间不足。 解决:
- 增加集群节点到3个以上;
- 清理节点空闲磁盘,确保每个节点有足够空间;
- 降低副本数(UI中修改StorageClass的“Replica Count”为2)。
3. 问题3:PVC创建后一直处于“Pending”状态
原因:Longhorn控制器未正常运行,或StorageClass配置错误。 解决:
# 查看Longhorn控制器日志
kubectl logs deployment/longhorn-manager -n longhorn-system
# 检查StorageClass是否存在
kubectl get sc longhorn
总结
Longhorn作为云原生分布式块存储,完美解决了K8s有状态服务的存储难题,核心优势在于“去中心化”“高可用”“易扩展”。通过本文的实战,你已经掌握了:
- 用Helm部署Longhorn到K8s集群;
- 通过StorageClass和PVC动态创建Longhorn卷;
- 挂载Longhorn卷到有状态服务(MySQL),实现数据持久化;
- 使用快照和备份功能保障数据安全。
在实际项目中,建议根据业务需求调整Longhorn的副本数(核心服务用3副本,非核心服务用2副本)、备份策略(每日全量备份+增量备份),同时监控卷的使用情况,避免磁盘空间不足。掌握Longhorn,能让你在云原生环境中轻松管理有状态服务,摆脱存储方案的束缚。