在Kubernetes集群中,容器存储的短暂性是一个必须解决的核心问题。当容器崩溃或Pod被重新调度时,容器内部的文件系统会丢失所有数据。这种特性虽然符合云原生应用的"无状态"设计理念,但对于需要持久化数据的应用场景来说却是个致命缺陷。
容器存储面临两个主要挑战:
Kubernetes通过Volume抽象解决了这些问题。Volume的生命周期与Pod绑定,而不是与容器绑定。这意味着:
Kubernetes提供了多种持久化存储方案,按功能复杂度可分为三个层次:
基础存储卷:emptyDir、hostPath等
静态PV/PVC:PersistentVolume和PersistentVolumeClaim
动态存储供给:StorageClass
emptyDir是最简单的存储卷类型,具有以下特点:
yaml复制apiVersion: v1
kind: Pod
metadata:
name: pod-emptydir
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html/
- name: busybox
image: busybox:latest
volumeMounts:
- name: html
mountPath: /data/
command: ['/bin/sh','-c','while true;do echo $(date) >> /data/index.html;sleep 2;done']
volumes:
- name: html
emptyDir: {}
注意:emptyDir默认使用节点磁盘存储,也可以通过设置
emptyDir.medium字段为"Memory"来使用tmpfs(内存文件系统)
hostPath将节点上的文件系统挂载到Pod中,特点包括:
yaml复制apiVersion: v1
kind: Pod
metadata:
name: pod-hostpath
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
hostPath:
path: /data/pod/volume1
type: DirectoryOrCreate
警告:hostPath存在安全隐患,可能允许容器访问节点敏感文件。生产环境应谨慎使用
NFS解决了多节点间的数据共享问题,主要优势包括:
bash复制# 在NFS服务器上执行
yum install -y nfs-utils rpcbind
mkdir /data/volumes -p
chmod 777 /data/volumes
echo "/data/volumes 192.168.10.0/24(rw,no_root_squash)" > /etc/exports
systemctl start rpcbind nfs
systemctl enable rpcbind nfs
yaml复制apiVersion: v1
kind: Pod
metadata:
name: pod-vol-nfs
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
nfs:
path: /data/volumes
server: stor01
PersistentVolume(PV):
PersistentVolumeClaim(PVC):
yaml复制apiVersion: v1
kind: PersistentVolume
metadata:
name: pv003
labels:
name: pv003
spec:
nfs:
path: /data/volumes/v3
server: stor01
accessModes: ["ReadWriteMany","ReadWriteOnce"]
capacity:
storage: 2Gi
persistentVolumeReclaimPolicy: Retain
yaml复制apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mypvc
spec:
accessModes: ["ReadWriteMany"]
resources:
requests:
storage: 2Gi
yaml复制apiVersion: v1
kind: Pod
metadata:
name: pod-vol-pvc
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
volumes:
- name: html
persistentVolumeClaim:
claimName: mypvc
StorageClass实现了动态PV供给,主要组件包括:
yaml复制apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-client-provisioner-clusterrole
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
yaml复制apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
spec:
replicas: 1
template:
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
env:
- name: PROVISIONER_NAME
value: nfs-storage
- name: NFS_SERVER
value: stor01
- name: NFS_PATH
value: /opt/k8s
yaml复制apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-client-storageclass
provisioner: nfs-storage
parameters:
archiveOnDelete: "false"
yaml复制apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-nfs-pvc
spec:
accessModes:
- ReadWriteMany
storageClassName: nfs-client-storageclass
resources:
requests:
storage: 1Gi
| 方案类型 | 典型代表 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 基础卷 | emptyDir | 简单易用 | 数据非持久化 | 临时存储 |
| 节点存储 | hostPath | 数据持久化 | 单节点限制 | 开发测试 |
| 网络存储 | NFS | 多节点共享 | 性能瓶颈 | 中小规模应用 |
| 静态PV | PV/PVC | 资源抽象 | 需预配置 | 固定存储需求 |
| 动态PV | StorageClass | 按需供给 | 配置复杂 | 生产环境 |
症状:PVC一直处于Pending状态
可能原因:
解决方案:
bash复制kubectl describe pvc <pvc-name> # 查看绑定失败原因
kubectl get pv # 检查PV状态和属性
症状:Pod启动失败,报权限错误
可能原因:
解决方案:
bash复制# 在NFS服务器检查导出选项
cat /etc/exports
# 临时禁用SELinux测试
setenforce 0
# 确保目录有足够权限
chmod 777 /path/on/nfs
症状:PVC无法自动创建PV
可能原因:
解决方案:
bash复制kubectl logs -f deploy/nfs-client-provisioner # 检查provisioner日志
kubectl get storageclass # 验证StorageClass配置
NFS性能调优:
mount -o rsize=65536,wsize=65536)存储分层设计:
资源监控:
NFS安全加固:
192.168.10.0/24)no_root_squash需谨慎RBAC最小权限:
数据加密: