Volume & PersistentVolume
1  | 官方文档  | 
- Kubernetes中的Volume提供了在容器中挂载外部存储的能力
 - Pod需要设置卷来源(spec.volume)和挂载点(spec.containers.volumeMounts)两个信息后才可以使用相应的Volume
 - 本地数据卷
- hostPath
 - emptyDir
 
 
Volume 概念
- 容器中的文件在磁盘上是临时存放的,这给容器中运行的特殊应用程序带来一些问题。
 - 首先,当容器崩溃时,kubelet 将重新启动容器,容器中的文件将会丢失——因为容器会以干净的状态重建。
 - 其次,当在一个 Pod 中同时运行多个容器时,常常需要在这些容器之间共享文件。
 - Kubernetes 抽象出 Volume 对象来解决这两个问题。
 
Volume 支持的类型
- 本地 emptyDir hostPath
 - 网络 自建存储 ceph
 
emptyDir
- 创建一个空卷,挂载到Pod中的容器。
 - Pod删除该卷也会被删除,随着pod的生命周期 而存在
 - 应用场景:Pod中容器之间数据共享,一个pod中有多个容器,他们之间完成数据共享,不使用数据卷容器之间的文件系统是隔离的,只能看到自己的
 - 使用数据卷让容器之间某个目录达到共享
 
1  | [root@k8s-master demo2]# vim emptydir.yaml  | 
1  | [root@k8s-master demo2]# kubectl apply -f emptydir.yaml  | 
hostPath
- 挂载 Node 文件系统上文件或者目录到Pod中的容器。
 - 应用场景:Pod中容器需要访问宿主机文件
 - hostPath 有点像 Bind Mounts
 - emptyDir 有点像 Volume
 
1  | [root@k8s-master demo2]# vim hostPath.yaml  | 
1  | [root@k8s-master demo2]# kubectl apply -f hostPath.yaml  | 
1  | [root@k8s-master demo2]# kubectl get pod -o wide  | 
1  | [root@k8s-master demo2]# kubectl exec -it my-pod2 sh  | 
NFS(网络存储)
- 本地数据卷 只能绑定指定的node上,如果node出现问题,node上的pod会被放到其他node上,数据就无从获取
 挂载网络卷 就算拉一起一个新的也能访问到
安装nfs
1  | # 选择master2 作为服务端  | 
- 配置服务端的访问路径 启动服务端守护进程
 
1  | [root@k8s-master2 ~]# vim /etc/exports  | 
- 配置启动
 
1  | # k8s帮我们mount 在配置文件里指定,只要安装nfs客户端即可  | 
1  | [root@k8s-master demo2]# kubectl apply -f nfs.yaml  | 
1  | [root@k8s-master demo2]# kubectl get pod  | 
1  | [root@k8s-master demo2]# kubectl exec -it nginx-nfs-deployment-5b8f7c4d57-9tbgq bash  | 
1  | # 销毁  | 
PersistentVolume 持久存储数据卷
- PersistenVolume(PV):对存储资源创建和使用的抽象,使得存储作为集群中的资源管理。(专业的存储人员来做)
- 静态 手动创建资源
 - 动态 自动创建PV
 
 PersistentVolumeClaim(PVC):让用户不需要关心具体的Volume实现细节,只关心用多大的容量。
作用: 将存储资源作为集群的一部分来管理,开发者不用关系如何创造出存储,也不必担心暴露存储的位置。
Pod使用持久卷在任何地点都能访问,即使POD销毁再拉起也能使用。
PV是提供存储容量的,PVC是消费存储的。PV与PVC的关系是绑定,绑定后其他人就无法使用了。
pv 静态供给
  
- 容器中指定 pvc
 - 创建pvc需求模板
 - 创建pv
 
创建 pv
- pv可以是存储人员定义,他们会创建很多pv等待pvc来挂载
 
1  | [root@k8s-master1 demo]# cat pv-nfs.yaml  | 
创建 deployment 指定pvc
1  | [root@k8s-master1 demo]# vim nfs-pvc.yaml  | 
1  | [root@k8s-master1 demo]# kubectl apply -f nfs-pvc.yaml  | 
1  | [root@k8s-master1 demo]# kubectl exec -it nginx-nfs-deployment-7ccdb4f76f-7m6cp bash  | 
删除 pvc 和 pv
- 默认情况下 删除的pvc,之前与他绑定的pv也不能够再使用了,需要手动清理pv,但是数据还在
 
1  | [root@k8s-master1 demo]# kubectl delete -f nfs-pvc.yaml  | 
1  | # 重新部署应用 , 查看数据  | 
  
  
总结 PV 静态供给
- 持久卷静态供给,pod需要申请pvc,可以在deployment同一个yaml中定义
 - 提供数据卷定义,创建 pv
 - pvc会根据绑定关系,尤其是存储的容量和访问模式去匹配pvc
 - 这种情况下创建pv需要手动创建,如何可以自动部署绑定
 
pv 动态供给
- 主要是针对容量问题,手动划分非常麻烦,如果pvc的容量匹配不上pv就无法绑定
 - k8s的动态供给就是可以动态划分容量
 - Dynamic Provisioning机制工作的核心在于StorageClass的API对象。
 - StorageClass声明存储插件,用于自动创建PV。
 
k8s 支持持久卷的存储插件
1  | https://kubernetes.io/docs/concepts/storage/persistent-volumes/  | 
  
StorageClass
- StorageClass 是能够自动操作后端存储,并且自动创建pv 。
 - StorageClass 声明使用哪种存储插件,它来对接存储。
 - Kubernetes支持动态供给的存储插件:
 
1  | https://kubernetes.io/docs/concepts/storage/storage-classes/  | 
  
  
1  | # 上传 storage-class  | 
StorageClass 定义
1  | [root@k8s-master1 storage-class]# cat storageclass-nfs.yaml  | 
提供者 自动创建pv
1  | # 该服务帮我们自动创建pv  | 
1  | 参考地址:  | 
授权
- 动态创建pv插件需要连接apiserver ,所以需要授权
 
1  | [root@k8s-master1 storage-class]# cat rbac.yaml  | 
创建 pv 动态供给
1  | [root@k8s-master1 storage-class]# kubectl apply -f storageclass-nfs.yaml  | 
自动供给流程
  
- kubectl 部署有状态应用,唯一的网路身份标识符,主机名=dns名称和持久存储
 - mysql主从的数据不一样的,所以需要存储保持不同的数据
 - Statefulset 也会去维护存储,网络身份和存储都标识 0 1 2
 - 部署一个应用存储部分会去请求 -> storageclass -> nfs-client-provisioner 这个pod -> 请求nfs创建pv
 - 应用里面指定好 使用哪个 storageclass 就行
 
pv 动态供给应用案例 Statefulset + MySQL
1  | [root@k8s-master1 storage-class]# cat mysql-demo.yaml  | 
1  | [root@k8s-master1 storage-class]# kubectl get pod,pv,pvc  | 
创建mysql pod 去测试连接数据库
1  | # mysql 通过dns访问  | 
测试删除一个pod 看能否自动挂载存储
1  | [root@k8s-master1 storage-class]# kubectl delete pod db-0  | 
删除 pv
1  | 1. 先删除 与其关联的 Pod 及 PVC  | 
重新建立pv,pvc和 mysql有状态部署
1  | # 如果删除了 pv和pvc 再重新创建pod 是会重新分配存储  | 
