【K8s】初识PV和PVC

news2024/11/18 17:33:59
目录
收起
O、致谢
一、前言
二、Volume
2.1 什么是Volume
2.2 为什么要引入Volume
2.3 Volume类型有哪些
2.4 Volume如何使用
2.4.1 通过emptyDir共享数据
2.4.2 使用HostPath挂载宿主机文件
2.4.3 挂载NFS至容器
三、PV和PVC
3.1 什么是PV和PVC
3.2 为什么要引入PV和PVC
3.3 PV回收策略
3.4 PV访问策略
3.5 PV状态
3.6 PV配置示例
3.6.1 基于NFS的PV
3.6.2 基于HostPath的PV
3.6.3 基于Ceph RBD的PV
3.7 PVC绑定PV
3.8 PVC创建和挂载失败的原因
3.8.1 PVC一直Pending的原因
3.8.2 挂载PVC的Pod一直处于Pending
四、存储分类

一、前言

本文主要以下几方面介绍k8s中的Volume:

  • 什么是Volume
  • 为什么要引入Volume
  • Volume类型有哪些
  • Volume如何使用

本文主要以下几方面介绍k8s中的PV和PVC:

  • 什么是PV和PVC
  • 为什么要引入PV和PVC
  • PV回收策略有哪些
  • PV访问策略有哪些
  • PV状态有哪些
  • PV和PVC如何使用
  • PVC如何绑定PV

本文主要以下几方面介绍存储分类:

  • 文件存储
  • 块存储
  • 对象存储

二、Volume

2.1 什么是Volume

对于大多数项目而言,数据文件的存储是非常常见的需求,比如存储用户上传的头像、上传的文件以及数据库的数据。在Kubernetes中,由于应用的部署具有高度的可扩展性和编排能力(不像传统架构部署在固定的位置),因此把数据存放在本地是非常不可取的,这样做也无法保障数据的安全。

卷的核心是一个目录,其中可能存有数据,Pod 中的容器可以访问该目录中的数据。 所采用的特定的卷类型将决定该目录如何形成的、使用何种介质保存数据以及目录中存放的内容。

使用卷时, 在 .spec.volumes 字段中设置为 Pod 提供的卷,并在 .spec.containers[*].volumeMounts 字段中声明卷在容器中的挂载位置。 容器中的进程看到的文件系统视图是由它们的容器镜像的初始内容以及挂载在容器中的卷(如果定义了的话)所组成的。 其中根文件系统同容器镜像的内容相吻合。 任何在该文件系统下的写入操作,如果被允许的话,都会影响接下来容器中进程访问文件系统时所看到的内容。

卷挂载在镜像中的指定路径下。 Pod 配置中的每个容器必须独立指定各个卷的挂载位置。

卷不能挂载到其他卷之上(不过存在一种使用 subPath的相关机制),也不能与其他卷有硬链接。

2.2 为什么要引入Volume

引入Volume的原因主要有两点:

  • Kubernetes卷具有明确的生命周期,与使用它的Pod相同。因此,在Kubernetes中的卷可以比Pod中运行的任何容器生命周期都长,并且可以在容器重启或者销毁之后保留数据。Kubernetes支持多种类型的卷,并且Pod可以同时使用任意数量的卷。
  • 当一个Pod运行多个容器时,各个容器可能需要共享一些文件,诸如此类的需求都可以使用Volume解决

2.3 Volume类型有哪些

在传统架构中,企业内可能有自己的存储平台,比如NFS、Ceph、GlusterFS、Minio等。如果读者的环境在公有云,可以使用公有云提供的NAS、对象存储等。在Kubernetes中,Volume也支持配置以上存储,用于挂载到Pod中实现数据的持久化。Kubernetes Volume支持的卷的类型有很多,以下为常用的卷:

  • CephFS
  • GlusterFS
  • ISCSI
  • Cinder
  • NFS
  • RBD
  • HostPath

当然,也支持一些Kubernetes独有的类型:

  • ConfigMap:用于存储配置文件
  • Secret:用于存储敏感数据
  • EmptyDir:用于一个Pod内多个容器的数据共享
  • PersistentVolumeClaim:对PersistentVolume的申请

2.4 Volume如何使用

本文通过几个比较常用的类型的Volume配置演示一下Volume的使用

  • 示例1---通过emptyDir共享数据
  • 示例2---使用HostPath挂载宿主机文件
  • 示例3---挂载NFS至容器

2.4.1 通过emptyDir共享数据

EmptyDir是一个特殊的Volume类型,与上述Volume不同的是,如果删除Pod,emptyDir卷中的数据也将被删除,所以一般emptyDir用于Pod中的不同Container共享数据,比如一个Pod存在两个容器A和B,容器A需要使用容器B产生的数据,此时可以采用emptyDir共享数据,类似的使用如Filebeat收集容器内程序产生的日志。

