kubernetes中可用将本地磁盘作为存储挂载到容器上,但这样做的弊端是当容器出现异常而重启之后数据也会随之消失
spec:
containers:
- name: logs
# 挂载
volumemounts:
- name: varlog
mountpath: /tmp/log
# 定义本地存储
volumes:
- name: varlog
hostpath:
path: /var/log
为了实现容器存储与计算的分离,可将容器的数据单独存放到**网络共享存储(network file system,nfs)**服务器上,当容器挂掉之后并不会影响到数据,之后容器重启或一个新的容器连接到服务器后可以重新读取到数据

1 nfs的使用
首先需要将一台服务器配置为nfs服务器
# 安装nfs yum install -y nfs-utils # 创建存放数据的目录 mkdir -p /data/nfs # 创建并设置挂载路径 vim /etc/exports /data/nfs *(rw,no_root_squash) # 启动服务 systemctl start nfs
之后在k8s集群的node节点上也安装nfs服务
yum install -y nfs-utils
最后就可以使用nfs作为数据挂载点了,在其中定义nfs服务器的地址server和其上面的存储路径path。
通过如下配置文件就将pod中的 /usr/share/nginx/html 挂载到了 192.168.44.134/data/nfs
spec:
containers:
- name: nginx
image: nginx
volumemounts:
# 挂载nfs
- name: mynfs
mountpath: /usr/share/nginx/html
ports:
- containerport: 80
volumes:
# 定义nfs数据挂载点
- name: mynfs
nfs:
server: 192.168.44.134
path: /data/nfs
2 pv与pvc
上面的nfs挂载时ip 和端口是直接写在容器yaml文件中的,这样管理起来可能不方便。pv 和 pvc 是持久性存储的概念,它们可帮助我们在集群中管理持久性存储,使数据更加稳定可靠:
1.pv(persistent volume):一个抽象的存储资源,可以由管理员预先设置,并由集群中的一个 pod 来使用。它可以是磁盘,nfs 共享或云存储等存储资源。pv 可以被动态或静态地绑定到一个 pvc 上,以供 pod 使用。
2.pvc(persistent volume claim):一个声明,它请求一个特定的 pv 资源。pvc 定义了我们所需的存储容量、访问模式、数据持久性和其他细节,从而与 pv 进行匹配。当 pvc 绑定到 pv 上时,它就可以被 pod 使用了。

2.1 使用
如下所示pv定义文件mypv.yaml,在其中定义其存储大小、路径等信息,通过kubectl apply -f mypv.yaml创建pv
apiversion: v1
kind: persistentvolume
metadata:
name: my-pv
spec:
capacity:
storage: 5gi
accessmodes:
- readwritemany
nfs:
# 定义pv的存储路径
path: /k8s/nfs
server: 192.168.44.134
创建pvc,系统会自动选择合适的pv分配给它进行绑定,可以在其中定义需要的存储容量、访问模式等信息
apiversion: v1
kind: persistentvolumeclaim
metadata:
name: my-pvc
spec:
# 访问模式;描述用户应用对存储资源的访问权限
accessmodes:
- readwritemany
resources:
requests:
# 资源请求的存储大小
storage: 5gi
其中,accessmodes有如下三种模式
- rwo:readwriteonce,仅允许单个节点挂载进行读写;
- rox:readonlymany,允许多个节点挂载且只读;
- rwx:readwritemany,允许多个节点挂载进行读写;
最后在创建容器时就可以通过pvc的方式挂载存储,不必关心其底层存储pv的实现细节
apiversion: apps/v1
kind: deployment
metadata:
name: nginx-dep1
spec:
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
volumemounts:
- name: wwwroot
mountpath: /usr/share/nginx/html
ports:
- containerport: 80
volumes:
- name: wwwroot
# 挂载到my-pvc
persistentvolumeclaim:
claimname: my-pvc
2.2 pv和pvc的生命周期

如图所示,pvc在与pv绑定之后状态就会变为bound,pvc一共有如下几种状态:
- available: 可用状态,无pv绑定;
- bound:绑定状态,已经和某个pv绑定;
- released:释放状态,被绑定的pv已删除,资源释放,但没有被集群回收;
- failed:失败状态,自动资源回收失败;
如下所示,容器pod经过pvc -> pv 使用存储资源,其生命周期可以分为供应、绑定、使用、释放和回收

