(九)Kubernetes 存储卷

网友投稿 185 2022-09-11

(九)Kubernetes 存储卷

Kubernetes存储卷概述

​​Pod​​​本身具有生命周期,这就带了一系列的问题,第一,当一个容器损坏之后,​​kubelet​​​会重启这个容器,但是文件会丢失-这个容器会是一个全新的状态;第二,当很多容器在同一​​Pod​​​中运行的时候,很多时候需要数据文件的共享。​​Docker​​​支持配置容器使用存储卷将数据持久存储于容器自身文件系统之外的存储空间之中,它们可以是节点文件系统或网络文件系统之上的存储空间。相应的,​​kubernetes​​​也支持类似的存储卷功能,不过,其存储卷是与​​Pod​​资源绑定而非容器。

简单来说,存储卷是定义在​​Pod​​​资源之上、可被其内部的所有容器挂载的共享目录,它关联至某外部的存储设备之上的存储空间,从而独立于容器自身的文件系统,而数据是否具有持久能力取决于存储卷自身是否支持持久机制。​​Pod​​、容器与存储卷的关系图如下。

Kubernetes支持的存储卷类型

​​Kubernetes​​​支持非常丰富的存储卷类型,包括本地存储(节点)和网络存储系统中的诸多存储机制,还支持​​Secret​​​和​​ConfigMap​​​这样的特殊存储资源。例如,关联节点本地的存储目录与关联​​GlusterFS​​​存储系统所需要的配置参数差异巨大,因此指定存储卷类型时也就限定了其关联到的后端存储设备。通过命令​​# kubectl explain pod.spec​​​可以查看当前​​kubernetes​​版本支持的存储卷类型。常用类型如下:非持久性存储emptyDirhostPath网络连接性存储SAN:iscsiNFS:nfs、cfs分布式存储glusterfs、cephfs、rbd云端存储awsElasticBlockStore、azureDisk、gitRepo

存储卷的使用方式

在Pod中定义使用存储卷的配置由两部分组成:一是通过​​.spec.volumes​​​字段定义在​​Pod​​​之上的存储卷列表,其支持使用多种不同类型的存储卷且配置参数差别很大;另一个是通过​​.spce.containers.volumeMounts​​​字段在容器上定义的存储卷挂载列表,它只能挂载当前​​Pod​​资源中定义的具体存储卷,当然,也可以不挂载任何存储卷。

在Pod级别定义存储卷时,​​.spec.volumes​​​字段的值为对象列表格式,每个对象为一个存储卷的定义,由存储卷名称(​​.spec.volumes.name ​​​)或存储卷对象(​​.spec.volumes.VOL_TYPE ​​​)组成,其中VOL_TYPE是使用的存储卷类型名称,它的内嵌字段随类型的不同而不同。下面示例定义了由两个存储卷组成的卷列表,一个为​​emptyDir​​​类型,一个是​​gitRepo​​类型。

......volumes:- name: data emptyDir: {}- name: example gitRepo: repository: revision: master directory:

无论何种类型的存储卷,挂载格式基本上都是相同的,通过命令​​# kubectl explain pod.spec.containers.volumeMounts​​ 可以进行查看。在容器中顶一个挂载卷时的通用语法形式如下:

......volumeMounts:- name -required- #指定要挂载的存储卷的名称,必选字段 mountPath -required- #挂载点路径,容器文件系统的路径,必选字段 readOnly #是否挂载为只读卷 subPath #挂载存储卷时使用的子路径,及mountPath指定的路径下使用一个子路径作为其挂载点。

示例,容器​​myapp​​​将上面定义的​​data​​​存储卷挂载于​​/var/log/myapp​​​,将​​examply​​​挂载到​​/webdata/example​​目录。

spec: containers: - name: myapp image: ikubernetes/myapp:v1 volumeMounts: - name: data mountPath: /var/log/myapp/ - name: example mountPath: /webdata/example/

存储卷使用示例

下面的所有示例的资源清单文件都放在新建的​​storage​​目录中。

[root@k8s-master ~]# mkdir storage[root@k8s-master ~]# cd storage/

emptyDir 存储卷