默认情况下,emptyDir 卷支持节点上的任何介质,可能是 SSD、磁盘或网络存储,具体取 决于自身的环境。可以将 emptyDir.medium 字段设置为 Memory,让 Kubernetes 使用 tmpfs(内 存支持的文件系统),虽然 tmpfs 非常快,但是 tmpfs 在节点重启时,数据同样会被清除,并且 设置的大小会被计入到 Container 的内存限制当中。

1.定义一个yaml文件

[root@k8s-master01 practice]# vim emptydir.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 
        imagePullPolicy: IfNotPresent
        name: nginx
        volumeMounts:
        - mountPath: /opt
          name: share-volume
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 
        imagePullPolicy: IfNotPresent
        name: nginx2
        command:
        - sh
        - -c
        - sleep 3600
        volumeMounts:
        - mountPath: /mnt
          name: share-volume
      volumes:
      - name: share-volume
        emptyDir: {}
          #medium: Memory

2.重新部署

[root@k8s-master01 practice]# kubectl apply -f emptydir.yaml

3.查看pod状态

[root@k8s-master01 practice]# kubectl get po
NAME                     READY   STATUS    RESTARTS      AGE
nginx-d8f544fdd-qgllm           2/2     Running   0               12m

4.验证-进入nginx的容器创建文件后,在nginx2容器查看

(1)进入nginx容器后,进入/opt目录下创建123文件

[root@k8s-master01 practice]# kubectl exec -it nginx-d8f544fdd-qgllm  -c nginx -- sh
root@nginx-d8f544fdd-qgllm:/# cd /opt
root@nginx-d8f544fdd-qgllm:/opt# touch 123

(2)进入nginx2容器后,进入/mnt目录下查看123文件是否创建成功

[root@k8s-master01 practice]# kubectl exec -it nginx-d8f544fdd-qgllm  -c nginx2 -- bash
root@nginx-d8f544fdd-qgllm:/# cd /mnt/
root@nginx-d8f544fdd-qgllm:/mnt# ls
123

2.4.2 使用HostPath挂载宿主机文件

hostPath 卷可将节点上的文件或目录挂载到 Pod 上,用于 Pod 自定义日志输出或访问 Docker 内部的容器等。

hostPath常用类型有如下:

取值行为
默认选项,意味着挂载 hostPath 卷之前不会执行任何检查
DirectoryOrCreate如果给定的 path 不存在任何东西,那么将根据需要创建一个权限为 0755 的空目录,和 Kubelet 具有相同的组和权限
Directory目录必须存在于给定的路径下
FileOrCreate如果给定的路径不存储任何内容,则会根据需要创建一个空文件,权限设 置为 0644,和 Kubelet 具有相同的组和所有权。
File文件必须存在于给定路径中
Socket在给定路径上必须存在的 UNIX 套接字
CharDevice在给定路径上必须存在的字符设备
BlockDevice在给定路径上必须存在的块设备

hostPath注意事项有如下:

  • HostPath 卷可能会暴露特权系统凭据(例如 Kubelet)或特权 API(例如容器运行时套接字),可用于容器逃逸或攻击集群的其他部分。
  • 具有相同配置(例如基于同一 PodTemplate 创建)的多个 Pod 会由于节点上文件的不同而在不同节点上有不同的行为。
  • 下层主机上创建的文件或目录只能由 root 用户写入。 你需要在特权容器中以 root 身份运行进程,或者修改主机上的文件权限以便容器能够写入 hostPath 卷。

下面进行hostPath示例说明,将主机的/etc/timezone文件挂载到 Pod 的/etc/timezone:

1.定义一个yaml文件

[root@k8s-master01 practice]# vim emptydir-hostpath.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nginx
  name: nginx
  namespace: default
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 
        imagePullPolicy: IfNotPresent
        name: nginx
        volumeMounts:
        - mountPath: /opt
          name: share-volume
        - mountPath: /etc/timezone
          name: timezone
      - image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2 
        imagePullPolicy: IfNotPresent
        name: nginx2
        command:
        - sh
        - -c
        - sleep 3600
        volumeMounts:
        - mountPath: /mnt
          name: share-volume
      volumes:
      - name: share-volume
        emptyDir: {}
          #medium: Memory
      - name: timezone
        hostPath:
          path: /etc/timezone
          type: File

2.重新部署

[root@k8s-master01 practice]# kubectl apply -f emptydir-hostpath.yaml

3.查看pod状态

[root@k8s-master01 practice]# kubectl get po
NAME                     READY   STATUS    RESTARTS      AGE
nginx-85fdffcd78-f9pwz           2/2     Running   0               12m

