PV、PVC、StorageClass

PersistentVolume(PV)

  • 是由管理员设置的存储,是集群的一部分,它不属于任何命名空间
  • PV的生命周期独立于使用它的pod的生命周期
  • PV更像是一种储备资源,先创建,有PVC需要它时才会被使用
  • PV可以是多种类型的(GCE,NFS等)
  • 分为静态和动态

PersistentVolumeClaim(PVC)

  • PVC 是用户对存储资源的请求,用户创建pvc以使用pv
  • PVC与PV的绑定是一对一的映射,小的pvc可能会使用大的pv,没有其他pvc可以利用剩余空间
  • 如果没有可用的PV,那么PVC会一直处于unbound未绑定状态,直到有新的pv产生,如果pvc与pv匹配,会自动绑定

PV 的生命周期

  • PV 的生命周期包含以下几个阶段:

供应 (Provisioning)

  • 静态供应:管理员手动创建 PV
  • 动态供应:通过 StorageClass 自动创建 PV

绑定 (Binding)

  • PVC 找到匹配的 PV 并绑定

使用 (Using)

  • Pod 通过 PVC 使用 PV

释放 (Releasing)

  • 用户删除 PVC,释放 PV

回收 (Reclaiming)

  • 根据 PV 的回收策略处理释放的 PV,策略如下
    • 保留(Retain):删除绑定的PVC后,PV不会被删除,需要手动删除
    • 删除(Delete):删除绑定的PVC后,PV不会被删除,其中的数据会被删除
    • 回收(Recycle):删除绑定的PVC后,PV会被自动删除(已废弃)

PV访问模式

  • 只能同时指定一种模式
  • ReadWriteOnce   (RWO)  该卷只能被单个节点以读/写模式挂载
  • ReadOnlyMany    (ROX)  该卷可以被多个节点以只读模式挂载
  • ReadWriteMany   (RWX)  该卷可以被多个节点以读/写模式挂载

PV和 PVC 的状态

PV的状态

  • Available:可用状态,目前还没有绑定给PVC
  • Bound:已经绑定给了某个PVC
  • Released:PVC已经解除与PV的绑定,但是PV还没有被集群回收
  • Failed:PV在自动回收中失败了

PVC的状态

  • Pending:PVC 正在等待可用的 PV。
  • Bound:PVC 已经与一个可用的 PV 绑定。
  • Lost:PVC 与绑定的 PV 断开连接,关联的 PV 已丢失

PV的静态供应示例

  • PV 示例 (NFS)
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: slow  # 和下方PVC的name一致
  nfs:
    server: nfs-server.example.com
    path: "/exports/data"
  • PVC 示例
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nfs
spec:
  storageClassName: slow
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Gi
  • Pod 使用 PVC
apiVersion: v1
kind: Pod
metadata:
  name: pod-with-pvc
spec:
  containers:
    - name: app
      image: nginx
      volumeMounts:
        - name: data
          mountPath: "/usr/share/nginx/html"
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: pvc-nfs  # 与上面的PVC name一致

PV的类型

  • AWSElasticBlockStore: AWS公有云提供的ElasticBlockStore。
  • AzureFile: Azure公有云提供的File。
  • AzureDisk: Azure公有云提供的Disk。
  • CephFS: 一种开源共享存储系统。
  • FC(Fibre Channel) : 光纤存储设备。
  • FlexVolume: 一种插件式的存储机制。
  • Flocker: 一种开源共享存储系统。
  • GCEPersistentDisk: GCE公有云提供的PersistentDisk。
  • Glusterfs: 一种开源共享存储系统。
  • HostPath: 宿主机目录, 仅用于单机测试。
  • iSCSI: iSCSI存储设备。
  • Local: 本地存储设备
  • NFS: 网络文件系统。
  • Portworx Volumes: Portworx提供的存储服务。
  • Quobyte Volumes: Quobyte提供的存储服务。
  • RBD(Ceph Block Device) : Ceph块存储。
  • ScaleIO Volumes: DellEMC的存储设备。
  • StorageOS: StorageOS提供的存储服务。
  • VsphereVolume: VMWare提供的存储系统。每种存储类型都有各自的特点, 在使用时需要根据它们各自的参数进行设置

Storage Class

  • 在 Kubernetes (K8S) 中,StorageClass 是一种用于动态管理存储资源的对象
  • StorageClass 是集群级资源,不属于任何名称空间。这意味着你可以在集群的任意名称空间中引用同一个 StorageClass

storage class的主要作用

  • 定义存储类型模板
    • 每个 StorageClass 对应一种特定的存储类型(如 SSD、HDD、分布式存储等),包含了该类型存储的配置信息(如存储后端、性能参数、回收策略等)。
  • 支持动态卷供应
    • 当用户创建 PersistentVolumeClaim (PVC) 时,K8S 可以根据 PVC 中指定的 StorageClass 自动创建对应的 PersistentVolume (PV),无需管理员手动预先创建 PV,极大简化了存储管理流程。
  • 实现存储的差异化
    • 通过定义多个 StorageClass,可以为不同应用提供不同性能、不同类型的存储服务(例如为数据库指定高性能 SSD 存储,为日志服务指定普通 HDD 存储)。

