k8s持久化存储

k8s中的常见存储类型

为什么要做数据持久化?

k8s中的pod的生命周期是短暂,当pod被删除时数据也会随之删除。当我们的数据不重要是也就无所谓了,但是生产环境中,我们的数据都是十分重要的,不能随意删除。

为了解决这个问题,我们需要再k8s中做数据持久化。数据持久化是将数据保存到持久化的存储介质上,以便pod删除被创建或者迁移到其它节点时仍然可用。

数据持久化的场景包括:

1、数据存储:许多应用程序需要保存用户生成的数据,如文件、图片、日志等。通过数据持久化,可以确保这些数据在容器销毁或重启后仍然存在。

2、数据共享:在某些情况下,多个容器或 Pod 可能需要访问和共享相同的数据。通过将数据存储在持久化卷中,可以使多个容器之间共享数据,实现数据一致性和共享访问。

3、数据备份和恢复:持久化存储解决方案通常提供数据备份和恢复机制,以防止数据丢失。这对于保护重要数据、应对故障或恢复到先前的状态非常重要。

4、数据迁移和扩展:在 Kubernetes 集群中,可能需要扩展应用程序到多个节点或迁移到其他集群。通过将数据存储在持久化卷中,可以方便地将数据与应用程序一起迁移到新的环境,无需担心数据丢失。

5、数据安全:某些行业或应用程序对数据的安全性有严格的要求。持久化存储解决方案通常提供数据 加密和访问控制功能,以确保数据在传输和存储过程中的安全性。

k8s 持久化存储方案-emptyDir(临时)

image-20240218140608589

[root@k8s-slave1 ~]# kubectl explain pods.spec.volumes
KIND:     Pod
VERSION:  v1

RESOURCE: volumes <[]Object>

DESCRIPTION:
     List of volumes that can be mounted by containers belonging to the pod.
     More info: https://kubernetes.io/docs/concepts/storage/volumes

     Volume represents a named volume in a pod that may be accessed by any
     container in the pod.

