循序渐进PersistentVolumes与PersistentVolumeClaim
文章目录
- 静态配置(Static Provisioning):
- Persistent volume(PV)
- Local 示例:
- NFS 示例:
- 检查pv
- PV 的常见状态说明
- Persistent volume claim(PVC)
- 1. local PVC示例:
- 2.NFS PVC示例:
- 3. 检查PVC:
- 挂载静态供应卷
- 验证静态供应卷挂载:
- 1. 查看 Deployment 和 Pod 状态
- 2. 进入容器内部验证挂载目录
- 动态供应(Dynamic Provisioning)
- StorageClasses:
- 使用 Helm 安装 NFS 动态存储卷插件
- 1. 添加存储库
- 2. 安装命令(请替换你的 NFS IP 和共享路径):
- 3. 检查stogrageclass
- 4 . storageclass参收说明:
- 创建 PVC(动态)
- 检查PVC:
- 动态挂载 PVC 到已部署 Pod
- 添加 Volume
- 添加 VolumeMount 到容器
- 验证挂载
静态配置(Static Provisioning):
由集群管理员预先创建 PersistentVolume(PV),这些 PV 携带实际存储的详细信息,可供集群用户使用。
Persistent volume(PV)
PersistentVolume(PV)是集群中的一种存储资源,可由管理员预先配置,或通过 StorageClass 实现动态配置。
Kubernetes 原生支持多种 PersistentVolume(PV)类型,叫做 volume plugins。它们允许你指定不同的底层存储方式,例如本地目录、NFS、云存储等。
实际开发/部署中最常见的内建类型:
类型 | 适用场景 | 说明 |
---|---|---|
local | 本地快速测试或特殊需求 | 需要设置 nodeAffinity |
nfs | 简单共享存储,手动配置即可 | 静态配置,适合小规模共享 |
hostPath | 单节点开发环境使用 | 不推荐用于生产 |
iscsi | 企业 SAN 接入 | 配置复杂 |
Local 示例:
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:name: mnt-pv
spec:accessModes:- ReadWriteManycapacity:storage: 100MivolumeMode: Filesystemlocal:fsType: ext4path: /mntnodeAffinity:required:nodeSelectorTerms:- matchExpressions:- key: kubernetes.io/hostnameoperator: Invalues:- k8sw01.lab.compersistentVolumeReclaimPolicy: Retain
EOF
检查 persistent Volumes:
NFS 示例:
cat << EOF | kubectl -f -
apiVersion: v1
kind: PersistentVolume
metadata:name: static-nfs-pv
spec:accessModes:- ReadWriteManycapacity:storage: 100MivolumeMode: Filesystemnfs:server: 172.20.32.247path: /data/static-pvpersistentVolumeReclaimPolicy: Retain
EOF
检查pv
kubectl get pv mnt-pv static-nfs-pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
mnt-pv 100Mi RWX Retain Available <unset> 41m
kubectl get pv 输出中的 STATUS 列显示 PersistentVolume (PV) 当前的状态。上面输出显示 Available ,是 PV 的一种状态,表示它当前没有被绑定(Bound)给任何 PersistentVolumeClaim (PVC)。
PV 的常见状态说明
状态 | 说明 |
---|---|
Available | PV 目前未被任何 PVC 绑定,可以被新的 PVC 申请使用。 |
Bound | PV 已经绑定到某个 PVC,正在被使用中。 |
Released | PV 原先被绑定的 PVC 已被删除,但 PV 还未被回收或重新配置,可能还保留旧数据。 |
Failed | PV 遇到错误或回收失败,可能无法正常使用。 |
Persistent volume claim(PVC)
为已声明的 PV 申请绑定:
1. local PVC示例:
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: mnt-pvcnamespace: kubeuser
spec:accessModes:- ReadWriteManyresources:requests:storage: 100MivolumeMode: FilesystemvolumeName: mnt-pv
EOF
2.NFS PVC示例:
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: static-nfs-pvcnamespace: kubeuser
spec:accessModes:- ReadWriteManyresources:requests:storage: 100MivolumeMode: FilesystemvolumeName: static-nfs-pv
EOF
3. 检查PVC:
kubectl get pvc mnt-pvc static-nfs-pvc -n kubeuser
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
mnt-pvc Bound mnt-pv 100Mi RWX <unset> 6m49s
static-nfs-pvc Bound static-nfs-pv 100Mi RWX <unset> 30s
挂载静态供应卷
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deploymentnamespace: kubeuserlabels:app: nginx
spec:replicas: 1 # 启动一个副本selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:latest # 使用官方 Nginx 镜像ports:- containerPort: 80volumeMounts:- mountPath: /mnt/mnt-pvcname: mnt-pvc- mountPath: /mnt/static-nfs-pvcname: static-nfs-pvcvolumes:- name: mnt-pvcpersistentVolumeClaim:claimName: mnt-pvc- name: static-nfs-pvcpersistentVolumeClaim:claimName: static-nfs-pvc
EOF
验证静态供应卷挂载:
在成功部署 Nginx 应用并绑定静态 NFS 卷后,我们可以通过以下步骤来验证卷是否已经正确挂载到容器中。
1. 查看 Deployment 和 Pod 状态
首先确认 nginx-deployment 已经成功运行,并且副本状态正常:
kubectl get deploy nginx-deployment -n kubeuser -o wide
输出结果类似如下,表示 Deployment 的 Pod 已就绪并运行中:
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deployment 1/1 1 1 4m4s nginx nginx:latest app=nginx
接着查看 Pod 的具体名称和状态:
root@k8sm01:/home/kubeadmin/yaml/deployments# kubectl get pod -n kubeuser
输出显示:
NAME READY STATUS RESTARTS AGE
nginx-deployment-f975675bc-ldgnk 1/1 Running 0 6m48s
2. 进入容器内部验证挂载目录
使用 kubectl exec 命令进入 Pod 的容器内部:
kubectl exec -it nginx-deployment-f975675bc-ldgnk -n kubeuser -- bash
进入容器后,可以查看主机名以确认所处环境:
hostname
nginx-deployment-f975675bc-ldgnk
接着检查挂载目录内容,例如挂载在 /mnt 下的子目录:
ls -lh /mnt/
total 8.0K
drwxr-xr-x 2 root root 4.0K Apr 23 2024 mnt-pvc
drwxr-xr-x 2 root root 4.0K May 27 15:14 static-nfs-pvc
这说明 PVC 已被正确挂载进 Pod 的指定路径中,Pod 可以直接读写对应的 NFS 共享目录,实现持久化存储。
动态供应(Dynamic Provisioning)
当没有任何静态 PersistentVolume 匹配某个 PersistentVolumeClaim 时,集群可能会尝试为该 PVC 进行动态分配。
此过程基于 StorageClass 进行。要在 Kubernetes 集群中实现 动态存储卷动态供给(Dynamic Provisioning),必须安装一个 StorageClass 和一个 支持动态创建 Volume 的 Provisioner。
StorageClasses:
在 GCP、AWS、Azure 或其他云平台上部署 Kubernetes 集群时,系统会预设创建一个默认的 StorageClass,该 StorageClass 使用标准类型的持久性磁盘。
运行 kubectl get storageclass 返回"No resources found"
kubectl get storageclass
No resources found
默认 Kubernetes 并不会自动安装这些,所以需要自己配置。
使用 Helm 安装 NFS 动态存储卷插件
有关helm的安装与使用,请参考这篇文章循序渐进掌握Helm
1. 添加存储库
helm repo add stable https://charts.helm.sh/stable
helm repo update
2. 安装命令(请替换你的 NFS IP 和共享路径):
helm install nfs-client nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \--namespace default \--set nfs.server=172.20.32.247 \--set nfs.path=/data/dynamic-pv \--set storageClass.defaultClass=true \--set storageClass.name=nfs-client
3. 检查stogrageclass
运行 kubectl get storageclass:
kubectl get storageclass
应该能看到:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client (default) cluster.local/nfs-client-nfs-subdir-external-provisioner Delete Immediate true 6m59s
storageclass yaml内容:
kubectl get storageclass -o yaml
apiVersion: v1
items:
- allowVolumeExpansion: trueapiVersion: storage.k8s.io/v1kind: StorageClassmetadata:annotations:meta.helm.sh/release-name: nfs-clientmeta.helm.sh/release-namespace: defaultstorageclass.kubernetes.io/is-default-class: "true"creationTimestamp: "2025-05-28T14:48:18Z"labels:app: nfs-subdir-external-provisionerapp.kubernetes.io/managed-by: Helmchart: nfs-subdir-external-provisioner-4.0.18heritage: Helmrelease: nfs-clientname: nfs-clientresourceVersion: "1018780"uid: 5912911f-4993-4965-8e75-ba79fe2dca25parameters:archiveOnDelete: "true"provisioner: cluster.local/nfs-client-nfs-subdir-external-provisionerreclaimPolicy: DeletevolumeBindingMode: Immediate
4 . storageclass参收说明:
-
Provisioner(供给器):
StorageClass 中包含一个 provisioner,用于指定创建 PV 时所使用的存储插件(volume plugin)。 -
Reclaim Policy(回收策略):
该策略决定当 PVC 被删除后,PV 应该如何处理。可以设置为:
Delete**:自动删除相关存储资源。
Retain**:保留数据,需要手动清理。
默认值为 Delete。 -
Volume Binding Mode(卷绑定模式):
volumeBindingMode 字段用于控制卷绑定(volume binding)和动态供给(dynamic provisioning)发生的时机。
Immediate(默认):立即分配卷。 -
Access Modes(访问模式):
PersistentVolume 支持以下访问模式:
ReadWriteOnce:卷可被单个节点以读写方式挂载。
ReadOnlyMany:卷可被多个节点以只读方式挂载。
ReadWriteMany:卷可被多个节点以读写方式挂载
创建 PVC(动态)
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:name: dynamic-nfs-pvcnamespace: kubeuser
spec:storageClassName: nfs-clientaccessModes:- ReadWriteManyresources:requests:storage: 100MivolumeMode: Filesystem
EOF
检查PVC:
可以看到刚刚创建的dynamic-nfs-pvc ,已经绑定storageclass:nfs-client,但status仍为pending状态,如果绑定成功,PVC 状态将变为 Bound,并关联到系统自动创建的 PV。
kubectl get pvc -n kubeuser
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
dynamic-nfs-pvc Pending nfs-client <unset> 3m6s
mnt-pvc Bound mnt-pv 100Mi RWX <unset> 23h
static-nfs-pvc Bound static-nfs-pv 100Mi RWX <unset> 23h
使用kubectl describe查看,将显示此pvc的细节信息
kubectl describe pvc dynamic-nfs-pvc -n kubeuser
输出显示仍然等待绑定
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal ExternalProvisioning 110s (x42 over 11m) persistentvolume-controller Waiting for a volume to be created either by the external provisioner 'cluster.local/nfs-client-nfs-subdir-external-provisioner' or manually by the system administrator. If volume creation is delayed, please verify that the provisioner is running and correctly registered.
动态挂载 PVC 到已部署 Pod
由于在静态供应(Static Provisioning)中已经部署了示例deployment,我们将继续使用这个deployment,并通过 kubectl patch 命令对已有 Deployment 添加动态 PVC:
kubectl patch deployment nginx-deployment -n kubeuser -p '{"spec":{"template":{"spec":{"volumes":[{"name":"dynamic-nfs-pvc","persistentVolumeClaim":{"claimName":"dynamic-nfs-pvc"}}]}}}}'
deployment.apps/nginx-deployment patched
添加 Volume
kubectl patch deployment nginx-deployment -n kubeuser -p '{"spec":{"template":{"spec":{"containers":[{"name":"nginx","volumeMounts":[{"mountPath":"/mnt/dynamic-nfs-pvc","name":"dynamic-nfs-pvc"}]}]}}}}'
添加 VolumeMount 到容器
kubectl get pvc -n kubeuser
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
dynamic-nfs-pvc Bound pvc-5179e3bb-831b-45f7-b0a0-96911e6b2b21 100Mi RWX nfs-client <unset> 22h
mnt-pvc Bound mnt-pv 100Mi RWX <unset> 45h
static-nfs-pvc Bound static-nfs-pv 100Mi RWX <unset> 45h
验证挂载
get pvc dynamic-nfs-pvc -n kubeuser
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
dynamic-nfs-pvc Bound pvc-5179e3bb-831b-45f7-b0a0-96911e6b2b21 100Mi RWX nfs-client <unset> 23h
进入容器内部
kubectl exec -it nginx-deployment-64699f648c-jlrl2 -n kubeuser -- bash
确认已经进入容器内部
hostname
nginx-deployment-64699f648c-jlrl2
输出目录中应包含:
ls -lh /mnt
total 12K
drwxrwxrwx 2 root root 4.0K May 28 15:21 dynamic-nfs-pvc
drwxr-xr-x 2 root root 4.0K Apr 23 2024 mnt-pvc
drwxr-xr-x 2 root root 4.0K May 27 15:14 static-nfs-pvc
说明所有三种 PVC(local、static NFS、dynamic NFS)已成功挂载,Pod 可读写使用。