目的
本文详细介绍了kubernentes的存储,使用NFS进行演示,让你充分了解和使用pv和pvc,可以举一反三的使用持久化存储。
概述
Volume
Volume可以支持local
、nfs
、cephfs
、glusterfs
以及各种云计算平台。
官网Volume的配置都是在一个创建pod的yaml文件中,例如
1 | apiVersion: v1 |
PV和PVC
PV的全称是: PersistentVolume (持久化卷),是对底层的共享存储的一种抽象,PV由管理员进行创建和配置,它和具体的底层的共享存储技术的实现方式有关,比如Ceph、GlusterFS、NFS等,都是通过插件机制完成与共享存储的对接.
PVC的全称是: PersistenVolumeClaim (持久化卷声明),PVC是用户存储的一种声明,PVC和Pod比较类型,Pod是消耗节点,PVC消耗的是PV资源,Pod可以请求CPU的内存,而PVC可以请求特定的存储空间和访问模式。对于真正存储的用户不需要关心底层的存储实现细节,只需要直接使用PVC即可.
但是通过PVC请求一定的存储空间也很有可能不足以满足对于存储设备的各种需求,而且不同的应用程序对于存储性能的要求也能也不尽相同,比如读写速度、并发性能等,为了解决这一问题,Kubernetes又为我们引入了一个新的资源对象: StorageClass,通过StorageClass的定义,管理员可以将存储资源定义为某种类型的资源,比如快速存储、慢速存储等,用户根据StorageClass的描述就可以非常直观的知道各种存储资源特性了,这样就可以根据应用的特性去申请合适的存储资源了
演示
安装NFS服务
#这里我使用单独服务器进行演示,实际上随便一台服务器安装nfs都可以 (建议和kubernetes集群分开,找单独一台机器)
1 | # 安装 |
NFS客户端
我们nfs server端已经完毕,接下来在所有需要nfs挂载的集群节点安装以下
1 | yum install -y nfs-utils rpcbind |
客户端挂载测试
1 | #首先检查nfs服务端挂载目录是否正常 |
创建PV
有了我们NFS共享存储,下面就可以来使用PV和PVC。PV作为存储资源,主要包括存储能力、访问模式、存储类型、回收策略等关键信息。pv.yaml如下
1 | apiVersion: v1 |
1 | # 创建 |
PV相关配置说明
Capacity 存储能力 通过PV的capacity属性来设置存储空间,目前仅支持storage=数据大小,未来可能会加入IOPS、吞吐量等指标配置
AccessModes 访问模式
AccessModes 是用来对PV进行访问模式的设置,用于描述用户应用对存储资源的访问权限, 访问权限包括下面几种方式:
- ReadWriteOnce (RWO): 读写权限,但是只能被单个节点挂载
- ReadOnlyMany (ROX): 只读权限,可能被多个节点挂载
- ReadWriteMany (RWX): 读写权限,可以被多个节点挂载
注意:一些PV可能支持多种访问模式,但是在挂载点时候只能使用一种访问模式,多种访问模式不生效
下面是一些常用的Volume插件支持的访问模式(需要根据我们配置的类型进行选择对应的访问模式)
persistentVolumeReclaimPolicy回收策略
- Retain (保留) 保留数据,需要管理员手动清理
- Recycle (回收) 清除PV中的数据,效果相当于执行删除命令
- Delete (删除) 与PV相连的后端存储完成volume的删除操作,常见于云服务商的存储服务
不过需要注意的是,目前只有NFS和HostPath两类支持回收策略,一般设置Retain比较保险
状态
Available (可用): 表示可用状态,还未被任何PVC绑定
Bound (已绑定):已经绑定到某个PVC
Released (已释放):对应的PVC已经删除,但资源还没有被集群收回
Failed:PV自动回收失败
创建PVC
前面说过,PV实际上没有创建存储,相当于我们node一样,还需要创建Pod进行消费,接下来我们进行PVC的创建与配置
#前面我们已经在集群上都安装nfs客户端,并且进行挂载了。下面进行创建pvc
1 | # 新建pvc同样需要建立一个数据卷声明 |
1 | #创建,pvc的yaml文件基本上和pv相同,这里不过多解释。 |
使用Labels匹配PV与PVC
pv与pvc中间还可以通过label标签进行匹配,配置如下
1 | #记得我们需要修改一下名字,名字是不可以重复的 |
1 | kubectl apply -f test.yaml |
Deployment引用pvc
1 | apiVersion: extensions/v1beta1 |
1 | #创建nginx deployment |
接下来我们直接访问nginx是无法访问的,因为在我们nfs挂载点的目录下面没有文件,所以无法访问
接下来我们到nfs挂载点创建一个index.html
1 | echo "I am abcdocker">>/data1/k8s/index.html |
然后我们在进行访问查看
由于我们的index.html直接挂在到了/data1/k8s目录下面,如果有很多个pod都使用pvc进行挂载,会造成我们数据目录的文件比较乱
这里我们添加一个subpathsubPath的目的是为了在单一Pod中多次使用同一个volume而设计的。
1 | #deployment文件如下 |
当我们更新完pod之后,等pod正常启动。就可以看到在我们nfs存储目录下面单独创建了一个名称为nginx-pvc的目录,这个目录实际上就是我们subpath后面指定的名称
1 | kubectl apply -f pv-nginx.yaml |
这个目录下面也是没有任何文件的,我们需要将原来index.html拷贝过去即可
现在我们删除deployment,下面的数据并不会删除。这样使用pv和pvc持久化就完成
如果我们直接删除或者有pod在使用pv或者pvc是无法直接删除的,当我们使用Recycle模式时,删除所有pv和pvc后,数据也会进行删除。所以删除pv和pvc请谨慎操作
问题
系统内有一个已经不再使用的 PV ,已经删除了与其关联的 Pod 及 PVC ,并对其执行了删除命令,但是无法正常删除,一直出于如下状态:
1 | $ kubectl get pv |
解决方法
1 | $ kubectl patch pv pv-nfs-gysl -p '{"metadata":{"finalizers":null}}' |
通过系统帮助信息,我们可以获取patch的简要使用说明:
patch: 使用 strategic merge patch 更新一个资源的 field(s)。