FIELDS:
   awsElasticBlockStore	<Object>
     awsElasticBlockStore represents an AWS Disk resource that is attached to a
     kubelet's host machine and then exposed to the pod. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore

   azureDisk	<Object>
     azureDisk represents an Azure Data Disk mount on the host and bind mount to
     the pod.

   azureFile	<Object>
     azureFile represents an Azure File Service mount on the host and bind mount
     to the pod.

   cephfs	<Object>
     cephFS represents a Ceph FS mount on the host that shares a pod's lifetime

   cinder	<Object>
     cinder represents a cinder volume attached and mounted on kubelets host
     machine. More info: https://examples.k8s.io/mysql-cinder-pd/README.md

   configMap	<Object>
     configMap represents a configMap that should populate this volume

   csi	<Object>
     csi (Container Storage Interface) represents ephemeral storage that is
     handled by certain external CSI drivers (Beta feature).

   downwardAPI	<Object>
     downwardAPI represents downward API about the pod that should populate this
     volume

   emptyDir	<Object>
     emptyDir represents a temporary directory that shares a pod's lifetime.
     More info: https://kubernetes.io/docs/concepts/storage/volumes#emptydir

   ephemeral	<Object>
     ephemeral represents a volume that is handled by a cluster storage driver.
     The volume's lifecycle is tied to the pod that defines it - it will be
     created before the pod starts, and deleted when the pod is removed.

     Use this if: a) the volume is only needed while the pod runs, b) features
     of normal volumes like restoring from snapshot or capacity tracking are
     needed, c) the storage driver is specified through a storage class, and d)
     the storage driver supports dynamic volume provisioning through a
     PersistentVolumeClaim (see EphemeralVolumeSource for more information on
     the connection between this volume type and PersistentVolumeClaim).

     Use PersistentVolumeClaim or one of the vendor-specific APIs for volumes
     that persist for longer than the lifecycle of an individual pod.

     Use CSI for light-weight local ephemeral volumes if the CSI driver is meant
     to be used that way - see the documentation of the driver for more
     information.

     A pod can use both types of ephemeral volumes and persistent volumes at the
     same time.

   fc	<Object>
     fc represents a Fibre Channel resource that is attached to a kubelet's host
     machine and then exposed to the pod.

   flexVolume	<Object>
     flexVolume represents a generic volume resource that is
     provisioned/attached using an exec based plugin.

   flocker	<Object>
     flocker represents a Flocker volume attached to a kubelet's host machine.
     This depends on the Flocker control service being running

   gcePersistentDisk	<Object>
     gcePersistentDisk represents a GCE Disk resource that is attached to a
     kubelet's host machine and then exposed to the pod. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk

   gitRepo	<Object>
     gitRepo represents a git repository at a particular revision. DEPRECATED:
     GitRepo is deprecated. To provision a container with a git repo, mount an
     EmptyDir into an InitContainer that clones the repo using git, then mount
     the EmptyDir into the Pod's container.

   glusterfs	<Object>
     glusterfs represents a Glusterfs mount on the host that shares a pod's
     lifetime. More info: https://examples.k8s.io/volumes/glusterfs/README.md

   hostPath	<Object>
     hostPath represents a pre-existing file or directory on the host machine
     that is directly exposed to the container. This is generally used for
     system agents or other privileged things that are allowed to see the host
     machine. Most containers will NOT need this. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath

   iscsi	<Object>
     iscsi represents an ISCSI Disk resource that is attached to a kubelet's
     host machine and then exposed to the pod. More info:
     https://examples.k8s.io/volumes/iscsi/README.md

   name	<string> -required-
     name of the volume. Must be a DNS_LABEL and unique within the pod. More
     info:
     https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names

   nfs	<Object>
     nfs represents an NFS mount on the host that shares a pod's lifetime More
     info: https://kubernetes.io/docs/concepts/storage/volumes#nfs

   persistentVolumeClaim	<Object>
     persistentVolumeClaimVolumeSource represents a reference to a
     PersistentVolumeClaim in the same namespace. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims

   photonPersistentDisk	<Object>
     photonPersistentDisk represents a PhotonController persistent disk attached
     and mounted on kubelets host machine

   portworxVolume	<Object>
     portworxVolume represents a portworx volume attached and mounted on
     kubelets host machine

   projected	<Object>
     projected items for all in one resources secrets, configmaps, and downward
     API

   quobyte	<Object>
     quobyte represents a Quobyte mount on the host that shares a pod's lifetime

   rbd	<Object>
     rbd represents a Rados Block Device mount on the host that shares a pod's
     lifetime. More info: https://examples.k8s.io/volumes/rbd/README.md

   scaleIO	<Object>
     scaleIO represents a ScaleIO persistent volume attached and mounted on
     Kubernetes nodes.

   secret	<Object>
     secret represents a secret that should populate this volume. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#secret

   storageos	<Object>
     storageOS represents a StorageOS volume attached and mounted on Kubernetes
     nodes.

   vsphereVolume	<Object>
     vsphereVolume represents a vSphere volume attached and mounted on kubelets
     host machine

常用的如下:

emptyDir 
hostPath 
nfs
persistentVolumeClaim
glusterfs
cephfs
configMap
secret

在 Kubernetes 中,EmptyDir 是一种卷(Volume),它提供了一个空目录来供容器使用。EmptyDir 卷在 Pod 级别上创建,与 Pod 的生命周期绑定。EmptyDir 卷在 Pod 被删除或重新启动时会被清空,因 此它不是持久化的存储解决方案。

EmptyDir 卷的使用场景包括:

  1. 临时文件共享:如果多个容器需要在同一个 Pod 中进行临时文件共享,EmptyDir 卷是一个简便 的解决方案。容器可以将文件写入 EmptyDir 卷,并且其他容器可以读取和修改这些文件。当 Pod 被删除或重启时,EmptyDir 卷中的文件会被清空。
  2. 共享数据:某些应用程序可能需要在容器之间共享一些中间结果或临时数据。EmptyDir 卷可以 作为容器之间的临时数据交换机制。容器可以将数据写入 EmptyDir 卷,其他容器可以读取和处 理这些数据,从而实现数据共享和协作。
  3. 缓存:EmptyDir 卷可以用作容器的缓存存储。某些应用程序可能需要将频繁访问的数据缓存到 本地存储中,以提高性能。EmptyDir 卷提供了一个临时的、高速的存储介质来存储缓存数据, 提供快速的读取和写入操作。