​​emptyDir​​​存储卷是​​Pod​​​对象生命周期中的一个临时目录,类似于​​Docker​​​上的​​“docker 挂载卷”​​​,在​​Pod​​​对象启动时即被创建,而在​​Pod​​​对象被移除时会被一并删除(永久删除)。​​Pod​​​中的容器都可以读写这个目录,这个目录可以被挂载到各个容器相同或者不相同的路径下。注意:一个容器崩溃了不会导致数据的丢失,因为容器的崩溃并不移除​​Pod​​。emptyDir的作用:普通空间,基于磁盘的数据存储作为从崩溃中恢复的备份点存储那些需要长久保存的数据,例如​​web​​服务中的数据

emptyDir字段说明:

[root@k8s-master ~]# kubectl explain pod.spec.volumes.emptyDirmedium : #此目录所在的存储介质的类型,可取值为“default”或“Memory”,默认为default,表示使用节点的的默认存储介质;Memory表示使用基于RAM的临时的文件系统temfs,空间受限于内存,但性能非常好,通常用于为容器中的应用提供缓存空间。sizeLimit #当前存储卷的空间限额,默认值为nil,表示不限制;不过,在medium字段值为“Memory”时建议务必定义此限额。

emptyDir示例:

这里定义了一个​​Pod​​​资源对象(​​vol-emptydir-pod​​​),在其内部定义了两个容器,其中一个容器是辅助容器​​sidecar​​​,每隔10秒生成一行信息追加到​​index.html​​​文件中;另一个是​​nginx​​​容器,将存储卷挂载到站点家目录。然后访问​​nginx​​​的​​html​​​页面验证两个容器之间挂载的​​emptyDir​​实现共享。

1)编辑资源清单文件

[root@k8s-master storage]# vim vol-emptydir.yamlapiVersion: v1kind: Podmetadata: name: vol-emptydir-podspec: volumes: #定义存储卷 - name: html #定义存储卷的名称 emptyDir: {} #定义存储卷的类型 containers: - name: nginx image: nginx:1.12 volumeMounts: #在容器中定义挂载存储卷的名和路径 - name: html mountPath: /usr/share/nginx/html - name: sidecar image: alpine volumeMounts: #在容器中定义挂载存储卷的名和路径 - name: html mountPath: /html command: ["/bin/sh", "-c"] args: - while true; do echo $(hostname) $(date) >> /html/index.html; sleep 10; done

2)创建并查看状态

[root@k8s-master storage]# kubectl apply -f vol-emptydir.yaml pod/vol-emptydir-pod created[root@k8s-master storage]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESvol-emptydir-pod 2/2 Running 0 63s 10.244.2.79 k8s-node2

3)访问测试

[root@k8s-master storage]# curl 10.244.2.79vol-emptydir-pod Wed Oct 9 03:32:43 UTC 2019vol-emptydir-pod Wed Oct 9 03:32:53 UTC 2019vol-emptydir-pod Wed Oct 9 03:33:03 UTC 2019vol-emptydir-pod Wed Oct 9 03:33:13 UTC 2019vol-emptydir-pod Wed Oct 9 03:33:23 UTC 2019......#进入vol-emptydir-pod中的sidecar容器中查看挂载目录下的index.html文件[root@k8s-master storage]# kubectl exec vol-emptydir-pod -c sidecar -it -- /bin/sh/ # ls bin etc html media opt root sbin sys usrdev home lib mnt proc run srv tmp var/ # ls /htmlindex.html/ # cat /html/index.html vol-emptydir-pod Wed Oct 9 03:32:43 UTC 2019vol-emptydir-pod Wed Oct 9 03:32:53 UTC 2019vol-emptydir-pod Wed Oct 9 03:33:03 UTC 2019......#进入vol-emptydir-pod中的nginx容器中查看挂载目录下的index.html文件[root@k8s-master storage]# kubectl exec vol-emptydir-pod -c nginx -it -- /bin/sh# cat /usr/share/nginx/html/index.htmlvol-emptydir-pod Wed Oct 9 03:32:43 UTC 2019vol-emptydir-pod Wed Oct 9 03:32:53 UTC 2019vol-emptydir-pod Wed Oct 9 03:33:03 UTC 2019......

hostPath 存储卷

​​hostPath​​​类型的存储卷是指将工作节点上的某文件系统的目录或文件挂载于​​Pod​​​中的一种存储卷,独立于​​Pod​​​资源的生命周期,具有持久性。在​​Pod​​删除时,数据不会丢失。

hostPath字段说明:

[root@k8s-master storage]# kubectl explain pod.spec.volumes.hostPathpath -required- #指定工作节点上的目录路径type #指定存储卷类型type类型如下:DirectoryOrCreate 指定的路径不存在时自动创建其权限为0755的空目录,属主和属组为kubeletDirectory 必须存在的目录路径FileOrCreate 指定的路径不存在时自动创建其权限为0644的空文件,属主和属组为kubeletFile 必须存在的文件路径Socket 必须存在的Socket文件路径CharDevice 必须存在的字符设备文件路径BlockDevice 必须存在的块设备文件路径

hostPath示例:

1)编辑资源清单文件

[root@k8s-master storage]# vim vol-hostpath.yamlapiVersion: v1kind: Podmetadata: name: pod-vol-hostpath namespace: defaultspec: containers: - name: myapp image: nginx:1.15 imagePullPolicy: IfNotPresent volumeMounts: - name: html mountPath: /usr/share/nginx/html volumes: - name: html hostPath: path: /data/pod/volume1 type: DirectoryOrCreate

2)创建并查看状态

[root@k8s-master storage]# kubectl apply -f vol-hostpath.yaml pod/vol-hostpath-pod created[root@k8s-master storage]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESvol-hostpath-pod 1/1 Running 0 7s 10.244.1.83 k8s-node1

3)通过上面查看pod被调度到节点1上面,查看节点1的目录并创建测试文件

[root@k8s-node1 ~]# ll /data/pod/volume1/总用量 0[root@k8s-node1 ~]# echo "

kubernetes hostPath test

" >> /data/pod/volume1/index.html

4)访问测试,及删除测试

[root@k8s-master storage]# curl 10.244.1.83

kubernetes hostPath test

#删除pod资源再次查看节点1上面的文件[root@k8s-master storage]# kubectl delete -f vol-hostpath.yaml pod "vol-hostpath-pod" deleted[root@k8s-node1 ~]# ll /data/pod/volume1/总用量 4-rw-r--r-- 1 root root 34 10月 9 16:09 index.html

nfs 存储卷

​​nfs​​​存储卷用于将事先存在的​​NFS​​​服务器上导出的存储空间挂载到​​Pod​​​中供容器使用。与​​emptyDir​​​不同的是,当​​pod​​​资源删除时​​emptyDir​​​也会被删除,而​​NFS​​​在​​Pod​​​对象删除时仅是被卸载而非删除。这就意味​​NFS​​​能够允许我们提前对数据进行处理,而且这些数据可以在​​Pod​​​之间相互传递,并且​​NFS​​​可以同时被多个​​Pod​​挂载并进行读写。

nfs字段说明:

[root@k8s-master ~]# kubectl explain pod.spec.volumes.nfsserver -required- #NFS服务器的IP地址或主机名,必选字段path -required- #NFS服务器导出(共享)的文件系统路径,必选字段readOnly #是否以只读方式挂载,默认为false

nfs示例:

1)首先准备一个nfs服务器

[root@storage ~]# yum -y install nfs-utils #安装软件[root@storage ~]# mkdir -p /data/k8s/v1 #创建共享目录[root@storage ~]# vim /etc/exports #编辑配置文件配置共享目录/data/k8s/v1 192.168.1.0/24(rw,no_root_squash)[root@storage ~]# systemctl start rpcbind #启动rpcbind服务(nfs依赖服务)[root@storage ~]# systemctl start nfs #启动nfs[root@k8s-node1 ~]# showmount -e 192.168.1.34 #k8s节点测试能否正常访问到nfs服务器Export list for 192.168.1.34:/data/k8s/v1 192.168.1.0/24

2)编辑资源清单文件

[root@k8s-master storage]# vim vol-nfs.yaml

3)创建并查看状态

[root@k8s-master storage]# kubectl apply -f vol-nfs.yaml pod/vol-nfs-pod created[root@k8s-master storage]# kubectl get pods NAME READY STATUS RESTARTS AGEvol-nfs-pod 1/1 Running 0 45s[root@k8s-master storage]# kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESvol-nfs-pod 1/1 Running 0 51s 10.244.2.80 k8s-node2

4)测试验证

[root@k8s-master storage]# kubectl exec -it vol-nfs-pod redis-cli127.0.0.1:6379> set mykey "hello test"OK127.0.0.1:6379> get mykey"hello test127.0.0.1:6379> bgsave Background saving started127.0.0.1:6379> exit#为了测试其数据持久化效果,下面删除Pod资源vol-nfs-pod,并于再次重新创建后检测数据是否依然能够访问[root@k8s-master storage]# kubectl delete -f vol-nfs.yaml pod "vol-nfs-pod" deleted[root@k8s-master storage]# kubectl apply -f vol-nfs.yaml pod/vol-nfs-pod created[root@k8s-master storage]# kubectl get pods -o wideNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESvol-nfs-pod 1/1 Running 0 47s 10.244.1.84 k8s-node1 [root@k8s-master storage]# kubectl exec -it vol-nfs-pod redis-cli127.0.0.1:6379> get mykey"hello test"127.0.0.1:6379>

通过上面测试可以看出,此前创建的​​mykey​​​及其数据在​​Pod​​​资源重建后依然存在,且不论​​pod​​​资源调度到哪个节点。这表明在删除​​Pod​​资源时,其关联的外部存储卷并不会被一同删除。如果需要删除此类的数据,需要用户通过存储系统的管理接口手动进行。

PVC与PV

介绍

前面提到​​Kubernetes​​​提供那么多存储接口,但是首先​​Kubernetes​​​的各个​​Node​​​节点能管理这些存储,但是各种存储参数也需要专业的存储工程师才能了解,由此我们的​​Kubernetes​​​管理变的更加复杂。由此​​kubernetes​​​提出了​​PV​​​和​​PVC​​的概念,这样开发人员和使用者就不需要关注后端存储是什么,使用什么参数等问题。如下图:

PV:

​​PersistentVolume​​​(​​PV​​​)是集群中已由管理员配置的一段网络存储。集群中的资源就像一个节点是一个集群资源。​​PV​​​是诸如卷之类的卷插件,但是具有独立于使用​​PV​​​的任何单个​​Pod​​​的生命周期。该​​API​​​对象捕获存储的实现细节,即​​NFS​​​,​​ISCSI​​或云提供商特定的存储系统。

PVC:

​​PersistentVolumeClaim​​​(​​PVC​​​)是用户存储的请求。它类似于​​Pod​​​。​​Pod​​​消耗节点资源,​​PVC​​​消耗存储资源。​​Pod​​​可以请求特定级别的资源(​​CPU​​和内存)。权限要求可以请求特定的大小和访问模式。虽然​​PersistentVolumeClaims​​​允许用户使用抽象存储资源,但是常见的是,用户需要具有不同属性(如性能)的​​PersistentVolumes​​​,用于不同的问题。集群管理员需要能够提供多种不同于​​PersistentVolumes​​​的​​PersistentVolumes​​​,而不仅仅是大小和访问模式,而不会使用户了解这些卷的实现细节。对于这些需求,存在​​StorageClass​​资源。​​StorageClass​​​为管理员提供了一种描述他们提供的存储的“类”的方法。不同的类可能映射到服务质量级别,或备份策略,或者由集群管理员确定的任意策略。​​Kubernetes​​本身对于什么类别代表是不言而喻的。这个概念有时在其它存储系统中称为“配置文件”

生命周期

​​PV​​​是集群中的资源。​​PVC​​​是对这些资源的请求,也是对资源的索赔检查。​​PV​​​和​​PVC​​之间的相互作用遵循这个生命周期:​​Provisioning—>Binding—>Using—>Releasing—>Recycling​​

供应准备Provisioning

绑定Binding

用户创建​​PVC​​​并指定需要的资源和访问模式。在找到可用​​PV​​​之前,​​PVC​​会保持未绑定状态。

使用Using

用户可在​​Pod​​​中像​​volume​​​一样使用​​PVC​​。

释放Releasing

用户删除​​PVC​​​来回收存储资源,​​PV​​​将变成​​“released”​​​状态。由于还保留着之前的数据,这些数据要根据不同的策略来处理,否则这些存储资源无法被其它​​PVC​​使用

回收Recycling

​​PV​​​可以设置三种回收策略:保留(​​Retain​​​)、回收(​​Recycle​​​)和删除(​​Delete​​)。

创建PV

字段说明:

​​PersistentVolume Spec​​​主要支持以下几个通用字段,用于定义​​PV​​的容量、访问模式、和回收策略

[root@k8s-master ~]# kubectl explain pv.speccapacity #当前PV的容量;目前,capacity仅支持空间设定,将来应该还可以指定IOPS和throughput。accessModes <[]string> #访问模式;尽管在PV层看起来并无差异,但存储设备支持及启用的功能特性却可能不尽相同。例如NFS存储支持多客户端同时挂载及读写操作,但也可能是在共享时仅启用了只读操作,其他存储系统也存在类似的可配置特性。因此,PV底层的设备或许存在其特有的访问模式,用户使用时必须在其特性范围内设定其功能。参考: - ReadWribeOnce:仅可被单个节点读写挂载;命令行中简写为RWO。 - ReadOnlyMany:可被多个节点同时只读挂载;命令行中简写为ROX。 - ReadWriteMany:可被多个节点同时读写挂载;命令行中简写为RWX。 persistentVolumeReclaimPolicy #PV空间被释放时的处理机制;可用类型仅为Retain(默认)、Recycle或Delete,具体说明如下。 - Retain:保持不动,由管理员随后手动回收。 - Recycle:空间回收,即删除存储卷目录下的所有文件(包括子目录和隐藏文件),目前仅NFS和hostPath支持此操作。 - Delete:删除存储卷,仅部分云端存储系统支持,如AWS EBS、GCE PD、Azure Disk和CindervolumeMode #卷模型,用于指定此卷可被用作文件系统还是裸格式的块设备;默认为Filesystem。storageClassName #当前PV所属的StorageClass的名称;默认为空值,即不属于任何StorageClass。mountOptions <[]string> #挂载选项组成的列表,如ro、soft和hard等。

创建PVC

字段说明:

​​PersistentVolumeClaim​​​是存储卷类型的资源,它通过申请占用某个​​PersistentVolume​​​而创建,它与​​PV​​​是一对一的关系,用户无须关系其底层实现细节。申请时,用户只需要指定目标空间的大小、访问模式、​​PV​​​标签选择器和​​StorageClass​​​等相关信息即可。​​PVC​​​的​​Spec​​字段的可嵌套字段具体如下:

[root@k8s-master ~]# kubectl explain pvc.specaccessModes <[]string> #当前PVC的访问模式,其可用模式与PV相同resources #当前PVC存储卷需要占用的资源量最小值;目前,PVC的资源限定仅指其空间大小selector #绑定时对PV应用的标签选择器(matchLabels)或匹配条件表达式(matchEx-pressions),用于挑选要绑定的PV;如果同时指定了两种挑选机制,则必须同时满足两种选择机制的PV才能被选出storageClassName #所依赖的存储卷的名称volumeMode #卷模型,用于指定此卷可被用作于文件系统还是裸格式的块设备;默认为“Filesystem”volumeName #用于直接指定要绑定的PV的卷名

在Pod中使用PVC

在​​Pod​​​资源中调用​​PVC​​​资源,只需要在定义​​volumes​​​时使用​​persistentVolumeClaims​​字段嵌套指定两个字段即可。具体如下:

[root@k8s-master ~]# kubectl explain pod.spec.volumes.persistentVolumeClaimclaimName -required- #要调用的PVC存储卷的名称,PVC卷要与Pod在同一名称空间中readOnly #是否将存储卷挂载为只读模式,默认为false。

示例使用PVC和PV

说明:下面示例中,准备了一台​​NFS Server​​​创建了几个共享目录提供给​​Kubernetes​​​作为​​PV​​​使用。在创建​​PV​​​的同时指定了不同的大小和不同的访问权限,然后在创建​​PVC​​​时候指定了大小为​​6Gi​​​,故满足条件的​​PV​​​只有​​pv003~pv005​​​,这里通过标签选择器选择了​​pv003​​​。Pod中的容器使用了​​MySQL​​​,并将​​MySQL​​​的数据目录挂载到​​PV​​上。示例图如下:

1)准备​​NFS​​服务

(1)创建存储卷对应的目录[root@storage ~]# mkdir /data/volumes/v{1..5} -p(2)修改nfs的配置文件[root@storage ~]# vim /etc/exports/data/volumes/v1 192.168.1.0/24(rw,no_root_squash)/data/volumes/v2 192.168.1.0/24(rw,no_root_squash)/data/volumes/v3 192.168.1.0/24(rw,no_root_squash)/data/volumes/v4 192.168.1.0/24(rw,no_root_squash)/data/volumes/v5 192.168.1.0/24(rw,no_root_squash)(3)查看nfs的配置[root@storage ~]# exportfs -arvexporting 192.168.1.0/24:/data/volumes/v5exporting 192.168.1.0/24:/data/volumes/v4exporting 192.168.1.0/24:/data/volumes/v3exporting 192.168.1.0/24:/data/volumes/v2exporting 192.168.1.0/24:/data/volumes/v1(4)使配置生效[root@storage ~]# showmount -eExport list for storage:/data/volumes/v5 192.168.1.0/24/data/volumes/v4 192.168.1.0/24/data/volumes/v3 192.168.1.0/24/data/volumes/v2 192.168.1.0/24/data/volumes/v1 192.168.1.0/24

2)创建​​PV​​​;这里创建​​5​​​个​​PV​​,存储大小各不相等,是否可读也不相同

(1)编写资源清单文件[root@k8s-master storage]# vim pv-nfs-demo.yamlapiVersion: v1kind: PersistentVolumemetadata: name: pv-nfs-001 labels: name: pv001spec: nfs: path: /data/volumes/v1 server: 192.168.1.34 readOnly: false accessModes: ["ReadWriteOnce","ReadWriteMany"] capacity: storage: 2Gi persistentVolumeReclaimPolicy: Retain---apiVersion: v1kind: PersistentVolumemetadata: name: pv-nfs-002 labels: name: pv002spec: nfs: path: /data/volumes/v2 server: 192.168.1.34 readOnly: false accessModes: ["ReadWriteOnce"] capacity: storage: 5Gi persistentVolumeReclaimPolicy: Retain---apiVersion: v1kind: PersistentVolumemetadata: name: pv-nfs-003 labels: name: pv003spec: nfs: path: /data/volumes/v3 server: 192.168.1.34 readOnly: false accessModes: ["ReadWriteOnce","ReadWriteMany"] capacity: storage: 10Gi persistentVolumeReclaimPolicy: Retain---apiVersion: v1kind: PersistentVolumemetadata: name: pv-nfs-004 labels: name: pv004spec: nfs: path: /data/volumes/v4 server: 192.168.1.34 readOnly: false accessModes: ["ReadWriteOnce","ReadWriteMany"] capacity: storage: 15Gi persistentVolumeReclaimPolicy: Retain---apiVersion: v1kind: PersistentVolumemetadata: name: pv-nfs-005 labels: name: pv005spec: nfs: path: /data/volumes/v5 server: 192.168.1.34 readOnly: false accessModes: ["ReadWriteOnce","ReadWriteMany"] capacity: storage: 20Gi persistentVolumeReclaimPolicy: Retain (2)创建PV[root@k8s-master storage]# kubectl apply -f pv-nfs-demo.yaml persistentvolume/pv-nfs-001 createdpersistentvolume/pv-nfs-002 createdpersistentvolume/pv-nfs-003 createdpersistentvolume/pv-nfs-004 createdpersistentvolume/pv-nfs-005 created(3)查看PV[root@k8s-master storage]# kubectl get pvNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEpv-nfs-001 2Gi RWO,RWX Retain Available 2spv-nfs-002 5Gi RWO Retain Available 2spv-nfs-003 10Gi RWO,RWX Retain Available 2spv-nfs-004 15Gi RWO,RWX Retain Available 2spv-nfs-005 20Gi RWO,RWX Retain Available 2s

3)创建​​PVC​​​,绑定​​PV​​

(1)编写资源清单文件[root@k8s-master storage]# vim vol-nfs-pvc.yaml#创建PVCapiVersion: v1kind: PersistentVolumeClaimmetadata: name: nfs-pvcspec: accessModes: ["ReadWriteMany"] resources: requests: storage: 6Gi #指定PVC大小为6Gi selector: #这里通过标签选择器指定了所使用的pv卷为key为name,value为pv003的pv资源 matchLabels: name: pv003---#创建PodapiVersion: v1kind: Podmetadata: name: pvc-mysql labels: app: mysqlspec: containers: - name: pvc-mysql-pod image: mysql:latest imagePullPolicy: IfNotPresent ports: - name: mysqlport containerPort: 3306 volumeMounts: - name: mysqldata mountPath: /var/lib/mysql env: - name: MYSQL_ROOT_PASSWORD value: "mysql" volumes: - name: mysqldata persistentVolumeClaim: #通过该字段定义使用pvc claimName: nfs-pvc #指定pvc的名称 readOnly: false #关闭只读(2)创建PVC和Pod[root@k8s-master storage]# kubectl apply -f vol-nfs-pvc.yaml persistentvolumeclaim/nfs-pvc createdpod/pvc-mysql created