storageclass关键字段解析

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/gce-pd  # 存储供应者
parameters:
  type: pd-ssd                     # 存储系统特定参数
  replication-type: none
reclaimPolicy: Delete              # 回收策略
allowVolumeExpansion: true         # 是否允许卷扩展
volumeBindingMode: Immediate       # 绑定模式
mountOptions:                      # 挂载选项
  - discard

storageclass核心组件详解

  • Provisioner(供应者)

    • 决定实际创建存储的后端系统,常见类型:
    • 云平台:kubernetes.io/gce-pd、kubernetes.io/aws-ebs
    • 网络存储:kubernetes.io/nfs、ceph.com/rbd
    • 本地存储:kubernetes.io/no-provisioner
  • 回收策略(reclaimPolicy)

    • Delete:删除 PVC 时自动删除后端存储(默认动态供应)
    • Retain:保留存储资源需手动清理
  • 卷绑定模式(volumeBindingMode)

    • Immediate:创建 PVC 时立即绑定(默认)
    • WaitForFirstConsumer:延迟绑定直到 Pod 使用
  • 允许卷扩展(allowVolumeExpansion)

    • true:允许 PVC 创建后扩展大小
    • false:禁止扩展(默认)

实现storage class

配置本地存储

  • 所有k8s节点安装NFS客户端,配置共享目录
apt install -y nfs-common
mkdir -p /data/nfs && chmod 777 /data/nfs
echo "/data/nfs 192.168.40.0/24(rw,sync,no_root_squash,no_subtree_check)" >> /etc/exports
systemctl restart nfs-utils

创建存储类供应器

# nfs-provisioner.yaml
---
# 1. RBAC 权限配置
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-client-provisioner
  namespace: default
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: nfs-client-provisioner-runner
rules:
  - 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
    namespace: default
roleRef:
  kind: ClusterRole
  name: nfs-client-provisioner-runner
  apiGroup: rbac.authorization.k8s.io
---
# 2. 部署 NFS 供应器(核心:配置你的 NFS 服务器地址/共享目录)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nfs-client-provisioner
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nfs-client-provisioner
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-client-provisioner
    spec:
      serviceAccountName: nfs-client-provisioner
      containers:
        - name: nfs-client-provisioner
          image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME  # 供应器名称(后续 StorageClass 要用到)
              value: k8s-sigs.io/nfs-subdir-external-provisioner
            - name: NFS_SERVER        # NFS 服务器 IP
              value: 192.168.40.10
            - name: NFS_PATH          # NFS 共享目录
              value: /data/nfs
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.40.10
            path: /data/nfs

创建StorageClass

  • 不区分命名空间
cat <<EOF> nfs-storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-sc                  # StorageClass 名称(需和 PV 的 storageClassName 一致)
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner    # NFS 供应器
parameters:
  archiveOnDelete: "false"      # 删除 PVC 时不归档数据(可选 true)
reclaimPolicy: Delete           # # 删除 PVC 时,自动删除对应的 PV
allowVolumeExpansion: true      # 是否允许卷扩容
EOF

kubectl apply -f nfs-storageclass.yaml
kubectl get sc nfs-sc

创建PVC

cat <<EOF> nfs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc       # PVC 名称
  namespace: default  # 命名空间(按需修改)
spec:
  accessModes:
    - ReadWriteMany   # 需和 PV 的 accessModes 一致
  resources:
    requests:
      storage: 5Gi    # 申请容量(需 ≤ PV 容量)
  storageClassName: nfs-sc  # 关联 StorageClass
EOF

kubectl apply -f nfs-pvc.yaml
# 验证 PVC 绑定(状态为 Bound 即为绑定成功)
kubectl get pvc nfs-pvc

创建 Pod 挂载 PVC

cat <<EOF> nfs-test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nfs-test-pod
spec:
  containers:
  - name: nginx
    image: nginx:latest
    volumeMounts:
    - name: nfs-volume
      mountPath: /usr/share/nginx/html  # 容器内挂载路径
  volumes:
  - name: nfs-volume
    persistentVolumeClaim:
      claimName: nfs-pvc                # 关联 PVC 名称
EOF

验证

kubectl apply -f nfs-test-pod.yaml
kubectl get pod nfs-test-pod

# 进入 Pod 写入文件,验证 NFS 存储
kubectl exec -it nfs-test-pod -- /bin/bash
echo "Hello NFS PV" > /usr/share/nginx/html/index.html
cat /usr/share/nginx/html/index.html  # 输出 Hello NFS PV

# 到 NFS 服务器查看文件(验证数据同步)
cat /data/nfs/index.html  # 同样输出 Hello NFS PV
posted @ 2024-05-10 10:11  立勋  阅读(21)  评论(0)    收藏  举报