当在 Kubernetes 中使用存储卷(Volume),需要经历以下步骤:

  1. 定义 Pod 的 Volume:在 Pod 的配置中定义一个 Volume,指定它要关联到哪个存储上。可以 使用不同类型的 Volume,如 EmptyDir、HostPath、PersistentVolumeClaim 等,具体选 择取决于需求。

  2. 在容器中使用 Volume Mounts:在 Pod 的配置中,为每个容器定义 Volume Mounts,将 Volume 挂载到容器内部的指定路径上。这样容器就能够访问和操作 Volume 中的数据。

  3. 通过 Volume 实现数据持久化和共享:一旦 Volume 被挂载到容器中,容器就可以将数据写入 Volume 或从 Volume 中读取数据。这使得数据能够在容器的生命周期内持久存在,并且可以被 其他容器共享和访问。

创建一个临时卷案例

参考:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#emptydir-配置示例

[root@k8s-slave1 volumes]# cat emptydir.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod-emptydir
spec:
  containers:
  - image: nginx
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
   #   sizeLimit: 500Mi   #可以设置目录大小

image-20240218142914247

image-20240218143517477

image-20240218143752612

k8s 持久化存储方案-hostPath

hostPath 是 Kubernetes 中的一种卷类型,它将主机节点上的文件或目录挂载到容器中。使用 hostPath,可以将主机节点上的文件系统路径直接映射到容器的文件系统中。这种方式在某些情况下非常有用,但也需要谨慎使用,因为它具有一些潜在的限制和风险。

以下是 hostPath 的一些关键特点和适用场景:

  1. 直接访问主机文件系统:hostPath 卷允许容器直接访问主机节点上的文件系统。这对于需要访问主机节点上的特定文件或目录的应用程序非常有用。例如,某些日志收集器可能需要访问主机 上的日志文件。
  2. 主机依赖性:hostPath 卷的挂载是与特定主机节点紧密关联的,因此在调度 Pod 时需要特别 注意。如果 Pod 被调度到另一个主机节点上,它将无法访问之前挂载的主机文件系统。
  3. 危险性:hostPath 卷的使用需要谨慎,因为容器可以访问主机节点上的任何文件或目录,包括 敏感的系统文件。此外,如果多个 Pod 使用相同的 hostPath 卷并且并发写入同一个文件,可 能会导致冲突和数据损坏。
  4. 开发和测试环境:hostPath 卷特别适用于开发和测试环境,因为它可以方便地将主机节点上的 文件或目录映射到容器中,从而加快开发和测试工作流程。

需要注意的是,hostPath 卷并不适合生产环境中的大多数用例。在生产环境中,建议使用更可靠和 弹性的持久化存储方案,例如网络存储卷(NFS)、云提供商的块存储或对象存储等。

查看 hostPath 存储卷的用法

[root@k8s-slave1 ~]# kubectl explain pod.spec.volumes.hostPath
KIND:     Pod
VERSION:  v1

RESOURCE: hostPath <Object>

DESCRIPTION:
     hostPath represents a pre-existing file or directory on the host machine
     that is directly exposed to the container. This is generally used for
     system agents or other privileged things that are allowed to see the host
     machine. Most containers will NOT need this. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath

     Represents a host path mapped into a pod. Host path volumes do not support
     ownership management or SELinux relabeling.

FIELDS:
   path	<string> -required-
     path of the directory on the host. If the path is a symlink, it will follow
     the link to the real path. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath

   type	<string>
     type for HostPath Volume Defaults to "" More info:
     https://kubernetes.io/docs/concepts/storage/volumes#hostpath


官网:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/#hostpath

image-20240218145616552

image-20240218152657527

apiVersion: v1
kind: Pod
metadata:
  name: tomcat
  namespace: volumes # 单独开一个ns环境
spec:
  

  volumes:
  - name: tomcat-log
    hostPath:
      path: /share/pod_share/tomcat/   #设置目录不用自动创建

  containers:
  - name: tomcat-log
    image: tomcat
    volumeMounts:
      - name: tomcat-log
        mountPath: /usr/local/tomcat/logs/

image-20240218154157995

image-20240218154509719

image-20240218154814255

删除pod查看数据是否存在

image-20240218155209438