4.查看挂载情况,观察到设置的nginx已成功进行挂载;而未设置的nginx2未进行挂载

[root@k8s-master01 practice]# kubectl exec nginx-85fdffcd78-f9pwz  -c nginx -- cat /etc/timezone
Asia/Shanghai

[root@k8s-master01 practice]# kubectl exec nginx-85fdffcd78-f9pwz -c nginx2 – cat /etc/timezone
cat: can’t open ‘/etc/timezone’: No such file or directory

2.4.3 挂载NFS至容器



在生产环境中,考虑到数据的高可用性,仍然不建议使用NFS作为后端存储。因为NFS存在单点故障,很多企业并非对其实现高可用,并且NFS的性能存在很大的瓶颈。所以生产中,建议使用分布式存储,在公有云中建议使用公有云提供的NAS存储来替代NFS,并且NAS性能更好,可用性更高。NFS作为一个比较流行的远端存储工具,在非生产环境中是一个比较好用的选择,可以快速地搭建使用。


首先我们需要安装一下NFS


1.每台机器安装NFS客户端



$ yum install nfs-utils -y


2.在k8s-node01(192.168.1.34)启动nfs



[root@k8s-node01 ~]# systemctl start nfs-server


在k8s-node01(192.168.1.34)查看nfs支持的版本



[root@k8s-node01 ~]# cat /proc/fs/nfsd/versions
-2 +3 +4 +4.1 +4.2


3.在k8s-node01(192.168.1.34)上创建一个共享目录



[root@k8s-node01 ~]# mkdir  -p  /data/nfs/test_nfs


4.在k8s-node01(192.168.134)编辑授权文件,这里网段根据自己主机来定,我这里网段是192.168.1.0/24



[root@k8s-node01 ~]# vim /etc/exports
/data/nfs/ 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)


5.在k8s-node01(192.168.1.34)配置生效



[root@k8s-node01 ~]# exportfs -r


6.在k8s-node01(192.168.1.34)重新加载NFS



[root@k8s-node01 ~]# systemctl reload nfs-server


7.在k8s-master01上进行挂载测试



[root@k8s-master01 ~]# mount -t nfs 192.168.1.34:/data/nfs /mnt/
[root@k8s-master01 ~]# cd /mnt/
[root@k8s-master01 mnt]# touch test123


8.在k8s-node01(192.168.1.34)进行验证



[root@k8s-node01 ~]# cd /data/nfs/
[root@k8s-node01 nfs]# ls
test123 test_nfs


接下来,我们对上面的测试进行卸载


1.针对上诉测试进行卸载



[root@k8s-master01 ~]# umount /mnt/



最后,和emptyDir、HostPath的配置方法类似,NFS的Volume配置也是在Volumes字段中配置的,和emptyDir不同的是,NFS属于持久化存储的一种,在Pod删除或者重启后,数据依旧会存储在NFS节点上。


1.在k8s-master01上定义一个yaml文件



[root@k8s-master01 ~]# vim nfs.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: /opt
name: share-volume
- mountPath: /etc/timezone
name: timezone
- image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx2
command:
- sh
- -c
- sleep 3600
volumeMounts:
- mountPath: /mnt
name: share-volume
- mountPath: /opt
name: nfs-volume
volumes:
- name: share-volume
emptyDir: {}
#medium: Memory
- name: timezone
hostPath:
path: /etc/timezone
type: File
- name: nfs-volume
nfs:
server: 192.168.1.34
path: /data/nfs/test_nfs


2.在k8s-master01重新部署



[root@k8s-master01 ~]# kubectl replace -f nfs.yaml


3.在k8s-master01查看pod状态



[root@k8s-master01 ~]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-5f974586bc-wv89n 2/2 Running 0 29s


4.在k8s-master01以容器的方式进入pod,查看挂载已经成功



[root@k8s-master01 ~]# kubectl exec -it nginx-5f974586bc-wv89n  -c nginx2 – sh
/ # df -Th
Filesystem Type Size Used Available Use% Mounted on
overlay overlay 35.0G 4.5G 30.4G 13% /
tmpfs tmpfs 64.0M 0 64.0M 0% /dev
tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/mapper/centos-root
xfs 35.0G 4.5G 30.4G 13% /mnt
192.168.1.34:/data/nfs/test_nfs
nfs4 35.0G 3.6G 31.4G 10% /opt


5.在k8s-master01挂载目录中创建文件



[root@k8s-master01 ~]# kubectl exec -it nginx-5f974586bc-wv89n  -c nginx2 – sh
/ # cd /opt/
/opt # touch 11111


6.在k8s-node01上进行结果验证



