k8s进阶-持久化基础 十八岁 2024-12-26 2024-12-26
1.持久化存储 1.1Volumes介绍 官方介绍:https://kubernetes.io/zh-cn/docs/concepts/storage/volumes/
Volumes是Kubernetes中的一个抽象概念,本质上是一个可以被Pod中容器访问的目录。它解决了容器中文件系统的临时性问题,使数据可以在容器重启后依然保持。
Volumes主要有以下几个用途:
数据持久化:保证容器重启后数据不丢失。
容器间数据共享:同一Pod中的多个容器可以访问同一个Volume。
扩展容器存储能力:可以将外部存储挂载到容器中。
配置注入:可以将配置文件以Volume的形式挂载到容器中。
1.1.1EmptyDir实现数据共享 emptyDir是一种临时存储卷,具有以下特点:
当Pod被分配到某个节点上时创建,初始内容为空。
与Pod的生命周期绑定,当Pod从节点上移除时,emptyDir中的数据会被永久删除。
可以存储在节点的任何介质上,如磁盘、SSD或网络存储,也可以设置为存储在内存中。
Pod中的所有容器都可以读写emptyDir卷中的相同文件。
案例:使用emptyDir实现同一个pod中多个容器数据共享
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 [root@k8s-master01 pra]# cat nginx-deployment.yaml apiVersion: apps/v1 #指定这个资源使用的 Kubernetes API 版本,固定写法 kind: Deployment #指定资源类型是 Deployment。 metadata: # deployment的元数据 name: nginx-deployment # 创建的deployment的名字 labels: #键值对标签,用于资源的分类和选择 app: nginx #给这个deployment资源打上'app: nginx'标签 spec: #描述 Deployment 的期望状态,定义 Deployment 的具体配置和行为。 replicas: 1 # 指定需要运行的 Pod 副本数量。 selector: #选择器,用于选择哪些pod属于这个deployment matchLabels: #匹配标签,选择带有特定标签的pod app: nginx #指定带有' app: nginx '标签的pod进行管理 template: # pod的模板,用于定义pod metadata: #pod的元数据 labels: #标签,配置pod的标签 app: nginx #确保创建的 Pod 具有'app: nginx' 标签。 spec: #描述pod的期望状态,定义pod的具体配置和行为 volumes: #定义pod中所有可用的卷 - name: emtydir #定义了一个名为emtydir的卷 emptyDir: {} #这个 emptyDir 卷在Pod启动时被创建,并且在Pod被删除时也会被删除。它本质上是一个临时存储,数据仅在Pod的生命周期内有效。 containers: #容器列表,复数,可配置多个容器 - name: nginx #容器的名称 image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #定义容器使用的镜像 volumeMounts: #定义了容器中挂载卷的位置 - name: emtydir #指定挂载的卷名为 emtydir mountPath: /opt #指定该卷挂载到容器内的 /opt 目录。 - name: nginx1 image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine command: - sh - -c - sleep 3600 volumeMounts: - name: emtydir mountPath: /data # 创建这个deployment [root@k8s-master01 pra]# kubectl replace -f nginx-deployment.yaml deployment.apps/nginx-deployment replaced # 在nginx的/opt目录中创建一个名字是test.log文件,验证在nginx1这个容器的/data是否存在这个test.log文件 [root@k8s-master01 pra]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-deployment-56c677c5df-9l94l 2/2 Running 0 112s # 进入第一个容器中创建文件 [root@k8s-master01 pra]# kubectl exec -ti nginx-deployment-56c677c5df-9l94l -c nginx -- sh / # touch /opt/text.log / # ls -l /opt/ total 0 -rw-r--r-- 1 root root 0 Aug 4 07:19 text.log # 进入nginx1容器的/data目录中验证是否有text.log [root@k8s-master01 pra]# kubectl exec -ti nginx-deployment-56c677c5df-9l94l -c nginx1 -- sh / # ls /data/ -l total 0 -rw-r--r-- 1 root root 0 Aug 4 07:19 text.log / # echo 'hello kubernetes' > /data/text.log #向文件中追加内容,然后去nginx容器中查看是否有改内容 # 进入nginx容器中 [root@k8s-master01 pra]# kubectl exec -ti nginx-deployment-56c677c5df-9l94l -c nginx -- sh / # cat /opt/text.log hello kubernetes #可以看到内容存在,实现了容器间数据共享
总结:用于多个容器之间的数据共享,同一个pod中a容器创建的数据在b容器中能获取到,与Pod的生命周期绑定,当Pod从节点上移除时,emptyDir中的数据会被永久删除。主要用于数据共享,而不是存储数据
1.1.2hostPath hostPath卷能将主机节点文件系统上的文件或目录挂载到Pod中。它允许Pod访问宿主机上的文件系统。并不推荐使用,因为创建的pod并不能保证创建在同一个节点上,当然也可以使用其他手段让pod创建在某个节点上
使用hostPath的示例:将宿主机上/data/log.txt文件挂载到容器中的/liujunwei/log.txt文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 [root@k8s-master01 pra]# vim nginx-deployment.yaml apiVersion: apps/v1 #指定这个资源使用的 Kubernetes API 版本,固定写法 kind: Deployment #指定资源类型是 Deployment。 metadata: # deployment的元数据 name: nginx-deployment # 创建的deployment的名字 labels: #键值对标签,用于资源的分类和选择 app: nginx #给这个deployment资源打上'app: nginx'标签 spec: #描述 Deployment 的期望状态,定义 Deployment 的具体配置和行为。 replicas: 1 # 指定需要运行的 Pod 副本数量。 selector: #选择器,用于选择哪些pod属于这个deployment matchLabels: #匹配标签,选择带有特定标签的pod app: nginx #指定带有' app: nginx '标签的pod进行管理 template: # pod的模板,用于定义pod metadata: #pod的元数据 labels: #标签,配置pod的标签 app: nginx #确保创建的 Pod 具有'app: nginx' 标签。 spec: #描述pod的期望状态,定义pod的具体配置和行为 nodeSelector: valume: hostpath volumes: #定义pod中所有可用的卷 - name: my-hostpath #定义了一个名字是my-hostpath的卷,用于在volumeMounts中引用。 hostPath: #卷类型,hostPath表示允许pod访问宿主机上的文件或目录 path: /data/log.txt #定义要挂载的宿主机文件路径 type: File #定义挂载的是文件,表示该路径必须是一个文件。(也可以是目录类型Directory) containers: #容器列表,复数,可配置多个容器 - name: nginx #容器的名称 image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #定义容器使用的镜像 volumeMounts: #定义如何使用卷 - name: my-hostpath #引用卷的名称是my-hostPath,该字段必须与volumes.name字段相同 mountPath: /liujunwei/log.txt #定义容器内的挂载路径 # 创建这个deploy [root@k8s-master01 pra]# kubectl replace -f nginx-deployment.yaml deployment.apps/nginx-deployment replaced # 查看创建的pod [root@k8s-master01 pra]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-deployment-676d4d6b7d-8zrn4 1/1 Running 0 6m # 进入该pod的nginx容器中查看是否存在/liujunwei/log.txt文件 [root@k8s-master01 pra]# kubectl exec -ti nginx-deployment-5bb8d84d8f-q2wpz -c nginx -- sh / # cat /liujunwei/liujunwei.log hello # 在上述案例中,是将宿主机的/data/log.txt文件挂载到容器的/liujunwei/liujunwei.log文件,在容器内liujunwei.log文件的内容是宿主机上log.txt文件的内容
hostPath卷有两个主要参数:
path: 指定宿主机上的文件或目录路径(必需)
type: 指定挂载类型(可选)
type支持的值包括:
DirectoryOrCreate: 如果路径不存在,则创建空目录
Directory: 必须存在的目录,是指每个运行pod的节点上都必须存在
FileOrCreate: 如果文件不存在,则创建空文件
File: 必须存在的文件,是指每个运行pod的节点上都必须存在
Socket: 必须存在的UNIX套接字
CharDevice: 必须存在的字符设备
BlockDevice: 必须存在的块设备
1.1.3挂载NFS至容器 1.1.3.1安装nfs服务 在使用nfs前需要先准备一台nfs服务器,这里用一台新机器作为nfs服务器,ip地址为192.168.0.106,主机名为:nfs-server。不占用k8s集群的五个节点资源。
在nfs-server机器上安装nfs服务端:
1 [root@nfs-server ~]# yum -y install rpcbind nfs-utils
启动服务并开机自启
1 2 3 4 5 [root@nfs-server ~]# systemctl start nfs-server^C [root@nfs-server ~]# systemctl enable nfs-server Created symlink from /etc/systemd/system/multi-user.target.wants/nfs-server.service to /usr/lib/systemd/system/nfs-server.service. [root@nfs-server ~]# systemctl enable rpcbind.service
创建共享目录:
1 2 mkdir -p /data/nfs/ chmod 755 -R /data/nfs/
编辑配置文件,配置谁能访问共享目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 vim /etc/exports # 在文件中假如下面配置 /data/nfs/ 192.168.0.0/24(rw,no_root_squash,no_all_squash,sync) 这行代码的意思是把共享目录/data/share/共享给192.168.0.0/24网段,表示该网段的机器都能访问该目录。 后面括号里的内容是权限参数,其中: rw 表示设置目录可读写。 sync 表示数据会同步写入到内存和硬盘中,相反 rsync 表示数据会先暂存于内存中,而非直接写入到硬盘中。 no_root_squash NFS客户端连接服务端时如果使用的是root的话,那么对服务端分享的目录来说,也拥有root权限。 no_all_squash 不论NFS客户端连接服务端时使用什么用户,对服务端分享的目录来说都不会拥有匿名用户权限。 如果有多个共享目录配置,则使用多行,一行一个配置。保存好配置文件后,需要执行以下命令使配置立即生效: [root@nfs-server ~]# exportfs -r
重启服务:
1 2 systemctl restart rpcbind systemctl restart nfs
重启后执行showmount 命令来查看服务端(本机)是否可连接:
1 2 3 [root@nfs-server ~]# showmount -e localhost Export list for localhost: /data/nfs 192.168.0.0/24
出现上面结果表明NFS服务端配置正常。
在需要挂载的机器节点上挂载测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 # 客服端挂载服务端的共享目录,前提客服端需要安装nfs客户端 # 这里在k8s-master01机器上挂载测试,所以在k8s-master01上安装客户端 [root@k8s-master01 ~]# yum -y install nfs-utils # 查看nfs服务器可挂载的共享目录,nfs服务器ip是192.168.0.106 [root@k8s-master01 ~]# showmount -e 192.168.0.106 Export list for 192.168.0.106: /data/nfs 192.168.0.0/24 # 挂载测试 [root@k8s-master01 ~]# mount -t nfs 192.168.0.106:/data/nfs /mnt/nfs/ [root@k8s-master01 ~]# df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 2.0G 0 2.0G 0% /dev tmpfs 2.0G 0 2.0G 0% /dev/shm tmpfs 2.0G 92M 1.9G 5% /run tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup /dev/mapper/centos_k8s--master01-root 17G 6.7G 11G 39% / /dev/sda1 1014M 170M 845M 17% /boot tmpfs 393M 0 393M 0% /run/user/0 192.168.0.106:/data/nfs 46G 2.7G 43G 6% /mnt/nfs #该目录是新挂载的 # 在/mnt/nfs目录创建文件,去nfs服务器(192.168.0.106)的/data/nfs目录查看是否存在 # 文件创建 [root@k8s-master01 ~]# cd /mnt/nfs/ [root@k8s-master01 nfs]# touch 123.txt # nfs服务器上验证文件是否存在 [root@nfs-server nfs]# pwd /data/nfs [root@nfs-server nfs]# ll 总用量 0 -rw-r--r-- 1 root root 0 8月 7 15:53 123.txt # 测试完成卸载/mnt/nfs目录 [root@k8s-master01 nfs]# umount /mnt/nfs # 上述测试完成表示nfs共享目录挂载成功!
上述安装操作参考https://cloud.tencent.com/developer/article/1721166
1.1.3.2在pod中挂载nfs 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 [root@k8s-master01 pra]# cat nginx-deployment.yaml apiVersion: apps/v1 #指定这个资源使用的 Kubernetes API 版本,固定写法 kind: Deployment #指定资源类型是 Deployment。 metadata: # deployment的元数据 name: nginx-deployment # 创建的deployment的名字 labels: #键值对标签,用于资源的分类和选择 app: nginx #给这个deployment资源打上'app: nginx'标签 spec: #描述 Deployment 的期望状态,定义 Deployment 的具体配置和行为。 replicas: 1 # 指定需要运行的 Pod 副本数量。 selector: #选择器,用于选择哪些pod属于这个deployment matchLabels: #匹配标签,选择带有特定标签的pod app: nginx #指定带有' app: nginx '标签的pod进行管理 template: # pod的模板,用于定义pod metadata: #pod的元数据 labels: #标签,配置pod的标签 app: nginx #确保创建的 Pod 具有'app: nginx' 标签。 spec: #描述pod的期望状态,定义pod的具体配置和行为 nodeSelector: #节点选择器,用于将pod部署到指定标签的节点上 valume: hostpath #节点上的标签 volumes: #定义pod中所有可用的卷 - name: my-hostpath #定义了一个名字是my-hostpath的卷,用于在volumeMounts中引用。 hostPath: #卷类型,hostPath表示允许pod访问宿主机上的文件或目录 path: /data/log.txt #定义要挂载的宿主机文件路径 type: File #定义挂载的是文件,表示该路径必须是一个文件。(也可以是目录类型Directory) - name: nfs-volume #定义了一个名字是nfs-volume的卷,用于在volumeMounts中引用。 nfs: server: 192.168.0.106 #nfs服务地址 path: /data/nfs/dp #nfs共享目录 containers: #容器列表,复数,可配置多个容器 - name: nginx #容器的名称 image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #定义容器使用的镜像 volumeMounts: #定义容器如何使用卷 - name: my-hostpath #引用卷的名称是my-hostPath,该字段必须与volumes.name字段相同 mountPath: /liujunwei/log.txt #定义容器内的挂载路径 - name: nfs-volume #引用卷的名称是nfs-volume ,该字段必须与volumes.name字段相同 mountPath: /junwei #指定容器中的目录,将/data/nfs/dp挂载到容器/junwei,也就是/junwei目录中的内容和/data/nfs/dp目录中的内容一样 # 创建资源 [root@k8s-master01 pra]# kubectl replace -f nginx-deployment.yaml deployment.apps/nginx-deployment replaced # 进入容器中验证目录是否挂载成功 [root@k8s-master01 pra]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-deployment-6df5d4d774-vgcrd 1/1 Running 0 6m [root@k8s-master01 pra]# kubectl exec -ti nginx-deployment-6df5d4d774-vgcrd -- sh / # df -h Filesystem Size Used Available Use% Mounted on overlay 17.0G 6.6G 10.4G 39% / tmpfs 64.0M 0 64.0M 0% /dev tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup 192.168.0.106:/data/nfs/dp 45.1G 2.6G 42.5G 6% /junwei /dev/mapper/centos_k8s--master01-root 17.0G 6.6G 10.4G 39% /liujunwei/acc.log /dev/mapper/centos_k8s--master01-root 17.0G 6.6G 10.4G 39% /etc/hosts /dev/mapper/centos_k8s--master01-root 17.0G 6.6G 10.4G 39% /dev/termination-log /dev/mapper/centos_k8s--master01-root 17.0G 6.6G 10.4G 39% /etc/hostname /dev/mapper/centos_k8s--master01-root 17.0G 6.6G 10.4G 39% /etc/resolv.conf shm 64.0M 0 64.0M 0% /dev/shm tmpfs 3.7G 12.0K 3.7G 0% /run/secrets/kubernetes.io/serviceaccount tmpfs 1.9G 0 1.9G 0% /proc/acpi tmpfs 64.0M 0 64.0M 0% /proc/kcore tmpfs 64.0M 0 64.0M 0% /proc/keys tmpfs 64.0M 0 64.0M 0% /proc/timer_list tmpfs 64.0M 0 64.0M 0% /proc/sched_debug tmpfs 1.9G 0 1.9G 0% /proc/scsi tmpfs 1.9G 0 1.9G 0% /sys/firmware / # cat /junwei/ 1.txt test/ / # cat /junwei/1.txt test # 在nfs服务器上查看文件 [root@nfs-server dp]# pwd /data/nfs/dp [root@nfs-server dp]# ll 总用量 4 -rw-r--r-- 1 root root 5 8月 7 17:00 1.txt drwxr-xr-x 2 root root 6 8月 7 17:00 test [root@nfs-server dp]# cat 1.txt test
1.2PV 和 PVC 1.2.1什么是pv和pvc 持久卷 PV (Persistent Volume) :是集群中的一块存储,可以由管理员事先制备, 或者使用存储类(Storage Class) 来动态制备,PV 卷的制备有两种方式:静态制备或动态制备。 持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用 PV 的 Pod 的生命周期。 此 API 对象中记述了存储的实现细节,无论其背后是 NFS、iSCSI 还是特定于云平台的存储系统。
**存储请求PVC (Persistent Volume Claim)**:表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而 PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存)。同样 PVC 申领也可以请求特定的大小和访问模式 (例如,可以挂载为 ReadWriteOnce、ReadOnlyMany、ReadWriteMany 或 ReadWriteOncePod, 请参阅访问模式 )。
PV和PVC的关系可以类比为“房东”和“租客”:
PV是房东 ,它提供了具体的存储资源。
PVC是租客 ,它向Kubernetes请求存储资源。
当PVC创建后,Kubernetes会根据PVC的需求去匹配一个合适的PV,并将它们绑定在一起。一旦绑定,PV就只能被这个PVC使用,无法再被其他PVC绑定。
PV和PVC的生命周期:
准备(Provisioning) :静态供应 :管理员手动创建PV。动态供应 :通过StorageClass动态创建PV。
绑定(Binding) :用户创建PVC并指定需要的资源和访问模式。Kubernetes找到匹配的PV并将它们绑定。
使用(Using) :Pod可以像使用普通Volume一样使用PVC。
释放(Releasing) :当用户删除PVC时,PV会进入“已释放”状态,但仍保留数据。
回收(Reclaiming) :PV的回收策略决定了如何处理已释放的PV:保留(Retain) :数据保留,需手动清理。回收(Recycle) :清除数据,PV可再次使用。删除(Delete) :删除PV及其数据。
1.2.2PV回收策略: 在Kubernetes中,PersistentVolume(PV)的回收策略用于定义当与之绑定的PersistentVolumeClaim(PVC)被删除后,PV应该如何处理。Kubernetes支持三种主要的PV回收策略:
Retain(保留) :当PVC被删除时,PV不会被删除,而是被标记为“Released”已释放状态。此时,PV中的数据仍然存在,需要管理员手动清理或重新利用这些数据。这种策略适用于数据需要保留的场景.
Recycle(回收) :此策略会清除PV中的数据,例如删除所有文件,然后PV可以被重新绑定到新的PVC。这种策略比较简单且适用于某些特定场景,但在Kubernetes 1.10版本后已经被弃用,不再推荐使用.
Delete(删除) :这是动态配置PV的默认策略。当PVC被删除时,PV和其存储资源将被自动删除。这种策略适用于不需要保留数据的场景.
可以通过persistentVolumeReclaimPolicy: Recycle字段配置
1.2.3PV的访问策略: 在Kubernetes中,Persistent Volume(PV)的访问策略(Access Modes)用于定义如何访问存储卷。PV支持以下几种访问模式:
ReadWriteOnce(RWO) :PV可以被单个节点以读写方式挂载。这意味着只有一个节点可以同时以读写方式访问该存储卷。
ReadOnlyMany(ROX) :PV可以被多个节点以只读方式挂载。这种模式允许多个节点同时访问存储卷,但只能以只读方式访问。
ReadWriteMany(RWX) :PV可以被多个节点以读写方式挂载。这种模式允许多个节点同时以读写方式访问存储卷。
需要注意的是,虽然一些PV可能支持多种访问模式,但在实际挂载时只能选择一种模式进行使用。选择合适的访问模式取决于应用程序的需求和存储卷的特性。
1.2.4存储的分类 文件存储:一些数据可能需要被多个节点使用,比如用户的头像、用户上传的文件等,实现方式:NFS、NAS、FTP、CephFS等。
➢ 块存储:一些数据只能被一个节点使用,或者是需要将一块裸盘整个挂载使用,比如数据库、Redis、rabbitmq、zookeeper、kafka等,实现方式:Ceph、GlusterFS、公有云。
➢ 对象存储:由程序代码直接实现的一种存储方式,云原生应用无状态化常用的实现方式,实现方式:一般是符合S3协议的云存储,比如AWS的S3存储、Minio、七牛云等。
1.3创建NFS或NAS类型的PV 生产环境不要使用NFS在k8s集群中做文件存储,nfs是单点的,如果出现故障会影响整个集群。生产环境可以用云平台的NAS服务
这里是测试使用,nfs使用10.1.3中搭建的nfs服务。这里五台k8s集群的节点都需要安装nfs客户端,因为pod会随机在节点上运行,所以每个节点都需要安装nfs客户端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 # k8s集群中所有节点都安装 yum -y install nfs-utils # 在服务端新增一个共享目录 [root@nfs-server ~]# vim /etc/exports /data/nfs/ 192.168.0.0/24(rw,no_root_squash,no_all_squash,sync) # /data/k8s/目录为新增的目录 /data/k8s/ 192.168.0.0/24(rw,no_root_squash,no_all_squash,sync) # 重载 [root@nfs-server ~]# exportfs -r # 重启服务 [root@nfs-server ~]# systemctl restart nfs rpcbind # 测试挂载 # 192.168.0.106:/data/k8s是nfs服务器的ip,目录是配置的nfs共享目录 # /test-nfs/ 挂载目录,就是将192.168.0.106:/data/k8s挂载到本地的/test-nfs目录 [root@k8s-master01 pra]# mount -t nfs 192.168.0.106:/data/k8s /test-nfs/ # 查看挂载目录 [root@k8s-master01 pra]# df -h Filesystem Size Used Avail Use% Mounted on devtmpfs 2.0G 0 2.0G 0% /dev tmpfs 2.0G 0 2.0G 0% /dev/shm tmpfs 2.0G 173M 1.8G 9% /run tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup /dev/mapper/centos_k8s--master01-root 17G 6.7G 11G 40% / /dev/sda1 1014M 170M 845M 17% /boot tmpfs 393M 0 393M 0% /run/user/0 192.168.0.106:/data/k8s 46G 2.7G 43G 6% /test-nfs #挂载目录已经存在,证明可用
创建一个pv类型的资源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 # 下面的 PV 定义了一个使用 NFS 存储的 10Gi 容量的持久化卷,可以被多个节点以读写模式挂载。当 PV 从 PVC 中释放后,数据会被保留。 [root@k8s-master01 pv]# cat pv-nfs.yaml apiVersion: v1 #指定了 Kubernetes API 的版本,这里使用的是 v1,表示最新稳定版本。 kind: PersistentVolume #定义了资源的类型,这里是一个 PersistentVolume。持久卷为集群提供持久化存储,与 PersistentVolumeClaim 配合使用。 metadata:#定义这个资源的元数据,通常包括 name、namespace、labels、annotations 等。 name: pv-nfs#指定了 PV 的名称,这里是 pv-nfs。在整个集群内必须是唯一的。 spec: #定义持久卷的详细规范和配置。 capacity: #定义持久卷的存储容量。 storage: 10Gi #定义了卷的大小,这里是 10Gi。 volumeMode: Filesystem #指定持久卷的卷模式,这里是 Filesystem,意味着它将作为文件系统被挂载。还有Block 模式 accessModes:#定义 PV 的访问模式,这里是 ReadWriteMany,表示可以被多个节点以读写模式挂载。 - ReadWriteMany #表示可以被多个节点以读写模式挂载。 persistentVolumeReclaimPolicy: Retain #定义当 PV 从 PVC 中释放后的回收策略,这里是 Retain,表示当持久卷被释放后,仍然保留数据而不自动删除。 storageClassName: nfs-slow #指定存储类名称,pvc要绑定到pv上就是根据这个名称进行绑定。 nfs: #定义 NFS(网络文件系统)卷的相关配置。 server: 192.168.0.106 #指定 NFS 服务器的 IP 地址或主机名,这里是 192.168.0.106。 path: /data/k8s #指定 NFS 服务器上的共享目录路径,这里是 /data/k8s。 # 创建pv [root@k8s-master01 pv]# kubectl replace -f pv-nfs.yaml persistentvolume/pv-nfs replaced # 查看创建的pv # pv创建成功不代表存储就是可用的,要在pod中挂载才知道能不能用 [root@k8s-master01 pv]# kubectl get -f pv-nfs.yaml NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv-nfs 10Gi RWX Retain Available nfs-slow 57m
pv的状态解释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@k8s-master01 pv]# kubectl get -f pv-nfs.yaml NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pv-nfs 10Gi RWX Retain Available nfs-slow 57m ---下面是对每个字段的解释--- NAME: 这是持久卷的名称。你的 PV 名为 pv-nfs,这是在 YAML 文件的 metadata.name 字段中指定的。 CAPACITY: 这个字段显示持久卷的存储容量。这里是 10Gi,代表这个 PV 提供 10 Gibibytes 的存储空间。这个值对应于 YAML 文件中的 spec.capacity.storage。 ACCESS MODES: 显示持久卷的访问模式。RWX 表示 ReadWriteMany,即允许多个节点同时挂载并读写该卷。这个值对应于 YAML 文件中的 spec.accessModes。 RECLAIM POLICY: 指定 PV 的回收策略。Retain 表示在 PV 被释放后(即关联的 PersistentVolumeClaim 被删除后),PV 保持现状而不自动删除。这与 YAML 文件中的 spec.persistentVolumeReclaimPolicy 字段一致。 STATUS: 显示持久卷的当前状态。Available 表示这个 PV 目前未绑定任何 PersistentVolumeClaim,可以被新的 PVC 绑定。 CLAIM: 如果这个持久卷已经被某个 PersistentVolumeClaim 绑定,这里会显示该 PVC 的名称。在你的例子中,这个字段是空的,表示没有 PVC 绑定这个 PV。 STORAGECLASS: 这个字段显示了持久卷所属的存储类(StorageClass)。nfs-slow 是在 YAML 文件中 spec.storageClassName 字段中定义的存储类名称。存储类定义了动态供应存储卷的配置和策略。 REASON: 如果持久卷无法正常使用或者有问题时,这个字段会显示具体原因。在你的例子中,这个字段是空的,表示 PV 没有问题。 AGE: 显示这个 PV 已经存在的时间。57m 表示这个 PV 已经创建了 57 分钟。 ------------------------- pv其他状态:(STATUS字段) ➢ Available:可用,没有被PVC绑定的空闲资源。 ➢ Bound:已绑定,已经被PVC绑定。 ➢ Released:已释放,PVC被删除,但是资源还未被重新使用。 ➢ Failed:失败,自动回收失败。
1.4创建hostPath类型的PV 定义一个hostPath的PV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@k8s-master01 pv]# cat hostpath-pv.yaml apiVersion: v1 #指定了 Kubernetes API 的版本,这里使用的是 v1,表示最新稳定版本。 kind: PersistentVolume #定义了资源的类型,这里是一个 PersistentVolume。持久卷为集群提供持久化存储,与 PersistentVolumeClaim 配合使用。 metadata: #定义这个资源的元数据,通常包括 name、namespace、labels、annotations 等。 name: hostpath-pv #指定了 PV 的名称,这里是 pv-nfs。在整个集群内必须是唯一的。 spec: #定义持久卷的详细规范和配置。 capacity: #定义持久卷的存储容量。 storage: 10Gi #定义了卷的大小,这里是 10Gi。 volumeMode: Filesystem #指定持久卷的卷模式,这里是 Filesystem,意味着它将作为文件系统被挂载。还有Block 模式 accessModes: #定义 PV 的访问模式,这里是 ReadWriteMany,表示可以被多个节点以读写模式挂载。 - ReadWriteOnce #表示可以被多个节点以读写模式挂载。 persistentVolumeReclaimPolicy: Retain #定义当 PV 从 PVC 中释放后的回收策略,这里是 Retain,表示当持久卷被释放后,仍然保留数据而不自动删除。 storageClassName: hostpath #指定存储类名称,这里使用 nfs-slow。存储类用来管理存储的动态供应和配置。 hostPath: path: /mnt/data
创建这个pv:
1 2 [root@k8s-master01 pv]# kubectl create -f hostpath-pv.yaml persistentvolume/hostpath-pv created
查看创建的pv
1 2 3 4 [root@k8s-master01 pv]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE hostpath-pv 10Gi RWO Retain Available hostpath 14s pv-nfs 10Gi RWX Retain Available nfs-slow 6d22h
1.5创建CephRBD类型的VP CephRBD类型的VP配置案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 apiVersion: v1 kind: PersistentVolume metadata: name: ceph-rbd-pv spec: capacity: storage: 1Gi storageClassName: ceph-fast accessModes: - ReadWriteOnce rbd: monitors: - 192.168.1.123:6789 - 192.168.1.124:6789 - 192.168.1.125:6789 pool: rbd image: ceph-rbd-pv-test user: admin secretRef: name: ceph-secret fsType: ext4 readOnly: false
➢ monitors:Ceph的monitor节点的IP
➢ pool:所用Ceph Pool的名称,可以使用ceph osd pool ls查看
➢ image:Ceph块设备中的磁盘映像文件,可以使用rbd create POOL_NAME/IMAGE_NAME – size 1024 创建,使用rbd list POOL_NAME 查看
➢ user:Rados的用户名,默认是admin
➢ secretRef:用于验证Ceph身份的密钥
➢ fsType:文件类型,可以是ext4、XFS等
➢ readOnly:是否是只读挂载
1.6PVC绑定pv
10.6.1pvc挂载示例 注意:pv是没有命名空间隔离的,但是pvc具有命名空间隔离,pod和pvc要在同一个命名空间才能正常使用
这里的pvc跟10.3示例中的pv进行绑定
PV配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [root@k8s-master01 pv]# cat pv-nfs.yaml apiVersion: v1 #指定了 Kubernetes API 的版本,这里使用的是 v1,表示最新稳定版本。 kind: PersistentVolume #定义了资源的类型,这里是一个 PersistentVolume。持久卷为集群提供持久化存储,与 PersistentVolumeClaim 配合使用。 metadata: #定义这个资源的元数据,通常包括 name、namespace、labels、annotations 等。 name: pv-nfs #指定了 PV 的名称,这里是 pv-nfs。在整个集群内必须是唯一的。 spec: #定义持久卷的详细规范和配置。 capacity: #定义持久卷的存储容量。 storage: 10Gi #定义了卷的大小,这里是 10Gi。 volumeMode: Filesystem #指定持久卷的卷模式,这里是 Filesystem,意味着它将作为文件系统被挂载。还有Block 模式 accessModes: #定义 PV 的访问模式,这里是 ReadWriteMany,表示可以被多个节点以读写模式挂载。 - ReadWriteMany #表示可以被多个节点以读写模式挂载。 persistentVolumeReclaimPolicy: Retain #定义当 PV 从 PVC 中释放后的回收策略,这里是 Retain,表示当持久卷被释放后,仍然保留数据而不自动删除。 storageClassName: nfs-slow #指定存储类名称,这里使用 nfs-slow。存储类用来管理存储的动态供应和配置。 nfs: #定义 NFS(网络文件系统)卷的相关配置。 server: 192.168.0.106 #指定 NFS 服务器的 IP 地址或主机名,这里是 192.168.0.106。 path: /data/k8s #指定 NFS 服务器上的共享目录路径,这里是 /data/k8s。
PVC配置:
1 2 3 4 5 6 7 8 9 10 11 12 [root@k8s-master01 pv]# cat pvc-nfs.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: nfs-pvc-claim spec: storageClassName: nfs-slow accessModes: - ReadWriteMany resources: requests: storage: 1Gi #<=pv的大小
创建这个pvc,与pv进行绑定:
1 2 [root@k8s-master01 pv]# kubectl create -f pvc-nfs.yaml persistentvolumeclaim/nfs-pvc-claim created
查看pv和pvc的状态:
1 2 3 4 5 6 7 [root@k8s-master01 pv]# kubectl get pv NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE hostpath-pv 10Gi RWO Retain Available hostpath 4d1h pv-nfs 10Gi RWX Retain Bound default/nfs-pvc-claim nfs-slow 162m [root@k8s-master01 pv]# kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE nfs-pvc-claim Bound pv-nfs 10Gi RWX nfs-slow 4m46s
1.6.2pod中使用pvc pod配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@k8s-master01 pv]# cat pvc-nfs-pod.yaml apiVersion: v1 kind: Pod metadata: name: pvc-nfs-pod #pod名称 spec: containers: - name: pvc-nfs-container #容器名称 image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #镜像地址 volumeMounts: #挂载卷 - name: nfs-pvc #卷的名称,这个名称要和下面volumes中的name一致 mountPath: /usr/share/nginx/html #挂载路径 volumes: #卷 - name: nfs-pvc #定义卷名称,这个名称要和上面volumeMounts中的name一致 persistentVolumeClaim: #持久卷声明 claimName: nfs-pvc-claim #声明名称,这个名称要和PersistentVolumeClaim中的metadata.name一致
创建pod:
1 2 [root@k8s-master01 pv]# kubectl create -f pvc-nfs-pod.yaml pod/pvc-nfs-pod created
查看pod状态:
1 2 3 [root@k8s-master01 pv]# kubectl get po NAME READY STATUS RESTARTS AGE pvc-nfs-pod 1/1 Running 0 15s
进入pod中查看挂载目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@k8s-master01 pv]# kubectl exec -ti pvc-nfs-pod -- sh / # df -h Filesystem Size Used Available Use% Mounted on overlay 17.0G 5.5G 11.5G 32% / tmpfs 64.0M 0 64.0M 0% /dev tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup 192.168.0.106:/data/k8s 45.1G 2.6G 42.4G 6% /usr/share/nginx/html tmpfs 1.9G 0 1.9G 0% /proc/acpi tmpfs 64.0M 0 64.0M 0% /proc/kcore tmpfs 64.0M 0 64.0M 0% /proc/keys tmpfs 64.0M 0 64.0M 0% /proc/timer_list tmpfs 64.0M 0 64.0M 0% /proc/sched_debug tmpfs 1.9G 0 1.9G 0% /proc/scsi tmpfs 1.9G 0 1.9G 0% /sys/firmware # 通过df -h 可以看出192.168.0.106:/data/k8s目录已经挂载到容器的/usr/share/nginx/html目录
在nfs服务器上的共享目录中创建一个文件,在该pod中查看是否存在这个文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 在nfs服务器上的共享目录中创建文件 [root@nfs-server ~]# cd /data/k8s [root@nfs-server k8s]# echo "hello" >index.html [root@nfs-server k8s]# ll 总用量 4 -rw-r--r-- 1 root root 6 8月 20 18:16 index.html # 在pod上验证是否存在这个index.html [root@k8s-master01 pv]# kubectl exec -ti pvc-nfs-pod -- sh #进入pod / # ls -l /usr/share/nginx/html total 4 -rw-r--r-- 1 root root 6 Aug 20 10:16 index.html / # cat /usr/share/nginx/html/index.html hello / # curl localhost hello
1.6.3deployment中使用pvc deployment配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [root@k8s-master01 pv]# cat nfs-deploy.yaml apiVersion: apps/v1 #指定这个资源使用的 Kubernetes API 版本,固定写法 kind: Deployment #指定资源类型是 Deployment。 metadata: # deployment的元数据 name: nginx-deployment # 创建的deployment的名字 labels: #键值对标签,用于资源的分类和选择 app: nginx #给这个deployment资源打上'app: nginx'标签 spec: #描述 Deployment 的期望状态,定义 Deployment 的具体配置和行为。 replicas: 5 # 指定需要运行的 Pod 副本数量。 selector: #选择器,用于选择哪些pod属于这个deployment matchLabels: #匹配标签,选择带有特定标签的pod app: nginx #指定带有' app: nginx '标签的pod进行管理 template: # pod的模板,用于定义pod metadata: #pod的元数据 labels: #标签,配置pod的标签 app: nginx #确保创建的 Pod 具有'app: nginx' 标签。 spec: #描述pod的期望状态,定义pod的具体配置和行为 volumes: - name: nfs-pvc #定义卷的名称,用于在容器中引用,这个名称要和下面volumeMounts中的name一致 persistentVolumeClaim: #指定要使用的PVC claimName: nfs-pvc-claim #指定要使用的PVC的名称 containers: #容器列表,复数,可配置多个容器 - name: pvc-nfs-container #容器的名称 image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #定义容器使用的镜像 volumeMounts: - mountPath: /usr/share/nginx/html #容器内的挂载路径 name: nfs-pvc #挂载的卷名称,与volumes中的name保持一致
创建找个5副本的deployment:
1 2 [root@k8s-master01 pv]# kubectl create -f nfs-deploy.yaml deployment.apps/nginx-deployment created
查看创建的pod:
1 2 3 4 5 6 7 [root@k8s-master01 pv]# kubectl get po NAME READY STATUS RESTARTS AGE nginx-deployment-9b55c9df6-4wc6v 1/1 Running 0 20h nginx-deployment-9b55c9df6-5bd2d 1/1 Running 0 20h nginx-deployment-9b55c9df6-c95lv 1/1 Running 0 20h nginx-deployment-9b55c9df6-kmvv9 1/1 Running 0 20h nginx-deployment-9b55c9df6-lc77f 1/1 Running 0 20h
验证挂载卷:在nfs服务器上的共享目录中(或者pod)创建一个文件,在该pod中(或者nfs的共享目录中)查看是否存在这个文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # 进入nginx-deployment-9b55c9df6-c95lv 的pod 中(任意pod即可),容器内的挂载目录是/usr/share/nginx/html [root@k8s-master01 pv]# kubectl exec -ti nginx-deployment-9b55c9df6-c95lv -- sh / # cd /usr/share/nginx/html /usr/share/nginx/html # ls -l total 4 -rw-r--r-- 1 root root 6 Aug 20 10:16 index.html /usr/share/nginx/html # echo 'hello kubernetes' > index.html /usr/share/nginx/html # cat index.html hello kubernetes #在其他pod(和nfs共享目录中)内查看该文件内容是否一致 # 进入nginx-deployment-9b55c9df6-lc77f查看 [root@k8s-master01 pv]# kubectl exec -ti nginx-deployment-9b55c9df6-lc77f -- sh / # cat /usr/share/nginx/html/index.html hello kubernetes #(一致) # 查看nfs共享目录中的文件 [root@nfs-server k8s]# cat /data/k8s/index.html hello kubernetes #(一致)
1.7PVC创建和挂载失败原因
PVC一直处于Pending的原因: pvc的空间申请大小大于pv的大小 pvc的storageClassName和pv的storageClassName不一致
pvc的accessModes和pv的accessModes不一致
挂载PVC的pod一直处于Pending: pvc没有创建成功
pvc的pod不在同一个namespace(命名空间)