- 资源供应:通过pv建立对不同磁盘资源的描述,提供pv资源给消费者使用
- 资源绑定:创建好pvc后,pvc会在已存在的pv中选择合适的pv进行绑定,绑定成功,状态变成bound,且该pv被对应的pvc独占绑定,不可以再被其他pvc绑定,除非该pvc释放。若在k8s系统中没有找到合适的pv,则pvc一直处于pending状态。
- 资源使用:在通过deployment创建容器时,在spec.template.spec.volumes进行磁盘挂载时选择persistentvolumeclaim挂载到对应的pvc。
- 资源释放:删除pvc,与该pvc绑定的pv状态就会变成“released”,该pvc在存储设备上的数据删除后,对应的pv才能与其他的pvc进行绑定。
- 资源回收:pv中可以通过spec.persistentvolumereclaimpolicy设置回收策略,用于在绑定的pvc删除后,资源释放后如何处理pvc写入存储设备的数据:
- retain:保留,删除pvc后,pv保留数据;
- recycle:回收空间,删除pvc后,简单的清除文件;(nfs和hostpath存储支持)
- delete:删除,删除pvc后,与pv相连接的后端存储会删除数据;(aws ebs、azure disk、cinder volumes、gce pd支持)
2.3 pv与pvc的绑定
pv与pvc之间可以通过静态绑定或者动态绑定建立连接:
- 静态模式就是集群管理员预先创建对应的pv对存储特性进行设置;
- 动态模式就是管理员预先创建好
storageclass资源对后端存储进行描述,pvc创建时对存储类型进行声明,k8s会自动创建合适的pv与pvc进行绑定。
手动绑定
如下所示,首先定义一个test-pv1
[root@k8s /pv_test]# vim test_pv1.yaml
apiversion: v1
kind: persistentvolume
metadata:
# 定义pv的名字
name: test-pv1
labels:
pv: test-pv1
spec:
capacity:
storage: 2mi
accessmodes:
- readwritemany
persistentvolumereclaimpolicy: retain
nfs:
path: /date-nfs/k8s
server: 10.139.12.14
之后定义 pvc,在其中通过spec.selector.matchlabels标签匹配上面定义的test-pv1
[root@k8s /pvc_test]# vim test_pvc1.yaml
#persistent volume claim
apiversion: v1
kind: persistentvolumeclaim
metadata:
name: test-pvc1
namespace: t1
spec:
#storageclassname: managed-nfs-storage
accessmodes:
- readwritemany
resources:
requests:
storage: 1mi
selector:
# 手动进行绑定
matchlabels:
pv: test-pv1
动态绑定
上面的手动绑定无法根据pvc的访问模式,容量大小等实际需要灵活地匹配到合适的pv,每次去手动选择或创建pv会变得十分繁琐。
这时可以通过storageclass根据pvc定义的来动态创建合适的pv,不仅节省了管理员的时间,还可以封装不同类型的存储供pvc选用。
如下所示通过storageclass将pvc和pv进行自动绑定的过程

首先创建一个storageclass
[root@master1 sc]# cat nfs-sc.yaml apiversion: storage.k8s.io/v1 kind: storageclass metadata: name: statefu-nfs namespace: default # 云盘资源提供方 provisioner: nfs-deploy reclaimpolicy: retain [root@master1 sc]# kubectl apply -f nfs-sc.yaml storageclass.storage.k8s.io/statefu-nfs created
然后创建pvc,在其中配置spec.storageclassname为上面的创建的statefu-nfs。
[root@master1 sc]# cat test-pvc.yaml
apiversion: v1
kind: persistentvolumeclaim
metadata:
name: test-claim
namespace: default
spec:
storageclassname: statefu-nfs #sc一定要指向上面创建的sc名称
accessmodes:
- readwritemany #采用readwritemany的访问模式
resources:
requests:
storage: 1gi
[root@master1 sc]# kubectl apply -f test-pvc.yaml
可以看到pvc test-claim创建成功之后,随之自动创建了对应的pv并且绑定到了test-claim
[root@master1 sc]# kubectl get pvc name status volume capacity access modes storageclass age test-claim bound pvc-0b9e1107-fefc-48b9-a5ec-8f8690e94435 1gi rwx statefu-nfs 107m [root@master1 sc]# kubectl get pv name capacity access modes reclaim policy status claim storageclass reason age pvc-0b9e1107-fefc-48b9-a5ec-8f8690e94435 1gi rwx delete bound default/test-claim statefu-nfs 107m
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论