4)查询验证​​pv​​​和​​pvc​​

[root@k8s-master storage]# kubectl get pvc #查看pvc,可以看到该pvc使用的是pv-nfs-003资源NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGEnfs-pvc Bound pv-nfs-003 10Gi RWO,RWX 12s[root@k8s-master storage]# kubectl get pv #查看pv,可以看出pv-nfs-003资源的状态从Availabel变成了BoundNAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGEpv-nfs-001 2Gi RWO,RWX Retain Available 64mpv-nfs-002 5Gi RWO Retain Available 64mpv-nfs-003 10Gi RWO,RWX Retain Bound default/nfs-pvc 64mpv-nfs-004 15Gi RWO,RWX Retain Available 64mpv-nfs-005 20Gi RWO,RWX Retain Available 64m[root@k8s-master storage]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATESpvc-mysql 1/1 Running 0 31s 10.244.2.84 k8s-node2 [root@storage ~]# ls /data/volumes/v3/ #查看nfs服务器的pv3对应的共享目录,里面生成了mysql的数据。auto.cnf ca-key.pem ib_buffer_pool ibtmp1 performance_schema server-key.pembinlog.000001 ca.pem ibdata1 #innodb_temp private_key.pem sysbinlog.000002 client-cert.pem ib_logfile0 mysql public_key.pem undo_001binlog.index client-key.pem ib_logfile1 mysql.ibd server-cert.pem undo_002

5)测试验证

#(1)进入到pod连接容器mysql并创建一个数据库[root@k8s-master ~]# kubectl exec -it pvc-mysql -- mysql -u root -pmysql......mysql> mysql> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || sys |+--------------------+4 rows in set (0.01 sec)mysql> create database volumes;Query OK, 1 row affected (0.00 sec)mysql> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || sys || volumes |+--------------------+5 rows in set (0.00 sec)mysql> exitBye#(2)删除pvc和pod和pv[root@k8s-master storage]# kubectl delete -f vol-nfs-pvc.yaml #删除pvcpersistentvolumeclaim "nfs-pvc" deletedpod "pvc-mysql" deleted[root@k8s-master storage]# kubectl delete -f pv-nfs-demo.yaml #删除pv(如果有pv在被使用的状态,需要先删除pvc方可删除pv)persistentvolume "pv-nfs-001" deletedpersistentvolume "pv-nfs-002" deletedpersistentvolume "pv-nfs-003" deletedpersistentvolume "pv-nfs-004" deletedpersistentvolume "pv-nfs-005" deleted[root@storage ~]# ls /data/volumes/v3/ #上面删除了pv和pvc,可以看出存储服务器上面的数据还是存在auto.cnf ca-key.pem ib_buffer_pool ibtmp1 performance_schema server-key.pem volumesbinlog.000001 ca.pem ibdata1 #innodb_temp private_key.pem sysbinlog.000002 client-cert.pem ib_logfile0 mysql public_key.pem undo_001binlog.index client-key.pem ib_logfile1 mysql.ibd server-cert.pem undo_002#(3)重新创建pv和pvc和pod验证数据[root@k8s-master storage]# kubectl apply -f pv-nfs-demo.yaml persistentvolume/pv-nfs-001 createdpersistentvolume/pv-nfs-002 createdpersistentvolume/pv-nfs-003 createdpersistentvolume/pv-nfs-004 createdpersistentvolume/pv-nfs-005 created[root@k8s-master storage]# kubectl apply -f vol-nfs-pvc.yaml persistentvolumeclaim/nfs-pvc createdpod/pvc-mysql created[root@k8s-master ~]# kubectl exec -it pvc-mysql -- mysql -u root -pmysqlmysql> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || sys || volumes |+--------------------+5 rows in set (0.00 sec)###测试说明:如果删除pvc不删除pv,重新创建同样的pvc,那么pvc状态会处于Pending状态,因为pv的当前状态为Released。这也和上面定义的回收策略息息相关。

人生是条无名的河,是浅是深都要过; 人生是杯无色的茶,是苦是甜都要喝; 人生是首无畏的歌,是高是低都要唱。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:(八)Kubernetes Ingress资源
下一篇:“五一”出游,避开这些不良营销的“坑”!
相关文章

 发表评论

暂时没有评论,来抢沙发吧~