[root@k8s-node01 ~]# cd /data/nfs/test_nfs
[root@k8s-node01 test_nfs]# ls
11111


注意:Kubernetes所有的节点都需要安装上nfs-utils才可以正常挂载NFS。


三、PV和PVC


3.1 什么是PV和PVC


持久卷(PersistentVolume,PV) 是集群中的一块存储,可以由管理员事先制备, 或者使用存储类来动态制备。
持久卷是集群资源,就像节点也是集群资源一样。PV 持久卷和普通的 Volume 一样, 也是使用卷插件来实现的,只是它们拥有独立于任何使用PV的Pod的生命周期。


注意:PV没有命名空间限制!!!


持久卷申领(PersistentVolumeClaim,PVC) 表达的是用户对存储的请求。概念上与 Pod 类似。 Pod 会耗用节点资源,而
PVC 申领会耗用 PV 资源。Pod 可以请求特定数量的资源(CPU 和内存);同样 PVC 申领也可以请求特定的大小和访问模式 。


注意:PVC有命名空间限制!!!


3.2 为什么要引入PV和PVC


虽然Volume已经可以接入大部分存储后端,但是实际使用时还有诸多问题,比如:



  • 当某个数据卷不再被挂载使用时,里面的数据如何处理?

  • 如果想要实现只读挂载如何处理?

  • 如果想要只能有一个Pod挂载如何处理?

  • 如果只允许某个Pod使用10G的空间?



如上所述,对于很多复杂的需求Volume可能难以实现,并且无法对存储卷的生命周期进行管理。为此Kubernetes引入了两个新的API资源:PersistentVolume和PersistentVolumeClaim。PersistentVolume(简称PV)是由Kubernetes管理员设置的存储,PersistentVolumeClaim(简称PVC)是对PV的请求,表示需要什么类型的PV。


下面介绍下引入的PV和PVC使用流程


1.开发人员需要申请存储


2.k8s管理员提前创建好不同的PV


3.k8s管理人员创建PVC并告诉开发人员指定storageClassName或直接告诉开发人员创建PVC并指定storageClassName即可




在这里插入图片描述


3.3 PV回收策略

当用户不再使用其存储卷时,他们可以从 API 中将 PVC 对象删除, 从而允许该资源被回收再利用。PersistentVolume 对象的回收策略告诉集群, 当其被从申领中释放时如何处理该数据卷。 目前,数据卷可以被 Retained(保留)、Recycled(回收)或 Deleted(删除)。可以通过persistentVolumeReclaimPolicy: Recycle字段配置。

1.Retain

保留,该策略允许手动回收资源,当删除PVC时,PV仍然存 在,PV被视为已释放,管理员可以手动回收卷。

回收策略 Retain 使得用户可以手动回收资源。当 PersistentVolumeClaim 对象被删除时,PersistentVolume 卷仍然存在,对应的数据卷被视为"已释放(released)"。 由于卷上仍然存在这前一申领人的数据,该卷还不能用于其他申领。 管理员可以通过下面的步骤来手动回收该卷:

  • 删除 PersistentVolume 对象。与之相关的、位于外部基础设施中的存储资产 (例如 AWS EBS、GCE PD、Azure Disk 或 Cinder 卷)在 PV 删除之后仍然存在。
  • 根据情况,手动清除所关联的存储资产上的数据。
  • 手动删除所关联的存储资产。

2.Recycle

回收,如果Volume插件支持,Recycle策略会对卷执行rm - rf清理该PV,并使其可用于下一个新的PVC。目前,仅 NFS 和 HostPath 支持回收(Recycle)

注意:回收策略 Recycle 已被废弃。取而代之的建议方案是使用动态制备。

3.Delete

删除,如果Volume插件支持,删除PVC时会同时删除PV, 动态卷默认为Delete,目前支持Delete的存储后端包括AWS EBS, GCE PD, Azure Disk, or OpenStack Cinder等。

3.4 PV访问策略

PersistentVolume 卷可以用资源提供者所支持的任何方式挂载到宿主系统上。因提供者(驱动)的能力不同,每个 PV 卷的访问模式都会设置为对应卷所支持的模式值。 例如,NFS 可以支持多个读写客户,但是某个特定的 NFS PV 卷可能在服务器上以只读的方式导出。 每个 PV 卷都会获得自身的访问模式集合,描述的是特定 PV 卷的能力。访问模式有:

1.ReadWriteOnce 可以被单节点以读写模式挂载,命令行中可以被缩写为RWO。 2.ReadOnlyMany 可以被多个节点以只读模式挂载,命令行中可以被缩写为ROX。 3.ReadWriteMany 可以被多个节点以读写模式挂载,命令行中可以被缩写为RWX。 4.ReadWriteOncePod 只允许被单个Pod访问,需要K8s 1.22+以上版本,并且是CSI 创建的PV才可使用

注意:每个卷同一时刻只能以一种访问模式挂载,即使该卷能够支持多种访问模式。

目前卷插件支持的访问策略如下:

这里是引用

3.5 PV状态

我们可以使用kubectl get pv命令查看PV状态

[root@k8s-node01 ~]# kubectl get pv 
NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-hostpath   10Gi       RWO            Retain           Available           hostpath                55s
pv-nfs        5Gi        RWO            Recycle          Available           nfs-slow                28m

常见的状态如下:

1.Available 可用,没有被PVC绑定的空闲资源。

2.Bound 已绑定,已经被PVC绑定。

3.Released 已释放,PVC被删除,但是资源还未被重新使用。

4.Failed 失败,自动回收失败。

3.6 PV配置示例

在企业内,可能存储很多不同类型的存储,比如NFS、Ceph、GlusterFS等,针对不同类型的后端存储具有不同的配置方式,这也是对集群管理员的一种挑战,因为集群管理员需要对每种存储都有所了解。接下来看一下几个常用的PV配置示例。

3.6.1 基于NFS的PV

首先我们需要安装一下NFS

1.每台机器安装NFS客户端

$ yum install nfs-utils -y

2.在k8s-node01(192.168.1.34)启动nfs

[root@k8s-node01 ~]# systemctl start nfs-server

在k8s-node01(192.168.1.34)查看nfs支持的版本

[root@k8s-node01 ~]# cat /proc/fs/nfsd/versions 
-2 +3 +4 +4.1 +4.2

3.在k8s-node01(192.168.1.34)上创建一个共享目录

[root@k8s-node01 ~]# mkdir  -p  /data/nfs/test_nfs

4.在k8s-node01(192.168.134)编辑授权文件,这里网段根据自己主机来定,我这里网段是192.168.1.0/24

[root@k8s-node01 ~]# vim /etc/exports
/data/nfs/ 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

5.在k8s-node01(192.168.1.34)配置生效

[root@k8s-node01 ~]# exportfs -r

6.在k8s-node01(192.168.1.34)重新加载NFS

[root@k8s-node01 ~]# systemctl reload nfs-server

7.在k8s-master01上进行挂载测试

[root@k8s-master01 ~]# mount -t nfs 192.168.1.34:/data/nfs /mnt/
[root@k8s-master01 ~]# cd /mnt/
[root@k8s-master01 mnt]# touch test123

8.在k8s-node01(192.168.1.34)进行验证

[root@k8s-node01 ~]# cd /data/nfs/
[root@k8s-node01 nfs]# ls
test123  test_nfs

接下来,我们对上面的测试进行卸载

1.针对上诉测试进行卸载

[root@k8s-master01 ~]# umount /mnt/

最后进行NFS配置示例

1.定义一个yaml文件

[root@k8s-master01 pv]# vim pv-nfs.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-nfs
spec:
  capacity:                   
    storage: 5Gi
  volumeMode: Filesystem 
  accessModes:          
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs-slow
  nfs:
    path: /data/nfs/test_nfs  
    server: 192.168.1.34

上面参数说明:

  • capacity:容量配置
  • volumeMode:卷的模式,目前支持Filesystem (文件系统) 和 Block(块),其中Block类型需 要后端存储支持,默认为文件系统
  • accessModes:该PV的访问模式,这里设置为RWO,可以被单节点以读写模式挂载
  • storageClassName:PV的类,一个特定类型的PV 只能绑定到特定类别的PVC
  • persistentVolumeReclaimPolicy:回收策略
  • nfs:NFS服务配置,包括以下两个选项:path:NFS上的共享目录;server:NFS的IP地址

2.部署

[root@k8s-master01 pv]# kubectl create -f pv-nfs.yaml

3.结果验证

[root@k8s-master01 pv]# kubectl get -f pv-nfs.yaml
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-nfs   5Gi        RWO            Recycle          Available           nfs-slow                16s

3.6.2 基于HostPath的PV

当公司目前没有可靠性的存储,但是想要部署k8s集群中应用的数据不丢失,这时把宿主机目录直接挂载到Pod,Pod的数据直接落在宿主机上。接下来介绍基于HostPath的PV:

1.在master01节点上创建挂载目录

[root@k8s-master01 pv]# mkdir -p /mnt/data

2.定义一个yaml文件

[root@k8s-master01 pv]# vim pv-hostpath.yaml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-hostpath
  labels:
    type: local
spec:
  storageClassName: hostpath
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

上面参数说明:

  • capacity:容量配置
  • accessModes:该PV的访问模式,这里设置为RWO,可以被单节点以读写模式挂载
  • storageClassName:PV的类,一个特定类型的PV 只能绑定到特定类别的PVC
  • hostPath:hostPath配置,path:"/mnt/data",其中/mnt/data为宿主机的目录

3.部署

[root@k8s-master01 pv]# kubectl create -f pv-hostpath.yaml

4.结果验证

[root@k8s-master01 pv]# kubectl get -f pv-hostpath.yaml 
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
task-pv-volume   10Gi       RWO            Retain           Available           hostpath                26s

3.6.3 基于Ceph RBD的PV

Ceph可能是目前企业内最常用的一种分布式存储之一,同时支持文件系统、块存储及对象存储,和上述NFS和HostPath相比,具有高可用性和读写高效性。接下来看一下Ceph RBD类型的PV配置:

1.定义一个yaml文件

[root@k8s-master01 pv]# vim pv-cephrbd.yaml 
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:是否是只读挂载

注意:Ceph的Pool和Image需要提前创建才能使用。虽然前面讲述了RBD类型的PV配置示例,但是在实际使用时,大多数Ceph存储的使用都是采用动态存储的方式,很少通过静态方式去管理。同时,Kubernetes所有的节点都需要安装ceph-common才能正常挂载Ceph.

2.部署

[root@k8s-master01 pv]# kubectl create -f pv-cephrbd.yaml

3.结果验证

[root@k8s-master01 pv]# kubectl get -f pv-cephrbd.yaml

3.7 PVC绑定PV

在工作场景中,k8s管理员会碰到两种场景:

  • 场景一:k8s管理员成功创建好PV,请求开发人员申请该PV并创建PVC配置到Volumes配置一个PVC类型的存 储,并指定PVC的名字是xxx即可
  • 场景二:k8s管理员成功创建好PV和PVC,请求开发人员在Volumes指定PVC的名字是xxx即可


这里是引用

            <p class="ztext-empty-paragraph"><br></p>
            <p data-pid="YEGCyHGC">
                <b>注意:PVC和PV进行绑定的前提条件是一些参数必须匹配,比如accessModes、storageClassName、volumeMode都需要相同,并且PVC的storage需要小于等于PV的storage配置。</b>
            </p>
            <p data-pid="ZvfdMEBO">下面进行PVC挂载示例:</p>
            <p data-pid="4PoPz8j_">首先创建PV</p>
            <p data-pid="RMUuywoX">1.定义一个yaml文件</p>
            <div class="highlight">
                <pre><code class="language-text">[root@k8s-master01 pv]# vim pv-nfs.yaml 

apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-nfs
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs-slow
nfs:
path: /data/nfs/test_nfs
server: 192.168.1.34

上面参数说明:



  • capacity:容量配置

  • volumeMode:卷的模式,目前支持Filesystem (文件系统) 和 Block(块),其中Block类型需 要后端存储支持,默认为文件系统

  • accessModes:该PV的访问模式,这里设置为RWO,可以被单节点以读写模式挂载

  • storageClassName:PV的类,一个特定类型的PV 只能绑定到特定类别的PVC

  • persistentVolumeReclaimPolicy:回收策略

  • nfs:NFS服务配置,包括以下两个选项:path:NFS上的共享目录;server:NFS的IP地址


2.部署



[root@k8s-master01 pv]# kubectl create -f pv-nfs.yaml


3.结果验证



[root@k8s-master01 pv]# kubectl get -f pv-nfs.yaml
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Available nfs-slow 16s


其次创建PVC


1.定义一个名为pvc-nfs.yaml 的yaml文件



[root@k8s-master01 pv]# vim pvc-nfs.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: nfs-pvc-claim
spec:
storageClassName: nfs-slow #要求PV一致
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi #小于等于PV大小


注意:PVC有命名空间限制,这里默认是default空间


2.部署



[root@k8s-master01 pv]# kubectl create -f pvc-nfs.yaml


3.结果验证,观察到状态已更改为Bound,但此时并不代表可用



[root@k8s-master01 pv]# kubectl get -f pvc-nfs.yaml
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nfs-pvc-claim Bound pv-nfs 5Gi RWO nfs-slow 60s


4.查看PV状态,此时PV状态由原来的Available变为Bound ,但此时并不代表可用



[root@k8s-master01 pv]# kubectl get pv pv-nfs
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv-nfs 5Gi RWO Recycle Bound default/nfs-pvc-claim nfs-slow 79m


最后,创建Pod


1.在k8s-master01上定义一个名为pvc-nfs-pod.yaml的yaml文件



[root@k8s-master01 pv]# vim pvc-nfs-pod.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx
name: nginx
namespace: default
spec:
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app: nginx
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: nfs-pvc-claim
containers:
- env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
image: registry.cn-hangzhou.aliyuncs.com/zq-demo/nginx:1.14.2
imagePullPolicy: IfNotPresent
name: nginx
volumeMounts:
- mountPath: “/usr/share/nginx/html”
name: task-pv-storage


2.在k8s-master01上开始部署



[root@k8s-master01 pv]# kubectl create  -f pvc-nfs-pod.yaml


3.在k8s-master01上查看pod状态



[root@k8s-master01 pv]# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-59fdd74bd4-2c2hk 1/1 Running 0 19s
nginx-59fdd74bd4-dlfgf 1/1 Running 0 19s


4.在k8s-master01上以容器的方式进入pod,修改文件内容,用于测试另一个Pod是否会同步



[root@k8s-master01 pv]# kubectl exec -it  nginx-59fdd74bd4-2c2hk  – sh
/ # cd /usr/share/nginx/html/
/usr/share/nginx/html # echo “test_nfs” > /usr/share/nginx/html/index.html
/usr/share/nginx/html # cat /usr/share/nginx/html/index.html
test_nfs


5.继续在k8s-master01上以容器的方式进入另一个pod后,查看已经同步



[root@k8s-master01 pv]# kubectl exec  nginx-59fdd74bd4-dlfgf  – cat /usr/share/nginx/html/index.html
test_nfs


3.8 PVC创建和挂载失败的原因


3.8.1 PVC一直Pending的原因


1.PVC的空间申请大小大于PV的大小


2.PVC的StorageClassName没有和PV的一致


3.PVC的accessModes和PV的不一致


3.8.2 挂载PVC的Pod一直处于Pending


1.PVC没有创建成功/PVC不存在


2.PVC和Pod不在同一个Namespace


四、存储分类


1.文件存储 一些数据可能需要被多个节点使用,比如用户的头像、用户上传的文 件等,实现方式:NFS、NAS、FTP、CephFS等。


2.块存储 一些数据只能被一个节点使用,或者是需要将一块裸盘整个挂载使用, 比如数据库、Redis等,实现方式:Ceph、GlusterFS、公有云。


3.对象存储
由程序代码直接实现的一种存储方式,云原生应用无状态化常用的实现方式,实现方式:一般是符合S3协议的云存储,比如AWS的S3存储、Minio、七牛云等。




参考

初识PV和PVC

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1472596.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「哈哥赠书活动 - 48期」-『商业分析思维与实践:用数据分析解决商业问题宣传文案』

⭐️ 赠书 - 《商业分析思维与实践》 ⭐️ 内容简介 本书以业务为导向&#xff0c;详细地讲解了如何通过大数据分析来解决商业问题。其目的在于运用大数据分析思维&#xff0c;帮助读者把学术知识应用于真实的业务场景&#xff0c;解决实际的业务问题。本书基于业务问题&#x…

鸿蒙 渲染控制

前提&#xff1a;基于官网3.1/4.0文档。参考官网文档 基于Android开发体系来进行比较和思考。&#xff08;或有偏颇&#xff0c;自行斟酌&#xff09; 1.概念 ArkUI通过自定义组件的build()函数和builder装饰器中的声明式UI描述语句构建相应的UI。在声明式描述语句中开发者除了…

GEE必须会教程—矢量数据类型

矢量这个词&#xff0c;我们在数学上并不陌生&#xff0c;它是既有方向又有大小的量。而在GIS中&#xff0c;常常利用欧氏空间的点、线、面来表示地理实体&#xff0c;进而构成我们使用频繁的矢量数据&#xff0c;它和栅格数据一同构成了地理信息数据的基础。今天开始&#xff…

AI:140-使用强化学习优化供应链管理

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

typecho 给文章创建目录树

受益于 shortcode 短代码插件和泽泽短代码中目录树的显示样式&#xff0c;形成了自己实现添加文章目录的思路&#xff1a; 一、文章目录树的结构 <div id"toc"><div class"toc-left"><div class"toc-btn" type"button&quo…

网络技术ensp 一个简单的交换机配置案例

由于工作调岗&#xff0c;转战网络运维了&#xff0c;第一次网络笔记 1.&#xff0c;目的&#xff1a;2台主机相互可以ping通&#xff0c;并且可以ping通网关地址&#xff0c;设备&#xff1a;2台主机&#xff0c;2台交换机 2网络拓扑图如下 3.主机pc1的配置信息 ip&#xff…

一个Post请求入门NestJS的路由与控制器

​ NestJS的控制器 控制器负责处理传入请求并向客户端返回响应。 控制器的目的是接收应用的特定请求。路由机制控制哪个控制器接收哪些请求。 通常&#xff0c;每个控制器都有不止一条路由&#xff0c;不同的路由可以执行不同的操作。 在使用了脚手架的项目中&#xff0c;我…

