k8s 中存储之 PV 持久卷 与 PVC 持久卷申请

目录

[1 PV 与 PVC 介绍](#1 PV 与 PVC 介绍)

[1.1 PersistentVolume(持久卷,简称PV)](#1.1 PersistentVolume(持久卷,简称PV))

[1.2 PersistentVolumeClaim(持久卷声明,简称PVC)](#1.2 PersistentVolumeClaim(持久卷声明,简称PVC))

[1.3 使用了PV和PVC之后,工作可以得到进一步的细分:](#1.3 使用了PV和PVC之后,工作可以得到进一步的细分:)

[2 持久卷实验配置介绍](#2 持久卷实验配置介绍)

[2.1 PV 的配置介绍](#2.1 PV 的配置介绍)

[2.2 PVC 的配置介绍](#2.2 PVC 的配置介绍)

[3 持久卷实验](#3 持久卷实验)

[3.1 创建 PV](#3.1 创建 PV)

[3.2 查看 PV 资源是否被创建成功](#3.2 查看 PV 资源是否被创建成功)

[3.3 创建 PVC 与 PV 进行绑定](#3.3 创建 PVC 与 PV 进行绑定)

[3.4 创建一个pod进行测试](#3.4 创建一个pod进行测试)

[3.5 接下来的 pv2 与 pv3 也是相同的操作](#3.5 接下来的 pv2 与 pv3 也是相同的操作)

[3.6 PV 2](#3.6 PV 2)

[3.7 PV 3](#3.7 PV 3)


1 PV 与 PVC 介绍

前面已经学习了使用NFS提供存储,此时就要求用户会搭建NFS系统,并且会在yaml配置nfs。由于kubernetes支持的存储系统有很多,要求客户全都掌握,显然不现实。为了能够屏蔽底层存储实现的细节,方便用户使用, kubernetes引入PV和PVC两种资源对象。

PV(Persistent Volume)是持久化卷的意思,是对底层的共享存储的一种抽象。一般情况下PV由kubernetes管理员进行创建和配置,它与底层具体的共享存储技术有关,并通过插件完成与共享存储的对接。

PVC(Persistent Volume Claim)是持久卷声明的意思,是用户对于存储需求的一种声明。换句话说,PVC其实就是用户向kubernetes系统发出的一种资源需求申请。

1.1 PersistentVolume(持久卷,简称PV)

  • pv是集群内由管理员提供的网络存储的一部分。

  • PV也是集群中的一种资源。是一种volume插件,

  • 但是它的生命周期却是和使用它的Pod相互独立的。

  • PV这个API对象,捕获了诸如NFS、ISCSI、或其他云存储系统的实现细节

  • pv有两种提供方式:静态和动态

    • 静态PV:集群管理员创建多个PV,它们携带着真实存储的详细信息,它们存在于Kubernetes API中,并可用于存储使用

    • 动态PV:当管理员创建的静态PV都不匹配用户的PVC时,集群可能会尝试专门地供给volume给PVC。这种供给基于StorageClass

1.2 PersistentVolumeClaim(持久卷声明,简称PVC)

  • 是用户的一种存储请求

  • 它和Pod类似,Pod消耗Node资源,而PVC消耗PV资源

  • Pod能够请求特定的资源(如CPU和内存)。PVC能够请求指定的大小和访问的模式持久卷配置

  • PVC与PV的绑定是一对一的映射。没找到匹配的PV,那么PVC会无限期得处于unbound未绑定状态

1.3 使用了PV和PVC之后,工作可以得到进一步的细分:

  • 存储:存储工程师维护

  • PV: kubernetes管理员维护

  • PVC:kubernetes用户维护

2 持久卷实验配置介绍

2.1 PV 的配置介绍

PV是存储资源的抽象,下面是资源清单文件的解释:

bash 复制代码
apiVersion: v1  
kind: PersistentVolume
metadata:
  name: pv2
spec:
  nfs: # 存储类型,与底层真正存储对应
  capacity:  # 存储能力,目前只支持存储空间的设置
    storage: 2Gi
  accessModes:  # 访问模式
  storageClassName: # 存储类别
  persistentVolumeReclaimPolicy: # 回收策略

PV 的关键配置参数说明:

  • 存储类型

    底层实际存储的类型,kubernetes支持多种存储类型,每种存储类型的配置都有所差异

  • 存储能力(capacity)

目前只支持存储空间的设置( storage=1Gi ),不过未来可能会加入IOPS、吞吐量等指标的配置

  • 访问模式(accessModes)

    用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:

    • ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载

    • ReadOnlyMany(ROX): 只读权限,可以被多个节点挂载

    • ReadWriteMany(RWX):读写权限,可以被多个节点挂载

    需要注意的是,底层不同的存储类型可能支持的访问模式不同

  • 回收策略(persistentVolumeReclaimPolicy)

    当PV不再被使用了之后,对其的处理方式。目前支持三种策略:

    • Retain (保留) 保留数据,需要管理员手工清理数据,当一个PV不再被任何PVC使用时(即PVC被删除或被绑定到其他PV),PV本身仍然存在,并且其上的数据不会被自动清除。管理员需要手动处理这些PV,可以重新绑定给新的PVC,或者手动删除PV。

    • Recycle(回收) 清除 PV 中的数据,效果相当于执行 rm -rf /thevolume/*

    • Delete (删除) 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务。当一个PV不再被任何PVC使用时,PV会被自动删除,并且其上的数据也会被清除。PV一旦不再使用,就会被自动清理,减少了管理员的工作量。

    需要注意的是,底层不同的存储类型可能支持的回收策略不同

只有 NFS 和 HostPath 支持回收利用

AWS EBS,GCE PD,Azure Disk,or OpenStack Cinder卷支持删除操作。

  • 存储类别

    PV可以通过storageClassName参数指定一个存储类别

    • 具有特定类别的PV只能与请求了该类别的PVC进行绑定

    • 未设定类别的PV则只能与不请求任何类别的PVC进行绑定

  • 状态(status)

    一个 PV 的生命周期中,可能会处于4中不同的阶段:

    • Available(可用): 表示可用状态,还未被任何 PVC 绑定

    • Bound(已绑定): 表示 PV 已经被 PVC 绑定

    • Released(已释放): 表示 PVC 被删除,但是资源还未被集群重新声明

    • Failed(失败): 表示该 PV 的自动回收失败

2.2 PVC 的配置介绍

PVC是资源的申请,用来声明对存储空间、访问模式、存储类别需求信息。下面是资源清单文件:

bash 复制代码
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc
  namespace: dev
spec:
  accessModes: # 访问模式
  selector: # 采用标签对PV选择
  storageClassName: # 存储类别
  resources: # 请求空间
    requests:
      storage: 5Gi

PVC 的关键配置参数说明:

  • 访问模式(accessModes)

用于描述用户应用对存储资源的访问权限

  • 选择条件(selector)

    通过Label Selector的设置,可使PVC对于系统中己存在的PV进行筛选

  • 存储类别(storageClassName)

    PVC在定义时可以设定需要的后端存储的类别,只有设置了该class的pv才能被系统选出

  • 资源请求(Resources )

    描述对存储资源的请求

3 持久卷实验

3.1 创建 PV

PV 资源用于在集群中管理持久性存储。PV 资源配置如下:

其实PV 主要的作用无非就是选择哪种类型的网络文件系统,如这次使用的就是NFS的文件系统。

或者说选择 回收的策略、访问的模式等等

bash 复制代码
[root@k8s-master volumes]# vim pv1-nfs.yml

apiVersion: v1 
kind: PersistentVolume  # 定义资源类型为PersistentVolume
metadata:  
  name: pv1  
spec:  
  storageClassName: my-nfs  # 指定存储类名称
  capacity:  # PV的容量
    storage: 5Gi  # PV的大小为5GiB
  volumeMode: Filesystem  # 指定卷的模式为文件系统
  accessModes:  # PV的访问模式
  - ReadWriteMany  # 支持多个节点同时读写
  # 设置PV的回收策略为Retain(保留),这意味着当PV不再被任何PVC使用时,
  # PV仍然存在,并且其上的数据不会被自动清除
  persistentVolumeReclaimPolicy: Retain  
  # 使用NFS类型的卷
  nfs:  # 使用NFS类型的卷
    server: 192.168.239.50  # NFS服务器的IP地址
    path: /nfsdata/pv1  # 在NFS服务器上的路径


[root@k8s-master volumes]# kubectl apply -f pv1-nfs.yml 

3.2 查看 PV 资源是否被创建成功

可以发现,虽然创建成功了,但他还处于 Available 的状态 ,这是未绑定的的状态但他是可用的,我们需要将 PV 与 PVC 进行绑定,最终实现的状态为 Bound

bash 复制代码
[root@k8s-master volumes]# kubectl get persistentvolume
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pv1    5Gi        RWX            Retain           Available           my-nfs         <unset>                          13s

3.3 创建 PVC 与 PV 进行绑定

bash 复制代码
[root@k8s-master volumes]# vim pv1-nfs.yml 

apiVersion: v1
kind: PersistentVolume  # 定义PersistentVolume资源
metadata:
  name: pv1  # PV的名称
spec:
  storageClassName: my-nfs  # 指定存储类名称,与PVC要对应
  capacity:
    storage: 5Gi  # PV的容量大小
  volumeMode: Filesystem  # 卷的模式为文件系统
  accessModes:  # PV的访问模式
  - ReadWriteMany  # 支持多个节点同时读写
  persistentVolumeReclaimPolicy: Retain  # 设置PV的回收策略为Retain(保留)
  nfs:  # 使用NFS类型的卷
    server: 192.168.239.50  # NFS服务器的IP地址
    path: /nfsdata/pv1  # 在NFS服务器上的路径
# 在pv的 基础上增加以下 pvc 内容
---
apiVersion: v1
kind: PersistentVolumeClaim  # 定义PersistentVolumeClaim资源
metadata:
  name: pvc1  # PVC的名称  , 注意记住这个名字 ,在后面建立pod 的时候得引用PVC的名字
spec:
  storageClassName: my-nfs  # 指定存储类名称,与PV中的storageClassName要对应
  accessModes:  # PVC请求的访问模式
  - ReadWriteMany  # 支持多个节点同时读写
  resources:  # PVC请求的资源
    requests:
      storage: 1Gi  # 请求的存储容量大小 ,注意这个值不能超过PV的实际值


# 声明 pvc
[root@k8s-master volumes]# kubectl apply -f pv1-nfs.yml 

# 查看pv 与pvc的状态是否变为Bound    
[root@k8s-master volumes]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pv1    5Gi        RWX            Retain           Bound    default/pvc1   my-nfs         <unset>                          164m

[root@k8s-master volumes]# kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
pvc1   Bound    pv1      5Gi        RWX            my-nfs         <unset>                 45s

3.4 创建一个pod进行测试

bash 复制代码
# 创建清单文件
[root@k8s-master volumes]# vim pvc1-nginx.yml 

apiVersion: v1
kind: Pod
metadata:
  name: pvc-nginx
spec:
  volumes:  # Pod中使用的卷列表
  - name: vol1  # 卷的名称
    persistentVolumeClaim:  # 使用PersistentVolumeClaim类型的卷
      claimName: pvc1  # 指定要使用的PVC的名称

  containers:
  - image: nginx
    name: nginx
    volumeMounts:    # 容器内卷的挂载点 , 即将vol1卷挂载到以下此目录下
    - mountPath: /usr/share/nginx/html
      name: vol1

# 声明清单文件
[root@k8s-master volumes]# kubectl apply -f pvc-nginx.yml 

# 查看pod是否创建成功
[root@k8s-master volumes]# kubectl get pods -o wide 
NAME                       READY   STATUS      RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
nginx-v1-dbd4bc45b-49hhw   1/1     Running     0          4d      10.244.2.54   k8s-node2   <none>           <none>
nginx-v2-bd85b8bc4-nqpv2   1/1     Running     0          4d      10.244.1.35   k8s-node1   <none>           <none>
pvc-nginx                  1/1     Running     0          15s     10.244.2.64   k8s-node2   <none>           <none>
testpod                    0/1     Completed   0          3d12h   10.244.2.58   k8s-node2   <none>           <none>

# 尝试以下去访问,发现访问不成功,这是因为这是一个新的卷里面并没有东西
[root@k8s-master volumes]# curl 10.244.2.64
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.27.1</center>
</body>
</html>

# NFS 服务器上在指定PV中添加数据内容
[root@harbor nfsdata]# echo this is pv1 nginx > /nfsdata/pv1/index.html
[root@harbor nfsdata]# ls pv1/
index.html


# 由于并没内使用 ingress 也没有使用 NodePode 来暴露 所以仅在集群内访问
[root@k8s-master volumes]# kubectl get pod pvc-nginx -o wide
NAME        READY   STATUS    RESTARTS   AGE    IP            NODE        NOMINATED NODE   READINESS GATES
pvc-nginx   1/1     Running   0          153m   10.244.2.64   k8s-node2   <none>           <none>

[root@k8s-master volumes]# curl 10.244.2.64
this is pv1 nginx

3.5 接下来的 pv2 与 pv3 也是相同的操作

步骤:

创建 PV --> 声明 PV --> 查看是否正确创建 --> 创建 PVC 与 PV 进行绑定(PVC 与 PV 的类名要相同storageClassName) --> 声明PVC --> 创建一个 pod 指定PVC名称 验证是否可用

3.6 PV 2

bash 复制代码
# 创建资源清单文件
[root@k8s-master volumes]# vim pv2-nfs.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv2
spec:
  storageClassName: my-nfs-pv2 # 与PVC 要对应
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
  - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 192.168.239.50
    path: /nfsdata/pv2
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc2
spec:
  storageClassName: my-nfs-pv2 # 与PV 中的 storageClassName 要对应
  accessModes:
  - ReadOnlyMany
  resources:
    requests:
      storage: 1Gi

# 声明 PV PVC 
[root@k8s-master volumes]# kubectl apply -f pv2-nfs.yml 
persistentvolume/pv2 created
persistentvolumeclaim/pvc2 created

[root@k8s-master volumes]# kubectl get pv
NAME   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
pv1    5Gi        RWX            Retain           Bound    default/pvc1   my-nfs         <unset>                          179m
pv2    5Gi        ROX            Retain           Bound    default/pvc2   my-nfs-pv2     <unset>                          2m52s

[root@k8s-master volumes]# kubectl get pvc
NAME   STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
pvc1   Bound    pv1      5Gi        RWX            my-nfs         <unset>                 169m
pvc2   Bound    pv2      5Gi        ROX            my-nfs-pv2     <unset>                 2m59s


[root@k8s-master volumes]# vim pvc2-nginx.yml 
apiVersion: v1
kind: Pod
metadata:
  name: pvc2-nginx
spec:
  containers:
  - image: nginx
    name: nginx-pvc2
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: vol2
  volumes:
  - name: vol2
    persistentVolumeClaim:
      claimName: pvc2


[root@k8s-master volumes]# kubectl apply -f pvc2-nginx.yml 
pod/pvc2-nginx created

[root@k8s-master volumes]# kubectl get pod pvc2-nginx -o wide
NAME         READY   STATUS    RESTARTS   AGE    IP            NODE        NOMINATED NODE   READINESS GATES
pvc2-nginx   1/1     Running   0          2m4s   10.244.1.37   k8s-node1   <none>           <none>

# NFS服务器添加数据文件
[root@harbor nfsdata]# ls 
pv1  pv2  pv3
[root@harbor nfsdata]# echo this is pv2 nginx > /nfsdata/pv2/index.html

# 测试访问
[root@k8s-master volumes]# curl 10.244.1.37 
this is pv2 nginx

3.7 PV 3

bash 复制代码
[root@k8s-master volumes]# vim pv3-nfs.yml 
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv3
spec:
  storageClassName: my-nfs-pv3 # 与PVC 要对应
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 192.168.239.50
    path: /nfsdata/pv3
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc3 # 名称必须与pod中引用的一致
spec:
  storageClassName: my-nfs-pv3 # 与PV 中的 storageClassName 要对应
  accessModes:
    - ReadOnlyMany
  resources:
    requests:
      storage: 1Gi

[root@k8s-master volumes]# kubectl apply -f pv3-nfs.yml 

[root@k8s-master volumes]# kubectl get pv,pvc
NAME                   CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM          STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/pv1   5Gi        RWX            Retain           Bound    default/pvc1   my-nfs         <unset>                          3h31m
persistentvolume/pv2   5Gi        ROX            Retain           Bound    default/pvc2   my-nfs-pv2     <unset>                          8m21s
persistentvolume/pv3   5Gi        ROX            Retain           Bound    default/pvc3   my-nfs-pv3     <unset>                          10s

NAME                         STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/pvc1   Bound    pv1      5Gi        RWX            my-nfs         <unset>                 3h20m
persistentvolumeclaim/pvc2   Bound    pv2      5Gi        ROX            my-nfs-pv2     <unset>                 8m21s
persistentvolumeclaim/pvc3   Bound    pv3      5Gi        ROX            my-nfs-pv3     <unset>                 10s
[root@k8s-master volumes]# vim pvc3-nginx.yml 
[root@k8s-master volumes]# kubectl apply -f pvc3-nginx.yml 


[root@k8s-master volumes]# vim pvc3-nginx.yml 
apiVersion: v1
kind: Pod
metadata:
  name: pvc3-nginx
spec:
  containers:
  - image: nginx
    name: nginx-pvc3
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: vol3
  volumes:
  - name: vol3
    persistentVolumeClaim:
      claimName: pvc3


[root@k8s-master volumes]# kubectl apply -f pvc3-nginx.yml 

[root@k8s-master volumes]# kubectl get pods pvc3-nginx -o wide
NAME         READY   STATUS    RESTARTS   AGE     IP            NODE        NOMINATED NODE   READINESS GATES
pvc3-nginx   1/1     Running   0          2m51s   10.244.2.65   k8s-node2   <none>           <none>

# NFS 增加数据文件
[root@harbor nfsdata]# echo this is pv3 nginx > /nfsdata/pv3/index.html

# 访问测试
[root@k8s-master volumes]# curl 10.244.2.65
this is pv3 nginx
相关推荐
CP-DD1 小时前
Docker 容器化开发 应用
运维·docker·容器
老司机张师傅2 小时前
【微服务实战之Docker容器】第七章-Dockerfile解析
容器·dockerfile·虚悬镜像·docker学习
登云时刻3 小时前
Kubernetes集群外连接redis集群和使用redis-shake工具迁移数据(一)
redis·kubernetes·bootstrap
运维&陈同学3 小时前
【zookeeper03】消息队列与微服务之zookeeper集群部署
linux·微服务·zookeeper·云原生·消息队列·云计算·java-zookeeper
吴半杯4 小时前
gateway漏洞(CVE-2022-22947)
docker·kubernetes·gateway
Code_Artist6 小时前
使用Portainer来管理并编排Docker容器
docker·云原生·容器
Eternal-Student6 小时前
【docker 保存】将Docker镜像保存为一个离线的tar归档文件
运维·docker·容器
码农小丘6 小时前
一篇保姆式centos/ubuntu安装docker
运维·docker·容器
灼烧的疯狂8 小时前
K8S + Jenkins 做CICD
容器·kubernetes·jenkins
wenyue11219 小时前
Revolutionize Your Kubernetes Experience with Easegress: Kubernetes Gateway API
容器·kubernetes·gateway