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
相关推荐
能不能别报错1 小时前
K8s学习笔记(十六) 探针(Probe)
笔记·学习·kubernetes
能不能别报错3 小时前
K8s学习笔记(十四) DaemonSet
笔记·学习·kubernetes
火星MARK4 小时前
k8s面试题
容器·面试·kubernetes
Serverless社区5 小时前
阿里云函数计算 AgentRun 全新发布,构筑智能体时代的基础设施
阿里云·云原生·serverless·函数计算
赵渝强老师6 小时前
【赵渝强老师】Docker容器的资源管理机制
linux·docker·容器·kubernetes
能不能别报错7 小时前
K8s学习笔记(十五) pause容器与init容器
笔记·学习·kubernetes
稚辉君.MCA_P8_Java7 小时前
kafka解决了什么问题?mmap 和sendfile
java·spring boot·分布式·kafka·kubernetes
乄bluefox7 小时前
保姆级docker部署nacos集群
java·docker·容器
每天进步一点_JL8 小时前
Docker 是什么?
后端·docker·容器
一叶飘零_sweeeet8 小时前
从 0 到 1 掌控云原生部署:Java 项目的 Docker 容器化与 K8s 集群实战指南
docker·云原生·kubernetes·项目部署