k8s 持久化存储方案-NFS

NFS(Network File System)是一种网络文件系统协议,它允许不同计算机之间共享文件和目录。 在 Kubernetes(k8s)中,NFS 是一种常见的持久化存储方案,用于将网络共享的存储卷挂载到容器中。

下面是 NFS 的基本介绍和常见应用场景:

  1. 基本原理:NFS 允许将存储资源(文件或目录)通过网络共享给其他计算机。NFS 服务器将存 储资源公开为共享,并将其挂载到客户端计算机上。客户端可以像访问本地文件系统一样访问这 些共享资源。
  2. 持久化存储方案:在 Kubernetes 中,NFS 可以作为持久化存储方案使用。它可以提供可靠的 存储,并在 pod 被重新调度到不同的节点时保持数据的一致性。
  3. 分布式访问:NFS 允许多个客户端同时访问共享资源。这使得它非常适合那些需要多个容器或 Pod 共享数据的场景,例如数据库系统或分布式文件共享。
  4. 跨平台兼容性:NFS 是一种跨平台的文件系统协议,支持在不同操作系统之间进行文件共享。这 使得它成为在混合操作系统集群中实现持久化存储的理想选择。
  5. 灵活性:NFS 提供了对存储资源的灵活访问和管理。管理员可以根据需求创建和配置 NFS 服务 器,设置共享权限以及实施访问控制策略。
  6. 备份和恢复:NFS 具备备份和恢复数据的能力。通过使用备份工具和策略,可以对 NFS 共享的 数据进行定期备份,以防止数据丢失或损坏。

NFS服务器搭建就不写了

image-20240218161518969

创建pod,挂载nfs共享目录

apiVersion: v1
kind: Pod
metadata:
  name: nfs
  namespace: volumes

spec:
  containers:
  - image: nginx
    name: nfs
    volumeMounts:
    - mountPath: /usr/share/nginx/html/
      name: nfs-volume
  volumes:
  - name: nfs-volume
    nfs:
      server: 192.168.33.100
      path: /volumes

image-20240218163828511

image-20240218164013170

nfs存储卷也可以保存用户数据,不受宿主机影响,但是万一nfs服务器宕机了,就会影响你的数据,生成环境中需要使用分布式存储,常见的分布式有glusterfs和cephfs。

k8s 持久化存储方案-PVC

官网:https://kubernetes.io/zh-cn/docs/concepts/storage/persistent-volumes/

K8s PV 是什么?

PersistentVolume(PV):PV 是集群中的存储资源,可以是物理存储设备、网络存储或云存储等。 PV 独立于 Pod 存在,它们是集群级别的资源,由集群管理员进行配置和管理。PV 具有持久性,即使 Pod 被删除,PV 中的数据也会保留。PV 定义了存储的容量、访问模式和其他属性。

K8s PVC 是什么?

PersistentVolumeClaim(PVC):PVC 是 Pod 对 PV 的申请,它表示 Pod 需要一定的存储资源来 满足其持久化存储需求。PVC 在 Pod 和 PV 之间建立了一个抽象层,使得 Pod 无需关心底层存储的具体 细节。PVC 定义了 Pod 对存储的需求,包括存储容量、访问模式等。

K8s PVC 和 PV 工作原理

当创建一个 PersistentVolume(PV)和 PersistentVolumeClaim(PVC)时,它们之间的相互作 用和工作原理如下:

  1. PV 的供应方式:

    • 静态配置:集群管理员预先创建 PV 对象,包含了实际存储资源的详细信息。这些 PV 存在于 Kubernetes API 中,供用户使用。

    • 动态配置:当静态 PV 无法匹配用户的 PVC 时,Kubernetes 可以尝试为 PVC 动态地 配置 PV。这基于 StorageClass,PVC 必须请求存储类,并且管理员必须创建和配置该 类以进行动态配置。

  2. 绑定:

• 用户创建 PVC 并指定所需的存储资源和访问模式。

