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,需手动清理旧数据。
练习#
- 用
emptyDir实现临时缓存,验证 Pod 重建后数据是否丢失。 - 搭建 NFS,创建 RWX 的 PV/PVC,并在两个 Pod 同时读写文件。
- 将 configMap 与 secret 同时挂载为文件,验证热更新行为。