javascript给对象添加迭代器

迭代器是啥就自行百度了 为啥for…of可以遍历数组&#xff0c;为啥不能遍历对象&#xff0c;就是for…of会调用迭代器&#xff0c;而数组是内置了迭代器了&#xff0c;而对象没有内置&#xff0c;所以直接使用for…of遍历对象会报错&#xff0c;因此只用在对象的原型上面自定义…

temu/亚马逊美国站烧烤炉UL报告UL2728A应该怎么办理?

temu/亚马逊美国站烧烤炉UL报告UL2728A应该怎么办理&#xff1f; 近年来&#xff0c;烧烤炉在美国市场越来越受欢迎&#xff0c;其便捷性和独特的烹饪方式吸引了许多消费者。然而&#xff0c;为了确保产品的安全性和质量&#xff0c;美国市场对于烧烤炉产品的上架要求日益严格…

Python中的atexit模块:优雅地处理程序退出

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站AI学习网站。 目录 前言 atexit模块概述 atexit模块的基本用法 示例代码&#xff1a;文件操作时的应用场景 典型应用场景 1 资源释放…

西宾视频下载工具(mediadown)

一个支持多网站的视频下载工具。目前已经支持的网站有知乎、哔哩哔哩、得到、猫耳、蜻蜓FM。 西宾视频下载工具能够帮助你下载知乎知学堂、哔哩哔哩、得到课程、猫耳音频、蜻蜓FM的音视频文件。如果你是这些网站的会员&#xff0c;它还能帮你下载会员节目的音视频。 工具也不是…

【好书推荐-第五期】《Java开发坑点解析:从根因分析到最佳实践》(异步图书出品)

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公粽号&#xff1a;程序员洲洲。 &#x1f388; 本文专栏&#xff1a;本文…

深入理解基于 eBPF 的 C/C++ 内存泄漏分析

对于 C/C 程序员来说&#xff0c;内存泄露问题是一个老生常谈的问题。排查内存泄露的方法有很多&#xff0c;比如使用 valgrind、gdb、asan、tsan 等工具&#xff0c;但是这些工具都有各自的局限性&#xff0c;比如 valgrind 会使程序运行速度变慢&#xff0c;gdb 需要了解代码…

★【递归】【构造二叉树】Leetcode 106.从中序与后序遍历序列构造二叉树

★【递归】【构造二叉树】Leetcode 106.从中序与后序遍历序列构造二叉树 105. 从前序与中序遍历序列构造二叉树 106.从中序与后序遍历序列构造二叉树:star:思路分析递归解法 105. 从前序与中序遍历序列构造二叉树递归解法 ---------------&#x1f388;&#x1f388;题目链接&a…

跳房子留脚印

题目描述 N个格子里从左到右里面的数字是0,1,2,3&#xff0c;…N-1。小米和小白2个同学玩跳房子游戏&#xff0c;开始从第0格跳&#xff0c;跳出第N-1格子就停。小米同学每次跳过2格&#xff0c;再向前走1格&#xff0c;再跳过2格&#xff0c;向前走1格…。小白同学每次跳过4格…

DevOps VS 敏捷的区别是什么?

原文链接&#xff1a;DevOps VS 敏捷_软件开发生产线 CodeArts_理论实践_DevOps概览 当我们面对敏捷和DevOps的时候&#xff0c;总会不可避免的思考下面这些问题&#xff1a; 敏捷是什么&#xff1f;DevOps是什么&#xff1f;两者有什么区别&#xff1f;持续集成不是XP里面的…

JS基本知识

JS作用域的内存模型 每个函数都有各自的作用域、作用域链、变量对象、执行环境。 一、函数初始化&#xff1a;3作用域链。 函数被调用&#xff1a;1作用域、2变量对象、4执行环境。执行结束后&#xff0c;1作用域、3作用域链、4执行环境被销毁、2变量对象&#xff08;如果函…

【前后端的那些事】文件上传组件封装

文章目录 效果前端代码后端代码组件封装 效果 前端代码 /views/file/file.vue <template><el-row><el-uploadv-model:file-list"fileList"class"upload-demo"multiple:auto-upload"false":on-preview"handlePreview"…

Java SpringBoot 整合 MyBatis 小案例

Java SpringBoot 整合 MyBatis 小案例 基础配置&#xff08;注意版本号&#xff0c;容易报错&#xff09; pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http…

面试经典150题 -- 二叉树搜索树 (总结)

总的链接 : https://leetcode.cn/studyplan/top-interview-150/ 二叉搜索树相关概念 : 二叉搜索树是一个有序树。 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b;若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结…