• 在找到可用的 PV 之前,PVC 保持未绑定状态。

  1. 使用:

    • 首先,存储管理员创建 PV,并将其划分为多个存储卷。

    • 用户在创建 Pod 之前创建 PVC,并指定所需的 PV 大小和访问模式。

    • 创建 PVC 后,可以将其作为存储卷使用,并在 Pod 定义中引用该 PVC。

    • PV 和 PVC 是一对一的关系。一旦 PV 被某个 PVC 绑定,其他 PVC 就不能使用它。

    • 如果没有合适的 PV 可用,PVC 将处于挂起状态,直到有一个合适的 PV 可用为止。

  2. 回收策略:

    • 当删除使用 PVC 作为存储卷的 Pod 时,PVC 与 PV 的绑定将解除。

    • PV 有不同的回收策略可供选择:

    • Retain(保留):删除 PVC 后,PV 保留,并且数据仍然存在。PV 不会被绑 定到其他 PVC 上,可以再次使用。

    • Recycle(回收,不推荐):删除 PVC 后,PV 会被清空数据并准备重新使用。 这个回收策略在 Kubernetes 1.15 版本后被废弃。

    • Delete(删除):删除 PVC 后,PV 也会从 Kubernetes 中移除,并且相关 的存储资源也会被删除。

通过 PV 和 PVC 的结合使用,Kubernetes 提供了一种灵活的持久化存储管理机制,使得 k8s 使用者可以轻松地申请、使用和管理存储资源,同时提供了不同的回收策略以满足不同的需求。

创建pod,使用pvc作为持久化存储卷

pvc后端的存储,支持多种iscsl、nfs、fc等,这里使用nfs作为后端存储。

查看定义pv需要的字段

image-20240219091706408

查看定义nfs类型的pv需要的字段

image-20240219091822057

创建pv

需要现在nfs服务器创建出来共享目录,一个pv对应一个共享目录。

image-20240219091923302

官网链接:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-persistent-volume-storage/

pv不属于任何名称空间,所以不用指定名称空间

[root@k8s-slave1 volumes]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 1Gi    #pv的存储空间容量
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /volumes/v1
    server: 192.168.33.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 5Gi    #pv的存储空间容量
  accessModes: 
    - ReadWriteOnce  
  nfs:
    path: /volumes/v2
    server: 192.168.33.100

查看pv

image-20240219100826037

创建pvc

pv相当于把硬盘分好放到库房,当有pod需要存储空间的时候,pod不能直接使用pv,需要通过pvc去申请空间,pvc和pv一一对应。

[root@k8s-slave1 volumes]# cat pvc1.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc1
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  

image-20240219102734154

image-20240219103032628

image-20240219103154582

使用标签绑定pv pvc

[root@k8s-slave1 volumes]# cat pv2.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
  labels:
    app: pv1
spec:
  capacity:
    storage: 1Gi    #pv的存储空间容量
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /volumes/v1
    server: 192.168.33.100
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
  labels:
    app: pv2
spec:
  capacity:
    storage: 1Gi    #pv的存储空间容量
  accessModes: 
    - ReadWriteOnce  
  nfs:
    path: /volumes/v2
    server: 192.168.33.100

image-20240219105714682

[root@k8s-slave1 volumes]# cat pvc2.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  

image-20240219110257253

[root@k8s-slave1 volumes]# cat pvc3.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
spec:
  selector:
    matchLabels:
      app: pv2
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  

image-20240219111027503

使用存储类型绑定pv pvc

[root@k8s-slave1 volumes]# cat pv4.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv1
spec:
  capacity:
    storage: 1Gi    #pv的存储空间容量
  accessModes:
    - ReadWriteOnce
  nfs:
    path: /volumes/v1
    server: 192.168.33.100
  storageClassName: nfs  # 添加存储类
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  capacity:
    storage: 5Gi    #pv的存储空间容量
  accessModes: 
    - ReadWriteOnce  
  nfs:
    path: /volumes/v2
    server: 192.168.33.100
  storageClassName: nfs  # 添加存储类

image-20240219111603066

[root@k8s-slave1 volumes]# cat pvc5.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc5
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

image-20240219112612467

创建pod挂载pvc

在 Kubernetes 中,PV(Persistent Volume)和PVC(Persistent Volume Claim)是资源对象,它们是独立于命名空间的。PV 和 PVC 在创建时不受命名空间的影响。PV 和 PVC 通常是在集群级别创建的,它们可以跨命名空间使用。

