在学习docker的过程中,已经了解到可以通过hostpath或者emtydir的方式来持久化我们的数据,但是显然我们应该选择更加可靠的持久化数据,这样容器在重建后,依然可以使用之前的数据。但是显然存储资源和 CPU 资源以及内存资源有很大不同,为了屏蔽底层的技术实现细节,让用户更加方便的使用,Kubernetes 便引入了 PV 和 PVC 两个重要的资源对象来实现对存储的管理。
PV 的全称是:PersistentVolume(持久化卷)。PersistentVolume 是 Volume 的一种类型,是对底层的共享存储的一种抽象。PV 由集群管理员进行创建和配置,就像节点 (Node) 是集群中的资源一样,PV 也是集群资源的一种。PV 包含存储类型、存储大小和访问模式。
PVC 的全称是:PersistentVolumeClaim(持久化卷声明),PVC 是用户存储的一种声明,PVC 和 Pod 比较类似,Pod 消耗的是节点,PVC 消耗的是 PV 资源,Pod 可以请求 CPU 和内存,而 PVC 可以请求特定的存储空间和访问模式。对于真正使用存储的用户不需要关心底层的存储实现细节,只需要直接使用 PVC 即可。
但是通过 PVC 请求到一定的存储空间也很有可能不足以满足应用对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求可能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes 又为我们引入了一个新的资源对象:StorageClass,通过 StorageClass 的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据 StorageClass 的描述就可以非常直观的知道各种存储资源的具体特性了,这样就可以根据应用的特性去申请合适的存储资源了。
一.演示后端存储为NFS
1.服务器172.31.132.151为NFS服务器,其他主机为客户端

2.NFS服务器设置共享目录/data/k8s/

3. 在客户端检查nfs是否有共享目录
##showmount -e 172.31.132.151

4. 在客户端新建目录,并挂载目录
##mkdir -p /root/course/kubeadm/data
##mount -t nfs 172.31.132.151:/data/k8s /root/course/kubeadm/data

5. NFS挂载验证


6.有了上面的 NFS 共享存储,下面我们就可以来使用 PV 和 PVC 了。PV 作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略等关键信息,下面我们来新建一个 PV 对象,使用 nfs 类型的后端存储,1G 的存储空间,访问模式为 ReadWriteOnce,回收策略为 Recyle,对应的 YAML 文件如下:(pv1-demo.yaml)
##touch pv1-demo.yaml

7.创建PV
##kubectl create -f pv1-demo.yaml
##kubectl get pv

8. 查看node信息
##kubectl get nodes

9. 新建PVC
同样的,我们来新建一个数据卷声明,我们来请求 1Gi 的存储容量,访问模式也是 ReadWriteOnce,YAML 文件如下:(pvc-nfs.yaml)
##touch pvc-nfs.yaml

##kubectl create -f pvc-nfs.yaml (创建PVC)

##kubectl get pv
同样我们可以看到 PV 也是 Bound 状态了,对应的声明是 default/pvc-nfs,就是 default 命名空间下面的 pvc-nfs,证明我们刚刚新建的 pvc-nfs 和我们的 pv-nfs 绑定成功了。

有的同学可能会觉得很奇怪,我们并没有在 pvc-nfs 中指定关于 pv 的什么标志,它们之间是怎么就关联起来了的呢?其实这是系统自动帮我们去匹配的,他会根据我们的声明要求去查找处于 Available 状态的 PV,如果没有找到的话那么我们的 PVC 就会一直处于 Pending 状态,找到了的话当然就会把当前的 PVC 和目标 PV 进行绑定,这个时候状态就会变成 Bound 状态了。
10.使用PVC
编写一个nginx的yaml文件,名字为nfs-pvc-deploy.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nfs-pvc
spec:
replicas: 3
template:
metadata:
labels:
app: nfs-pvc
spec:
containers:
- name: nginx
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: pvc2-nfs
---apiVersion: v1
kind: Service
metadata:
name: nfs-pvc
labels:
app: nfs-pvc
spec:
type: NodePort
ports:
- port: 80
targetPort: web
selector:
app: nfs-pvc
我们这里使用 nginx 镜像,将容器的 /usr/share/nginx/html 目录通过 volume 挂载到名为 pvc2-nfs 的 PVC 上面,然后创建一个 NodePort 类型的 Service 来暴露服务:
$ kubectl create -f nfs-pvc-deploy.yaml
deployment.extensions "nfs-pvc" created
service "nfs-pvc" created
$ kubectl get pods
kubectl get pods
NAME READY STATUS RESTARTS AGE
...
nfs-pvc-57c9945bd9-5r4r6 1/1 Running 0 19s
nfs-pvc-57c9945bd9-gz6p9 1/1 Running 0 19s
nfs-pvc-57c9945bd9-x6mvc 1/1 Running 0 19s
...
$ kubectl get svc
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
...
nfs-pvc NodePort 10.98.246.155 <none> 80:30769/TCP 1m
...
二.相关概念理解
1.Capacity(存储能力)
一般来说,一个 PV 对象都要指定一个存储能力,通过 PV 的 capacity属性来设置的,目前只支持存储空间的设置,就是我们这里的 storage=1Gi,不过未来可能会加入 IOPS、吞吐量等指标的配置。
2.AccessModes(访问模式)
AccessModes 是用来对 PV 进行访问模式的设置,用于描述用户应用对存储资源的访问权限,访问权限包括下面几种方式:
· ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载
· ReadOnlyMany(ROX):只读权限,可以被多个节点挂载
· ReadWriteMany(RWX):读写权限,可以被多个节点挂载
3.persistentVolumeReclaimPolicy(回收策略)
我这里指定的 PV 的回收策略为 Recycle,目前 PV 支持的策略有三种:
· Retain(保留)- 保留数据,需要管理员手工清理数据
· Recycle(回收)- 清除 PV 中的数据,效果相当于执行 rm -rf /thevoluem/*
· Delete(删除)- 与 PV 相连的后端存储完成 volume 的删除操作,当然这常见于云服务商的存储服务,比如 ASW EBS。
不过需要注意的是,目前只有 NFS 和 HostPath 两种类型支持回收策略。当然一般来说还是设置为 Retain 这种策略保险一点。
4.状态
一个 PV 的生命周期中,可能会处于4中不同的阶段:
· Available(可用):表示可用状态,还未被任何 PVC 绑定
· Bound(已绑定):表示 PV 已经被 PVC 绑定
· Released(已释放):PVC 被删除,但是资源还未被集群重新声明
· Failed(失败):表示该 PV 的自动回收失败
我们平时真正使用的资源其实是 PVC,就类似于我们的服务是通过 Pod 来运行的,而不是 Node,只是 Pod 跑在 Node 上而已
------后续会继续补充持久化存储相关内容




