前面讲的都是数据卷,就是我们自己来定义,在pod控制器里面直接定义一个volumes,自己创建一个数据卷类型,然后通过volumMounts来挂载到指定的目录下.这个叫数据卷.

持久存储卷:PV PVC

两种单独的资源对象,我们需要创建一个PV 然后再创建PVC

PV

PV(PersistentVolume)与PVC(PersistentVolumeClaime)就是在用户与存储服务之间添加的一个中间层,管理员事先根据 PV支持的存储卷插件及适配的存储方案(目标存储系统)细节定义好可以支撑存储卷的底层存储空间,而后由用户通过PVC 声明要使用的存储特性来绑定符合条件的最佳 PV 定义存储卷,从而实现存储系统的使用与管理职能的解耦,大大简化了用户使用存储的方式。 PV和 PVC的生命周期由 Controller Manager 中专用的 PV 控制器(PV Controller)独立管理,这种机制的存储卷不再依附并受限于 Pod 对象的生命周期,从而实现了用户和集群管理员的职责相分离,也充分体现出 Kubernetes 把简单留给用户,把复杂留给自己的管理理念

PV就是在持久卷上面划分一块固定空间,PVC需要向PV申请

这是两种单独的资源对象,首先我们需要创建PV,然后PV就是划定一块固定的空间,比如2个G 权限 读写,再创建PVC,然后PVC会自动去找符合PVC要求的PV

生产上手工创建很多很多的PV出来,然后创建PVC会去你当前k8s系统里面去找符合PVC要求的一个PV出来,然后PV和PVC之间发生绑定,一旦绑定以后,PVC就可以给容器来用,PVC绑定到容器上,pod里面挂载.最终是pod通过PVC和PV来使用你的存储资源,这就是个持久存储卷.

Kubernetes PV和PVC_ci

看右面有个存储系统,假设他是nfs,手工创建很多 PV出来,PV对象包含两个比较关键的信息,一个是大小一个是模式(权限) 然后我在k8s上面创建PVC出来,这个PVC他会告诉你的系统我要找一个什么样的PV,比如 PV有三个空间分别是 1G 2G 3G 然后PVC的需求是 2.5G的 那只有3G的PV符合要求

不光是说容量符合要求,权限也要符合要求,两个都符合就绑定起来了,如果没有符合要求那就绑定不成功,PV和PVC一旦绑定成功以后,PVC 就可以拿到给pod使用,通过volumes和volumeMounts挂载上,

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

RESOURCE: persistentVolumeClaim <Object>
#PVS  固定的持久卷  这里面可以直接引用PVC的名称

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

     PersistentVolumeClaimVolumeSource references the user's PVC in the same
     namespace. This volume finds the bound PV and mounts that volume for the
     pod. A PersistentVolumeClaimVolumeSource is, essentially, a wrapper around
     another type of volume that is owned by someone else (the system).

FIELDS:
   claimName    <string> -required-
   #PVC的名字
     claimName is the name of a PersistentVolumeClaim in the same namespace as
     the pod using this volume. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims

   readOnly     <boolean>
     readOnly Will force the ReadOnly setting in VolumeMounts. Default false.

我们用手工纯静态的方式创建一个PV,这个方式比较麻烦.首先得需要一个存储,今天先用nfs模拟个存储

我们需要利用nfs手工创建PV,然后再手工创建PVC,然后PVC会看有没有符合要求的PV绑定,然后给pod引用PVC

PV的生命周期

Kubernetes PV和PVC_sed_02

我在删除对应的pod,或者删除pvc的时候,我的pv还要不要保留,那是靠pv控制器来控制的,有三个策略

一 Retain(保留)

我删除pvc以后我绑定的pv存储数据要存储下来 pv不删除 但是会把该pv设置的Release状态,就是后面在创建的pvc就不能与这个pv绑定了,并且需要手动进行后续操作,就是要手工删除pv才能把这个数据回收

二 Delete(删除)

删除pvc的时候pv也会被删除

三 Recycle(回收) 已被淘汰

对于支持该回收策略的卷插件,删除 PVC时,其绑定的 PV 所关联的外部存储组件上的数据会被清空,随后,该PV将转为 Available状态,可再次接受其他 PVC 的绑定请求。不过,该策略已被废弃。

创建过程

Kubernetes PV和PVC_ci_03

PV和PVC创建过程状态变化

PV的状态

Pending:

如果我创建一个pv出来最开始是个Pending状态

Available

一旦创建成功会变成 Available(可用) 一旦这个状态就是可用

Bound:

PVC和PV绑定成功了

Released:

删除PVC如果是保留的话 就会变成 Released状态 不可用

Deleted:

被删除

PVC的状态:

Pending

最初状态

Bound

一旦和某个PVC挂载成功就成为Bound状态

Delected

PVC删除后

这是PV和PVC的状态值

PV有五个状态值,PVC只有三个

1)存储预配(provision)∶存储预配是指为 PVC准备 PV的途径,Kubernetes 支持静态和动态两种PV 预配方式,前者是指由管理员以手动方式创建 PV的操作,而后者则是由 PVC 基于 StorageClass 定义的模板,按需请求创建 PV的机制。

这个和存储预配和动态存储有关系,动态存储就比较简单,只需要去创建class类 根据class类去创建pvc就行了,pvc会在东的去存储里面 存储里面会给pvc创建个符合要求的pv出来

2)存储绑定∶ 用户基于一系列存储需求和访问模式定义好 PVC 后,PV控制器即会为其查找匹配的PV,完成关联后它们二者同时转为已绑定状态,而且动态预配的 PV与PVC之间存在强关联关系。无法找到可满足条件的 PV的 PVC将一直处于 Pending状态,直到有符合条件的 PV出现并完成绑定为止。

存储绑定就是PV和PVC的绑定

3)存储使用∶ Pod 资源基于 persistenVolumeClaim存储卷插件的定义,可将选定的 PVC 关联为存储卷并用于内部容器应用的数据存取。

存储使用就是我们给pod负责挂载

4)存储回收∶存储卷的使用目标完成之后,删除 PVC 对象可使得此前绑定的 PV资源进入 Released状态,并由PV控制器根据 PV 回收策略对 PV作出相应的处置。目前,可用的回收策略有Retaine、Delete 和 Recycle 这 3种。

存储回收就是我们在删除PVC的时候,去回收

来一个纯静态的匹配创建:

看下PVC的字段

他是一种资源对象类型

[root@k8s-master1 ~]# kubectl explain persistentVolume
KIND:     PersistentVolume
VERSION:  v1

DESCRIPTION:
     PersistentVolume (PV) is a storage resource provisioned by an
     administrator. It is analogous to a node. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes

FIELDS:
   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-architectur                                                                                      e/api-conventions.md#resources

   kind <string>
     Kind is a string value representing the REST resource this obje                                                                                      ct
     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-architectur                                                                                      e/api-conventions.md#types-kinds

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

   spec <Object>
     spec defines a specification of a persistent volume owned by th                                                                                      e cluster.
     Provisioned by an administrator. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#                                                                                      persistent-volumes

   status       <Object>
     status represents the current information/status for the persis                                                                                      tent volume.
     Populated by the system. Read-only. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#

看下spec

[root@k8s-master1 ~]# kubectl explain persistentVolume.spec
KIND:     PersistentVolume
VERSION:  v1

RESOURCE: spec <Object>

DESCRIPTION:
     spec defines a specification of a persistent volume owned by the cluster.
     Provisioned by an administrator. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistent-volumes

     PersistentVolumeSpec is the specification of a persistent volume.

FIELDS:
   accessModes  <[]string>
   #访问模式有四个
   #:
   # ReadWriteOnce
   # 卷可以被一个节点以读写方式挂载,只是有和你挂载的那个节点可以读写,再有一个挂载的节点无法读写,同一时刻只能有一个节点进行读写。 ReadWriteOnce 访问模式也允许运行在同一节点上的多个 Pod 访问卷。
   
   # ReadOnlyMany
   # 卷可以被多个节点以只读方式挂载。 都可以挂载,但是只是只读的 不能写,
   
   # ReadWriteMany
   # 卷可以被多个节点以读写方式挂载。
   
   # ReadWriteOncePod
    #特性状态: Kubernetes v1.27 [beta]
    #卷可以被单个 Pod 以读写方式挂载。 如果你想确保整个集群中只有一个 Pod 可以读取或写入该 PVC, 请使用 ReadWriteOncePod 访问模式。这只支持 CSI 卷以及需要 Kubernetes 1.22 以上版本。
    
   # 在命令行接口(CLI)中,访问模式也使用以下缩写形式:
   # RWO - ReadWriteOnce
   # ROX - ReadOnlyMany
   # RWX - ReadWriteMany
   # RWOP - ReadWriteOncePod
     accessModes contains all ways the volume can be mounted. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes

   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.

   capacity     <map[string]string>
   #容量 
   # Gi: 单位是 GibiByte,基于1024的运算
   # Ti: 单位是 TiB,基于1024的运算
   # Mi: 单位是 MebiByte,基于1024的运算
   # Ki: 单位是 KibiByte,基于1024的运算
   # G: 单位是 GB,基于1000的运算
   # M: 单位是MB,基于1000的运算
   # K: 单位是KB,基于1000的运算
   #书写格式如:
#capacity:
#  storage: 100Gi #硬盘给了100GB
#  cpu: 1  #cpu给了1核心
#  memory: 500Mi  #内存给了500MB
  
     capacity is the description of the persistent volume's resources and
     capacity. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#capacity

   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

   claimRef     <Object>
     claimRef is part of a bi-directional binding between PersistentVolume and
     PersistentVolumeClaim. Expected to be non-nil when bound. claim.VolumeName
     is the authoritative bind between PV and PVC. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#binding

   csi  <Object>
     csi represents storage that is handled by an external CSI driver (Beta
     feature).

   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
     and exposed to the pod for its usage. 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. Provisioned by an
     admin. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk

   glusterfs    <Object>
     glusterfs represents a Glusterfs volume that is attached to a host and
     exposed to the pod. Provisioned by an admin. More info:
     https://examples.k8s.io/volumes/glusterfs/README.md

   hostPath     <Object>
     hostPath represents a directory on the host. Provisioned by a developer or
     tester. This is useful for single-node development and testing only!
     On-host storage is not supported in any way and WILL NOT WORK in a
     multi-node cluster. 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. Provisioned by an admin.

   local        <Object>
     local represents directly-attached storage with node affinity

   mountOptions <[]string>
   #挂载选项,可以自定义一些内容 ,如果不写这个那么默认就是读写挂载
   #因为这次使用的nfs方式创建pv 那么可以写:
# ro: 将卷以只读模式挂载,不允许在挂载的卷上进行写入操作。
# rw: 将卷以读写模式挂载,允许在挂载的卷上进行读取和写入操作。
# hard: 使用硬挂载,系统会尝试保持连接,直到连接恢复或达到超时限制。
# soft: 使用软挂载,在连接问题时更快地放弃等待,以避免长时间的阻塞。
# intr: 允许中断。这允许用户通过中断(Ctrl+C)来终止挂载操作。
# noac: 禁用所有属性缓存,确保文件更改能够立即反映到挂载的系统中。
# actimeo=<seconds>: 设置属性缓存的超时时间,以秒为单位。
# vers=<NFS version>: 指定要使用的 NFS 版本,如 vers=4 表示使用 NFSv4。
   #(这个版本是可以查看的
#   [root@k8s-node3 ~]# rpcinfo -p | grep nfs
#    100003    3   tcp   2049  nfs
#    100003    4   tcp   2049  nfs
#    100227    3   tcp   2049  nfs_acl
#    100003    3   udp   2049  nfs
#    100227    3   udp   2049  nfs_acl
  #这些就代表 3 和 4 都可以写 )
  
# rsize=<size>: 指定读取缓冲区的大小,以字节为单位。
# wsize=<size>: 指定写入缓冲区的大小,以字节为单位。
     mountOptions is the list of mount options, e.g. ["ro", "soft"]. Not
     validated - mount will simply fail if one is invalid. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options

   nfs  <Object>
     nfs represents an NFS mount on the host. Provisioned by an admin. More
     info: https://kubernetes.io/docs/concepts/storage/volumes#nfs

   nodeAffinity <Object>
     nodeAffinity defines constraints that limit what nodes this volume can be
     accessed from. This field influences the scheduling of pods that use this
     volume.

   persistentVolumeReclaimPolicy        <string>
   #删除策略 : Retain 保留  Delete 删除
# Retain(保留): 这是手动创建的持久卷的默认策略。当持久卷被释放时,它的资源(如存储)将保留不变,不会被删除或重用。这允许管理员手动处理释放的持久卷。

# Delete(删除): 这是动态分配的持久卷的默认策略。当持久卷被释放时,它的资源将被立即删除,释放底层存储资源。这适用于许多动态分配的存储后端,因为它们可以自动处理资源释放。

# Recycle(回收): 这是一种已被弃用的策略,不再推荐使用。在过去,该策略会尝试在持久卷上执行某些清理操作,以使其再次可用。但是,由于它的实现方式受到存储后端和应用的影响,因此不再建议使用该策略。
     persistentVolumeReclaimPolicy defines what happens to a persistent volume
     when released from its claim. Valid options are Retain (default for
     manually created PersistentVolumes), Delete (default for dynamically
     provisioned PersistentVolumes), and Recycle (deprecated). Recycle must be
     supported by the volume plugin underlying this PersistentVolume. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming

     Possible enum values:
     - `"Delete"` means the volume will be deleted from Kubernetes on release
     from its claim. The volume plugin must support Deletion.
     - `"Recycle"` means the volume will be recycled back into the pool of
     unbound persistent volumes on release from its claim. The volume plugin
     must support Recycling.
     - `"Retain"` means the volume will be left in its current phase (Released)
     for manual reclamation by the administrator. The default policy is Retain.

   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

   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.

   storageClassName     <string>
     storageClassName is the name of StorageClass to which this persistent
     volume belongs. Empty value means that this volume does not belong to any
     StorageClass.

   storageos    <Object>
     storageOS represents a StorageOS volume that is attached to the kubelet's
     host machine and mounted into the pod More info:
     https://examples.k8s.io/volumes/storageos/README.md

   volumeMode   <string>
   #这里有两种模式: Filesystem or Block
   
   #第一种:Filesystem 模式:
   #在 "Filesystem" 模式下,持久卷将会被格式化为文件系统,就像您在操作系统中格式化硬盘或分区一样。这意味着您可以在卷上创建目录和文件,就像在常规文件系统上一样。这种模式适用于大多数应用场景,包括 Web 服务器、应用程序数据存储等。
#优点:可以方便地在卷上创建文件和目录,使数据的管理更加直观。适用于大多数应用程序,因为它们通常需要操作文件系统。
   
   #第二种:Block 模式:
   #在 "Block" 模式下,持久卷将被视为原始的块设备,而不会被格式化为文件系统。这意味着您不能在上面创建文件和目录,而是可以直接访问磁盘块。这种模式适用于一些特定的应用,如一些数据库系统,它们更喜欢直接管理底层块而不受文件系统的限制。
#优点:提供更高的性能,因为没有文件系统的开销。适用于需要直接管理数据块的应用,如数据库引擎。

#总结:
#"Filesystem" 模式适合大多数应用,因为它提供了文件系统的功能,使数据管理更加直观。
#"Block" 模式适用于需要直接访问底层数据块的应用,它们更关心底层磁盘块而不是文件系统。
     volumeMode defines if a volume is intended to be used with a formatted
     filesystem or to remain in raw block state. Value of Filesystem is implied
     when not included in spec.

   vsphereVolume        <Object>
     vsphereVolume represents a vSphere volume attached and mounted on kubelets
     host machine
[root@k8s-master1 ~]# kubectl explain persistentVolume.spec.nfs
KIND:     PersistentVolume
VERSION:  v1

RESOURCE: nfs <Object>

DESCRIPTION:
     nfs represents an NFS mount on the host. Provisioned by an admin. More
     info: https://kubernetes.io/docs/concepts/storage/volumes#nfs

     Represents an NFS mount that lasts the lifetime of a pod. NFS volumes do
     not support ownership management or SELinux relabeling.

FIELDS:
   path <string> -required- 	
   #路径
     path that is exported by the NFS server. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#nfs

   readOnly     <boolean>
   #是否只读
     readOnly here will force the NFS export to be mounted with read-only
     permissions. Defaults to false. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#nfs

   server       <string> -required-
   #nfs ip 或者主机名
     server is the hostname or IP address of the NFS server. More info:
     https://kubernetes.io/docs/concepts/storage/volumes#nfs

静态PV资源

PersistentVolume是隶属于Kubernetes 核心 API群组中的标准资源类型,它的目标在于通过存储卷插件机制,将支持的外部存储系统上的存储组件定义为可被 PVC 声明所绑定的资源对象。但 PV资源隶属于Kubernetes 集群级别,因而它只能由集群管理员进行创建。这种由管理员手动定义和创建的 PV被人们习惯地称为静态 PV 资源。capacity容量,指定PV 的大小

PV支持的存储卷插件类型是 Pod对象支持的存储卷插件类型的一个子集,它仅涵盖 Pod支持的网络存储卷类别中的所有存储插件以及 local卷插件。除了存储卷插件之外, PersistentVolume资源规范Spec 字段主要支持嵌套以下几个通用字段,它们用于定义PV的容量、访问模式和回收策略等属性。

capacity<map[string]string>∶

指定 PV的容量;目前,Capacity 仅支持存储容量设定,将来应该还可以指定 IOPS 和吞吐量(throughput)。

accessModes <[]string>∶

指定当前 PV 支持的访问模式;存储系统支持的存取能力大体可分为ReadWriteOnce(单路读写)、ReadOnlyMany(多路只读)和 ReadWriteMany(多路读写)3种类型,某个特定的存储系统可能会支持其中的部分或全部的能力。

persistentVolumeReclaimPolicy ;

PV 空间被释放时的处理机制;可用类型仅为Retain(默认)、Recycle 或 Delete。目前,仅 NFS 和 hostPath支持 Recycle策略,也仅有部分存储系统支持 Delete 策略。

volumeMode∶

该PV的卷模型,用于指定此存储卷被格式化为文件系统使用还是直接使用裸格式的块设备;默认值为 Filesystem,仅块设备接口的存储系统支持该功能。

storageClassName∶

当前 PV所属的 StorageClass 资源的名称,指定的存储类需要事先存在;默认为空值,即不属于任何存储类。

mountOptions ∶

挂载选项组成的列表,例如 ro、soft 和 hard等。

nodeAffinity ∶

节点亲和性,用于限制能够访问该 PV的节点,进而会影响与该 PV 关联的 PVC的Pod 的调度结果。需要注意的是,PV的访问模式用于反映它关联的存储系统所支持的某个或全部存取能力,例如 NFS存储系统支持以上3种存取能力,于是NFS PV可以仅支持ReadWriteOnce访问模式。需要注意的是,PV在某个特定时刻仅可基于一种模式进行存取,哪怕它同时支持多种模式

最关键的两个就是 capacity和accessModes,这两个参数

我们创建个PV出来

我们去nfs服务器多共享几个目录

[root@k8s-node3 ~]# cat /etc/exports
/data/redis 192.168.1.0/24(rw,no_root_squash)
/data/redis01 192.168.1.0/24(rw,no_root_squash)
/data/redis02 192.168.1.0/24(rw,no_root_squash)
/data/redis03 192.168.1.0/24(rw,no_root_squash)
/data/redis04 192.168.1.0/24(rw,no_root_squash)
[root@k8s-node3 data]# mkdir /data/redis{01..04}
[root@k8s-node3 data]# ll /data/
total 0
drwxr-xr-x 2 polkitd root 59 Aug 18 09:56 redis
drwxr-xr-x 2 root    root  6 Aug 18 13:46 redis01
drwxr-xr-x 2 root    root  6 Aug 18 13:46 redis02
drwxr-xr-x 2 root    root  6 Aug 18 13:46 redis03
drwxr-xr-x 2 root    root  6 Aug 18 13:46 redis04
[root@k8s-node3 ~]# systemctl enable --now rpcbind
[root@k8s-node3 ~]# systemctl enable --now nfs-server
#搞定

写一个PV

apiVersion: v1
kind: PersistentVolume  #PV
metadata:
  name: nfspv  #起个名字
spec:
  capacity: # 资源限制
    storage: 2Gi  #硬盘2GB
  accessModes:  #访问模式
    - ReadWriteMany  #可以被多个节点读写方式挂载
  persistentVolumeReclaimPolicy: Retain
  mountOptions: #更详细的挂载选项 这个是nfs服务器的
    - rw   #读写方式  这个模式就是读写
    - hard   #硬挂载 硬挂载就是使用硬挂载,系统会尝试保持连接,直到连接恢复或达到超时限制。
    - vers=4 #nfs版本  这个看笔记有详细介绍
  nfs: #nfs类型
    path: /data/redis01 #共享的目录
    server: 192.168.1.103 #共享的主机

查看一下

[root@k8s-master1 nfs]# kubectl apply -f pv-nfs-1.yml
persistentvolume/nfspv created
[root@k8s-master1 nfs]# kubectl get pv
NAME    CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfspv   2Gi        RWX            Retain           Available                                   20s
#NAME: 持久卷的名称,此处是 "nfspv"。

#CAPACITY: 持久卷的存储容量,这里是 "2Gi",表示2GB的存储容量。

#ACCESS MODES: 访问模式,表示哪些节点可以访问该持久卷。这里是 "RWX",表示该持久卷支持读写多节点访问。

#RECLAIM POLICY: 回收策略,指定了当持久卷从绑定的声明中释放时的处理方式。这里是 "Retain",表示该持久卷在释放后保留,不会自动删除。

#STATUS: 持久卷的状态,这里是 "Available",表示该持久卷当前可用,尚未被绑定到声明。

#CLAIM: 表示当前绑定到持久卷的声明(如果有的话)。在这里是空白,说明该持久卷当前没有绑定到任何声明。

#STORAGECLASS: 存储类,表示持久卷所属的存储类(如果有的话)。这里没有显示存储类。

#REASON: 原因,显示持久卷状态的原因(如果有的话)。在这里是空白。

#AGE: 持久卷的存在时间,显示自创建持久卷以来的时间。在这里是 "20s",表示20秒。

现在我创建了个PV出来,现在我可以创建PVC

PVC资源

pvc也是一种单独的资源对象,如果和PV匹配成功了,成为一个Bound状态,这里PV也有两个关键字

PersistentVolumeClaim也是 Kubernetes 系统上标准的 API资源类型之一,它位于核心 API群组,属于名称空间级别。用户提交新建的 PVC 资源最初处于Pending 状态,由 PV控制器找寻最佳匹配的 PV并完成二者绑定后,两者都将转入 Bound状态,随后 Pod对象便可基于 persistentVolumeClaim 存储卷插件配置使用该 PVC 对应的持久存储卷。

PersistentVolumeClaim #首字母大写表示 PVC 这种资源,而首字母小写则代表 Pod 上对应的存储卷插件的固定名称格式

定义PVC时,用户可通过访问模式(accessModes)、数据源(dataSource)、存储资源空间需求和限制(resources)、存储类、标签选择器、卷模型和卷名称等匹配标准来筛选集群上的 PV 资源,其中,resources和 accessModes 是最重要的筛选标准。PVC的 Spec 字段的可嵌套字段有如下几个。

accessModes <[]string>∶

PVC的访问模式;它同样支持RWO、RWX 和 ROX这3种模式。
 和PVC一样,找到一个符合要求的PV出来
 这个字段最少要有一个

dataSrouces ∶

用于从指定的数据源恢复该 PVC卷,它目前支持的数据源包括一个现存的卷快照对象(snapshot.storage.k8s.io/VolumeSnapshot)、一个既有的 PVC 对象
(PersistentVolumeClaim)或一个既有的用于数据转存的自定义资源对象(resourc/object)。
这个用的少

resources∶

声明使用的存储空间的最小值和最大值;目前,PVC的资源限定仅支持空间大小一个维度。
资源限制的

selector ∶

筛选 PV 时额外使用的标签选择器(matchLabels)或匹配条件表达式(matchExpressions)。
这个用的少

storageClassName ;

该PVC 资源隶属的存储类资源名称;指定了存储类资源的 PVC 仅能在同一个存储类下筛选 PV 资源,否则就只能从所有不具有存储类的 PV中进行筛选。
存储类 现在用不到

volumeMode ∶

卷模型,用于指定此卷可被用作文件系统还是裸格式的块设备;默认值为Filesystem。
卷模型

volumeName ∶

直接指定要绑定的 PV 资源的名称。
可以不去让他自己寻找,直接给他指定个PV,类似于内定

在创建个PV

[root@k8s-master1 nfs]# cat pv-nfs-2.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv-2
spec:
  accessModes:
    - ReadWriteMany
  capacity:
    storage: 10Gi
  mountOptions:
    - rw
    - soft
    - vers=4
  persistentVolumeReclaimPolicy: Delete
  volumeMode: Filesystem
  nfs:
    path: /data/redis02
    server: 192.168.1.103

[root@k8s-master1 nfs]# kubectl apply -f pv-nfs-2.yml
persistentvolume/nfs-pv-2 created
[root@k8s-master1 nfs]# kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
nfs-pv-2   10Gi       RWX            Delete           Available                                   61s
nfspv      2Gi        RWX            Retain           Available                                   17h

现在有两个PV

现在创建个PVC

PVC要求accessModes符合

PVC最终靠accessModes和resources

就相当于accessModes权限要够 对应的大小resources也要够

查看一下PersistentVolumeClaim的参数

[root@k8s-master1 nfs]# kubectl explain PersistentVolumeClaim.spec
KIND:     PersistentVolumeClaim
VERSION:  v1

RESOURCE: spec <Object>

DESCRIPTION:
     spec defines the desired characteristics of a volume requested by a pod
     author. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims

     PersistentVolumeClaimSpec describes the common attributes of storage
     devices and allows a Source for provider-specific attributes

FIELDS:
   accessModes  <[]string>
 #PVC的.spec.accessModes字段指定了PVC的访问模式,它定义了PVC可以以哪些方式被挂载。
 #accessModes有以下几种模式:

#  ReadWriteOnce - 该卷可以被单个节点以读写方式挂载
#  ReadOnlyMany - 该卷可以被多个节点以只读方式挂载
#  ReadWriteMany - 该卷可以被多个节点以读写方式挂载
#他的书写规则是
accessModes: ["ReadWriteOnce"]
#或者
accessModes:
  - ReadWriteOnce
#以上两种都可以
     accessModes contains the desired access modes the volume should have. More
     info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1

   dataSource   <Object>
     dataSource field can be used to specify either: * An existing
     VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An
     existing PVC (PersistentVolumeClaim) If the provisioner or an external
     controller can support the specified data source, it will create a new
     volume based on the contents of the specified data source. When the
     AnyVolumeDataSource feature gate is enabled, dataSource contents will be
     copied to dataSourceRef, and dataSourceRef contents will be copied to
     dataSource when dataSourceRef.namespace is not specified. If the namespace
     is specified, then dataSourceRef will not be copied to dataSource.

   dataSourceRef        <Object>
     dataSourceRef specifies the object from which to populate the volume with
     data, if a non-empty volume is desired. This may be any object from a
     non-empty API group (non core object) or a PersistentVolumeClaim object.
     When this field is specified, volume binding will only succeed if the type
     of the specified object matches some installed volume populator or dynamic
     provisioner. This field will replace the functionality of the dataSource
     field and as such if both fields are non-empty, they must have the same
     value. For backwards compatibility, when namespace isn't specified in
     dataSourceRef, both fields (dataSource and dataSourceRef) will be set to
     the same value automatically if one of them is empty and the other is
     non-empty. When namespace is specified in dataSourceRef, dataSource isn't
     set to the same value and must be empty. There are three important
     differences between dataSource and dataSourceRef: * While dataSource only
     allows two specific types of objects, dataSourceRef allows any non-core
     object, as well as PersistentVolumeClaim objects.
     * While dataSource ignores disallowed values (dropping them), dataSourceRef
     preserves all values, and generates an error if a disallowed value is
     specified.
     * While dataSource only allows local objects, dataSourceRef allows objects
     in any namespaces. (Beta) Using this field requires the AnyVolumeDataSource
     feature gate to be enabled. (Alpha) Using the namespace field of
     dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to
     be enabled.

   resources    <Object>
   #这个是我对PV的要求
   #他两个子字段分别是
   # limits       <map[string]string>  最大限制  
   # requests     <map[string]string>   最小限制
   #书写格式如
   
    limits:
      storage: 3Gi
    requests:
      storage: 1Gi
   #这段意思是 最大不要超过3GB  最小不要低于 1GB硬盘
     resources represents the minimum resources the volume should have. If
     RecoverVolumeExpansionFailure feature is enabled users are allowed to
     specify resource requirements that are lower than previous value but must
     still be higher than capacity recorded in the status field of the claim.
     More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources

   selector     <Object>
     selector is a label query over volumes to consider for binding.

   storageClassName     <string>
   #torageClassName字段指定该PVC需要使用的StorageClass的名称。	
	#当创建PVC时,如果指定了storageClassName,系统就会查找具有该名称的StorageClass对象,并使用其定义的	provisioner和parameters来动态创建匹配的PersistentVolume。
	#一些关键点:

# storageClassName将PVC与某个StorageClass关联,用于动态分配PV
# 需确保集群中存在指定名称的StorageClass对象
# 如果没有指定,将使用默认StorageClass
# 允许通过不同的StorageClass获取不同性能、可用区等的PV
	
     storageClassName is the name of the StorageClass required by the claim.
     More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1

   volumeMode   <string>
   #文件系统类型
      #这里有两种模式: Filesystem or Block
   
   #第一种:Filesystem 模式:
   #在 "Filesystem" 模式下,持久卷将会被格式化为文件系统,就像您在操作系统中格式化硬盘或分区一样。这意味着您可以在卷上创建目录和文件,就像在常规文件系统上一样。这种模式适用于大多数应用场景,包括 Web 服务器、应用程序数据存储等。
#优点:可以方便地在卷上创建文件和目录,使数据的管理更加直观。适用于大多数应用程序,因为它们通常需要操作文件系统。
   
   #第二种:Block 模式:
   #在 "Block" 模式下,持久卷将被视为原始的块设备,而不会被格式化为文件系统。这意味着您不能在上面创建文件和目录,而是可以直接访问磁盘块。这种模式适用于一些特定的应用,如一些数据库系统,它们更喜欢直接管理底层块而不受文件系统的限制。
#优点:提供更高的性能,因为没有文件系统的开销。适用于需要直接管理数据块的应用,如数据库引擎。

#总结:
#"Filesystem" 模式适合大多数应用,因为它提供了文件系统的功能,使数据管理更加直观。
#"Block" 模式适用于需要直接访问底层数据块的应用,它们更关心底层磁盘块而不是文件系统。
     volumeMode defines what type of volume is required by the claim. Value of
     Filesystem is implied when not included in claim spec.

   volumeName   <string>
     volumeName is the binding reference to the PersistentVolume backing this
     claim.
[root@k8s-master1 pvc]# cat pvc-1.yml
apiVersion: v1
kind: PersistentVolumeClaim #PVC
metadata:
  name: pvc5g #PVC的名字
spec:
  accessModes: #使用模式    这个很关键 因为我们需要靠他和下面的resources 都要符合要求才能挂载pv
    - ReadWriteMany #该卷可以被多个节点以读写方式挂载
  volumeMode: Filesystem #文件系统类型 
  resources: #资源的需求
    limits: #最大需求
      storage: 20Gi
    requests: #最下要求
      storage: 5Gi
[root@k8s-master1 pvc]# kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM           STORAGECLASS   REASON   AGE
nfs-pv-2   10Gi       RWX            Delete           Bound       default/pvc5g                           173m
nfspv      2Gi        RWX            Retain           Available                                           20h
#当前看来 nfs-pv-2 已经和pvc pvc5g挂载上了  状态为Bound
[root@k8s-master1 pvc]# kubectl get pvc
NAME    STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
pvc5g   Bound    nfs-pv-2   10Gi       RWX                           101s
#pvc状态也为Bound 也能看到PV是谁

这样就相当于PVC和PV 绑定起来了

两个PV分别是 2G和10G 如果我的需求是2G 那么PVC就会随便找个 必须模式和容量都符合要求

使用PVC

在pod下的spec下的volumes下有个persistentVolumeClaim字段

[root@k8s-master1 nfs]# kubectl explain pod.spec.volumes.persistentVolumeClaim
KIND:     Pod
VERSION:  v1

RESOURCE: persistentVolumeClaim <Object>

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

     PersistentVolumeClaimVolumeSource references the user's PVC in the same
     namespace. This volume finds the bound PV and mounts that volume for the
     pod. A PersistentVolumeClaimVolumeSource is, essentially, a wrapper around
     another type of volume that is owned by someone else (the system).

FIELDS:
   claimName    <string> -required-
   #pvc的名称
     claimName is the name of a PersistentVolumeClaim in the same namespace as
     the pod using this volume. More info:
     https://kubernetes.io/docs/concepts/storage/persistent-volumes#persistentvolumeclaims

   readOnly     <boolean>
     readOnly Will force the ReadOnly setting in VolumeMounts. Default false.

写一个pod 挂载pvc

[root@k8s-master1 pod]# cat pvs-nginx-1.yml
apiVersion: v1
kind: Pod
metadata:
  name: pvc-nginx
spec:
  volumes:
  - name: pvc-index #起个名字 下面要引用
    persistentVolumeClaim: #pvc
      claimName: pvc5g #挂载的pvc名字  必须已经存在并且已经与pv绑定成功
  containers:
  - name: nginx
    image: images.guoguo.com/apps/nginx:1.22.1
    ports:
    - containerPort: 80
    volumeMounts: #挂载
    - name: pvc-index #和上面起的名字关联
      mountPath: /apps/nginx/html/  #挂载的目录
[root@k8s-master1 pod]# kubectl apply -f pvs-nginx-1.yml
pod/pvc-nginx created

查看一下

[root@k8s-master1 pod]# kubectl get pods -owide
NAME        READY   STATUS    RESTARTS   AGE    IP              NODE                   NOMINATED NODE   READINESS GATES
pvc-nginx   1/1     Running   0          7m3s   192.17.65.199   k8s-node3.guoguo.com   <none>           <none>

去容器里面修改一下文件

[root@k8s-master1 pod]# kubectl exec pvc-nginx -it /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@pvc-nginx:/# cd /apps/nginx/html/
root@pvc-nginx:/apps/nginx/html# ll
total 0
drwxr-xr-x 2 root root   6 Aug 18 05:46 ./
drwxr-xr-x 1 root root 115 Aug 19 05:50 ../
root@pvc-nginx:/apps/nginx/html# echo "nfs-nginx" > index.html
root@pvc-nginx:/apps/nginx/html# exit
exit
[root@k8s-master1 pod]# curl 192.17.65.199
nfs-nginx

然后切换 node3 nfs服务器去看下 这个目录有没有这个文件

[root@k8s-node3 ~]# cd /data/redis02/
[root@k8s-node3 redis02]# ll
总用量 4
-rw-r--r-- 1 root root 10 8月  19 13:51 index.html
[root@k8s-node3 redis02]# cat index.html
nfs-nginx
[root@k8s-node3 redis02]# echo 192.168.1.103-node-nfs >> index.html

说明成功了

这个是我们纯手工的方式的

首先我们需要创建一个PV

然后再创建一个PVC 挂载PV

然后在创建个pod 挂载PVC

Kubernetes PV和PVC_sed_04

最终给我们容器使用,说白了容器最终使用的是pv或者说容器最终使用的后端的存储系统storage

为什么我们要这种方式呢,本来数据卷就可以直接挂载了,

生产上在k8s集群上,为什么要定义一个单独的资源对象出来,在公司里面,会有专门的存储工程师,存储工程师只负责维护存储,他不需要懂k8s,他维护好了只需要把对应的接口给k8s管理员,拿nfs举例,只要知道nfs的地址和目录就可以了,这些目录我作为一个k8s管理员,手工去创建各种各样的pv和pvc,在生产上这些是隔离的,存储工程师只负责维护存储,不负责维护k8s,而作为k8s管理员,只需要懂k8s,不需要懂存储,只需要你把地址告诉我就可以了.我就可以创建pv引用到存储上的东西

这样方式有个很大的问题,你去创建pvc的适合还需要去创建pv,在生产级别有个动态预分配机制,

叫存储类,之前讲kubelet有个csi接口,csi接口可以模拟

存储类

存储类也是Kubernetes 系统上的 API资源类型之一,它位于 storage.k8s.io 群组中。存储类通常由集群管理员为管理PV资源之便而按需创建的存储资源类别(逻辑组),例如可将存储系统按照其性能高低或者综合服务质量级别分类(见图5-9)、依照备份策略分类,甚至直接按管理员自定义的标准分类等。存储类也是PVC筛选PV时的过滤条件之一,这意味着 PVC 仅能在其隶属的存储类之下找寻匹配的PV资源。不过,Kubernetes系统自身无法理解"类别"到底意味着什么,它仅仅把存储类中的信息当作 PV资源的特性描述使用。

他是利用存储系统,比如nfs和ceph存储系统他通过storage的方式把存储系统作为一种资源对象,导入到k8s集群里来,让你k8s直接认识后端的存储系统,未来通过这种存储类就不需要创建pv了,pvc会自动的在你的存储系统上,我们创建pvc的适合会指定一个存储类StorageClass 存储类就相当于告诉你去那个存储系统上去找pv,这里pv不需要手工创建,他会自动的给你创建出来符合pvc要求的pv出来 自动完成绑定 .

这就是存储类

所有的存储系统都有CSI接口,比如NFS ceph 都需要CSI接口 把这个cis接口装起来 对应的csi接口装到你的k8s集群上去 k8s才能去使用你对应的存储系统

k8s官方默认没有提供这种存储类的存储系统,它是通过csi接口的方式把接口同步给专门做存储的公司 你只要开发出来符合我这个接口的系统就可以了,然后你把你的系统集成到我的k8s上 利用cis接口的方式集成到k8s系统上,

分布式文件系统比k8s早得多,所以不可能专门为ks集成一套文件系统,所以k8s基于市面上已有的存储系统,你只要开发一个cis接口 和符合k8s接口的标准规范就可以了,然后把对应的规范的接口 装起来 nfs有nfs 的csi ceph有ceph的csi

今天用nfs举例, 我们装一下nfs的cis接口,然后利用nfs去创建存储类,然后利用nfs存储类在pod上使用

[root@k8s-master1 nfs-csi]# cd /apps/nfs-csi/
[root@k8s-master1 nfs-csi]# ll
总用量 40
-rw-r--r-- 1 root root 3356 3月  15 08:14 csi-nfs-controller.yaml
-rw-r--r-- 1 root root  170 3月  15 08:14 csi-nfs-driverinfo.yaml
-rw-r--r-- 1 root root 4023 3月  15 08:14 csi-nfs-node.yaml
										#上面这三我们需要这三个装一下
-rw-r--r-- 1 root root   85 3月  15 08:14 nfs-csi-liveness-probe.txt
-rw-r--r-- 1 root root   97 3月  15 08:14 nfs-csi-node-driver-registrar.txt
-rw-r--r-- 1 root root   87 3月  15 08:14 nfs-csi-provisioner.txt
-rw-r--r-- 1 root root  602 4月  17 18:19 pod-csi.yaml
-rw-r--r-- 1 root root 1352 3月  15 08:14 rbac-csi-nfs-controller.yaml
									#↑这个先不用管,这个是基于角色的权限管理
-rw-r--r-- 1 root root  389 4月  17 18:16 storageclass-nfs.yaml
-rw-r--r-- 1 root root  873 3月  15 08:14 sts1.yaml
#现状rbac 创建权限
[root@k8s-master1 nfs-csi]# kubectl apply -f rbac-csi-nfs-controller.yaml
serviceaccount/csi-nfs-controller-sa created
clusterrole.rbac.authorization.k8s.io/nfs-external-provisioner-role created
clusterrolebinding.rbac.authorization.k8s.io/nfs-csi-provisioner-binding created
#把所有csi开头的的装上
[root@k8s-master1 nfs-csi]# kubectl apply -f csi-nfs-controller.yaml -f csi-nfs-driverinfo.yaml -f csi-nfs-node.yamldeployment.apps/csi-nfs-controller created
csidriver.storage.k8s.io/nfs.csi.k8s.io created
daemonset.apps/csi-nfs-node created
[root@k8s-master1 nfs-csi]# kubectl get pods -n kube-system
NAME                                             READY   STATUS              RESTARTS        AGE
calico-kube-controllers-6bd6b69df9-pkvpl         1/1     Running             4 (5h47m ago)   40h
calico-node-47crw                                1/1     Running             4 (5h47m ago)   40h
calico-node-5mdfn                                1/1     Running             4 (5h47m ago)   40h
calico-node-dqbqh                                1/1     Running             4 (5h47m ago)   40h
calico-node-hmt24                                1/1     Running             4 (5h47m ago)   40h
calico-node-tqxd6                                1/1     Running             4 (5h47m ago)   40h
calico-node-xqb5x                                1/1     Running             4 (5h47m ago)   40h
calico-typha-77fc8866f5-cxp59                    1/1     Running             4 (5h47m ago)   40h
coredns-567c556887-fbznc                         1/1     Running             4 (5h47m ago)   40h
coredns-567c556887-tlkrs                         1/1     Running             4 (5h47m ago)   40h
csi-nfs-controller-cb6f6fc45-2d748               3/3     Running             0               50s
csi-nfs-controller-cb6f6fc45-wkvhr               2/3     ImagePullBackOff    0               50s
csi-nfs-node-2hq8l                               0/3     ContainerCreating   0               50s
csi-nfs-node-56x7f                               0/3     ContainerCreating   0               50s
csi-nfs-node-f5zms                               0/3     ContainerCreating   0               50s
csi-nfs-node-hvwh8                               0/3     ContainerCreating   0               50s
csi-nfs-node-jfkhk                               3/3     Running             0               50s
csi-nfs-node-qf6km                               0/3     ContainerCreating   0               50s
etcd-k8s-master1                                 1/1     Running             4 (5h47m ago)   40h
#等待安装成功
etcd-k8s-master2.guoguo.com                      1/1     Running             4 (5h47m ago)   40h
etcd-k8s-master3.guoguo.com                      1/1     Running             4 (5h47m ago)   40h
kube-apiserver-k8s-master1                       1/1     Running             9 (5h47m ago)   40h
kube-apiserver-k8s-master2.guoguo.com            1/1     Running             4 (5h47m ago)   40h
kube-apiserver-k8s-master3.guoguo.com            1/1     Running             4 (5h47m ago)   40h
kube-controller-manager-k8s-master1              1/1     Running             4 (5h47m ago)   40h
kube-controller-manager-k8s-master2.guoguo.com   1/1     Running             4 (5h47m ago)   40h
kube-controller-manager-k8s-master3.guoguo.com   1/1     Running             4 (5h47m ago)   40h
kube-proxy-bchkh                                 1/1     Running             4 (5h47m ago)   40h
kube-proxy-gwdhd                                 1/1     Running             4 (5h47m ago)   40h
kube-proxy-n6496                                 1/1     Running             4 (5h47m ago)   40h
kube-proxy-tdqwb                                 1/1     Running             4 (5h47m ago)   40h
kube-proxy-tww9t                                 1/1     Running             4 (5h47m ago)   40h
kube-proxy-vgv8r                                 1/1     Running             4 (5h47m ago)   40h
kube-scheduler-k8s-master1                       1/1     Running             5 (5h47m ago)   40h
kube-scheduler-k8s-master2.guoguo.com            1/1     Running             5 (5h47m ago)   40h
kube-scheduler-k8s-master3.guoguo.com            1/1     Running             4 (5h47m ago)   40h
metrics-server-684999f4d6-csxjd                  1/1     Running             4 (5h47m ago)   40h

通过标签查询

[root@k8s-master1 nfs-csi]# kubectl get pods -n kube-system -l  app=csi-nfs-node
NAME                 READY   STATUS              RESTARTS   AGE
csi-nfs-node-2hq8l   3/3     Running             0          3m18s
csi-nfs-node-56x7f   0/3     ContainerCreating   0          3m18s
csi-nfs-node-f5zms   3/3     Running             0          3m18s
csi-nfs-node-hvwh8   3/3     Running             0          3m18s
csi-nfs-node-jfkhk   3/3     Running             0          3m18s
csi-nfs-node-qf6km   3/3     Running             0          3m18s

存储类很简单一般都是官方给提供好的,到时候下载比如nfs的 ceph 的

只需要你去改名称

我们去生成一个存储类

StorageClass

[root@k8s-master1 ~]# 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-
       #用于指定存储服务方 或称为预配器 存储类要基于该字段值来判定要使用的存储插件 以便适配到目标存储系统,k8内置支持许多的provisioner 
       #他们的名字都以kubernetes.io/为前缀 列如 kubernetes.io/glusterfs 等

    #provisioner是Kubernetes StorageClass资源中的一个字段,它定义将由哪一个volume插件提供动态分配的持久化存储卷(PersistentVolume)。

    #当用户创建PersistentVolumeClaim时,系统会查找带有匹配存储类名称的StorageClass对象,
    #然后使用该对象中定义的provisioner来自动创建所需的持久卷。
       #举个例子:

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: standard
    provisioner: kubernetes.io/aws-ebs

    #这个StorageClass对象指定名为kubernetes.io/aws-ebs的provisioner。它会调用AWS EBS卷插件在AWS上创建卷。

    #用户创建PVC时,指定storageClassName为standard,就会自动获得AWS EBS卷。

    #常见的provisioner值包括:

    kubernetes.io/aws-ebs
    kubernetes.io/gce-pd
    kubernetes.io/azure-file
    #等等。每种存储类型都有对应的provisioner实现。

    #所以provisioner字段很重要,它定义了由哪个存储插件提供动态分配的持久卷,从而实现存储的自动化配置。

     Provisioner indicates the type of the provisioner.

   reclaimPolicy        <string>
   #当前存储卷 回收策略 
   #两个值 Delete Retain
   #  Delete:默认值,表示当PersistentVolumeClaim被删除后,关联的PersistentVolume也会被删除,数据会被永久删除。
   #  Retain:当PersistentVolumeClaim被删除后,关联的PersistentVolume会被保留下来,以便后续再重新使用,数据不会被删除。
     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.
[root@k8s-master1 nfs-csi]# vim storageclass-nfs.yaml
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-csi  #这个是自己定义的名称
provisioner: nfs.csi.k8s.io  #这是官方提供的接口  你的存储类基于什么来的
parameters:
  server: 192.168.1.103 #修改为自己的nfs的服务器地址  如果是nfs那这个就写nfs ip地址
  share: /data/redis03 #修改为nfs的目录
reclaimPolicy: Retain # only retain is supported,目前这个回收策略只支持Retain
volumeBindingMode: Immediate
mountOptions:
  - hard
  - nfsvers=4.1

这些是官方给的 只需要修改 ip和对应的目录就可以

这是存储类 我们不需要 定义pv了

创建这个 然后我们去定义pvc

[root@k8s-master1 nfs-csi]# kubectl apply -f storageclass-nfs.yaml
storageclass.storage.k8s.io/nfs-csi created
[root@k8s-master1 nfs-csi]# kubectl get storageclass
NAME      PROVISIONER      RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
nfs-csi   nfs.csi.k8s.io   Retain          Immediate           false                  29s

#根据这个`kubectl get storageclass`的输出,我们可以看到这个名为nfs-csi的StorageClass对象的一些关键信息:

#- PROVISIONER:设置为nfs.csi.k8s.io,这表示该StorageClass使用NFS CSI provisioner提供持久卷

#- RECLAIMPOLICY:设置为Retain,这意味着当PVC删除时,关联的PV会被保留下来,不会被删除,实现数据重用

#- VOLUMEBINDINGMODE:设置为Immediate,这表示PV的绑定将立即生效,不会延迟

#- ALLOWVOLUMEEXPANSION:设置为false,表示不允许扩容已有的PV

#综上,这个StorageClass通过NFS CSI动态创建PV,PV的数据在PVC删除后会被保留,且绑定是即时的,不允许扩容。

#一般来说,ReclaimPolicy和VolumeBindingMode是StorageClass中较为重要的两个配置。

#- ReclaimPolicy决定了数据保留策略

#- VolumeBindingMode决定了PV绑定的时间,立即或延迟

#ALLOWVOLUMEEXPANSION控制了是否可以扩展PV。

#合理配置StorageClass非常重要,直接影响存储的动态分配和生命周期管理。

写一个

[root@k8s-master1 pvc]# cat pvc-pods-nginx-1.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-nginx-storageclass  #定义一个名字  volumes.pvc.claimName 要引用
spec:
  accessModes:  #使用模式
    - ReadWriteOnce  # nfs只能用这个  这个的意思卷可以被一个节点读写方式挂载使用,再加节点 同一时刻 只能有一个节点进行读写
  resources:
    requests:
      storage: 10Gi
  storageClassName: nfs-csi #这个是 nfs 的 storageClass类的名字 我们创建的
---
apiVersion: v1
kind: Pod
metadata:
  name: storage-nginx
spec:
  volumes:
  - name: stoarge-nfs #定义一个名字 containers里面的volumeMount要引用
    persistentVolumeClaim: #PVC
      claimName: pvc-nginx-storageclass #引用上面 metadata.name 定义的名字
  containers:
  - name: nginx
    image: images.guoguo.com/apps/nginx:1.22.1
    ports:
    - containerPort: 80
    volumeMounts:
    - name: stoarge-nfs  #引用 spec.mounts.name 定义的名字
      mountPath: /apps/nginx/html/ #挂载到容器的路径
[root@k8s-master1 pvc]# kubectl apply -f pvc-pods-nginx-1.yml
persistentvolumeclaim/pvc-nginx-storageclass created
pod/storage-nginx created
[root@k8s-master1 pvc]# kubectl get persistentVolumeClaim
NAME                     STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS 
pvc-nginx-storageclass   Bound    pvc-929188d5-ef1c-456a-912c-1231a7a97d7e   10Gi       RWO            nfs-csi    
#刚创建的pvc			#已被挂载   挂载的

#NAME:PVC的名称
#STATUS:PVC的状态,Bound表示已经成功绑定到了后端的PersistentVolume
#VOLUME:绑定的PV的名称,这里是pvc-929188d5-ef1c-456a-912c-1231a7a97d7e
#CAPACITY:申请的存储容量,这里是10Gi
#ACCESS MODES:访问模式,RWO表示该卷以读写方式可以被单个节点挂载
#STORAGECLASS:关联的StorageClass名称,这里是nfs-csi
#AGE:PVC已经存在的时间
#所以这个PVC申请了10Gi的存储,与名为nfs-csi的StorageClass关联,系统自动为它动态分配了一个RWO模式的PV,状态为已绑定。

#通过PVC的状态我们可以判断其是否正确绑定了后端的PV,以及绑定的PV是否满足容量和访问模式的需求。

#PVC和PV的绑定关系是实现存储动态分配的关键。
[root@k8s-master1 pvc]# kubectl get pods
NAME            READY   STATUS    RESTARTS   AGE
storage-nginx   1/1     Running   0          6m6s

我们去pod挂载的目录创建点东西 然后再去nfs服务器查看一下

[root@k8s-master1 nfs]# kubectl exec storage-nginx -it /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
root@storage-nginx:/# echo test > /apps/nginx/html/index.html
root@storage-nginx:/#

切换nfs服务器

[root@k8s-node3 redis03]# tree /data/redis03/pvc-929188d5-ef1c-456a-912c-1231a7a97d7e/
/data/redis03/pvc-929188d5-ef1c-456a-912c-1231a7a97d7e/
└── index.html

0 directories, 1 file
[root@k8s-node3 redis03]#

说明没问题

未来只需要不同的文件系统创建存储类

然后引用的时候创建pvc然后pvc和pv关联上,

我们生产上使用就是用动态存储的方式 storageClass类基于csi接口创建存储类,然后就关联上后端的存储系统

存储系统关联好后后面再使用的时候直接和对应的pod挂载就行了

只要保证后期存储空间是够的,后面就可以无限使用了.不停的创建pvc

数据就挂载存储系统上去了

这里使用的nfs的 所以数据都写到nfs上去

这就是基于csi的class存储类

这就是动态与分配机制

这样就不用手工创建pv了

比如我需要pvc是8个G 但是关联到一个10个G的pv 这样两个g就浪费了

nfs生产是不用的.

生产上用ceph