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

716 阅读5分钟

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

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

图片

01 emptyDir

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

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

图片

    准备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

    测试:

图片

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

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

图片

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

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

kubectl delete pod emptydir-pod-5db4b4ccc7-vcrzn

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

图片

02 HostPath

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

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

图片

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

本地资源的HostPath实验:

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

图片

    资源配置清单:

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

图片

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

图片

    在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>

    测试:

图片

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

图片

HostPath补充:

支持的type:

图片

    支持挂载模式:

图片

03 NFS

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

nfs实验:

图片

    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 ~]

图片

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


图片

本文使用 文章同步助手 同步