AI Infra 训练营
总览
  • 总览
  • 完整安装
  • 核心 K8s
  • Cilium 网络
  • Longhorn 存储
  • 监控日志
  • CI / GitOps
  • 安全准入
  • CI/CD 实战(MySQL+Go+Vue)
  • HPA/Ingress/Hubble 实战
  • 面试速查 + 真实踩坑
  • Day 0 · 新手接管 Runbook
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
命令手册
HiHuo 主站
GitHub
总览
  • 总览
  • 完整安装
  • 核心 K8s
  • Cilium 网络
  • Longhorn 存储
  • 监控日志
  • CI / GitOps
  • 安全准入
  • CI/CD 实战(MySQL+Go+Vue)
  • HPA/Ingress/Hubble 实战
  • 面试速查 + 真实踩坑
  • Day 0 · 新手接管 Runbook
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
命令手册
HiHuo 主站
GitHub
  • 实操 Runbook

    • Runbook 总览:从零部署、查看、调试
    • 完整安装总 Runbook:5 台 Ubuntu 到可用平台
    • 核心 K8s Runbook:apiserver / etcd / kubelet / containerd / HAProxy
    • Cilium 网络 Runbook:安装、查看、调试
    • Longhorn 存储 Runbook:安装、查看、调试
    • 监控日志 Runbook:Prometheus / Grafana / Loki / Alertmanager
    • CI / GitOps Runbook:Harbor / Gitea / Jenkins / Kaniko / ArgoCD
    • 安全准入 Runbook:RBAC / PSA / Kyverno / ResourceQuota
    • 实战 Runbook:MySQL + Go + Vue 全链路 CI/CD 真实发布
    • 实战 Runbook:给应用加 HPA 自动扩缩 + Ingress 域名 + Hubble 流量观测
    • 面试速查:这套平台 + 高频问答 + 真实踩坑

Longhorn 存储 Runbook:安装、查看、调试

Longhorn 是本集群的分布式块存储。它让 Pod 可以申请 PVC,Pod 重启或迁移后数据还在。


1. Longhorn 解决什么问题

没有 Longhorn 时:

  • Pod 的容器文件系统随 Pod 删除而消失。
  • 数据库、Jenkins、Grafana、Harbor 这类有状态服务不能稳定落盘。
  • 节点坏了,本地盘上的数据很难恢复。

Longhorn 做的事:

  • 提供默认 StorageClass。
  • PVC 自动创建 Longhorn Volume。
  • Volume 有多个 replica,分散在不同节点。
  • CSI 负责把卷 attach/mount 到运行 Pod 的节点。
  • UI 能查看卷、replica、snapshot、backup。

为什么选 Longhorn:学习和中小集群运维成本低,有 UI,概念比 Ceph 简单。


2. 安装前置

5 台节点都要有:

apt-get update
apt-get install -y open-iscsi nfs-common jq
systemctl enable --now iscsid
modprobe iscsi_tcp
echo iscsi_tcp > /etc/modules-load.d/iscsi_tcp.conf
mkdir -p /var/lib/longhorn

为什么:

  • Longhorn RWO 块卷通过 iSCSI/engine 暴露给 kubelet。
  • RWX 卷需要 NFS client。
  • /var/lib/longhorn 是 Longhorn 数据目录。

先看清磁盘布局,别把 Longhorn 数据写到小盘上:

ssh root@<ip> 'lsblk -f -o NAME,FSTYPE,SIZE,MOUNTPOINT; df -h /'

本集群真实布局(重装后实测,和老笔记不一样):

vda    30G            ← 系统盘
└─vda1 ext4 29.9G /   ← 根分区,只有 ~24G 可用
vdb    100G           ← 数据盘
└─vdb1 ext4 100G /www ← 100G 大盘挂在 /www

问题:Longhorn 默认数据目录是 /var/lib/longhorn,落在只有 24G 的根盘上;而 100G 大盘空在 /www。生产应让 Longhorn 用大盘。

最省事、对 runbook 其它步骤零改动的办法:用 bind mount 把 /var/lib/longhorn 指到大盘上的目录。5 台都做:

ssh root@<ip> '
  mkdir -p /www/longhorn /var/lib/longhorn
  mountpoint -q /var/lib/longhorn || mount --bind /www/longhorn /var/lib/longhorn
  grep -q "/var/lib/longhorn" /etc/fstab || echo "/www/longhorn /var/lib/longhorn none bind 0 0" >> /etc/fstab
  df -h /var/lib/longhorn          # 应显示挂载源 /dev/vdb1、可用 ~80G+
'

mount --bind A B:把目录 A 再挂到路径 B,之后读写 B 实际落在 A 所在的文件系统上。写进 /etc/fstab 才能重启后保留。Longhorn 仍按默认路径 /var/lib/longhorn 工作,但字节落在 100G 的 vdb1 上。

⚠️ 别 mkfs /dev/vdb——它已经有数据(挂在 /www)。只在里面建子目录 /www/longhorn,不碰 /www 本身。


3. 安装 Longhorn

kubectl create namespace longhorn-system

kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.7.2/deploy/longhorn.yaml

小集群要允许 Longhorn 跑在 control-plane 节点(本集群只有 2 个 worker,默认 3 副本凑不齐,必须让控制面也当存储节点):

kubectl patch setting taint-toleration -n longhorn-system --type=merge \
  -p '{"value":"node-role.kubernetes.io/control-plane:NoSchedule;node-role.kubernetes.io/master:NoSchedule"}'

⚠️ 只改这个设置不够(实测坑)。taint-toleration 设置只作用于 Longhorn 系统托管组件(instance-manager / CSI 等),不会自动给 longhorn.yaml 部署的 longhorn-manager DaemonSet 加 toleration。结果:longhorn-manager 的 tolerations 仍为空,只跑在 2 个 worker 上(kubectl get ds longhorn-manager -n longhorn-system 看到 DESIRED 2),存储节点只有 2 个。

还要直接给这三个用户部署的组件补 toleration:

TOL='[{"op":"add","path":"/spec/template/spec/tolerations","value":[
  {"key":"node-role.kubernetes.io/control-plane","operator":"Exists","effect":"NoSchedule"},
  {"key":"node-role.kubernetes.io/master","operator":"Exists","effect":"NoSchedule"}]}]'
for r in ds/longhorn-manager deploy/longhorn-driver-deployer deploy/longhorn-ui; do
  kubectl patch -n longhorn-system $r --type=json -p "$TOL"
done

改完 longhorn-manager 应扩到 DESIRED 5 / READY 5,5 个节点都成为存储节点。

暴露 UI:

kubectl patch svc longhorn-frontend -n longhorn-system \
  -p '{"spec":{"type":"NodePort","ports":[{"port":80,"targetPort":8000,"nodePort":31172}]}}'

设置默认 StorageClass:

kubectl patch storageclass longhorn \
  -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

4. 安装后验收

kubectl get pods -n longhorn-system -o wide
kubectl get sc
kubectl get csidrivers
kubectl get nodes.longhorn.io -n longhorn-system
kubectl get volumes.longhorn.io -n longhorn-system

真实输出(健康时):

$ kubectl get sc
NAME                 PROVISIONER          RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION
longhorn (default)   driver.longhorn.io   Delete          Immediate           true
longhorn-static      driver.longhorn.io   Delete          Immediate           true

$ kubectl get csidrivers
NAME                 ATTACHREQUIRED   PODINFOONMOUNT   MODES        AGE
driver.longhorn.io   true             true             Persistent   6m

$ kubectl get nodes.longhorn.io -n longhorn-system
NAME       READY   ALLOWSCHEDULING
k8s-cp-1   True    true       ← 5 个都 True,说明 5 个存储节点就位
k8s-cp-2   True    true
k8s-cp-3   True    true
k8s-w-1    True    true
k8s-w-2    True    true

期望:

  • longhorn-manager 每节点都有(5 个)。
  • longhorn-csi-plugin 每节点都有,且 3/3 Running。
  • driver.longhorn.io 出现在 kubectl get csidrivers。
  • longhorn StorageClass 是默认(名字后带 (default))。

⚠️ 刚装完 / 刚改完 toleration 时,CSI 边车可能短暂 CrashLoopBackOff(实测)。csi-attacher / csi-provisioner / csi-resizer / csi-snapshotter / longhorn-csi-plugin 报:

Failed to connect to the CSI driver ... /csi/csi.sock ... context deadline exceeded
Failed to initialize Longhorn API client: Get "http://longhorn-backend:9500/v1/..." context deadline exceeded

