目录
[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