完整部署清单
yaml
# 1. 命名空间:独立隔离 Local Path Provisioner 相关资源
# 功能:避免与其他业务资源冲突,便于权限控制和资源管理
apiVersion: v1
kind: Namespace
metadata:
name: local-path-storage
---
# 2. 服务账号:为 Local Path Provisioner 提供专属运行身份
# 功能:关联 RBAC 权限,实现权限最小化,避免使用默认服务账号带来的安全风险
apiVersion: v1
kind: ServiceAccount
metadata:
name: local-path-provisioner-service-account
namespace: local-path-storage # 与组件命名空间强绑定
---
# 3. 集群角色:定义 Provisioner 所需的集群级权限集合
# 遵循最小权限原则:仅授予组件正常运行必需的权限,避免过度授权
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: local-path-provisioner-role # 角色名称,用于后续权限绑定
rules:
# 权限组1:读取节点和PVC基础信息
# 用途:判断节点存储可用性、感知PVC状态
- apiGroups: [""] # 核心API组(无组名)
resources: ["nodes", "persistentvolumeclaims"] # 操作的资源类型
verbs: ["get", "list", "watch"] # 只读操作,无修改权限
# 权限组2:管理PV、Pod、Endpoint资源
# 用途:动态创建/删除PV、感知Pod调度状态、维护组件服务发现
- apiGroups: [""]
resources: ["endpoints", "persistentvolumes", "pods"]
verbs: ["*"] # 需完整操作权限(创建/删除/更新等)
# 权限组3:上报事件
# 用途:向K8s集群上报PV创建/删除、错误等状态事件,便于排查问题
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"] # 仅允许创建和更新事件
# 权限组4:读取存储类配置
# 用途:关联本地存储类,获取存储供给规则
- apiGroups: ["storage.k8s.io"] # 存储相关API组
resources: ["storageclasses"]
verbs: ["get", "list", "watch"] # 只读操作,无需修改存储类
---
# 4. 集群角色绑定:将集群角色权限授予服务账号
# 功能:建立权限关联,使Provisioner通过服务账号获得上述角色权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: local-path-provisioner-bind # 绑定名称,便于识别
roleRef:
apiGroup: rbac.authorization.k8s.io # RBAC API组
kind: ClusterRole # 绑定的资源类型为集群角色
name: local-path-provisioner-role # 关联上述定义的集群角色
subjects:
- kind: ServiceAccount # 被授权对象类型为服务账号
name: local-path-provisioner-service-account # 被授权的服务账号名称
namespace: local-path-storage # 明确命名空间,避免跨命名空间权限泄漏
---
# 5. Deployment:定义 Local Path Provisioner 核心组件的运行配置
# 功能:管理Provisioner容器的生命周期,确保组件稳定运行
apiVersion: apps/v1
kind: Deployment
metadata:
name: local-path-provisioner # 部署名称,与组件名称一致
namespace: local-path-storage # 部署到独立命名空间
spec:
replicas: 1 # 单副本部署:本地存储Provisioner无需多副本,单节点即可满足需求
selector:
matchLabels:
app: local-path-provisioner # 标签选择器,匹配目标Pod
template:
metadata:
labels:
app: local-path-provisioner # Pod标签,与选择器对应,用于服务发现和调度
spec:
serviceAccountName: local-path-provisioner-service-account # 关联专属服务账号
containers:
- name: local-path-provisioner # 容器名称,与组件名称一致
image: rancher/local-path-provisioner:v0.0.14 # 组件镜像:固定版本,避免兼容性问题
imagePullPolicy: IfNotPresent # 镜像拉取策略:本地有镜像时优先使用,减少网络依赖
command: # 容器启动命令
- local-path-provisioner # 启动二进制文件
- --debug # 开启调试日志:便于问题排查(生产环境可按需关闭)
- start # 启动服务指令
- --config # 指定配置文件参数
- /etc/config/config.json # 配置文件路径(挂载自ConfigMap)
volumeMounts: # 挂载配置文件卷
- name: config-volume # 卷名称,与下方volumes定义对应
mountPath: /etc/config/ # 容器内挂载目录,对应启动命令中的配置路径
env: # 环境变量配置
- name: POD_NAMESPACE # 变量名:当前Pod所在命名空间
valueFrom:
fieldRef:
fieldPath: metadata.namespace # 动态获取Pod命名空间,避免硬编码
volumes: # 定义卷资源:挂载ConfigMap配置
- name: config-volume # 卷名称,与volumeMounts对应
configMap:
name: local-path-config # 关联下方定义的ConfigMap,加载配置数据
---
# 6. 存储类:定义本地存储的动态供给规则
# 功能:为PVC提供存储供给模板,指定Provisioner、绑定策略等核心规则
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: local-path # 存储类名称:创建PVC时需通过storageClassName引用
provisioner: rancher.io/local-path # 存储供给者:与Provisioner镜像内置的Provisioner名称一致
volumeBindingMode: WaitForFirstConsumer # 卷绑定模式:等待第一个Pod调度后再创建PV,避免PV与Pod跨节点
reclaimPolicy: Delete # 回收策略:PVC删除后自动清理PV及本地数据,释放资源
---
# 7. ConfigMap:存储Provisioner核心配置数据
# 功能:分离配置与应用,支持动态调整存储路径、初始化/清理脚本(需重启Pod生效)
kind: ConfigMap
apiVersion: v1
metadata:
name: local-path-config # ConfigMap名称,与Deployment卷配置关联
namespace: local-path-storage # 与组件命名空间一致
data:
# 核心配置:节点-存储路径映射表
config.json: |-
{
"nodePathMap":[
{
"node":"DEFAULT_PATH_FOR_NON_LISTED_NODES",
"paths":["/data"]
}
]
}
# 初始化脚本:PV创建时执行
# 功能:创建存储目录并设置权限,确保Pod可正常读写
setup: |-
#!/bin/sh
path=$1
mkdir -m 0777 -p ${path}
# 清理脚本:PV删除时执行
# 功能:删除存储目录及数据,释放节点磁盘空间
teardown: |-
#!/bin/sh
path=$1
rm -rf ${path}
部署前准备(最佳实践)
1. 节点环境检查
bash
# 1. 所有节点创建存储目录并设置权限(与 ConfigMap 中 paths 一致)
sudo mkdir -p /data && sudo chmod 777 /data
# 2. 检查目录所在分区剩余空间(建议至少保留 10Gi 空闲空间)
df -h /data
# 3. 确保节点已安装必要依赖(如 util-linux 提供 pgrep 命令,用于健康检查)
sudo apt install -y util-linux # Debian/Ubuntu 系统
# sudo yum install -y util-linux # CentOS/RHEL 系统
2. 镜像预处理(离线环境必备)
bash
# 提前拉取镜像并推送到私有仓库(或直接在所有节点加载)
docker pull rancher/local-path-provisioner:v0.0.14
# 离线环境保存镜像
docker save -o local-path-provisioner-v0.0.14.tar rancher/local-path-provisioner:v0.0.14
# 在其他节点加载镜像
docker load -i local-path-provisioner-v0.0.14.tar
部署与验证(标准化流程)
1. 部署执行
bash
# 保存上述清单为 local-path-provisioner.yaml,执行部署
kubectl apply -f local-path-provisioner.yaml
# 验证命名空间创建
kubectl get ns local-path-storage -o wide
# 验证 Pod 运行状态(确保 STATUS 为 Running)
kubectl get pod -n local-path-storage -o wide --watch
# 验证存储类创建
kubectl get sc local-path -o yaml
2. 功能验证(标准化测试用例)
bash
# 1. 创建测试 PVC(动态申请 2Gi 存储)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-local-path-pvc
namespace: default
labels:
app.kubernetes.io/name: test-local-path
spec:
accessModes:
- ReadWriteOnce # 本地存储仅支持单节点读写
storageClassName: local-path
resources:
requests:
storage: 2Gi
EOF
# 2. 创建测试 Pod 挂载 PVC
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: test-local-path-pod
namespace: default
labels:
app.kubernetes.io/name: test-local-path
spec:
containers:
- name: test-container
image: busybox:1.35 # 固定镜像版本,避免兼容性问题
command: ["sleep", "86400"] # 持续运行 24 小时
volumeMounts:
- name: local-storage
mountPath: /data # 挂载到 Pod 内部 /data 目录
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
volumes:
- name: local-storage
persistentVolumeClaim:
claimName: test-local-path-pvc
EOF
# 3. 验证资源状态
# PVC 状态应为 Bound(绑定成功)
kubectl get pvc test-local-path-pvc -n default -o wide
# PV 状态应为 Bound(自动创建并绑定)
kubectl get pv -o wide
# Pod 状态应为 Running(挂载成功)
kubectl get pod test-local-path-pod -n default -o wide
# 4. 读写验证(确认存储可用)
kubectl exec -it test-local-path-pod -n default -- sh -c "echo 'k8s local-path test success' > /data/test.txt && cat /data/test.txt"
# 预期输出:k8s local-path test success
# 5. 节点本地验证(确认数据存储在 /data 目录)
# 先获取 Pod 所在节点
POD_NODE=$(kubectl get pod test-local-path-pod -n default -o jsonpath='{.spec.nodeName}')
# 登录节点查看数据目录(或通过 kubectl debug 查看)
kubectl debug node/${POD_NODE} -it --image=busybox:1.35 -- sh -c "ls -l /data/pvc-*/default/test-local-path-pvc/"
清理资源
bash
# 删除测试 Pod 和 PVC
kubectl delete pod test-local-path-pod -n default
kubectl delete pvc test-local-path-pvc -n default
# 彻底卸载 Local Path Provisioner
kubectl delete -f local-path-provisioner.yaml
# 清理节点本地残留目录(可选)
sudo rm -rf /data/pvc-*