超10万字整理完k8s的volume卷之持久性存储pv和pvc原理和创建绑定-超详细说明,代码和理论都超详细,建议跟着做一遍实验【2】

文章目录

说明【必看】

在这里插入图片描述

  • 总数将近11万,存储一共有4大类,本地卷、网络卷、持久性存储和动态卷供应 ,为了能够直观理解,所以我分成了3篇来发布;
    初次看的时候,建议3篇都打开,按顺序学习和使实验,有助于理解哈。 后面查阅的时候看标题,点进相应的文章哈
  • 这篇是第二篇

本地卷&网络卷【必看】【1】

动态卷供应 【必看】【3】

看这篇博客【上面的本地卷和网络卷是基础知识,足够用了,如果想更深学习,就去这篇博客】【学习动态卷供应之前,建议先学持久性存储】:
超10万字整理完k8s的volume卷之动态卷供应-超详细说明,代码和理论都超详细,建议跟着做一遍实验【3】

持久性存储 【Persistent Volume】

持久性存储说明

  • 这是官方文档网址,下面操作其实都可以在这文档里看到,只是可能不大容易看得懂:http://docs.kubernetes.org.cn/429.html#persistentVolumeClaim

  • 普通Volume和使用它的Pod之间是一种静态绑定关系,在定义Pod的文件里,同时定义了它使用的Volume。Volume 是Pod的附属品,我们无法单独创建一个Volume,因为它不是一个独立的K8S资源对象。

  • 而Persistent Volume 简称PV是一个K8S资源对象,所以我们可以单独创建一个PV。它不和Pod直接发生关系,而是通过Persistent Volume Claim,简称PVC来实现动态绑定。Pod定义里指定的是PVC,然后PVC会根据Pod的要求去自动绑定合适的PV给Pod使用。

  • 既然有了PV这个概念,那么PVC(PersistentVolumeClaim)这个概念也不得不说一下,PVC代表用户使用存储的请求,应用申请PV持久化空间的一个申请、声明。K8s集群可能会有多个PV,你需要不停的为不同的应用创建多个PV。
    如图:
    在这里插入图片描述

    • 1)PV是集群中的存储资源,通常由集群管理员创建和管理;
    • 2)StorageClass用于对PV进行分类,如果配置正确,Storage也可以根据PVC的请求动态创建PV;
    • 3)PVC是使用该资源的请求,通常由应用程序提出请求,并指定对应的StorageClass和需求的空间大小;
    • 4)PVC可以作为数据卷的一种,被挂载到Pod中使用;

持久性使用流程

  • PV与PVC的管理过程如下:

    • 1)主机共享存储目录【任何共享形式均可,一般使用nfs】
    • 2)在主机上划分出一个单独的目录用于PV使用,并且定义其可用大小;
    • 3)创建PVC这个资源对象,便于申请PV的存储空间;
    • 4)Pod中添加数据卷,数据卷关联到PVC;
    • 5)Pod中包含容器,容器挂载数据卷;
  • 既然提到了pv和pvc,那么我们就单独对这2样做下说明

PV概述

  • PersistentVolume (PV)是集群中由管理员提供或使用存储类动态提供的一块存储。它是集群中的资源,就像节点是集群资源一样。

  • PV是与Volumes类似的卷插件,但其生命周期与使用PV的任何单个Pod无关。由此API对象捕获存储的实现细节,不管是NFS、iSCSI还是特定于云提供商的存储系统。

PVC概述

  • PersistentVolumeClaim (PVC) 是用户对存储的请求。它类似于Pod;Pods消耗节点资源,而PVC消耗PV资源。Pods可以请求特定级别的资源(CPU和内存)。Claim可以请求特定的存储大小和访问模式(例如,它们可以挂载一次读写或多次只读)。

  • 虽然PersistentVolumeClaims (PVC) 允许用户使用抽象的存储资源,但是用户通常需要具有不同属性(比如性能)的PersistentVolumes (PV) 来解决不同的问题。集群管理员需要能够提供各种不同的PersistentVolumes,这些卷在大小和访问模式之外还有很多不同之处,也不向用户公开这些卷是如何实现的细节。对于这些需求,有一个StorageClass资源。

volume 和 claim的生命周期

PV是集群中的资源。PVC是对这些资源的请求,并且还充当对资源的声明检查。PV和PVC之间的交互遵循以下生命周期:

供应

  • 有两种方式配置PV:
    • 静态的
    • 动态的
静态配置

集群管理员创建一些PV。它们带有可供集群用户使用的实际存储的详细信息。存在于Kubernetes API中,可供使用。

动态配置
  • 当管理员创建的静态PV没有一个与用户的PersistentVolumeClaim匹配时,集群可能会尝试动态地为PVC提供一个卷。此配置基于StorageClasses:PVC必须请求存储类,并且管理员必须已经创建并配置了该类,才能进行动态配置。声明该类为 “”,可以有效地禁用其动态配置。

  • 要启用基于存储级别的动态存储配置,集群管理员需要启用API Server上的DefaultStorageClass[准入控制器]。例如,通过确保DefaultStorageClass位于API Server组件的 --enable-admission-plugins标志,使用逗号分隔的有序值列表中,可以完成此操作。

绑定

  • 用户创建(或者在动态配置的情况下,已经创建)具有特定存储请求量(大小)和特定访问模式的PersistentVolumeClaim。主控制器中的控制循环监视新的PV,找到匹配的PV(如果可能的话),并将它们绑定在一起。如果PV为新的PVC动态配置,那么循环始终将该PV绑定到PVC。否则,用户始终至少得到他们所要求的,但是存储量可能会超过所要求的范围。

  • 一旦绑定,无论是如何绑定的,PersistentVolumeClaim绑定都是互斥的。PVC到PV的绑定是一对一的映射,使用ClaimRef,它是PersistentVolume和PersistentVolumeClaim之间的双向绑定。

  • 如果不存在匹配的卷,声明(Claims)将无限期保持未绑定。随着匹配量的增加,声明将受到约束。例如,配备有许多50Gi PV的群集将与请求100Gi的PVC不匹配。当将100Gi PV添加到群集时,可以绑定PVC。

  • 注意:静态时PVC与PV绑定时会根据storageClassName(存储类名称)和accessModes(访问模式)判断哪些PV符合绑定需求。然后再根据存储量大小判断,首先存PV储量必须大于或等于PVC声明量;其次就是PV存储量越接近PVC声明量,那么优先级就越高(PV量越小优先级越高)。

使用

  • Pods使用声明(claims)作为卷。集群检查声明以找到绑定卷并为Pod挂载该卷。对于支持多种访问模式的卷,用户在其声明中作为Pod中卷使用时指定所需的模式。

  • 一旦用户拥有一个声明并且该声明被绑定,则绑定的PV就属于该用户。用户通过在Pod的卷块中包含的persistentVolumeClaim部分来调度Pods并访问其声明的PV。

持久化声明保护

  • “使用中的存储对象保护” :该功能的目的是确保在Pod活动时使用的PersistentVolumeClaims (PVC)和绑定到PVC的PersistentVolume (PV)不会从系统中删除,因为这可能会导致数据丢失。

  • 如果用户删除了Pod正在使用的PVC,则不会立即删除该PVC;PVC的清除被推迟,直到任何Pod不再主动使用PVC。另外,如果管理员删除绑定到PVC的PV,则不会立即删除该PV;PV的去除被推迟,直到PV不再与PVC结合。

PV示例与参数说明

PV文件参数说明

下面就是pv的文件

apiVersion: v1 # 自定义版本名称
kind: PersistentVolume
metadata:
  name: test-pv #自定义pv名称
spec:
  capacity:
    storage: 1Gi          #指定该PV资源分配的容器为1G
  accessModes:         #指定访问模式
    - ReadWriteOnce # 一共有3种模式
  persistentVolumeReclaimPolicy: Recycle       #指定回收策略(实验环境,实际环境很少会这样做,就是回收策略会用保留(Retain),而不是回收(Recycle)】
  storageClassName: nfs           #指定存储类名字
  nfs:                          #需要与存储类名字一致
    path: /nfsdata/test-pv                #指定NFS的目录
    server: 192.168.1.4                  #指定NFS的IP地址

部分参数详细说明如下

accessModes【访问模式】

**accessModes:**PersistentVolume可以通过资源提供者支持的任何方式安装在主机上。如下文表中所示,提供商将具有不同的功能,并且每个PV的访问模式都将设置为该特定卷支持的特定模式。例如,NFS可以支持多个读/写客户端,但是特定的NFS PV可能以只读方式在服务器上导出。每个PV都有自己的一组访问模式,用于描述该特定PV的功能。

ReadWriteOnce
  • ReadWriteOnce-该卷可以被单个节点以读写方式挂载

  • 在CLI命令行中,访问模式缩写为:RWO-ReadWriteOnce

ReadOnlyMany
  • ReadOnlyMany-该卷可以被许多节点以只读方式挂载
  • 在CLI命令行中,访问模式缩写为:ROX-ReadOnlyMany
ReadWriteMany
  • ReadWriteMany-该卷可以被多个节点以读写方式挂载
  • 在CLI命令行中,访问模式缩写为:RWX-ReadWriteMany
persistentVolumeReclaimPolicy【回收策略】

当用户处理完他们的卷时,他们可以从允许回收资源的API中删除PVC对象。PersistentVolume的回收策略告诉集群在释放卷的声明后该如何处理它。目前,卷可以被保留、回收或删除。

Recycle (回收)

如果基础卷插件支持,Recycle回收策略将rm -rf /thevolume/*对该卷执行基本的擦除并使其可用于新的声明。

Retain (保留)

保留回收策略允许手动回收资源。当PersistentVolumeClaim被删除时,PersistentVolume仍然存在,并且该卷被认为是“释放”的。但是,由于之前声明的数据仍然存在,因此另一个声明尚无法得到。管理员可以手动回收卷。

Delete (删除)

对于支持Delete回收策略的卷插件,删除操作会同时从Kubernetes中删除PersistentVolume对象以及外部基础架构中的关联存储资产,例如AWS EBS,GCE PD,Azure Disk或Cinder卷。动态配置的卷将继承其StorageClass的回收策略,默认为Delete。管理员应根据用户的期望配置StorageClass。

storageClassName【指定类】
  • 这个可以理解为一个秘钥匹配,这个值可以任意定义,用来和pvc绑定使用。
  • 使用情况一般是,如果nfs共享了多个文件,那么在pv文件中的storageClassName定义一个秘钥,然后在pvc中也定义storageClassName和pv一致,这样pvc和pv就能指定绑定在一定了。
volumeMode 【文件挂载类型】
  • volumeMode 是一个可选的 API 参数,所以上面配置文件中并没有写该行内容, 如果该参数被省略,默认的卷模式是 Filesystem。

  • 针对 PV 持久卷,Kubernetes 支持两种卷模式(volumeModes):Filesystem(文件系统) 和 Block(块)。

  • volumeMode 属性设置为 Filesystem 的卷会被 Pod 挂载(Mount) 到某个目录。 如果卷的存储来自某块设备而该设备目前为空,Kuberneretes 会在第一次挂载卷之前 在设备上创建文件系统。

  • 这个是定义在spec下面的,如下【默认的一般mei有这行,只是知道这个以后,如果配置文件有这行,看得懂而已】

 spec:
   volumeMode: Filesystem
说明【必看】
  • 一个卷一次只能使用一种访问模式挂载,即使它支持多种访问模式。

  • **storageClassName:**PV可以有一个类,通过将storageClassName属性设置为一个StorageClass的名称来指定这个类。特定类的PV只能绑定到请求该类的PVC。没有storageClassName的PV没有类,只能绑定到不请求特定类的PVC。

  • **persistentVolumeReclaimPolicy:**当前的回收政策是:

    • Retain (保留)-手动回收
    • Recycle (回收)-基本擦除(rm -rf /thevolume/*)
    • Delete (删除)-删除相关的存储资产 (例如AWS EBS,GCE PD,Azure Disk或OpenStack Cinder卷)。
  • 备注:当前,仅NFS和HostPath支持回收。AWS EBS,GCE PD,Azure Disk和Cinder卷支持删除。

Persistent Volumes类型

  • PersistentVolume类型作为插件实现。Kubernetes当前支持以下插件:
    所谓插件,可以理解为卷目录存在形式【和网络卷一样】
    • NFS
    • iSCSI
    • GCEPersistentDisk
    • AWSElasticBlockStore
    • AzureFile
    • AzureDisk
    • CSI
    • FC (Fibre Channel)
    • FlexVolume
    • Flocker
    • RBD (Ceph Block Device)
    • CephFS
    • Cinder (OpenStack block storage)
    • Glusterfs
    • VsphereVolume
    • Quobyte Volumes
    • HostPath (仅用于单节点测试——本地存储不受任何方式的支持,也不能在多节点集群中工作)
    • Portworx Volumes
    • ScaleIO Volumes
    • StorageOS

PV卷状态说明

  • 卷有一下4种状态【kubectl get pv】:
  • CLI将显示绑定到PV的PVC的名称。

Available

Available:尚未绑定到声明(claim)的空闲资源

Bound

Bound:卷已被声明绑定

Released

Released:声明已被删除,但群集尚未回收该资源

Failed

Failed:该卷自动回收失败

PV类型与支持的访问模式对应关系

Volume PluginReadWriteOnceReadOnlyManyReadWriteMany
AWSElasticBlockStore--
AzureFile
AzureDisk--
CephFS
Cinder--
CSIdepends on the driverdepends on the driverdepends on the driver
FC-
FlexVolumedepends on the driver
Flocker--
GCEPersistentDisk-
Glusterfs
HostPath--
iSCSI-
Quobyte
NFS
RBD-
VsphereVolume-- (works when Pods are collocated)
PortworxVolume-
ScaleIO-
StorageOS--

PV-PVC示例【搭建过程】

主机信息

  • 下面4台主机呢,其中3台是一个集群,一台已经安装好nfs的服务
    如果没有下面环境的,先搭建这么一套出来【k8s集群搭建和nfs服务端配置我博客中都有,如果不会的可以去翻翻博客先学习一下】
服务器名称(hostname)系统版本IP部署模块
masterCentOS Linux release 7.6.1810 (Core)192.168.59.142k8s集群-master节点
node1CentOS Linux release 7.6.1810 (Core)192.168.59.143k8s集群-node节点
node2CentOS Linux release 7.6.1810 (Core)192.168.59.144k8s集群-node节点
etcd1CentOS Linux release 7.4.1708 (Core)192.168.59.156仅部署nfs【未加入集群】

nfs文件共享配置

  • 【nfs这个,建议先去我k8s分类中,找到volume卷的网络卷配置里面有详细说明nfs主机服务搭建和node节点服务安装】

文件创建并共享【nfs节点操作】

我们随便创建几个文件然后共享出去

[root@etcd1 ~]# mkdir -p /data/nfs1 /data/nfs2 /data/nfs3 /data/nfs4 /data/nfs5
[root@etcd1 ~]# chown -R nfsnobody.nfsnobody /data/
[root@etcd1 ~]# ll /data
总用量 0
drwxr-xr-x 2 nfsnobody nfsnobody 6 820 10:23 nfs1
drwxr-xr-x 2 nfsnobody nfsnobody 6 820 10:23 nfs2
drwxr-xr-x 2 nfsnobody nfsnobody 6 820 10:23 nfs3
drwxr-xr-x 2 nfsnobody nfsnobody 6 820 10:23 nfs4
drwxr-xr-x 2 nfsnobody nfsnobody 6 820 10:23 nfs5
[root@etcd1 ~]# 
[root@etcd1 ~]# cat /etc/exports
/data/nfs1 *(rw,async,no_root_squash)
/data/nfs2 *(rw,async,no_root_squash)
/data/nfs3 *(rw,async,no_root_squash)
/data/nfs4 *(rw,async,no_root_squash)
/data/nfs5 *(rw,async,no_root_squash)
[root@etcd1 ~]# 
[root@etcd1 ~]# systemctl restart nfs-server.service 
[root@etcd1 ~]# 
[root@etcd1 ~]# showmount -e 192.168.59.156
Export list for 192.168.59.156:
/data/nfs5 *
/data/nfs4 *
/data/nfs3 *
/data/nfs2 *
/data/nfs1 *
[root@etcd1 ~]# 

验证【node节点操作】

任意node节点均可以操作,可以不用验证的,验证一下只是为了更能理解nfs挂载罢了。

[root@node1 ~]# showmount -e 192.168.59.156
Export list for 192.168.59.156:
/data/nfs5 *
/data/nfs4 *
/data/nfs3 *
/data/nfs2 *
/data/nfs1 *
[root@node1 ~]# mkdir /test
[root@node1 ~]# mount -t nfs 192.168.59.156:/data/nfs1 /test
[root@node1 ~]# df -h | grep test
192.168.59.156:/data/nfs1  150G  6.8G  144G   5% /test
[root@node1 ~]# 
[root@node1 ~]# umount -lf 192.168.59.156:/data/nfs1
[root@node1 ~]# 
[root@node1 ~]# 

PV部署

pv创建好以后,再创建pcv,这个和linux中的pv类似。

编辑文件并创建

  • pv部署是以yaml文件形式创建,创建方式和pod一样。
    命令:kubectl apply -f pv.yaml
  • 如果需要创建多个pv,中间需要以---隔开【每个pv配置文件一致】
    平常呢,建议一个配置文件就写一个信息,不要写多个,我这只是为了展示可以实现这样的场景
  • 如下,我创建了2个pv【如果配置文件看不懂,上面有pv文件参数说明,qu看看】
    注:因为我们使用的是nfs,所以下面storage参数控制大小是无效的【这个大小需要到nfs主机上设置】,如果使用的块存储的话,定义了3G那么容量就3G
[root@master volume]# cat pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs1
spec:
  capacity:
    storage: 3Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /data/nfs1
    server: 192.168.59.156

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs2
spec:
  capacity:
    storage: 3Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /data/nfs2
    server: 192.168.59.156
[root@master volume]# 
[root@master volume]# kubectl apply -f pv.yaml
persistentvolume/pv-nfs1 created
persistentvolume/pv-nfs2 created

查看pv

命令:kubectl get pv
需要注意的是,这个pv是全局生效的,无论在哪个命名空间都是可以看到该pv信息的

[root@master volume]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Available           nfs                     4m30s
pv-nfs2   3Gi        RWO            Recycle          Available           nfs                     4m30s
[root@master volume]# 
[root@master volume]# kubectl get pv -n default 
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Available           nfs                     4m36s
pv-nfs2   3Gi        RWO            Recycle          Available           nfs                     4m36s
[root@master volume]# kubectl get pv -n ccx
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Available           nfs                     4m40s
pv-nfs2   3Gi        RWO            Recycle          Available           nfs                     4m40s
[root@master volume]# 

查看已创建pv详细信息

命令:kubectl describe pv pvname

[root@master volume]# kubectl describe pv pv-nfs
Name:            pv-nfs1
Labels:          <none>
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    nfs
Status:          Bound
Claim:           volume/ccx-pvc
Reclaim Policy:  Recycle
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        3Gi
Node Affinity:   <none>
Message:         
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    192.168.59.156
    Path:      /data/nfs1
    ReadOnly:  false
Events:        <none>

Name:            pv-nfs2
Labels:          <none>
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    nfs
Status:          Bound
Claim:           volume/hero-pvc
Reclaim Policy:  Recycle
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        3Gi
Node Affinity:   <none>
Message:         
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    192.168.59.156
    Path:      /data/nfs2
    ReadOnly:  false
Events:        <none>

[root@master volume]# 

删除pv

命令:kubectl delete pv pv_name

[root@master volume]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Failed   volume/ccx-pvc    nfs                     35m
pv-nfs2   3Gi        RWO            Recycle          Failed   volume/hero-pvc   nfs                     35m
[root@master volume]# kubectl delete pv pv-nfs1
persistentvolume "pv-nfs1" deleted
[root@master volume]# 
[root@master volume]# kubectl delete pv pv-nfs2
persistentvolume "pv-nfs2" deleted
[root@master volume]# 
[root@master volume]# kubectl get pv
No resources found
[root@master volume]# 

创建PVC资源对象

  • pvc和pv进行关联主要由2个参数决定

    • 1、capcity
      pvc里的要求容量 <= pv—capcity
    • 2、accessmode
      必须要和pv里相同
  • 文件说明如下,如果有需要定义多个,用---隔开

[root@master ~]# vim test-pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ccx-pvc    #自定义名称
spec:
  accessModes:             
  - ReadWriteOnce  #定义访问模式,必须与PV定义的访问模式一致
  resources:
    requests:
      storage: 1Gi            #定义容量【不能高于pv容量】
  storageClassName: nfs           #定义的名称需与PV定义的名称一致

常规创建

  • 命令:kubectl apply -f pvc.yaml
  • 需要注意的是,如果使用---隔开了,那么pv中必须也是这样格式,因为是一一对应的,如下,我创建了2个,可以看到后面使用的卷是nfs1和nfs2【我定义在pv中了】
    平常呢,建议一个配置文件就写一个信息,不要写多个,我这只是为了展示可以实现这样的场景
[root@master volume]# cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ccx-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi      
  storageClassName: nfs 

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: hero-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi      
  storageClassName: nfs 
[root@master volume]# kubectl apply -f pvc.yaml
persistentvolumeclaim/ccx-pvc created
persistentvolumeclaim/hero-pvc created
[root@master volume]# 
[root@master volume]# kubectl get pvc
NAME       STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc    Bound    pv-nfs1   3Gi        RWO            nfs            15s
hero-pvc   Bound    pv-nfs2   3Gi        RWO            nfs            15s
[root@master volume]# 

注意:“PV与PVC的状态都是Bound,表示PV与PVC的关联成功

指定命名空间创建

  • 指定命名空间创建和普通创建一样,就是在后面加了指定命名空间的参数罢了。
    命令:kubectl apply -f pvc.yaml -n ccx【kubectl get ns查看当前命名空间】
  • 注:指定命名空间创建呢,后面查看也需要指定命名空间,否则是无法查看到创建的内容的。
    并且,一个pv只能被一个pvc使用,如下,我下面指定的这个pv已经在上面通过默认方式创建了,没有删除他,现在指定命名空间创建,就会报错【正常情况这么创建是和常规创建效果是一样的,我就不去删除新建了】。
[root@master volume]# kubectl get ns
NAME              STATUS   AGE
ccx               Active   44d
ccxhero           Active   44d
default           Active   49d
kube-node-lease   Active   49d
kube-public       Active   49d
kube-system       Active   49d
ns1               Active   44d
pod-1             Active   35d
volume            Active   3d18h
[root@master volume]# 
[root@master volume]# cat pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ccx-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi      
  storageClassName: nfs 

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: hero-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi      
  storageClassName: nfs 
[root@master volume]# 
[root@master volume]# kubectl apply -f pvc.yaml -n ccx
persistentvolumeclaim/ccx-pvc created
persistentvolumeclaim/hero-pvc created
[root@master volume]# 
[root@master volume]# kubectl get pvc -n ccx
NAME       STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc    Pending                                      nfs            10s
hero-pvc   Pending                                      nfs            10s
[root@master volume]# 

查看pvc【含指定ns查看】

  • 前面说过pv是全局的,但pvc不是,在哪个命名空间创建的,就只能在哪个命名空间中查看到。
    • 常规查看【当前默认ns】:kubectl get pvc
    • 指定ns查看【kubectl get ns查看所有命名空间】:kubectl get pvc -n nsname
[root@master volume]# kubectl get pvc
NAME       STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc    Bound    pv-nfs1   3Gi        RWO            nfs            15s
hero-pvc   Bound    pv-nfs2   3Gi        RWO            nfs            15s
[root@master volume]# 
[root@master volume]# kubectl get pvc -n ccx
NAME       STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc    Pending                                      nfs            8m4s
hero-pvc   Pending                                      nfs            8m4s
[root@master volume]#
[root@master volume]#

删除pvc

  • 常规删除【删除当前所处ns空间的pvc】:
  • 方式1:命令:kubectl delete -f pvc.yaml_name
[root@master volume]# 
[root@master volume]# kubectl delete -f pvc.yaml 
persistentvolumeclaim "ccx-pvc" deleted
persistentvolumeclaim "hero-pvc" deleted
[root@master volume]# 
[root@master volume]# kubectl get pvc
No resources found in volume namespace.
[root@master volume]# 
  • 方式2:命令:kubectl delete pvc pvc_name
[root@master volume]# kubectl get pvc
NAME       STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc    Bound    pv-nfs1   3Gi        RWO            nfs1           7m9s
ccx-pvc2   Bound    pv-nfs2   3Gi        RWO            nfs2           6m4s
[root@master volume]# 
[root@master volume]# kubectl get pv^C
[root@master volume]# kubectl delete pvc ccx-pvc
persistentvolumeclaim "ccx-pvc" deleted
[root@master volume]# kubectl delete pvc ccx-pvc2
persistentvolumeclaim "ccx-pvc2" deleted
[root@master volume]#
  • 指定命名空间删除:
    命令:kubectl delete -f pvc.yaml_name -n ns_name
[root@master volume]# kubectl delete -f pvc.yaml -n ccx
persistentvolumeclaim "ccx-pvc" deleted
persistentvolumeclaim "hero-pvc" deleted
[root@master volume]# 
[root@master volume]# kubectl get pvc -n ccx
No resources found in ccx namespace.
[root@master volume]# 

pv回收策略测试【了解逻辑为主】

注:下面设计到的回收策略和状态都在上面:PV示例与参数说明 中有详细介绍的。

Recycle

  • 我们先创建pc和pvc,并且要pv和pvc的状态都为Bound才行
[root@master volume]# cat pvtest.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs1
spec:
  capacity:
    storage: 3Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfs
    server: 192.168.59.156

[root@master volume]# cat pvctest.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ccx-pvc
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi      
  storageClassName: nfs 

[root@master volume]# 
[root@master volume]# kubectl apply -f pvtest.yaml 
persistentvolume/pv-nfs1 created
[root@master volume]# kubectl apply -f pvctest.yaml 
persistentvolumeclaim/ccx-pvc created
[root@master volume]# 
[root@master volume]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Bound    volume/ccx-pvc   nfs                     8s
[root@master volume]# kubectl get pvc
NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc   Bound    pv-nfs1   3Gi        RWO            nfs            5s
[root@master volume]# 
[root@master volume]# 
  • 可以看到,pv-nfs1的挂载目录是/nfs,所以我们去nfs主机的这个目录上随便创建几个文件,然后回到master节点上,删除pvc
[root@etcd1 ~]# cd /nfs
[root@etcd1 nfs]# touch {aa,bb,cc,dd}.txt
[root@etcd1 nfs]# ls
aa.txt  bb.txt  cc.txt  dd.txt
[root@etcd1 nfs]# ls
aa.txt  bb.txt  cc.txt  dd.txt
[root@etcd1 nfs]# 
  • 然后我们回到master节点,删除pvc,这时候pv的状态就会为Available,同时再回到nfs节点中,/nfs中我们创建的文件就没了。
    【当然,凡事有意外,比如我这删了pvc以后,pv状态成Failed了,这个时候nfs中文件是不会被删除的,但这是意外情况,正常情况为available才对】
[root@master volume]# kubectl delete -f pvctest.yaml 
persistentvolumeclaim "ccx-pvc" deleted
[root@master volume]# 
[root@master volume]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Failed   volume/ccx-pvc   nfs                     47s
[root@master volume]# 
事件查看【pv详细、报错内容查看】
  • 因为我上面测试出现意外了,所以我们可以执行这个命令查看:kubectl describe pv pv_name
    可以看到,提示镜像pull失败了,因为我这集群是没有外网的,因为没联网,所以没法下载回收镜像busybox:1.27,所以导致pv回收失败,这个玩意没法指定镜像获取方式,所以没得玩,你如果在有外网的机子上测试,是不会出现这种意外报错的。
[root@master volume]# kubectl describe pv pv-nfs1 
Name:            pv-nfs1
Labels:          <none>
Annotations:     pv.kubernetes.io/bound-by-controller: yes
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    nfs
Status:          Failed
Claim:           volume/ccx-pvc
Reclaim Policy:  Recycle
Access Modes:    RWO
VolumeMode:      Filesystem
Capacity:        3Gi
Node Affinity:   <none>
Message:         Recycle failed: old recycler pod found, will retry later
Source:
    Type:      NFS (an NFS mount that lasts the lifetime of a pod)
    Server:    192.168.59.156
    Path:      /nfs
    ReadOnly:  false
Events:
  Type     Reason               Age                    From                         Message
  ----     ------               ----                   ----                         -------
  Warning  VolumeFailedRecycle  4m24s                  persistentvolume-controller  Recycle failed: old recycler pod found, will retry later
  Warning  RecyclerPod          4m20s                  persistentvolume-controller  Recycler pod: Failed to pull image "busybox:1.27": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:49162->[::1]:53: read: connection refused
  Normal   RecyclerPod          4m20s (x3 over 4m20s)  persistentvolume-controller  Recycler pod: Pulling image "busybox:1.27"
  Warning  RecyclerPod          4m20s                  persistentvolume-controller  Recycler pod: Failed to pull image "busybox:1.27": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:58916->[::1]:53: read: connection refused
  Warning  RecyclerPod          4m20s (x3 over 4m20s)  persistentvolume-controller  Recycler pod: Error: ErrImagePull
  Normal   RecyclerPod          4m20s (x2 over 4m20s)  persistentvolume-controller  Recycler pod: Back-off pulling image "busybox:1.27"
  Warning  RecyclerPod          4m20s (x2 over 4m20s)  persistentvolume-controller  Recycler pod: Error: ImagePullBackOff
  Normal   RecyclerPod          4m20s (x4 over 4m20s)  persistentvolume-controller  Recycler pod: Successfully assigned default/recycler-for-pv-nfs1 to node1
  Warning  RecyclerPod          4m20s                  persistentvolume-controller  Recycler pod: Failed to pull image "busybox:1.27": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:52686->[::1]:53: read: connection refused
  Warning  RecyclerPod          4m20s                  persistentvolume-controller  Recycler pod: Failed to pull image "busybox:1.27": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:39752->[::1]:53: read: connection refused
  Warning  RecyclerPod          4m20s                  persistentvolume-controller  Recycler pod: Failed to pull image "busybox:1.27": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:39082->[::1]:53: read: connection refused
  Warning  RecyclerPod          4m20s                  persistentvolume-controller  Recycler pod: Failed to pull image "busybox:1.27": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:58654->[::1]:53: read: connection refused
  Warning  RecyclerPod          4m20s                  persistentvolume-controller  Recycler pod: Failed to pull image "busybox:1.27": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:60514->[::1]:53: read: connection refused
  Warning  RecyclerPod          4m20s (x3 over 4m20s)  persistentvolume-controller  (combined from similar events): Recycler pod: Failed to pull image "busybox:1.27": rpc error: code = Unknown desc = Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io on [::1]:53: read udp [::1]:39184->[::1]:53: read: connection refused
[root@master volume]# 

因为没外网测试第一个就有问题了,所以剩下2个我都不想测试了,反正就是这么个逻辑,感兴趣的自己测吧。

绑定pv创建pod

代码解释

  • 创建pod前需要先创建好pv和pvc,方法见上面哦。
    如下,我已经创建好如下pvc了
[root@master ~]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Bound    volume/ccx-pvc   nfs                     12m
[root@master ~]# kubectl get pvc
NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc   Bound    pv-nfs1   3Gi        RWO            nfs            12m
[root@master ~]# 
  • 下面是一些创建pod的基本参数规则,已经在代码后面注明作用了
    这个和创建pod差不太多,只是卷定义稍有不同,pod更多参数可以参考pod创建自定义测试哦。
[root@master volume]# cat pvpod.yaml 
apiVersion: v1 #自定义版本号
kind: Pod
metadata:
  name: pvpod #自定义pod名称
spec:
  containers:
  - name: pv-pod #自定义名称
    image: nginx #镜像名称
    imagePullPolicy: IfNotPresent #定义镜像获取规则,默认pull
    args: # 下面是自定义command的一种方式,只有一个容器不定义也可
    - /bin/sh
    - -c
    - sleep 300000
    volumeMounts:
    - mountPath: /testdata  #定义容器中的目录
      name: volumedata  #保证与卷的名称一致【卷名称在下面】
  volumes:
    - name: volumedata    #定义卷的名称
      persistentVolumeClaim:
        claimName: ccx-pvc  #指定逻辑卷对应的PVC名称【kubectl get pvc查看】

编辑文件并创建pod

[root@master volume]# cat pvpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pvpod
spec:
  containers:
  - name: pv-pod
    image: nginx
    imagePullPolicy: IfNotPresent
    args:
    - /bin/sh
    - -c
    - sleep 300000
    volumeMounts:
    - mountPath: /testdata
      name: volumedata
  volumes:
    - name: volumedata
      persistentVolumeClaim:
        claimName: ccx-pvc
[root@master volume]# kubectl apply -f pvpod.yaml
pod/pvpod created
[root@master volume]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
pvpod   1/1     Running   0          6s

pod数据测试

  • 数据测试前,我们需要获取到卷存储的路径和容器内的存储路径
    • 我们上面pod绑定的pvc中的pv卷来源是nfs主机中共享的,/nfs1目录【可以通过配置文件看出来】
    • 然后容器内指定的目录是:/testdata【通过配置文件可以看出来
[root@master ~]# kubectl get pvc
NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc   Bound    pv-nfs1   3Gi        RWO            nfs            12m
[root@master volume]# cat pvtest.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs1
spec:
  capacity:
    storage: 3Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfs1
    server: 192.168.59.156
[root@master volume]#
[root@master volume]# 
[root@master volume]# cat pvpod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pvpod
spec:
  containers:
  - name: pv-pod
    image: nginx
    imagePullPolicy: IfNotPresent
    args:
    - /bin/sh
    - -c
    - sleep 300000
    volumeMounts:
    - mountPath: /testdata
      name: volumedata
  volumes:
    - name: volumedata
      persistentVolumeClaim:
        claimName: ccx-pvc
[root@master volume]# 
  • 这2个路径都知道以后呢
    • 我们先去nfs主机的/nfs1中随便创建几个目录,然后进入到容器内看是否能看到
    • 然后进入到容器的目录总创建几个文件,再回到nfs主机看是否能看到
#nfs主机
[root@etcd1 ~]# touch /nfs1/fdaf /nfs1/111 /nfs1/2222
[root@etcd1 ~]# ls /nfs1/
111  2222  fdaf

# master节点
[root@master volume]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
pvpod   1/1     Running   0          6s
[root@master volume]# kubectl exec -it pvpod -- bash
root@pvpod:/# ls /testdata/     
111  2222  fdaf
root@pvpod:/# 
root@pvpod:/# touch /testdata/pvpod{test1,test2,test3}.20210820
root@pvpod:/# ls /testdata/
111  2222  fdaf  pvpodtest1.20210820  pvpodtest2.20210820  pvpodtest3.20210820
root@pvpod:/#

# nfs主机
[root@etcd1 ~]# ls /nfs1/
111  2222  fdaf  pvpodtest1.20210820  pvpodtest2.20210820  pvpodtest3.20210820
[root@etcd1 ~]# 

综上,全部测试都很正常,持久性存储没毛病。

删除pod测试

  • 这个呢,就要就是为了证明,删除pod是对数据没有任何影响的,影响数据的因素是,pvc和pv的删除操作【回收策略决定】,具体规则上面都有说明的哈。

  • 如下,我删除pod,去nfs节点,数据依然存在。

[root@master volume]# kubectl delete pod pvpod 
pod "pvpod" deleted
[root@master volume]# 

#nfs节点
[root@etcd1 ~]# ls /nfs1/
111  2222  fdaf  pvpodtest1.20210820  pvpodtest2.20210820  pvpodtest3.20210820
[root@etcd1 ~]# 
  • 在通过这个pod文件创建pods,进入容器,数据肯定都在【此期间没有对pvc做过任何变动】
[root@master volume]# kubectl apply -f pvpod.yaml
pod/pvpod created
[root@master volume]# kubectl get pods
NAME    READY   STATUS    RESTARTS   AGE
pvpod   1/1     Running   0          4s
[root@master volume]# kubectl exec -it pvpod -- bash
root@pvpod:/# ls /testdata/
111  2222  fdaf  pvpodtest1.20210820  pvpodtest2.20210820  pvpodtest3.20210820
root@pvpod:/# exit
exit
[root@master volume]# 

关于持久性存储的几个思考和解决思路

这些也仅仅是我针对上面测试中产生的想法罢了,肯定有考虑不周全的地方,也不一定全部正确,如果有误或有更好的建议,还请i留下评论指正为谢。

pv和pvc的对应关系

  • 上面测试中我们可以看到,pvc并没有指定pv的参数,如果一台nfs主机共享了很多个目录,且这些目录都需要挂载到不同的pod上,如果你做上面实验了,应该知道有2种方式
    • 方式1:使用多个文件创建多个pv,然后绑定pvc
    • 方式2:一个文件中使用---隔开,对应创建pvc

上面2种方式有对应的问题,我下面分别说明

方式1【多个文件创建pv】

一个pv和一个pvc创建
  • 创建pv文件如下【代码如果有看不懂的,回到上面去查看详解】
[root@master volume]# cat pvtest.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs1
spec:
  capacity:
    storage: 3Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfs1
    server: 192.168.59.156
[root@master volume]# 
[root@master volume]# cat pvctest.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ccx-pvc
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi      
  storageClassName: nfs 

[root@master volume]# 


# 创建流程和成功截图
[root@master volume]#kubectl apply -f pvtest.yaml
[root@master volume]#kubectl apply -f pvctest.yaml 
[root@master volume]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM            STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Bound    volume/ccx-pvc   nfs                     51m
[root@master volume]# kubectl get pvc
NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc   Bound    pv-nfs1   3Gi        RWO            nfs            51m
[root@master volume]# 
问题思考【pvc如何指定pv】
  • 根据上面代码:
    我们一个pv文件只绑定一个nfs路径,且文件中文件指定存储类型为nfs,我们创建pv的时候,是通过文件创建出pv的,创建pvc的时候,并不能指定pv名称,只能通过这个pv中的类型【nfs这种】来创建pvc,这种情况创建一个pv和pvc肯定没有问题
  • 那么如果我通过这个配置文件创建了2个pv呢【存储路径变了,其他不变】,这个时候创建pvc,这个pvc又会指定到哪里呢?
  • 直接创建测试看结果
    前面说过pvc是不能指定pv名称的,所以pv文件有2个,pvc文件就一个
[root@master volume]# cat pvtest2.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs2
spec:
  capacity:
    storage: 3Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfs
    server: 192.168.59.156
[root@master volume]# cat pvtest.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs1
spec:
  capacity:
    storage: 3Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /nfs1
    server: 192.168.59.156
[root@master volume]# 
[root@master volume]# cat pvctest.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ccx-pvc
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi      
  storageClassName: nfs 

[root@master volume]# 

现在我们来创建pv和pvc【先删除之前创建的】
可以看到,pv确实有2个,但创建pvc的时候,自动给我绑定到nfs2了

[root@master volume]# kubectl delete -f pvctest.yaml 
persistentvolumeclaim "ccx-pvc" deleted
[root@master volume]# kubectl delete pv pv-nfs1 
persistentvolume "pv-nfs1" deleted
[root@master volume]#
[root@master volume]# kubectl apply -f pvtest.yaml 
persistentvolume/pv-nfs1 created
[root@master volume]# kubectl apply -f pvtest2.yaml 
persistentvolume/pv-nfs2 created
[root@master volume]# 
[root@master volume]# kubectl get  pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Available           nfs                     9s
pv-nfs2   3Gi        RWO            Recycle          Available           nfs                     6s
[root@master volume]# kubectl apply -f pvctest.yaml 
persistentvolumeclaim/ccx-pvc created
[root@master volume]# 
[root@master volume]# kubectl get pvc
NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc   Bound    pv-nfs2   3Gi        RWO            nfs            5s
[root@master volume]# 
[root@master volume]# 

如果我再次创建,那么就会报错,也就是说,常规情况,创建了2个pv,我们是没有办法控制pvc绑定在哪个pv上的。
【kubectl get pv,status中bound是已经使用的,available是没有使用的】

[root@master volume]# kubectl apply -f pvctest.yaml 
persistentvolumeclaim/ccx-pvc unchanged
[root@master volume]# 
[root@master volume]# kubectl get pvc
NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc   Bound    pv-nfs2   3Gi        RWO            nfs            31s
[root@master volume]# 
[root@master volume]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM            STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Available                    nfs                     2m28s
pv-nfs2   3Gi        RWO            Recycle          Bound       volume/ccx-pvc   nfs                     2m25s
[root@master volume]# 
解决问题【pvc无法指定pv】
  • 其实这个问题很好解决,配置文件中有一个参数是:storageClassName:这个后面我们一般使用的是存储类型【nfs这种参数】,其实这个还有一个功能,类似于秘钥匹配机制,这个参数是可以用来pvc和pv绑定,首先要明白这个参数是可以自定义的,使用啥都可以
    • 所以我们可以在2个pv文件中定义这个参数分别为:nfs1和nfs2
    • 同理,在2个pvc文件中定义这个参数分别为:nfs1和nfs2
  • 这样的话这2个pvc和pv就分别绑定起来了,pv和pvc的文件如下
[root@master volume]# cat pvtest.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs1
spec:
  capacity:
    storage: 3Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs1
  nfs:
    path: /nfs1
    server: 192.168.59.156
[root@master volume]# cat pvtest2.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs2
spec:
  capacity:
    storage: 3Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs2
  nfs:
    path: /nfs
    server: 192.168.59.156
[root@master volume]# 
[root@master volume]# cat pvctest.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ccx-pvc
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi      
  storageClassName: nfs1 

[root@master volume]# cat pvctest2.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ccx-pvc2
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi      
  storageClassName: nfs2 

[root@master volume]#

现在我们通过这4个文件分别创建pvc看效果

[root@master volume]# kubectl apply -f pvtest.yaml 
persistentvolume/pv-nfs1 created
[root@master volume]# kubectl apply -f pvtest2.yaml 
persistentvolume/pv-nfs2 created
[root@master volume]# 
[root@master volume]# kubectl apply -f pvctest.yaml 
persistentvolumeclaim/ccx-pvc created
[root@master volume]# kubectl apply -f pvctest2.yaml 
persistentvolumeclaim/ccx-pvc2 created
[root@master volume]# 
[root@master volume]# kubectl get pvc
NAME       STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc    Bound    pv-nfs1   3Gi        RWO            nfs1           68s
ccx-pvc2   Bound    pv-nfs2   3Gi        RWO            nfs2           3s
[root@master volume]#
  • 完美解决,上面可以看到我们有了ccx-pvc和ccx-pvc2这2个pvc了,这样就可以正常使用pvc名称来创建pod了哦

方式2【一个文件创建多个pv和pvc】

文件代码
  • 关于这个,我上面测试其实就已经说过了,而且代码也是之前的代码,反正原理就是,一个文件创建多个pv和pvc【pv数量和pvc要对应起来】
  • 原理呢其实就是方式1中的解决问题一样,只是这次代码不用分开文件存放而已。
    这个相比较于方式1呢,其实还不用考虑storageClassName,一样也无所谓,更nice。
[root@master volume]# cat pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs1
spec:
  capacity:
    storage: 3Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /data/nfs1
    server: 192.168.59.156

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs2
spec:
  capacity:
    storage: 3Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /data/nfs2
    server: 192.168.59.156
[root@master volume]# cat pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ccx-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi      
  storageClassName: nfs 

---

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: hero-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi      
  storageClassName: nfs 
[root@master volume]#
创建pv和pvc
  • 这样创建的话呢,就可以一次性创建出很多个pv和pvc了,很方便
#y因为代码中名称一样,所以我需要先删除之前创建的
[root@master volume]# kubectl delete pvc ccx-pvc
persistentvolumeclaim "ccx-pvc" deleted
[root@master volume]# kubectl delete pvc ccx-pvc2
persistentvolumeclaim "ccx-pvc2" deleted
[root@master volume]# kubectl delete pv pv-nfs1
persistentvolume "pv-nfs1" deleted
[root@master volume]# kubectl delete pv pv-nfs2
persistentvolume "pv-nfs2" deleted
[root@master volume]# 
# 开始创建
[root@master volume]# kubectl apply -f pv.yaml 
persistentvolume/pv-nfs1 created
persistentvolume/pv-nfs2 created
[root@master volume]# kubectl apply -f pvc.yaml 
persistentvolumeclaim/ccx-pvc created
persistentvolumeclaim/hero-pvc created
[root@master volume]# 
[root@master volume]# kubectl get pvc
NAME       STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
ccx-pvc    Bound    pv-nfs2   3Gi        RWO            nfs            8s
hero-pvc   Bound    pv-nfs1   3Gi        RWO            nfs            8s
[root@master volume]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pv-nfs1   3Gi        RWO            Recycle          Bound    volume/hero-pvc   nfs                     18s
pv-nfs2   3Gi        RWO            Recycle          Bound    volume/ccx-pvc    nfs                     18s
[root@master volume]# 
  • 上面可以看到我们有了ccx-pvc和hero-pvc这2个pvc了,这样就可以正常使用pvc名称来创建pod了哦

当pod状态不正常时,一般我们可以采用以下三种方式进行排错:

1)使用“kubectl describe pod pod名称查看pod的详细信息;
2)使用kubectl logs pod名称查看pod的日志信息;
3)使用cat /var/log/messages | grep kubelet查看对应节点kubelet系统日志;

【demo】mysql对数据持久化的应用

下面通过创建mysql容器的方式来验证Persistent volume的作用!

1)搭建NFS共享存储

本次案例直接在master节点上创建NFS存储!

[root@master ~]# yum -y install nfs-utils rpcbind
[root@master ~]# vim /etc/exports
/nfsdata *(rw,sync,no_root_squash)
[root@master ~]# systemctl start nfs-server
[root@master ~]# systemctl start rpcbind
[root@master ~]# showmount -e
Export list for master:
/nfsdata *

2)创建PV资源对象

[root@master ~]# vim mysql-pv.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain                  #注意指定的回收策略为手动回收
  storageClassName: nfs
  nfs:
    path: /nfsdata/mysql-pv
    server: 192.168.1.4
[root@master ~]# kubectl apply -f mysql-pv.yaml 
[root@master ~]# kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
test-pv   1Gi        RWO            Retain           Available           nfs                     15s
[root@master ~]# mkdir -p /nfsdata/mysql-pv 

3)创建PVC资源对象

[root@master ~]# vim mysql-pvc.yaml 
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: nfs
[root@master ~]# kubectl apply -f mysql-pvc.yaml 
[root@master ~]# kubectl get pvc
NAME        STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pvc   Bound    mysql-pv   1Gi        RWO            nfs            13s
[root@master ~]# kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
mysql-pv   1Gi        RWO            Retain           Bound    default/mysql-pvc   nfs                     8m14s

4)创建pod资源

[root@master ~]# vim mysql-pod.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: mysql-pod
spec:
  selector:                     #设置给予等值的标签选择器
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - image: mysql:5.6
        name: mysql
        env:                      #设置环境变量,数据库root用户的密码
        - name: MYSQL_ROOT_PASSWORD
          value: 123.com
        volumeMounts:
        - name: mysql-storage
          mountPath: /var/lib/mysql               #这个目录是数据库存放数据的目录(指定的是容器中的目录)
      volumes:
      - name: mysql-storage
        persistentVolumeClaim:
          claimName: mysql-pvc
[root@master ~]# kubectl apply -f mysql-pod.yaml 
[root@master ~]# kubectl get pod
NAME                         READY   STATUS    RESTARTS   AGE
mysql-pod-6cc889468b-gq4qz   1/1     Running   0          3s

5)测试数据持久化效果

[root@master ~]# kubectl exec -it mysql-pod-6cc889468b-gq4qz -- mysql -u root -p123.com
#直接登录运行mysql数据库的pod中的mysql
#插入数据进行测试
mysql> create database lzj;
mysql> use lzj;
mysql> create table my_id( id int(4) );
mysql> insert my_id values (9527);
mysql> select * from my_id;
+------+
| id   |
+------+
| 9527 |
+------+
[root@master ~]# ls /nfsdata/mysql-pv/
auto.cnf  ibdata1  ib_logfile0  ib_logfile1  lzj  mysql  performance_schema
#查看pod对应的NFS的目录,确实有了数据
[root@master ~]# kubectl get pod -o wide             #查看pod的详细信息
NAME                         READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
mysql-pod-6cc889468b-gq4qz   1/1     Running   0          23m   10.244.2.6   node02   <none>           <none>
#查看到pod是运行在node02节点上的
#模拟node02宕机,步骤省略,关机、挂起都可以!
[root@node01 ~]# systemctl restart kubelet
#重启node01的kubelet服务
#接下来耐心等待pod的转移,可能需要差不多5分钟
^C[root@master ~]# kubectl get pod  -o wide                                #可以看到pod已经运行在node01上
NAME                         READY   STATUS        RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
mysql-pod-6cc889468b-gdf7k   1/1     Running       0          66s   10.244.1.6   node01   <none>           <none>
mysql-pod-6cc889468b-gq4qz   1/1     Terminating   0          32m   10.244.2.6   node02   <none>           <none>
[root@master ~]# kubectl exec -it mysql-pod-6cc889468b-gdf7k  -- mysql -u root -p123.com
#再次登录到pod中运行的mysql(注意:pod的名称)
mysql> select * from lzj.my_id;                     #再次数据是否存在
+------+
| id   |
+------+
| 9527 |
+------+
1 row in set (0.01 sec)
#数据依旧存在
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

҉人间无事人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值