但是,当 PVC 与 Pod 绑定时,Pod 和 PVC 必须在同一命名空间中。如果不在同一名称空间,创建pod将是pending状态。

#创建名称空间
apiVersion: v1
kind: Namespace
metadata: 
  name: aa
 


---
#创建pv
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
  labels:
    app: pv2
spec:
  capacity:
    storage: 1Gi    #pv的存储空间容量
  accessModes: 
    - ReadWriteMany 
  nfs:
    path: /volumes/v2
    server: 192.168.33.100
---
#创建pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
spec:
  selector:
    matchLabels:
      app: pv2
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi
  
---
#创建pod挂载pvc
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  #namespace: aa
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        volumeMounts:
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-html
        persistentVolumeClaim:
          claimName: pvc2


image-20240219152341268

image-20240219153251621

image-20240219153435127

image-20240219153543699

image-20240219154008922

k8s 存储类:storageclass

Kubernetes 提供了 StorageClass 来自动创建 PV,以减轻管理员的维护成本。以下是关于 Kubernetes PV、PVC 和 StorageClass 的更新内容:

PV(PersistentVolume)是 Kubernetes 中的持久化存储资源,而 PVC(PersistentVolumeClaim) 是 Pod 对 PV 的申请。传统的 PV 和 PVC 模式需要管理员预先创建 PV,然后将其与 PVC 进行一对一的 绑定。这种方式在大规模部署中可能导致管理复杂性和维护成本的增加。

为了解决这个问题,Kubernetes 引入了 StorageClass 机制。StorageClass 是一种动态创建 PV 的模板。 集群管理员可以创建多个 StorageClass,每个 StorageClass 定义了存储的类型、访问模式和其他属性。

当用户创建一个 PVC 并指定 StorageClass 时,Kubernetes 会自动根据该 StorageClass 创建一个 PV, 并将其与 PVC 进行绑定。这样,管理员无需手动创建 PV,而是根据 StorageClass 的定义,动态生成 PV 来满足用户的存储需求。

StorageClass 提供了以下好处:

  1. 简化管理:StorageClass 允许管理员创建一组可重用的存储配置模板,而无需为每个 PVC 手动 创建和管理 PV。这降低了管理成本和复杂性。
  2. 动态供应:使用 StorageClass,管理员可以根据需求动态创建 PV,从而自动为 PVC 提供存储 资源。这种动态供应的机制使得存储的分配更加灵活和自动化。
  3. 可选性和灵活性:StorageClass 允许管理员根据存储的不同特性和需求创建不同的 StorageClass。用户可以根据自己的需求选择合适的 StorageClass,并使用相应的存储资源。

查看定义storageclass需要的字段

[root@k8s-slave1 volumes]# kubectl explain StorageClass
KIND:     StorageClass
VERSION:  storage.k8s.io/v1

DESCRIPTION:
     StorageClass describes the parameters for a class of storage for which
     PersistentVolumes can be dynamically provisioned.

     StorageClasses are non-namespaced; the name of the storage class according
     to etcd is in ObjectMeta.Name.

FIELDS:
   allowVolumeExpansion	<boolean>
     AllowVolumeExpansion shows whether the storage class allow volume expand

   allowedTopologies	<[]Object>
     Restrict the node topologies where volumes can be dynamically provisioned.
     Each volume plugin defines its own supported topology specifications. An
     empty TopologySelectorTerm list means there is no topology restriction.
     This field is only honored by servers that enable the VolumeScheduling
     feature.

   apiVersion	<string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind	<string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata	<Object>
     Standard object's metadata. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

   mountOptions	<[]string>
     Dynamically provisioned PersistentVolumes of this storage class are created
     with these mountOptions, e.g. ["ro", "soft"]. Not validated - mount of the
     PVs will simply fail if one is invalid.

   parameters	<map[string]string>
     Parameters holds the parameters for the provisioner that should create
     volumes of this storage class.

   provisioner	<string> -required-
     Provisioner indicates the type of the provisioner.

   reclaimPolicy	<string>
     Dynamically provisioned PersistentVolumes of this storage class are created
     with this reclaimPolicy. Defaults to Delete.

   volumeBindingMode	<string>
     VolumeBindingMode indicates how PersistentVolumeClaims should be
     provisioned and bound. When unset, VolumeBindingImmediate is used. This
     field is only honored by servers that enable the VolumeScheduling feature.


