Kubernetes 集群部署 Longhorn 分布式存储完全指南
本指南专为 1 主 2 从(3 节点) 的 Kubernetes 集群设计,旨在构建一个高可用、支持动态供给的分布式存储系统。
📋 核心概念速览
在开始之前,了解几个关键概念有助于理解后续操作:
- StorageClass (存储类): 定义存储的“模板”(如副本数、性能策略)。K8s 通过它实现动态供给。
- PVC (PersistentVolumeClaim): 用户提出的“存储申请单”(我要 10G 空间)。
- PV (PersistentVolume): 实际分配出来的“存储资源”,由 StorageClass 自动创建。
- Replica (副本): Longhorn 会将你的数据复制多份(默认 3 份),分散在不同节点,防止单点故障。
- Degraded (降级): 当实际副本数 < 设定副本数时的状态(例如设定 3 份,但只成功了 2 份)。数据依然可用,但冗余度降低。
1️⃣ 前置准备:安装系统依赖
Longhorn 基于 iSCSI 协议提供块存储,因此集群中的每一个节点(包括 Master)都必须安装 open-iscsi 发起器。
🛠️ 操作步骤
请在 Master、Worker1、Worker2 所有节点上分别执行以下命令:
Ubuntu / Debian 系统
# 1. 更新软件源
sudo apt-get update
# 2. 安装 open-iscsi (核心依赖) 和 nfs-common (辅助依赖)
sudo apt-get install -y open-iscsi nfs-common
# 3. 启动服务并设置开机自启
# 解释:ensure iscsid daemon runs on boot and starts now
sudo systemctl enable iscsid
sudo systemctl start iscsid
# 4. 【验证步骤】检查服务状态
# 预期输出应包含 "active (running)"
systemctl status iscsid
CentOS / RHEL / Rocky Linux 系统
# 1. 安装依赖包
sudo yum install -y iscsi-initiator-utils nfs-utils
# 2. 启动服务
sudo systemctl enable iscsid
sudo systemctl start iscsid
# 3. 【验证步骤】
systemctl status iscsid
💡 原理解释:如果没有安装这个服务,当 Pod 尝试挂载 Longhorn 卷时,K8s 节点无法识别 iSCSI 设备,Pod 会卡在 ContainerCreating 状态并报错 mount failed。
2️⃣ 部署 Longhorn
🚀 方法 A:一键部署(推荐)
官方 YAML 文件已经内置了大多数场景所需的配置,包括对 Master 节点常见污点(Taints)的容忍度。
# 应用官方最新稳定版 (v1.7.0)
kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.7.0/deploy/longhorn.yaml
🔧 方法 B:处理调度失败(如果 Master 节点没跑起来)
如果在部署后发现 Master 节点上没有 longhorn-manager Pod,说明集群的污点比较特殊。我们需要手动添加容忍度。
- 下载配置文件:
curl -L https://raw.githubusercontent.com/longhorn/longhorn/v1.7.0/deploy/longhorn.yaml -o longhorn-custom.yaml
- 编辑文件 (
vim longhorn-custom.yaml):
找到kind: DaemonSet且name: longhorn-manager的部分,在spec.template.spec层级下,确保tolerations包含以下内容:
tolerations:
# 容忍新版 K8s 的控制平面污点
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
# 容忍旧版 K8s 的 master 污点
- key: "node-role.kubernetes.io/master"
operator: "Exists"
effect: "NoSchedule"
# 容忍云厂商未初始化污点
- key: "node.cloudprovider.kubernetes.io/uninitialized"
operator: "Exists"
effect: "NoSchedule"
注意:tolerations 必须与 containers 平级,缩进要正确。
- 应用配置:
kubectl apply -f longhorn-custom.yaml
✅ 验证部署状态
关键检查点:确认 longhorn-manager 是否在 所有 3 个节点 上都运行了。
kubectl get pods -n longhorn-system -o wide
✅ 成功标准:
你应该看到 3 个 longhorn-manager-xxx Pod,它们的 NODE 列分别对应:
masterwork1work2
如果某个节点缺失,请检查该节点的 iscsid 服务或查看 Pod 日志 (kubectl logs -n longhorn-system <pod-name>)。
3️⃣ 访问 Longhorn 管理界面 (UI)
Longhorn 提供了一个强大的 Web UI 用于监控和管理存储。默认服务类型是 ClusterIP(仅限集群内访问)。
🌐 方式一:端口转发(最安全,适合临时调试)
在你的本地电脑终端执行(需要本地配置了 kubectl):
kubectl -n longhorn-system port-forward svc/longhorn-frontend 8080:80
然后在浏览器访问:http://localhost:8080
💡 提示:如果你是在远程服务器上操作且没有本地 kubectl,可以使用 SSH 隧道:ssh -L 8080:10.96.x.x:80 root@<Master-IP> (其中 10.96.x.x 是 kubectl get svc -n longhorn-system 查到的 longhorn-frontend IP)。
🌍 方式二:配置 Ingress(适合生产/长期访问)
如果你集群内有 Nginx Ingress Controller,可以配置域名访问。
创建 longhorn-ingress.yaml:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: longhorn-ingress
namespace: longhorn-system
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "false"
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: longhorn.example.com # 替换为你的实际域名
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: longhorn-frontend
port:
number: 80
应用后,解析域名到 Ingress IP 即可访问。
4️⃣ 实战测试:动态存储供给
我们将部署一个 Nginx 应用,它会自动触发 PVC 创建,验证“动态供给”功能。
📝 创建测试清单
创建文件 nginx-test.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-longhorn-test
labels:
app: nginx-longhorn
spec:
replicas: 1
selector:
matchLabels:
app: nginx-longhorn
template:
metadata:
labels:
app: nginx-longhorn
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
# 将存储卷挂载到 Nginx 的网页目录
- name: data-volume
mountPath: /usr/share/nginx/html
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: longhorn-dynamic-pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: longhorn-dynamic-pvc
spec:
accessModes:
- ReadWriteOnce # 读写模式:单节点读写
# 不指定 storageClassName,K8s 会自动使用标记为 (default) 的 'longhorn' 类
resources:
requests:
storage: 1Gi # 申请 1GB 空间
🏃 执行与验证
- 部署应用:
kubectl apply -f nginx-test.yaml
- 观察状态变化:
# 监视 PVC 状态,应从 Pending -> Bound
kubectl get pvc longhorn-dynamic-pvc -w
# 监视 Pod 状态,应从 ContainerCreating -> Running
kubectl get pods -l app=nginx-longhorn -w
💡 原理解释:当你创建 PVC 时,K8s 发现没有对应的 PV。它会查找默认的 StorageClass (longhorn),调用 Longhorn 的 CSI Provisioner。Provisioner 会在后台创建 3 个副本(分布在 3 个节点),生成 PV,并绑定给 PVC。全过程无需人工干预。
- 写入测试数据:
kubectl exec -it deploy/nginx-longhorn-test -- bash -c "echo '<h1>Hello from Longhorn HA Storage!</h1>' > /usr/share/nginx/html/index.html"
- 验证持久化(模拟故障):
删除 Pod,让 K8s 重新调度一个新的 Pod。如果存储是持久的,新 Pod 应该能读到刚才写的文件。
# 删除 Pod
kubectl delete pod -l app=nginx-longhorn
# 等待新 Pod 运行 (约 10-20 秒)
kubectl get pods -l app=nginx-longhorn -w
# 再次读取文件
kubectl exec -it deploy/nginx-longhorn-test -- cat /usr/share/nginx/html/index.html
✅ 成功标志:输出依然是 <h1>Hello from Longhorn HA Storage!</h1>。
5️⃣ 故障排查与深度优化
⚠️ 常见问题:Volume 状态显示 Degraded (降级)
现象:在 UI 中看到卷状态为黄色 Degraded,提示 Scheduling Failure。
原因:Longhorn 默认策略是 3 副本。如果你的集群只有 2 个节点可用,或者某个节点磁盘空间不足(小于预留空间 + 卷大小),第 3 个副本就无法创建,导致状态降级。
解决方案:
- 检查磁盘空间:
-
- 进入 UI -> Node。
- 点击节点名称,查看 Storage Available 是否大于 Storage Reserved。
- 如果空间紧张,点击 Edit Disk,将
Storage Reserved调小(例如从 7Gi 改为 2Gi),保存。
- 手动修复副本:
-
- 如果空间足够但依然报错,可能是调度器卡住。
- 进入 UI -> Volume -> 点击故障卷。
- 删除那个灰色的、失败的 Replica。
- 点击 Add Replica,手动选择缺失的那个节点(如
master),强制添加。
- 验证恢复:
-
- 操作后,卷状态应在几秒内变为绿色
Healthy。 - 在 Replicas 列表中确认有 3 个蓝色健康的副本,分别位于 3 个不同节点。
- 操作后,卷状态应在几秒内变为绿色
🔍 如何查看数据物理位置?
如果你想确认数据真的存在磁盘上:
- 逻辑查看(在 Pod 内):
kubectl exec -it <pod-name> -- ls -lh /usr/share/nginx/html
- 物理查看(在节点上):
-
- 在 UI 的 Volume 详情页,记下 Replica 的路径(例如
/var/lib/longhorn/replicas/pvc-xxx...)。 - SSH 登录对应节点,进入该目录:
- 在 UI 的 Volume 详情页,记下 Replica 的路径(例如
cd /var/lib/longhorn/replicas/pvc-xxx...
ls -lh
-
- 你会看到
volume-head-000.img等文件,你的数据就以二进制形式存储在这个镜像文件中。
- 你会看到
🎉 总结
至此,你已经成功完成:
- ✅ 在 3 节点集群上部署了 Longhorn。
- ✅ 实现了 Master 节点参与存储(3 副本高可用)。
- ✅ 验证了 PVC 的动态创建和数据持久化。
- ✅ 掌握了 UI 监控和故障修复方法。
你的 Kubernetes 集群现在拥有了生产级的分布式存储能力,可以安心部署数据库、中间件等有状态应用了!
更多推荐
所有评论(0)