使用过docker的同学应该都知道,docker只有容器层是可读写的,如果不将容器提交为镜像,当容器被删除后,可读写层的数据也会被删除,无法保留。在docker的解决方案中,我们一般使用 -v 参数将一个目录挂载容器中,实现数据持久化存储。

    而在kubernetes中,数据持久化存储的解决方案更加丰富,今天主要是学习以下emptydir和hostpath这两种本地存储和网络存储nfs。

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_nginx


01 emptyDir

    emptyDir是一个空目录,不需要提前创建相关目录,他的声明周期和Pod是完全一致的,Pod被删除时,emptyDir也会被删除。emptyDir主要是用于同一个Pod内不同的容器之间共享工作过程中产生的文件。

    比如以下这种模型,busybox每隔1s向index.html写入当前时间,当用户不同的时间访问nginx提供的index.html时,就会产生不同的结果。再比如同个pod内有一个container产生临时数据,另一个container对数据进行分析并储存的场景,也可以使用emptyDir。

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_html_02

    准备emptydir.yaml文件

apiVersion: apps/v1
kind: Deployment
metadata:
name: emptydir-pod
labels:
app: emptydir-pod
spec:
selector:
matchLabels:
app: emptydir-pod
template:
metadata:
labels:
app: emptydir-pod
spec:
containers:
- image: harbor.od.com/public/nginx:v1.7.9
name: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nginx-html
- image: harbor.od.com/public/busybox:latest
name: busybox
args:
- /bin/sh
- -c
- >
while :; do
echo "The Time is [$(date)]" > /data/html/index.html
sleep 1
done
volumeMounts:
- mountPath: "/data/html"
name: nginx-html
volumes:
- name: nginx-html
emptyDir: # 定义一个emptyDir,默认类型为目录
sizeLimit: 20Mi # 定义大小
---
apiVersion: v1
kind: Service
metadata:
name: emptydir-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: emptydir-pod

    mptydir除了默认支持的目录以外,还可以支持Menory和HugePages,提供快的访问速率。

    应用资源

kubectl apply -f emptydir.yaml

    查看pod和svc

[root@host22 ~]# kubectl get pod,svc -o wide | grep emptydir
pod/emptydir-pod-5db4b4ccc7-vcrzn 2/2 Running 0 28m 172.7.22.7 host22.yunwei.com <none> <none>
service/emptydir-svc ClusterIP 10.254.53.210 <none> 80/TCP 49m app=emptydir-pod

    测试:

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_nginx_03

   登录容器所在node节点,查看挂载信息:

# kubectl describe pod emptydir-pod-5db4b4ccc7-vcrzn | grep "Container ID"
Container ID: docker://607b6415a944375de49d60fac8002d9bfe01f7bfd670c696d843720d0ea0791b
Container ID: docker://de5905b474f340147257dc124999c401c33afda76f10ff9f24767de18a83a179

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_html_04

   可以看出两个容器挂载的是同一个目录,而且这个目录是自动创建的。

   重启pod,查看目录内容是否会被清空

kubectl delete pod emptydir-pod-5db4b4ccc7-vcrzn

    再次查看挂载信息,很明显可以看到重启前后的目录不一样了,而且查看重启前的目录,已经不存在。-- 所以emptyDir和pod的生命周期是一致的。

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_nginx_05


02 HostPath

    与emptyDir相比,Hostpath的数据是独立于pod生命周期的。

    HostPath可以将node的目录/文件/socket/dev等文件挂载到pod中。比如jenkins将harbor仓库主机的docker的sock文件挂载到了pod内,实现镜像自动打包上传等场景会使用到HostPath。

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_数据_06

   事实上HostPath比较少用,因为我们无法保证集群内每个主机都有相同的目录,目录中都有相同的内容,如果这都不能保证,那容器一次打包到处运行的特点就无法体现了。


    本地资源的HostPath实验:

    在一个节点上创建/data/html目录,并生成index.html文件,通过HostPath挂载给pod。

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_数据_07

    资源配置清单:

cat hostpath.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
name: hostpath-pod
labels:
app: hostpath-pod
spec:
selector:
matchLabels:
app: hostpath-pod
template:
metadata:
labels:
app: hostpath-pod
spec:
containers:
- image: harbor.od.com/public/nginx:v1.7.9
name: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nginx-html
volumes:
- name: nginx-html
hostPath:
path: /data/html # node上的目录
type: Directory # 类型为目录
---
apiVersion: v1
kind: Service
metadata:
name: hostpath-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: hostpath-pod

    准备目录:

[root@host22 ~]# mkdir /data/html                                                                                    
[root@host22 ~]# cd /data/html/
[root@host22 html]# vi index.html
hello 运维少年.

    应用:

kubectl apply -f hostpath.yaml

    查看pod

kubectl get pod -o wide

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_html_08

    很不幸,我只在host22上准备了/data/html资源,而pod被调度到了host21上,导致pod无法正常运行。-- 如果无法保证集群内所有节点都有该目录且内容相同,建议不要使用本地资源hostpath。

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_html_09

    在host21上也建立相同的目录和内容

[root@host21 ~]# mkdir /data/html
[root@host21 ~]# cd /data/html/
[root@host21 html]# echo 'hello 运维少年' > index.html
[root@host21 html]#

    再查看相关资源

[root@host21 html]# kubectl get svc,pod -o wide | grep hostpath
service/hostpath-svc ClusterIP 10.254.15.227 <none> 80/TCP 7m56s app=hostpath-pod
pod/hostpath-pod-74d8856d5b-p2vl7 1/1 Running 0 26s 172.7.22.7 host22.yunwei.com <none> <none>

    测试:

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_html_10


    删除pod,再查看数据是否被清除 -- 可以看到数据依旧还保留着。

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_数据_11

     HostPath补充:

    支持的type:

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_数据_12

    支持挂载模式:

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_数据_13


03 NFS

    在节点网络与NFS Server网络互通的情况下,使用nfs存储可以保证container一次打包,集群内任意节点运行,和hostpath一样,nfs数据独立于pod的生命周期。


    nfs实验:

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_nginx_14

    host200上准备nfs资源 -- 略

    资源配置清单

cat nfs.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-pod
labels:
app: nfs-pod
spec:
selector:
matchLabels:
app: nfs-pod
template:
metadata:
labels:
app: nfs-pod
spec:
containers:
- image: harbor.od.com/public/nginx:v1.7.9
name: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nginx-html
volumes:
- name: nginx-html
nfs:
server: host200 # nfs服务器
path: /data/nfs-volume/html # nfs目录
---
apiVersion: v1
kind: Service
metadata:
name: nfs-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nfs-pod

    应用和测试:

[root@host22 ~]# kubectl apply -f nfs.yaml 
deployment.apps/nfs-pod created
service/nfs-svc created
[root@host22 ~]# kubectl get pod,svc | grep nfs
pod/nfs-pod-7664d9f54b-pw76t 1/1 Running 0 81s
service/nfs-svc ClusterIP 10.254.215.77 <none> 80/TCP 81s
[root@host22 ~]#

[kubernetes] 持久化存储之emptyDir/HostPath/NFS_nginx_15


---太晚了,就写到这吧,再见。



[kubernetes] 持久化存储之emptyDir/HostPath/NFS_html_16