找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

478

积分

0

好友

62

主题
发表于 4 小时前 | 查看: 2| 回复: 0

在日常 Kubernetes 部署中,大多数生产环境会使用云存储或网络存储(如 EBS、NAS、Ceph)。但对于本地环境、轻量级集群,最快速、最低成本、性能最高的存储方式其实是:本地存储(Local PV)

然而 Local PV 的一个缺点是——需要手工创建 PV,并指定 nodeAffinity,非常麻烦。

于是,Rancher 开源的 Local Path Provisioner 成为了本地存储的最佳实践:开箱即用、自动创建 PV、自动处理节点路径,无额外依赖。

为了方便后面阅读:Local Path Provisioner 都简写为 LPP

本文主要内容:

  • 如何部署 LPP
  • 如何使用 LPP
  • 多节点集群中 Pod 会落到哪个节点
  • Pod 重启是否会丢数据?
  • 哪些情况下会丢数据?如何避免?

1. LPP 是什么?

Local Path Provisioner(LPP)是一个 Kubernetes 本地存储动态卷插件,用于:

  • 动态创建 Local PV
  • 自动创建与回收节点上的真实目录
  • 无需手动写 PV
  • 性能接近裸盘
  • 各个节点独立提供存储

LPP 基于节点亲和性(Node Affinity)机制和 Kubernetes 调度器的感知能力,确保使用本地存储的 Pod 始终调度到存储所在的特定节点,从而实现本地磁盘的持久化访问。

2. 部署 LPP

项目地址:https://github.com/rancher/local-path-provisioner

一键安装:

kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/v0.0.32/deploy/local-path-storage.yaml

查看状态:

[root@k8s-master ~]# kubectl get po -n local-path-storage
NAME                                             READY   STATUS    RESTARTS   AGE
local-path-provisioner-7d6dddf9dd-mc7r7   1/1     Running   0          8m40s
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl get sc
NAME                 PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE      ALLOWVOLUMEEXPANSION   AGE
local-path   rancher.io/local-path   Delete          WaitForFirstConsumer   false                  8m49s

默认 StorageClasslocal-path

LPP 部署架构

默认情况下,所有节点都会使用 /opt/local-path-provisioner 作为存储路径,不过可以修改 ConfigMap 来自定义存储路径。这是 云原生 环境下常见的灵活配置方式。

下面为可选操作:

kubectl -n local-path-storage edit configmap local-path-config

修改不同节点使用不同目录作为存储:

{
  "nodePathMap": [
    {
      "node": "node1",
      "paths": ["/data/local1"]
    },
    {
      "node": "node2",
      "paths": ["/data/local2"]
    }
  ]
}

修改后重启:

kubectl -n local-path-storage rollout restart deploy/local-path-provisioner

3. 创建 PVC

创建 PVC ,动态请求 2Gi 本地卷:

cat > nginx-local-pvc.yaml <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-local-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: local-path
  resources:
    requests:
      storage: 2Gi
EOF

执行部署:

[root@k8s-master ~]# kubectl apply -f nginx-local-pvc.yaml

创建后可查看 PVC:

[root@k8s-master ~]# kubectl get pvc
NAME              STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
nginx-local-pvc   Pending                                      local-path     <unset>                 48s

4. 测试挂载本地存储

下面以 Nginx 为例,测试一下 LPP。

  • 使用 PVC 挂载本地卷
  • 用 initContainer 写入 index.html
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: nginx-local
    spec:
    replicas: 1
    selector:
    matchLabels:
      app: nginx-local
    template:
    metadata:
      labels:
        app: nginx-local
    spec:
      initContainers:
        - name: init-index
          image: busybox
          command: ["sh", "-c", "echo 'Hello from Local Path Provisioner!' > /data/index.html"]
          volumeMounts:
            - name: local-storage
              mountPath: /data
      containers:
        - name: nginx
          image: nginx:1.27
          ports:
            - containerPort: 80
          volumeMounts:
            - name: local-storage
              mountPath: /usr/share/nginx/html
      volumes:
        - name: local-storage
          persistentVolumeClaim:
            claimName: nginx-local-pvc

应用:

kubectl apply -f nginx-deploy.yaml

5. 验证效果

查看 Pod 跑在哪个节点:

kubectl get pod -o wide | grep nginx-local

这会告诉你 Pod 为何落到该节点(原理见文末)。

查看 index.html:

kubectl exec -it nginx-local-66bcc5bffb-j45b5 -- cat /usr/share/nginx/html/index.html

你会看到:

Hello from Local Path Provisioner!

查看节点真实目录。进入 Pod 所在节点:

ls /opt/local-path-provisioner/

即可看到对应的 PVC 目录。以上验证都没问题,就说明已经部署好了。

数据验证

6. Pod 重启后数据会丢吗?

只要你不删除 PVC,Pod 重启、重建、部署更新,都不会导致数据丢失。

理由:

  • PVC 与 PV 始终存在
  • 对应的节点本地目录也始终存在
  • 重启 Pod 后仍挂载同一目录

简单说:Pod 是短暂的,PVC 是持久的。

7. 哪些情况下会导致数据丢失?

以下是实际生产中最需要警惕的点。

7.1 你删除了 PVC

这也是最常见的真实踩坑。

kubectl delete pvc nginx-local-pvc

默认 StorageClass(local-path)保持策略是 Delete,你以为是 Retain,导致删除 PVC 时数据被自动清理。

删除 PVC = 删除 PV + 删除对应节点目录(数据完全消失)。

这是本地存储最常见的数据丢失原因。

7.2 节点磁盘损坏 / 重装系统

Local PV 仅存储在某个节点的本地路径,没有副本:

  • 节点重装
  • 节点磁盘故障
  • 手工格式化目录 都会导致数据永久丢失。
7.3 管理员误删目录

某些管理员不小心执行:

rm -rf /opt/local-path-provisioner/*

直接导致 PV 空指针,这时数据彻底消失。

8. 如何避免数据丢失?

8.1 把 StorageClass 改为 Retain

这在生产环境是强烈建议的,即使删除了 PVC 数据只是解除绑定,并没有删除本地的数据。

kubectl patch sc local-path -p '{"reclaimPolicy":"Retain"}'
8.2 使用 StatefulSet

这种就适合持久化服务。StatefulSet 的 PVC 是一对一的:

  • nginx-0 → nginx-local-pvc-nginx-0
  • Pod 重建名字不变
  • 卷绝不会漂移 更适合数据库,日志、缓存、业务状态等“长期存在的数据”。理解 持久化卷的管理 对于数据安全至关重要。
8.3 使用 nodeAffinity 固定节点

虽然 Local PV 自带 nodeAffinity,但你也可以手动限制 Pod 只在某节点运行,减少误操作。

8.4 定期备份(非常重要)

可使用 CronJob + rsync 组合或使用 Velero 进行备份,生产环境是很有必要备份的。

9. LPP 调度规则

多节点集群中 Pod 为什么会落到某个节点?这一点很多同学不清楚,我们放到最后解释。

9.1 多节点下 Local PV 的调度机制

当你创建 PVC:

  1. Local Path Provisioner 会从所有可用节点中随机选择一个节点
  2. 在该节点创建本地目录。
  3. 生成 PV,并自动写入 nodeAffinity
  4. 调度器在调度 Pod 时,必须把 Pod 调度到 PV 所属节点。

因此: 是 PV 决定 Pod 落在哪个节点,而不是 Pod 自己决定。

9.2 什么情况下会落到你预期节点?
  • 你在 ConfigMap 里对某节点配置了独立路径
  • 或你使用 nodeSelector/affinity 对 Pod 设定节点偏好
  • 或你为 PVC 调整 StorageClass 让某些节点可用某些路径

Local PV 是轻量环境最优的持久化方案,但也有风险。 理解其调度原理与正确的保留策略,是安全使用本地存储的关键,这也是 Kubernetes运维 的核心技能之一。




上一篇:Python GUI开发痛点解析:为何缺乏优秀的可视化设计工具?
下一篇:Spring事务中异步任务导致数据丢失:@Transactional避坑指南与实战解决方案
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-6 22:47 , Processed in 0.087447 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表