provisioner:供应商,storageclass 需要有一个供应者,用来确定我们使用什么样的存储来创建 pv,常见的 provisioner 如下:

官网: https://kubernetes.io/zh-cn/docs/concepts/storage/storage-classes/

provisioner 既可以由内部供应商提供,也可以由外部供应商提供,如果是外部供应商可以参考 https://github.com/kubernetes-incubator/external-storage/下提供的方法创建。

allowVolumeExpansion:允许卷扩展,PersistentVolume 可以配置成可扩展。将此功能设置为 true 时,允许用户通过编辑相应的 PVC 对象来调整卷大小。当基础存储类的 allowVolumeExpansion 字段设置为 true 时,以下类型的卷支持卷扩展。

安装 nfs provisioner,用于配合存储类动态生成 pv

因为nfs是外部的存储,所以需要安装制备器

参考:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner

1、创建运行 nfs-provisioner 需要的 sa 账号

[root@k8s-slave1 volumes]# cat serviceaccount.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: nfs-provisioner

image-20240219164758881

扩展:什么是 sa?

sa 的全称是 serviceaccount。 serviceaccount 是为了方便 Pod 里面的进程调用 Kubernetes API 或其他外部服务而设计的。

指定了 serviceaccount 之后,我们把 pod 创建出来了,我们在使用这个 pod 时,这个 pod 就有了 我们指定的账户的权限了。

2、对 sa 授权

kubectl create clusterrolebinding nfs-provisioner --clusterrole=cluster-admin --serviceaccount=default:nfs-provisioner

image-20240219164938744

3、安装 nfs-provisioner 程序

在nfs服务器上创建一个共享目录

image-20240219165354919

[root@nfs 课程资料]# cat nfs-deployment.yaml 
kind: Deployment
apiVersion: apps/v1
metadata:
  name: nfs-provisioner
spec:
  selector:
    matchLabels:
       app: nfs-provisioner
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: nfs-provisioner
    spec:
      serviceAccount: nfs-provisioner
      containers:
        - name: nfs-provisioner
          image: registry.cn-beijing.aliyuncs.com/mydlq/nfs-subdir-external-provisioner:v4.0.0
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: nfs-client-root
              mountPath: /persistentvolumes
          env:
            - name: PROVISIONER_NAME
              value: example.com/nfs
            - name: NFS_SERVER
              value: 192.168.33.100 #改成你自己的地址
            - name: NFS_PATH
              value: /volumes/nfs   #改成你自己的共享目录
      volumes:
        - name: nfs-client-root
          nfs:
            server: 192.168.33.100
            path: /volumes/nfs

image-20240219170005738

创建 storageclass,动态供给 pv

[root@k8s-slave1 volumes]# cat nfs-storageclass.yaml 
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: nfs
provisioner: example.com/nfs

image-20240219170356895

image-20240219170712987

创建 pvc,通过 storageclass 动态生成 pv

[root@k8s-slave1 volumes]# cat claim.yaml 
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: test-claim1
spec:
  accessModes:  ["ReadWriteMany"]
  resources:
    requests:
      storage: 1Gi
  storageClassName:  nfs

image-20240219171303435

可以看到到 test-claim1 的 pvc 已经成功创建了,绑定的 pv 是pvc-b8526c49-f2ca-4cab-b679-b0d3e65059a4,这个 pv 是由 storageclass 调用 nfs provisioner 自动生成的。

步骤总结:

1、供应商:创建一个 nfs provisioner (只需要创建一次

2、创建 storageclass,storageclass 指定刚才创建的供应商 (只需要创建一次

3、创建 pvc,这个 pvc 指定 storageclass

创建 pod,挂载 storageclass 动态生成的 pvc

[root@k8s-slave1 volumes]# cat pvc3-pod.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx3
  namespace: aa
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx3
  template:
    metadata:
      labels:
        app: nginx3
    spec:
      containers:
      - name: nginx3
        image: nginx
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: nginx-html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: nginx-html
        persistentVolumeClaim:
          claimName: test-claim2

hou

image-20240219172126502

image-20240219172619603

image-20240220092500086

posted @   挖挖挖  阅读(290)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示