k8s localpath csi原理
Rancher
自带的 Local Path Provisioner(简称 local-path-provisioner)是一个非常轻量的 CSI(Container Storage Interface)实现,用于在集群节点的本地磁盘上快速创建持久卷(PV)。
它的原理非常简单,但机制清晰,可以总结为一句话:
它通过在节点的本地文件系统上创建一个目录,然后把该目录通过 hostPath 挂载进 Pod 实现持久存储。
下面详细讲解它的 原理、核心流程、关键组件 与 使用机制。
🧩 一、核心原理概述
Local Path CSI(其实是基于 CSI 思想的一个轻量实现)核心是:
- 每当需要创建 PVC(PersistentVolumeClaim)时,
- 它在选定的节点上创建一个目录(路径如
/opt/local-path-provisioner/pvc-xxxx/
), - 然后动态生成一个 PV(PersistentVolume),PV 使用
hostPath
绑定该目录, - Pod 调度到同一个节点时,直接通过 hostPath 访问该目录实现持久化。
因此它本质上是:
一个自动管理 hostPath 的控制器(Provisioner),让用户像用 NFS/Longhorn 那样用 PVC,但数据仍存在本地磁盘上。
⚙️ 二、工作流程(从 PVC 到 PV)
下面是它的执行过程(简化版):
1️⃣ 用户创建 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: my-data
spec:accessModes:- ReadWriteOncestorageClassName: local-pathresources:requests:storage: 1Gi
2️⃣ StorageClass 控制逻辑
local-path
的 StorageClass 通常这样定义:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:name: local-path
provisioner: rancher.io/local-path
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
关键点:
- provisioner:
rancher.io/local-path
→ 对应的是一个运行在集群内的控制器 Deployment。 - volumeBindingMode: WaitForFirstConsumer → 只有当 Pod 使用了这个 PVC 并调度确定节点后,才会创建 PV(因为需要知道在哪个节点上建目录)。
3️⃣ local-path-provisioner Controller 收到请求
当 PVC 被创建且 Pod 调度到具体节点后,Kubernetes 调用 rancher.io/local-path
这个 Provisioner:
-
控制器(在 kube-system 或 local-path-storage namespace 中运行)被触发;
-
它查看目标节点;
-
然后通过执行一个 helper Pod(Local Path Helper) 在目标节点上运行;
-
该 helper Pod 会在该节点上创建目录,例如:
/opt/local-path-provisioner/pvc-<namespace>-<pvc-name>
-
目录创建完毕后,控制器生成一个对应的 hostPath PV,指向这个目录。
4️⃣ Pod 挂载阶段
当 Pod 启动时:
- PV 已经存在,指向
/opt/local-path-provisioner/...
- kubelet 在同一节点上挂载该 hostPath;
- Pod 里
/data
(或你定义的 mountPath)就映射到节点本地该目录; - 数据写入时直接写入节点磁盘。
🧠 三、架构组件
组件 | 功能 |
---|---|
local-path-provisioner | 核心控制器,监听 PVC/PV 创建删除事件。 |
helper Pod | 临时在目标节点执行 mkdir / rm 操作。 |
StorageClass (local-path) | 定义 provisioner 名称和路径模板。 |
hostPath PV | 由 controller 自动生成,指向节点本地路径。 |
🧱 四、存储路径结构
默认路径:
/opt/local-path-provisioner/pvc-<namespace>-<pvc-name>/
可以通过 ConfigMap 修改路径模板,例如:
apiVersion: v1
kind: ConfigMap
metadata:name: local-path-confignamespace: local-path-storage
data:config.json: |-{"nodePathMap":[{"node":"DEFAULT_PATH_FOR_NON_LISTED_NODES","paths":["/opt/local-path-provisioner"]}]}
这让不同节点可以使用不同目录挂载路径。
🔁 五、删除流程
- 当 PVC 被删除时,Provisioner 会检测到事件;
- 创建一个临时 Pod 到相应节点;
- Pod 执行
rm -rf /opt/local-path-provisioner/pvc-...
; - 删除目录后再删除 PV;
- 清理完毕。
⚠️ 注意:如果 Pod 被意外删除或节点下线,这个目录不会自动转移;属于单节点本地数据。
📊 六、优缺点总结
优点 | 缺点 |
---|---|
✅ 轻量、部署极简单(一个 Deployment + ConfigMap) | ❌ 数据不具备高可用性(只在单节点) |
✅ 动态创建与自动清理 | ❌ 节点损坏或被调度走,数据无法访问 |
✅ 非常适合开发、测试环境 | ❌ 不支持多节点访问(非网络存储) |
✅ 支持标准 PVC/PV API(与 CSI 兼容) | ❌ 性能依赖节点本地磁盘 IO,无数据同步 |
🧩 七、与真正 CSI 的关系
严格意义上:
- local-path-provisioner 不是完全的 CSI 驱动;
- 它是基于 Kubernetes 原始
external-provisioner
接口的实现; - 不像 Longhorn、Rook-Ceph 那样注册完整的 CSI 驱动;
- 但从使用者角度上看,它与 CSI 的行为一致:你声明 PVC,它帮你动态创建 PV。
从 Kubernetes 1.13 以后,rancher.io/local-path
实际上是通过 CSI provisioner framework 来实现的(部分功能兼容),所以常被称为“轻量 CSI 实现”。
💡 八、简图(执行过程)
PVC ──► local-path-provisioner Controller│├─> 选择调度节点(WaitForFirstConsumer)│├─> 在节点启动 helper Pod│ ││ └─> mkdir /opt/local-path-provisioner/pvc-xxx│├─> 创建 hostPath PV 绑定该路径│└─> Pod 使用 PVC → kubelet 挂载 hostPath → 数据写入节点磁盘
✅ 总结一句话
Rancher Local Path Provisioner 的原理是:
使用控制器 + 临时 helper Pod,在目标节点上自动创建本地目录,并通过 hostPath 动态生成 PV,实现 PVC 动态供给,但数据实际存储在节点本地磁盘上。