PV(Persistent Volume)和PVC(Persistent Volume Claim)是Kubernetes中用于管理存储资源的两个核心概念,它们通过解耦存储资源与应用需求实现灵活管理。以下是两者的核心区别及协作机制:
PV 是集群管理员预先配置的物理存储资源,如NFS、云存储或本地磁盘等,其生命周期独立于Pod存在。
PVC 是用户为应用程序提交的存储需求申请,通过声明容量、访问模式等参数匹配可用PV
管理员创建PV或定义存储模板(如StorageClass)
用户提交PVC申请,Kubernetes自动匹配符合条件的PV
若动态供给已启用,未匹配的PVC可触发自动创建新PV
在Kubernetes中,静态供给(Static Provisioning)是指管理员预先创建并配置好PV(PersistentVolume),然后由用户通过PVC(PersistentVolumeClaim)申请匹配的存储资源。
yml# ========== PersistentVolume (PV) 定义 ==========
apiVersion: v1
kind: PersistentVolume
metadata:
name: static-pv-nfs
spec:
capacity:
storage: 1Gi # PV的总容量
accessModes:
- ReadWriteMany # 支持多节点同时读写
persistentVolumeReclaimPolicy: Retain # Pod删除后保留PV和数据
nfs:
server: 192.168.201.104 # NFS服务器地址
path: "/data/nfs_share" # NFS服务器共享路径
# 可选参数:readOnly: false # 默认可读写
---
# ========== PersistentVolumeClaim (PVC) 定义 ==========
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: static-pvc-app # PVC名称,Pod中会引用此名称
spec:
accessModes:
- ReadWriteMany # 必须与PV的accessModes匹配
resources:
requests:
storage: 1Gi # 申请1GB存储空间,申请的容量必须和PV一样
storageClassName: "" # 显式设置为空字符串以确保使用静态供给
---
# ========== Pod 定义 ==========
apiVersion: v1
kind: Pod
metadata:
name: nginx-with-pvc # Pod名称
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: nfs-storage # 必须与volumes.name匹配
mountPath: "/usr/share/nginx/html" # 容器内挂载路径
# 可选参数:readOnly: false # 默认可读写
volumes:
- name: nfs-storage # 卷名称
persistentVolumeClaim:
claimName: static-pvc-app # 绑定前面定义的PVC
# 可选参数:readOnly: false # 默认可读写
Kubernetes中PV(PersistentVolume)和PVC(PersistentVolumeClaim)的动态供给是一种自动化存储资源分配机制。
动态供给:当用户创建PVC时,系统根据预定义的StorageClass自动创建并绑定匹配的PV,无需管理员手动预置PV。
ymlapiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: kube-system
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: chronolaw/nfs-subdir-external-provisioner:v4.0.2
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
value: 192.168.201.104 #nfs服务器ip地址
- name: NFS_PATH
value: /root/nfs/data #nfs服务器共享数据目录
volumes:
- name: nfs-client-root
nfs:
server: 192.168.201.104 #nfs服务器ip地址
path: /root/nfs/data #nfs服务器共享数据目录
ymlapiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: kube-system
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: kube-system
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: kube-system
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: kube-system
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: kube-system
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
yml# ==================== 存储类配置 ====================
apiVersion: storage.k8s.io/v1 # 存储类API版本标识
kind: StorageClass # 声明资源类型为存储类
metadata: # 资源元数据开始
name: mysql-nfs-sc # 存储类命名(MySQL专用NFS存储类)
namespace: ems # 归属ems命名空间
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # 指定NFS子目录动态供应器
parameters: # 供应器参数配置开始
onDelete: "remain" # 数据保留策略:删除时不清理
yml# ==================== 命名空间配置 ====================
apiVersion: v1 # Kubernetes核心API版本标识
kind: Namespace # 声明资源类型为命名空间
metadata: # 资源元数据开始
name: ems # 定义命名空间名称为ems(Enterprise Management System)
---
# ==================== 有状态应用配置 ====================
apiVersion: apps/v1 # 应用API版本标识
kind: StatefulSet # 声明资源类型为有状态副本集
metadata: # 资源元数据开始
name: mysql # StatefulSet名称
namespace: ems # 归属ems命名空间
labels: # 标签集合开始
app: mysql # 应用标识标签
spec: # 规格定义开始
serviceName: mysql-headless # 关联的无头服务名(用于DNS解析)
replicas: 1 # 副本数配置(MySQL单实例部署)
template: # Pod模板定义开始
metadata: # Pod元数据开始
labels: # Pod标签集合开始
app: mysql # 应用标识标签(需与selector匹配)
spec: # Pod规格定义开始
containers: # 容器定义列表开始
- name: mysql # 容器名称标识
image: mysql/mysql-server:8.0 # 官方MySQL 8.0镜像
ports: # 端口映射列表开始
- containerPort: 3306 # MySQL服务默认端口
env: # 环境变量列表开始
- name: MYSQL_ROOT_PASSWORD # root密码变量名
value: "root" # 密码明文值(测试环境使用)
volumeMounts: # 存储卷挂载列表开始
- name: data # 引用下方PVC模板名称
mountPath: /var/lib/mysql # MySQL数据存储路径
volumeClaimTemplates: # PVC模板列表开始
- metadata: # PVC元数据开始
name: data # PVC资源名称
spec: # PVC规格定义开始
accessModes: [ "ReadWriteMany" ] # 存储访问模式(多节点读写)
storageClassName: "mysql-nfs-sc" # 绑定前文定义的存储类
resources: # 资源请求定义开始
requests: # 资源请求参数开始
storage: 2Gi # 存储空间大小请求值
selector: # Pod选择器定义开始
matchLabels: # 标签匹配规则开始
app: mysql # 需匹配的Pod标签键值
本文作者:松轩(^U^)
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!