原因:longhorn-manager 刚因 toleration 改动在重排,longhorn-backend Service 的 endpoints 短暂不稳,CSI 组件连不上后端 API。等 manager 全部 2/2 Running、Service endpoints 齐了,删掉这些 CrashLoop pod 让控制器重建即可(绕过 backoff 退避):

kubectl get pods -n longhorn-system --no-headers | grep -vE 'Running|Completed' \
  | awk '{print $1}' | xargs -r kubectl delete pod -n longhorn-system

验证后端通:kubectl exec -n longhorn-system <任一 longhorn-manager> -c longhorn-manager -- curl -sS -o /dev/null -w '%{http_code}' http://longhorn-backend:9500/v1/,返回 301/200 即正常。


5. 创建 PVC 验证

kubectl create ns storage-test

cat <<'EOF' | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
  namespace: storage-test
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: longhorn
---
apiVersion: v1
kind: Pod
metadata:
  name: writer
  namespace: storage-test
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh", "-c", "date >> /data/hello.txt; sleep 3600"]
    volumeMounts:
    - mountPath: /data
      name: data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: data
EOF

kubectl wait -n storage-test --for=condition=Ready pod/writer --timeout=120s
kubectl exec -n storage-test writer -- cat /data/hello.txt

查 Longhorn 卷:

kubectl get pvc,pv -n storage-test
kubectl get volumes.longhorn.io -n longhorn-system
kubectl get replicas.longhorn.io -n longhorn-system | grep pvc-

成功长这样(真实输出):

$ kubectl exec -n storage-test writer -- cat /data/hello.txt
Thu May 28 07:40:15 UTC 2026          ← 数据真的写进卷了

$ kubectl get pvc -n storage-test
NAME   STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS
data   Bound    pvc-efe3f0fb-38bf-42e3-a81e-1db083e4fbc3   1Gi        RWO            longhorn
       ^^^^^ Bound = 动态制备成功;PV 名 pvc-xxx 由 Longhorn 自动创建

$ kubectl get volumes.longhorn.io -n longhorn-system \
    -o custom-columns=NAME:.metadata.name,STATE:.status.state,ROBUSTNESS:.status.robustness
NAME        STATE      ROBUSTNESS
pvc-efe3..  attached   healthy        ← attached=已挂到 Pod 所在节点;healthy=3 副本齐

✅ 验证点:PVC Bound + 能读到写入内容 + 卷 attached/healthy。 ⚠️ 若卡在 Pending(PVC)或 degraded(卷),分别见 7.1 和 7.5。


6. 看懂状态

kubectl get volumes.longhorn.io -n longhorn-system \
  -o custom-columns=NAME:.metadata.name,STATE:.status.state,ROBUSTNESS:.status.robustness,CURRENT:.status.currentNodeID
字段含义
STATE=detached卷没挂到任何节点,通常没有 Pod 在用
STATE=attached卷已经挂到某节点
ROBUSTNESS=healthy副本数满足要求
ROBUSTNESS=degraded副本不足或正在重建
ROBUSTNESS=unknownmanager/engine 状态不明,需要继续查

看到 degraded 不要马上删卷。先看 replica:

kubectl get replicas.longhorn.io -n longhorn-system \
  -o custom-columns=NAME:.metadata.name,VOLUME:.spec.volumeName,NODE:.spec.nodeID,STATE:.status.currentState,FAILED:.status.failedAt

7. 常见故障

7.1 PVC 一直 Pending

kubectl describe pvc -n <ns> <pvc>
kubectl get sc
kubectl get pods -n longhorn-system
kubectl logs -n longhorn-system deploy/csi-provisioner --tail=100

常见原因:

  • 没有默认 StorageClass。
  • CSI provisioner 没 Running。
  • Longhorn manager 不健康。
  • 节点磁盘不可调度。

7.2 Pod 卡在 ContainerCreating / MountVolume

kubectl describe pod -n <ns> <pod>
kubectl get volumeattachments.storage.k8s.io | grep <pvc>
kubectl get volumes.longhorn.io -n longhorn-system | grep <pvc>
journalctl -u kubelet --since "20 min ago" --no-pager | grep -i mount

describe pod 里的 Events 最重要。常见事件:

事件含义处理
driver.longhorn.io not foundCSI driver 没注册好查 longhorn-csi-plugin
Multi-Attach errorRWO 卷还挂在旧节点等旧 Pod 删除,必要时查 VolumeAttachment
volume is not ready for workloadsLonghorn 卷还在恢复观察 Longhorn UI / manager 日志
Input/output error卷或 engine I/O 异常停止自动重试,查 Longhorn engine/replica

7.3 Multi-Attach

RWO 卷同一时间只能挂到一个节点。单副本 Deployment 挂 RWO PVC 时,不要用默认 RollingUpdate,改 Recreate:

kubectl patch deployment -n <ns> <deploy> --type=merge \
  -p '{"spec":{"strategy":{"type":"Recreate","rollingUpdate":null}}}'

如果由 Helm 管理,要把值写回 Helm values,避免下次 upgrade 覆盖。

7.4 degraded 卷

VOL=pvc-xxxx

kubectl get volumes.longhorn.io -n longhorn-system $VOL -o yaml | sed -n '1,220p'
kubectl get replicas.longhorn.io -n longhorn-system -l longhornvolume=$VOL -o wide
kubectl get engines.longhorn.io -n longhorn-system -l longhornvolume=$VOL -o yaml | grep -A20 replicaModeMap

原则:

  • 业务还在 Running 时,先观察 replica rebuild,不要删 PVC。
  • WO 通常表示副本正在写入/重建。
  • RW 表示 engine 正在读写这个 replica。
  • 多个副本都失败时,先做快照/备份评估,再操作。

7.5 卷一直 degraded、副本卡在 WO 重建不完 → 八成是跨节点 MTU(实测踩坑)

本集群装完后第一个 PVC 就遇到:卷 attached 但 robustness=degraded,3 个副本都 running,可 engine 的 replicaModeMap 里总有一个卡在 WO(写入/重建中),robustness 死活不转 healthy。

# 看 engine 认了几个副本是 RW(健康),几个是 WO(卡重建)
kubectl get engines.longhorn.io -n longhorn-system -o jsonpath='{.items[0].status.replicaModeMap}'; echo
# 坏的样子:{"...-r-3204":"WO","...-r-4fd6":"RW","...-r-d541":"RW"}  ← 一个 WO

# 看 instance-manager 重建日志(在 WO 副本所在节点)
kubectl logs -n longhorn-system <该节点的 instance-manager> --tail=200 | grep -iE 'rebuild|sync|error'

关键报错长这样:

FailedRebuilding ... failed to sync files ... failed to write data:
Post "http://10.244.0.241:10024/v1-ssync/writeData?begin=557056&end=561152":
context deadline exceeded

注意 begin=557056——同步传到约 544KB 才超时,小数据过、大数据断。这不是 Longhorn 的问题,是跨节点 VXLAN MTU 配大了:Longhorn 副本同步走 Pod IP 直连传大块数据,MTU 一超路径就丢,重建永远完不成。

修复步骤:

  1. 按 Cilium Runbook 2.5 节 把 Cilium MTU 调到 1400 并重启 cilium。

  2. 重启 Longhorn 的 instance-manager(旧 Pod 还是旧 MTU 的 veth,副本进程跑在里面):

    # 先确保没有重要卷 attached,再删(控制器会重建)
    kubectl delete pod -n longhorn-system -l longhorn.io/component=instance-manager
    
  3. 删掉旧的 degraded 卷重建(或等 Longhorn 自动重试重建)。新卷的 3 副本应很快全 RW、robustness=healthy:

    kubectl get volumes.longhorn.io -n longhorn-system \
      -o custom-columns=NAME:.metadata.name,STATE:.status.state,ROBUSTNESS:.status.robustness
    # 好的样子:STATE=attached  ROBUSTNESS=healthy
    

教训:验证 CNI 时一定要把测试 Pod 强制分到不同节点测大包,否则同节点测不出 MTU 问题,等装了 Longhorn 才暴露,排查链路长得多。


8. UI 入口

http://154.201.73.31:31172

UI 里重点看:

  • Node:节点是否 schedulable、磁盘剩余。
  • Volume:state、robustness、attached node。
  • Replica:分布在哪些节点,是否 rebuilding。
  • Event log:Longhorn 自身错误。
在 GitHub 上编辑此页
Prev
Cilium 网络 Runbook:安装、查看、调试
Next
监控日志 Runbook:Prometheus / Grafana / Loki / Alertmanager