Kubernetes-storage-PV-PVC

Linux

概览

本文对常见的容器存储方案进行整理,包括 Docker 本地存储、Kubernetes 常用 Volume(emptyDir、hostPath)以及持久化存储资源对象 PersistentVolume(PV)、PersistentVolumeClaim(PVC)和 StorageClass。并以 NFS 为例,演示静态 PV/PVC 的创建与使用流程。

目录

  • 常见存储机制(Docker、Kubernetes)
    • Docker 本地存储
    • Kubernetes 本地存储:emptyDir、hostPath
  • PV / PVC / StorageClass 概念
  • NFS 环境准备
  • 原生 NFS 挂载示例(Deployment)
  • 使用 PV 与 PVC(静态 PV)示例
    • 创建 PV 池
    • 创建 PVC
    • 使用 PVC 的 Deployment
    • 清理顺序与注意事项

常见存储机制

Docker 本地存储

  • 宿主机目录挂载:
    docker run -v /local/path:/container/path ...
    
  • 命名卷(volume)挂载:
    docker run -v volume_name:/container/path ...
    

Kubernetes 本地存储

emptyDir

  • emptyDir 在 Pod 被调度到 Node 时由 kubelet 在该 Node 上创建目录。
  • 初始内容为空;当 Pod 从 Node 上移除后数据会被删除(非持久化)。
  • 适用场景:
    • 临时缓存、合并排序、短期中间文件
    • 容器间共享临时数据(例如临时日志)
  • 查看帮助:
    kubectl explain pod.spec.volumes.emptyDir
    kubectl explain pod.spec.containers.volumeMounts
    

hostPath

  • 将宿主机的文件或目录直接映射到 Pod 内。
  • 可指定 type(File、Directory、Socket、CharDevice、BlockDevice 等)。
  • 适用场景与注意点:
    • 适用于特定 Node 上的资源(跨 Node 时可能不一致)。
    • 需关注宿主机权限(宿主机目录通常只有 root 写权限)。
    • 不会被调度感知(不会计入资源调度决策)。
  • 查看帮助:
    kubectl explain pod.spec.volumes.hostPath
    kubectl explain pod.spec.containers.volumeMounts
    
  • 示例 Pod(hostPath):
    apiVersion: v1
    kind: Pod
    metadata:
      name: test-pod2
    spec:
      containers:
      - image: busybox
        name: test-hostpath
        command: ["sleep","3600"]
        volumeMounts:
        - mountPath: /test-data
          name: test-volume
      volumes:
      - name: test-volume
        hostPath:
          path: /data
          type: Directory
    

PV / PVC / StorageClass — 核心概念

  • PersistentVolume(PV):由管理员创建或动态供应的集群级存储资源抽象(表示具体存储,如 NFS、Ceph、GlusterFS 等)。
  • PersistentVolumeClaim(PVC):用户对存储的申请(类似 Pod 对 CPU/内存的请求),PVC 会绑定到合适的 PV。
  • StorageClass:描述存储类型与动态供应策略(如快速/慢速、不同 provisioner),供用户在 PVC 中指定。

使用 PV/PVC 可以把存储管理与底层实现解耦,使应用可以通过 PVC 方便地申请持久化存储。


NFS 环境准备(示例)

在 master 节点上安装并配置 NFS:

yum install -y nfs-utils rpcbind
mkdir -p /nfs/data && chmod 755 /nfs/data

# /etc/exports 内容(示例)
# /nfs/data/ *(insecure,rw,sync,no_root_squash)

systemctl enable --now rpcbind.service nfs.service
exportfs -r
exportfs

原生方式数据挂载(直接在 Deployment 中使用 NFS)

示例:直接在 Deployment volumes 中声明 nfs(属于“原生”方式,需提前在 NFS 服务端创建目录)。

nginx-pv-demo.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-pv-demo
  name: nginx-pv-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-pv-demo
  template:
    metadata:
      labels:
        app: nginx-pv-demo
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        nfs:
          server: 192.168.5.31   # 填写 NFS 服务器 IP
          path: /nfs/data/nginx-pv

示例操作(先在 NFS 上创建目录):

mkdir -p /nfs/data/nginx-pv
kubectl apply -f storage/nginx-pv-demo.yaml
kubectl get deploy
kubectl get pods
# 在宿主机写入文件,Pod 中可读取
echo "success" > /nfs/data/nginx-pv/index.html
kubectl exec -it <pod> -- curl localhost

原生挂载的局限性:

  1. 需要手动在存储端创建目录。
  2. 删除 Pod/Deployment 后,存储上的数据不会自动清理。
  3. 无法通过声明限制或管理存储容量(需要外部管理)。

使用 PV 与 PVC(静态 PV 管理示例)

1) 在 NFS 服务端准备多个目录作为 PV 池

mkdir -p /nfs/data/01
mkdir -p /nfs/data/02
mkdir -p /nfs/data/03

2) 静态 PV 定义(示例文件:nfs-pv.yaml)

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01-10m
spec:
  capacity:
    storage: 10M
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    path: /nfs/data/01
    server: 192.168.5.31
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv02-1gi
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    path: /nfs/data/02
    server: 192.168.5.31
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv03-3gi
spec:
  capacity:
    storage: 3Gi
  accessModes:
    - ReadWriteMany
  storageClassName: nfs
  nfs:
    path: /nfs/data/03
    server: 192.168.5.31

应用并查看:

kubectl apply -f storage/nfs-pv.yaml
kubectl get pv

3) 创建 PVC(示例文件:nfs-pvc.yaml)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 200Mi
  storageClassName: nfs
kubectl apply -f storage/nfs-pvc.yaml
kubectl get pvc
kubectl get pv
# PVC 会被调度并绑定到满足条件的 PV(例如上面的 pv02-1gi)

4) 在 Deployment 中使用 PVC(示例:nginx-deploy-pvc.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx-deploy-pvc
  name: nginx-deploy-pvc
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-deploy-pvc
  template:
    metadata:
      labels:
        app: nginx-deploy-pvc
    spec:
      containers:
      - image: nginx
        name: nginx
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        persistentVolumeClaim:
          claimName: nginx-pvc

部署后验证:

kubectl apply -f storage/nginx-deploy-pvc.yaml
kubectl get pods
kubectl get pv,pvc
# 在 NFS 上写入 /nfs/data/02/index.html,Pod 内访问应能看到相同内容

注意事项与清理流程(静态 PV)

  • 静态 PV:管理员预先创建 PV(如上示例)。PVC 绑定后会使用该 PV。
  • 删除静态 PV 的推荐顺序(避免残留问题):
    1. 删除使用该 PV 的 Pod/Deployment/StatefulSet。
    2. 在宿主(存储)端清理或移除对应目录的内容。
    3. 删除 PVC。
    4. 删除 PV。
  • 若使用动态供应(StorageClass + provisioner),则可实现自动创建/回收 PV,便于自动化管理。

参考命令(常用)

kubectl get pv
kubectl get pvc
kubectl get pods
kubectl apply -f <file.yaml>
kubectl delete -f <file.yaml>
kubectl exec -it <pod> -- /bin/bash
kubectl explain pod.spec.volumes

图片示意: k8s-storage-pv

结束。