
一台服务器装完单节点 K8s 之后我第一个遇到的问题就是Pod 我可以随便删数据呢这个问题几乎每个刚接触 K8s 的人都跑不掉。我之前用 hostPath 硬撑过一阵子后来实在受不了开始研究 Longhorn 这类容器存储方案。Longhorn 是 Rancher 团队开源的 K8s 块存储项目调度策略由 Controller 管数据通道走 iSCSI新版本也支持 SPDK/NVMe配合 CSI 驱动对外提供 PVC。你可能听过它是做“分布式存储”的那我明确告诉你单节点场景下它给不了你分布式高可用但它能把单节点上的本地盘变成一套可管理、可快照、可备份的存储服务对于有状态应用来说这才是我真正需要的。如果你有三五台机器做集群Longhorn 的价值会更高如果你只有一台机器这篇文章更适合你。1. 为什么要在单节点 K8s 上装 Longhorn先认清价值边界先说结论单节点 Longhorn 不是“缩水版高可用存储”它是一套“本地盘的管家”。Longhorn 跑起来之后集群里会有这些核心组件longhorn-manager 负责通过 CRD 管理卷和引擎instance-manager 负责实际的数据引擎进程longhorn-csi-plugin 负责让 Kubernetes 通过 CSI 接口挂载卷再加上一个前端 UI 服务。在单节点上这些组件全都挤在同一台机器上看起来有点“热闹”但正好体现了 Kubernetes Operator 的那套控制循环逻辑状态声明、控制器巡检、子资源调和。那它在单节点上到底解决了什么问题我总结下来有四个动态 PVC不再手动挂盘、手动分目录。写一个 PVCLonghorn 自动创建 PVPod 直接挂载删除 PVC 也能在 UI 里看到卷的最终状态。可视化管理节点磁盘使用率、卷副本状态、引擎运行情况全部在一个页面里看比 SSH 进机器翻目录直观太多了。快照与备份这是单节点场景下最有用的部分。升级前打个快照出问题一分钟回滚定期备份到 S3机器被清空也能恢复数据。数据生命周期统一删除应用时连带清理数据这种事在 hostPath 模式下容易漏Longhorn 让你明确知道“PVC 还在不在、卷还在不在”。但必须把预期摆正单节点上 Longhorn 默认只保留一个数据副本节点宕机、磁盘损坏数据就真没了。它不是帮你做容灾的它是帮你把“一块本地盘上的数据”管起来的。下面这个表格可以直观说明差异能力项单节点 Longhorn多节点 Longhorn默认副本数1必须手动改3数据高可用无有节点故障后自动重建副本快照与备份支持支持跨节点卷迁移无法体现支持管理复杂度低中我当时说服自己的逻辑很简单在一台机器上跑 K8s本来就是单点环境与其嘲笑 Longhorn“没有高可用”不如把它当成一个带快照、带备份、带可视化管理界面的本地存储管理工具。这个价值已经足够大。2. 宿主机准备系统依赖、内核模块和数据盘规划Longhorn 最大的坑不在 Helm 命令而在宿主机。官方文档虽然写了依赖但实际装的时候很多人会漏掉某个内核模块导致卷一直 attached 失败。我在单节点上踩过一遍把完整准备过程写在这里。2.1 安装运行依赖open-iscsi 和 NFS 客户端Longhorn v1 引擎的数据通道依赖 iSCSI所以每个节点都必须装 open-iscsi 或对应发行版的 iscsi-initiator。同时为了支持 NFS 备份和某些挂载场景还要装 NFS 客户端工具。Debian/Ubuntu 系apt-get update apt-get install -y open-iscsi nfs-common util-linux systemctl enable --now iscsidRHEL/Rocky/CentOS 系yum install -y iscsi-initiator-utils nfs-utils systemctl enable --now iscsid有些系统里iscsid默认没开机自启如果你发现容器里挂载卷之后重启机器就掉盘多半是这里的问题。装完以后验证一下systemctl status iscsid cat /etc/iscsi/initiatorname.iscsiutil-linux主要提供blkid和findmntLonghorn 在检查磁盘和挂载点时会调用它们Debian 最小化安装容易漏。2.2 内核模块target_core_mod 和 iscsi_target_mod这一项是最容易忽略的。Longhorn 的数据引擎在节点上要启用 iSCSI target 能力依赖两个内核模块target_core_mod和iscsi_target_mod。我见过不少案例装好 Longhorn 后一切组件都 Running但一创建卷就报错日志里说的是找不到设备或者 attach 超时最后排查下来就是内核模块没加载。先在当前环境手动加载modprobe target_core_mod modprobe iscsi_target_mod确认加载成功lsmod | grep iscsi lsmod | grep target如果系统重启后不想手动重新加载写进持久化配置cat /etc/modules-load.d/longhorn.conf EOF target_core_mod iscsi_target_mod EOF如果你的内核版本比较新还建议把nvme-tcp也加载上因为 Longhorn v2 数据引擎走的是 NVMe over TCP提前备着没坏处modprobe nvme-tcp2.3 数据盘规划把数据路径从根目录挪出来Longhorn 默认的数据目录是/var/lib/longhorn。如果你机器上有独立数据盘建议挂到这个路径下别让 Longhorn 跟系统日志挤在同一块盘上。我用的方式是直接把数据盘挂载到/var/lib/longhorn然后写进/etc/fstabmkdir -p /var/lib/longhorn mount /dev/sdb1 /var/lib/longhorn然后编辑/etc/fstab加入/dev/sdb1 /var/lib/longhorn ext4 defaults,nofail 0 2nofail很重要否则机器启动时数据盘没接好系统可能因为挂载失败进不去。如果你不想动 fstab也可以在 Longhorn UI 的 Node 页面里手动添加额外的磁盘目录Longhorn 会把目录当作数据盘使用。不过我的经验是提前把目录挂好安装后省心得多。磁盘空间这块Longhorn 默认要求节点可用空间不低于storageMinimalAvailablePercentage默认是 25%低于这个值会把节点标记为不健康新卷调不上去。所以你至少要让数据盘剩 20% 以上的余量别把空间打满。3. 用 Helm 完成安装版本选择、values 配置与调度坑依赖准备好的前提下安装本身反而不难。关键是搞清楚 Helm 安装时哪些参数必须改哪些默认值在单节点环境会埋雷。3.1 为什么用 Helm Chart而不是直接 apply 官方 YAMLLonghorn 官方仓库提供了完整的 YAML 清单kubectl apply -f也能装。但我个人强烈建议用 Helm因为单节点场景有太多默认值需要覆盖Helm 的 values 文件可以一次性把副本数、数据路径、超卖比例全部设置好。用官方 YAML 的话装完还得一个个去 UI 里点设置麻烦且容易漏。添加仓库并更新helm repo add longhorn https://charts.longhorn.io helm repo update我这次安装参考的是Longhorn 1.6.x Kubernetes 1.28如果你用 2.x安装流程基本一致只是多了一个 v2 数据引擎的选择不影响下面这些配置逻辑。3.2 单节点必改的三个配置项replicaCount、defaultDataPath、over-provision这是我踩过的最深的一个坑Longhorn 默认副本数是 3而默认又不允许同一个节点上放多个副本所以在单节点集群上如果你不修改副本数创建 PVC 时会一直失败或卷状态卡住因为系统永远找不到足够的节点放副本。所以必须把副本数改成 1。我用的 values.yaml 是这样的defaultSettings: defaultDataPath: /var/lib/longhorn replicaCount: 1 storageOverProvisioningPercentage: 100 storageMinimalAvailablePercentage: 20 persistence: defaultClass: true逐项解释defaultDataPathLonghorn 创建卷时的默认数据目录改成你规划好的路径。replicaCount: 1单节点集群的硬性要求。不改成 1新卷根本建不起来。storageOverProvisioningPercentage存储超卖比例默认通常是 100 或 200。单节点只有一块盘我建议保守一点设为 100也就是说最多允许调度卷的总大小超过实际磁盘 100%再高就容易把盘写满到时候整个节点都会被 Longhorn 标记为不健康。storageMinimalAvailablePercentage: 20保留 20% 可用空间作为安全余量低于这个值停止调度新卷。persistence.defaultClass: true让 Longhorn 创建的 StorageClass 成为集群默认 StorageClass这样普通 PVC 不指定 StorageClass 也会自动用 Longhorn。执行安装helm install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace -f values.yaml3.3 调度问题单节点 control-plane 的默认污点用 kubeadm 搭建的单节点集群节点默认带有node-role.kubernetes.io/control-plane:NoSchedule污点。如果不处理你可能会看到 longhorn 的部分 Pod 一直 Pending比如 instance-manager、longhorn-csi-plugin 这类需要调度到节点上的组件。两种解法。第一种是单节点最省事的直接把污点去掉kubectl taint nodes --all node-role.kubernetes.io/control-plane-单节点本来就只有一个节点去掉污点不会有什么副作用反而让你自己部署的其他工作负载也能正常调度。第二种是你想保留污点那需要给 Longhorn 配置 Taint Toleration在 UI 的设置里能找到对应字段或者在 Helm values 里配置。我的建议是学习环境就别留污点了省得后续每个应用都要加容忍。安装完以后检查 Pod 状态kubectl -n longhorn-system get pod kubectl -n longhorn-system get svc正常情况下你应该看到 longhorn-manager、longhorn-csi-plugin、instance-manager、UI 这些 Pod 全部 Running。再看一眼 StorageClass 是否变成了默认kubectl get storageclass如果输出里longhorn有(default)标记就说明默认配置生效了。4. 首次访问 UI账号获取、节点磁盘设置与默认配置落地Longhorn 装好以后我建议第一件事不是急着创建 PVC而是先把 UI 打开把节点和磁盘状态摸清楚。4.1 访问方式和初始账号默认情况下 Longhorn UI 是通过longhorn-frontend服务暴露的一般是个 NodePort。直接查端口kubectl -n longhorn-system get svc longhorn-frontend然后浏览器访问http://节点IP:NodePort。Longhorn 默认开启了 basic-auth初始账号是admin密码不是固定的而是安装时自动生成放在 Secret 里面。获取方式kubectl -n longhorn-system get secret longhorn-basic-auth -o jsonpath{.data.password} | base64 -d我第一次装的时候不知道密码翻了好一会儿 YAML后来发现就是这个命令。拿密码登录后建议立刻在 UI 右上角账号设置里改掉。如果你不想暴露 NodePort也可以用 port-forwardkubectl port-forward -n longhorn-system svc/longhorn-frontend 8080:80然后访问http://localhost:8080。这个方式我做临时排障时用得比较多。4.2 在 UI 里确认节点和数据盘登录后先进Node页面。这里会列出集群里的所有节点包括节点状态、磁盘路径、可用空间。如果你像我一样把数据盘挂到了/var/lib/longhorn这里应该能看到该路径以及剩余容量。重点确认两件事节点状态是 Ready没有被标记为scheduling disabled。磁盘目录显示的空间和实际挂载一致。有些时候因为路径挂载不对Longhorn 默认扫描到的是根目录你会看到它打算把数据写到系统盘上。如果发现不对可以在 Node 页面的 Edit 里添加磁盘或调整磁盘路径。Longhorn 会把目录形式的数据盘当作“Disk”纳入调度不必要求必须是独立块设备。4.3 确认 StorageClass 与副本数落地光看 StorageClass 还不算数真正要确认的是新建卷时副本数是不是 1。你可以在 UI 的 Volume 页面点 Create Volume随便填个名字和大小创建后查看卷详情Replica Count 应该显示 1Replica 状态应该是Running。这里有一个容易混淆的点defaultSettings.replicaCount只对新建的卷生效存量卷不会因为修改默认值而自动调整副本数。如果你在安装后再从 UI 修改全局副本数为 1之前已经创建过的卷还是老配置需要在每个卷的详情页手动修改。所以我一般建议在 Helm 安装阶段就把副本数定好一步到位。5. 持久化实测从 PVC 创建到删除 Pod 后数据依然存在安装完成、UI 能打开以后终于到了验证阶段。我习惯用一个最简单的流程来验收 Longhorn 是否真的能提供持久化创建 PVC写入一个文件删掉 Pod 甚至删掉整个 Deployment再重新部署检查文件是否还在。先创建 PVCapiVersion: v1 kind: PersistentVolumeClaim metadata: name: demo-longhorn-pvc spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 2Gi应用并查看状态kubectl apply -f demo-pvc.yaml kubectl get pvc demo-longhorn-pvc正常情况下 PVC 会很快变成 Bound对应的 PV 也在 Longhorn UI 里能看到。然后跑一个简单的工作负载挂载这个 PVC写入数据apiVersion: apps/v1 kind: Deployment metadata: name: pv-writer spec: replicas: 1 selector: matchLabels: app: pv-writer template: metadata: labels: app: pv-writer spec: containers: - name: busybox image: busybox:1.36 command: - /bin/sh - -c - | echo longhorn test $(date) /mnt/data/test.txt sleep 3600 volumeMounts: - name: data mountPath: /mnt/data volumes: - name: data persistentVolumeClaim: claimName: demo-longhorn-pvc等 Pod Running 后确认文件写进去了kubectl exec -it deploy/pv-writer -- cat /mnt/data/test.txt现在做关键一步删掉整个 Deployment模拟应用完全被销毁的场景。kubectl delete deploy pv-writer注意 PVC 还在Pod 没了但不影响数据。然后重新 apply 同一个 YAML再进去读文件kubectl exec -it deploy/pv-writer -- cat /mnt/data/test.txt如果能看到之前写入的内容说明 Longhorn 的持久化链路是通的。这套流程虽然简单但我实际验证时还是发现过问题比如 Pod 卡在ContainerCreating多半是挂载没就绪去看longhorn-csi-plugin日志或 instance-manager 状态就能定位。还有一个细节删除 PVC 会导致 Longhorn 里的卷连同数据一起删除除非在卷设置里开启retain。所以做实验时PVC 别乱删。更贴近真实场景的验证是跑一个 MySQL StatefulSet插几条数据重启 Pod 甚至把节点重启一遍数据依然完整的。逻辑和上面的 busybox 测试完全一样只是工作负载换成了有状态应用。6. 快照、备份与恢复单节点 Longhorn 最有价值的运维手段如果说 PVC 持久化是 Longhorn 的“本职工作”那快照和备份就是它在单节点环境里最值得夸的部分。一台机器没有高可用但通过快照和备份至少能把“误操作”和“软故障”的损失降到最低。6.1 快照Copy-on-Write不是全量拷贝Longhorn 的快照基于 CoW写时复制机制创建时几乎不占空间只有后续写入的数据会累积到新的快照层。所以你可以频繁打快照不用担心瞬间把磁盘撑爆。创建快照的方式有两种。一种是直接在 UI 的 Volume 页面点击 Create Snapshot另一种是通过 Kubernetes 的 VolumeSnapshot API方便自动化管理。先创建 VolumeSnapshotClassapiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshotClass metadata: name: longhorn-snapshot driver: driver.longhorn.io deletionPolicy: Delete然后为你的 PVC 创建快照apiVersion: snapshot.storage.k8s.io/v1 kind: VolumeSnapshot metadata: name: demo-longhorn-pvc-snapshot spec: volumeSnapshotClassName: longhorn-snapshot source: persistentVolumeClaimName: demo-longhorn-pvc创建后在 Longhorn UI 里能看到对应的快照条目。如果要恢复用快照作为 PVC 的 dataSource 创建新 PVCapiVersion: v1 kind: PersistentVolumeClaim metadata: name: demo-longhorn-pvc-restored spec: storageClassName: longhorn dataSource: name: demo-longhorn-pvc-snapshot kind: VolumeSnapshot apiGroup: snapshot.storage.k8s.io accessModes: - ReadWriteOnce resources: requests: storage: 2Gi这个恢复出来的新 PVC里面的数据和快照时刻完全一致。我的习惯是给数据库这类重要应用升级前打一个快照升级失败就在 UI 里把卷回滚到快照点整个过程一分钟以内。有一点要特别注意快照不是无限的多次快照会形成快照链占用的空间会逐渐变大。过期快照要定期清理Longhorn UI 里删除快照即可。我见过有人在测试环境狂打快照磁盘很快被撑满。6.2 定期快照与备份到对象存储手动打快照只是兜底更合理的是配置定时快照和备份。在 Longhorn UI 的 Volume 页面你可以给卷设置 Schedule例如每小时打一次快照每天做一次备份。快照留在本机备份推到 S3 兼容的对象存储。配置外部备份需要先在 UI 的Backup Target页面填对象存储信息。我常用的方案是自建 MinIO 或者兼容 S3 的对象存储填好 Endpoint、Bucket、Access Key、Secret Key 后Longhorn 就能把备份推到远端。备份的实际意义在于单节点机器如果整机损坏本地快照也会一起没。只有把备份放到另一台机器或者对象存储里数据才是真正安全的。我目前的做法是快照每小时一个滚动保留 24 个备份每天晚上推一次保留 7 份这个节奏对个人服务器够用了。恢复外部备份的方式也很直接在 UI 的 Backup 页面找到对应备份点击 Restore选择恢复到新卷或者替换现有卷。数据可以从“机器外的某个地方”拉回来这才是单节点环境下最后一道防线。7. 单节点 Longhorn 的风险边界与日常维护清单写了这么多好处最后还是得说清楚风险。单节点 Longhorn 有不少边界是你必须心里有数的否则某天数据没了你会觉得被这个方案坑了。7.1 三个必须认账的风险第一单副本等于磁盘损坏即全丢。这是单节点 Longhorn 最根本的短板。只要机器上那块盘坏了卷数据基本救不回来。所以重要数据一定要开外部备份。第二节点重启后卷恢复需要时间。机器断电重启K8s 服务和 Longhorn 都要重新起来卷会重新 attach不是像本地文件夹一样开机秒见。预留一点恢复时间别一开机就急着库里查数据。第三快照链和磁盘空间是互斥的。快照越多可用空间越少。如果你不看 UI、不清理快照某一天磁盘会悄无声息地满掉然后 Longhorn 停止调度新卷现有卷也会进入不健康状态。7.2 日常维护清单我把日常要做的操作总结成下面几条照着做基本不会出大问题每周至少看一次 UI Dashboard确认节点健康、磁盘空间、卷副本状态正常。设置一个定时提醒定期清理过期快照别让快照永久堆积。检查storageMinimalAvailablePercentage不要在生产数据盘上把空间用到 100%。升级 Longhorn 前先给关键卷打快照再执行helm upgrade升级完成后 UI 里可能会提示你需要手动确认升级底层的引擎和实例管理器跟着向导走就行。配置好对象存储备份目标之后刻意做一次恢复演练确认备份真的能拉回来而不是等灾难发生时才第一次测试。如果用的是 Longhorn v2 数据引擎注意它需要专门的块设备如 NVMe 盘不能简单借用在根分区上先确认硬件满足条件再切。7.3 我的一些实际操作体会最后说点个人感受。我最初对在单节点上装 Longhorn 是有点犹豫的因为它的定位是分布式块存储单节点怎么想都别扭。但实际用下来我发现自己真正的需求并不是“多副本高可用”而是“一块本地盘能不能管得更好”。Longhorn 把这个问题解决得很彻底PVC 动态供给、UI 可视化、快照秒级回滚、对象存储备份这些能力让单节点集群的存储体验完全不输云厂商的云盘服务。如果你目前也只有一台机器跑 K8s短期也不打算扩成多节点那我建议先把副本数改成 1、把默认数据路径改到独立数据盘、把外部备份配好这套组合足够支撑你故意折腾各种有状态应用。至于未来要不要加节点Longhorn 的多副本能力是之后设置一下就能释放出来的前期的存储管理习惯和知识都能直接复用。我现在维护单节点集群时的习惯是任何有状态应用一律走 PVC删除应用时保留 PVC 以便回滚升级任何中间件之前先打快照每天晚上确认一次备份任务执行成功。这些动作都做完你基本就不用再手动 SSH 到机器里翻目录找数据了。Longhorn 在单节点上到底是“大材小用”还是“刚好合适”关键看你怎么用。