16.5.1 Kubernetes存储体系与卷类型概览

Kubernetes 存储体系围绕“容器无状态、数据需持久化”的核心目标设计,分为临时卷与持久化卷两大类,并通过 CSI(Container Storage Interface)对接外部存储系统。卷作为 Pod 级别资源,由 kubelet 负责挂载与卸载,实现数据与容器生命周期解耦。

文章图片

存储体系要点
- Pod 级别挂载:卷定义在 Pod spec 中,可被容器挂载为目录。
- 控制面与数据面分离:控制器管理资源对象,kubelet 负责实际挂载。
- CSI 标准化:通过 CSI 插件统一对接块存储、文件存储、对象存储等后端。
- 访问模式:ReadWriteOnce / ReadOnlyMany / ReadWriteMany 影响调度与部署形态。
- 回收策略:保留(Retain)、删除(Delete)、回收(Recycle 已废弃)。


临时卷类型(与 Pod 同生命周期)#

emptyDir 示例(缓存目录)#

# /opt/k8s/yaml/emptydir-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo-emptydir
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh","-c","echo hello > /cache/hello.txt; sleep 3600"]
    volumeMounts:
    - name: cache
      mountPath: /cache
  volumes:
  - name: cache
    emptyDir: {}
kubectl apply -f /opt/k8s/yaml/emptydir-pod.yaml
kubectl exec demo-emptydir -- cat /cache/hello.txt
# 预期:输出 hello

命令解释
- kubectl apply -f:创建/更新资源。
- kubectl exec:进入容器验证挂载是否生效。

configMap/secret 示例(配置注入)#

kubectl create configmap app-conf --from-literal=APP_PORT=8080
kubectl create secret generic app-secret --from-literal=DB_PASS=123456
# /opt/k8s/yaml/cm-secret-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: demo-config
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh","-c","env; sleep 3600"]
    env:
    - name: APP_PORT
      valueFrom:
        configMapKeyRef:
          name: app-conf
          key: APP_PORT
    - name: DB_PASS
      valueFrom:
        secretKeyRef:
          name: app-secret
          key: DB_PASS
kubectl apply -f /opt/k8s/yaml/cm-secret-pod.yaml
kubectl logs demo-config | grep -E 'APP_PORT|DB_PASS'

持久化卷类型(与 Pod 生命周期解耦)#

PV/PVC(NFS)示例#

环境安装(NFS 服务器)

# 服务端
yum install -y nfs-utils
mkdir -p /data/nfs/k8s
chmod -R 777 /data/nfs/k8s
echo "/data/nfs/k8s *(rw,sync,no_root_squash)" >> /etc/exports
systemctl enable --now nfs-server
exportfs -rv

PV/PVC 与 Pod

# /opt/k8s/yaml/pv-pvc-nfs.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs-01
spec:
  capacity:
    storage: 2Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 192.168.1.10
    path: /data/nfs/k8s
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs-01
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-nfs
spec:
  containers:
  - name: app
    image: busybox:1.36
    command: ["sh","-c","echo nfs-ok > /data/test.txt; sleep 3600"]
    volumeMounts:
    - name: data
      mountPath: /data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: pvc-nfs-01
kubectl apply -f /opt/k8s/yaml/pv-pvc-nfs.yaml
kubectl get pv,pvc
kubectl exec demo-nfs -- cat /data/test.txt

预期效果
- PV 处于 Bound,PVC 与 PV 绑定。
- Pod 中写入文件后,NFS 服务端目录可见数据。


卷类型选择建议#

  • 共享读写(RWX):优先 NFS、CephFS。
  • 数据库高性能(RWO):iSCSI、Ceph RBD、云盘 + StatefulSet。
  • 配置/证书:configMap/secret。
  • 生产环境避免 hostPath(除非明确节点绑定与容灾方案)。

常用排错#

# 查看 Pod 事件,定位挂载失败原因
kubectl describe pod demo-nfs | sed -n '/Events:/,$p'

# 查看 PV/PVC 绑定状态
kubectl get pv,pvc -o wide

# kubelet 挂载日志(节点上)
journalctl -u kubelet --since "10 min ago" | tail -n 100

# 检查 NFS 共享可达
showmount -e 192.168.1.10

常见问题
- PVC 处于 Pending:PV 不满足容量/访问模式或未创建。
- Mount failed:网络不通、NFS 导出权限不足、节点缺少 nfs-utils。
- 读写异常:回收策略为 Retain,需手动清理旧数据。


练习#

  1. emptyDir 实现临时缓存,验证 Pod 重建后数据是否丢失。
  2. 搭建 NFS,创建 RWX 的 PV/PVC,并在两个 Pod 同时读写文件。
  3. 将 configMap 与 secret 同时挂载为文件,验证热更新行为。