概述
Kubernetes
对于有状态的容器应用或者对数据需要持久化的应用,可以通过 hostPath
或者 emptyDir
的方式来持久化我们的数据,但是我们需要更加可靠的存储来保存应用的持久化数据。不过存储资源和 CPU 资源以及内存资源有很大不同,为了屏蔽底层的技术实现细节,让用户更加方便的使用,Kubernetes
便引入了 PV
和 PVC
两个重要的资源对象来实现对存储的管理。
概念
PV (PersistentVolume)
是对底层网络共享存储的抽象,将共享存储定义为一种 “资源”。PV 一般由K8S的管理员所创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如 Ceph
、GlusterFS
、NFS
等,都是通过插件机制完成与共享存储的对接。
PVC (PersistentVolumeClaim)
是用户对存储资源的一个 “申请”。就像 Pod
消费 Node
资源一样,PVC
能够消费 PV
的资源。Pod
可以请求节点的CPU和内存,而 PVC
可以请求特定的存储空间和访问模式。对于用户来说,不需要关心底层的存储实现细节,只需要直接使用 PVC
即可。
实战:基于NFS共享存储创建PV和PVC
示例:基于NFS存储来创建PV和PVC
本次共享存储资源选择本地自建的NFS,关于搭建NFS的教程参考之前写的博文:centos7搭建NFS服务
试验环境如下,注意所有k8s节点都要安装nfs,yum install -y nfs-tools
:
主机名hostname | IP地址 | 说明 |
---|---|---|
master | 192.168.18.10 | k8s主节点 |
node1 | 192.168.18.11 | k8s的node1节点 |
node2 | 192.168.18.12 | k8snode2节点 |
db | 192.168.18.7 | NFS服务器,共享目录/data/nfs/test-pv |
PV
PV 作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略、后端存储类型等关键信息的设置。PV 是没有名称空间的隔离性的。下面来创建一个PV 资源对象:
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
storageClassName: nfs-slow
nfs:
path: /data/nfs/test-pv
server: 192.168.18.7
上面yaml文件表明:创建了一个名字是pv001的PV,使用NFS类型的后端存储,声明5G的存储空间,访问模式是 ReadWriteMany
,回收策略为 Recyle
。有了yaml文件后,直接创建即可。
# 创建pv
[root@master k8s-yaml]# kubectl create -f pv.yaml
# 查看pv
[root@master k8s-yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 5Gi RWX Recycle Available nfs-slow 5s
PV的常用配置参数
1. 存储能力(Capacity)
一个 PV 对象一般都要指定一个存储能力,通过 PV 的 capacity
属性来设置的,比如这里的 storage: 5Gi
,目前只支持对存储空间的设置,未来可能加入IOIPS、吞吐量等指标的设置。
2. 访问模式(Access Modes)
对 PV 进行访问模式的设置,用于描述用户的应用对存储资源的访问权限。分为三种:
ReadWriteOnce
:读写权限,并且只能被单个 Node 挂载;ReadOnlyMany
:只读权限,允许被多个 Node 挂载;ReadWriteMany
:读写权限,允许被多个 Node 挂载
一些 PV 可能支持多种访问模式,但是在挂载的时候只能使用一种访问模式,多种访问模式是不会生效的。
3. 存储类别(Class)
PV 可以设定其存储的类别,通过 storageClassName
参数指定一个 StorageClass
资源对象的名称。具有特定类别的 PV 只能与请求了该类别的 PVC 进行绑定。未设定类别的 PV 则只能与不请求任何类别的 PVC 进行绑定。
4. 回收策略
回收策略是通过 persistentVolumeReclaimPolicy
参数进行设置,可选性如下:
Retain
:保留,需要手动清理数据Recycle
:回收,清楚PV中的数据,相当于rm -rf /thevolume/*
命令Delete
:删除,与 PV 相连的后端存储完成volume的删除操作,删除 PVC 后,PV也会被删掉。这一类的PV,需要支持删除功能,是动态存储的默认方式。
PV 的生命周期
一个 PV 在生命周期可能处于下面四个阶段之一:
Available
:可用状态,还没有于某个PVC进行绑定Bound
:已跟某个PVC绑定Released
:绑定的PVC已经删除,资源已经释放,但是没有被集群回收Failed
:自动资源回收失败
上面创建了PV之后,由于还没有任何PVC跟PV绑定,所以PV的状态还是 Available
。
PVC
PVC 作为用户对存储资源的需求申请,主要包括存储空间请求、访问模式、PV选择条件和存储类别的信息的设置。如下,新建一个PVC,跟上面创建的PV进行绑定。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: myclaim
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 3Gi
storageClassName: nfs-slow
该PVC申请了与存储类别名称为 nfs-slow
的 PV 进行绑定,请求3G的存储容量,访问模式是 ReadWriteMany
,创建该PVC:
[root@master k8s-yaml]# kubectl create -f pvc.yaml
# 查看default名称空间下的PVC
[root@master k8s-yaml]# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
myclaim Bound pv001 5Gi RWX nfs-slow 6s
# 注意,PVC有名称空间的隔离性
[root@master k8s-yaml]# kubectl get pvc -n kube-system
No resources found in kube-system namespace.
# 查看PV状态
[root@master k8s-yaml]# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001 5Gi RWX Recycle Bound default/myclaim nfs-slow 3h29m
可以看到,在PVC与PV进行绑定之后,PV的状态变成了 Bound
。但是从上面也看出,我的 PVC 里面声明的容量是3G,而PV里面声明的容量是5G,结果创建出来的PVC容量却是5G,说明,PV的容量是多少,PVC的容量就是多少。
如果PVC里面设置的容量超过PV里面定义的容量,那么PVC是创建不成功的,会一直处于Pending状态。
使用PVC
上面创建了PV和PVC,接下来就可以使用它们了,使用下面nginx-pvc.yaml
进行测试:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-pvc
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.18.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
volumeMounts:
- mountPath: /usr/share/nginx/html
name: my-pvc-volume
volumes:
- name: my-pvc-volume
persistentVolumeClaim:
claimName: myclaim
然后在nfs的共享目录里面创建个html文件:
[root@db ]# cd /data/nfs/test-pv/
[root@db test-pv]# echo "hello k8s pvc" > index.html
创建Deployment
[root@master k8s-yaml]# kubectl create -f nginx-pvc.yaml
查看Pod:
[root@master k8s-yaml]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-pvc-78c9859d7-94lxn 1/1 Running 0 38s 10.244.166.165 node1 <none> <none>
访问Pod:
[root@master k8s-yaml]# curl 10.244.166.165
hello k8s pvc
可以看到,Pod内部的容器已经成功挂载nfs的后端存储。
参考资料
-
《Kubernetes 权威指南:从 Docker 到 Kubernetes 实践全接触 (第四版) 》