K8s - Kubernetes使用详解8(使用Volume存储实现数据持久化)

作者: hangge 发布时间: 2019-09-02 浏览: 2947 次 编辑

    我们知道容器和 Pod 的生命周期可能很短,会被频繁地销毁和创建。当容器销毁时,保存在容器内部文件系统中的数据都会被清除。为了持久化保存容器的数据,我们可以使用 Kubernetes Volume。 

    除此之外,有一些场景可能一个 pod 里面的多个容器需要共享数据。同样可以借助 Volume 来实现。


八、Volume 存储

1,什么是 Volume?

(1)Volume 的生命周期独立于容器,Pod 中的容器可能被销毁和重建,但 Volume 会被保留。

(2)本质上,Kubernetes Volume 是一个目录,这一点与 Docker Volume 类似。当 Volume 被 mount 到 PodPod 中的所有容器都可以访问这个 Volume

(3)Volume 也支持多种 mount 类型,包括: emptyDirhostPathGCE Persistent DiskAWS Elastic Block StoreNFSCeph 等。


2,emptyDir

(1)基本介绍

  • emptyDir 是最基础的 Volume 类型。正如其名字所示,一个 emptyDir Volume 实际上是 Host 上的一个临时空目录。

  • emptyDir Volume 对于容器来说是持久的,对于 Pod 则不是。当 Pod 从节点删除时,Volume 的内容也会被删除。但如果只是容器被销毁而 Pod 还在,则 Volume 不受影响。

  • 也就是说,emptyDir Volume 的生命周期与 Pod 一致。


(2)emptyDir 常用于一个 pod 内多个容器共享临时数据(如日志收集),首先我创建 app.yml 文件,内容如下:

(1)该 pod 中有两个容器:

  • app 容器:模拟实际场景中的应用,负责把日志写到日志文件中。

  • log-collector 容器:模拟实际场景中的日志收集,负责从日志文件中读取日志。

(2)文件最底部 volumes 定义了一个 emptyDir 类型的 Volume shared-dirapp 和 log-collector 都是共享这个 Volume

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: v1
kind: Pod
metadata:
  name: emptydir-test
spec:
  containers:
  - image: busybox
    name: app
    volumeMounts:
    - mountPath: /logs # 将 shared-dir mount 到 /logs 目录。
      name: shared-dir
    args:
    - /bin/sh
    - -c
    echo `date '+%H:%M:%S'` >> /logs/app.log; sleep 60 #通过echo将数据写到文件app.log里(60秒一次)
  - image: busybox
    name: log-collector
    volumeMounts:
    - mountPath: /app_logs # 将 shared-dir mount 到 /app_logs 目录。
      name: shared-dir
    args:
    - /bin/sh
    - -c
    - cat /app_logs/app.log; sleep 60 # 通过cat从文件app.log读数据(60秒一次)
  volumes:
  - name: shared-dir #定义了一个 emptyDir 类型的 Volume shared-dir
    emptyDir: {}


(3)接着执行如下命令创建 pod

1
kubectl apply -f app.yml


(4)过个几分钟,通过 kubectl logs 命令查看 log-collector 容器日志,可以发现该容器成功读到了 app 写入的数据,验证了两个容器共享 emptyDir Volume

1
kubectl logs emptydir-test log-collector

原文:K8s - Kubernetes使用详解8(使用Volume存储实现数据持久化)

(5)通过 docker inspect 查看容器的详细配置信息,我们发现两个容器都 mount 了同一个目录:

因为 emptyDir 是 Docker Host 文件系统里的目录,其效果相当于执行了 docker run -v /logs 和 docker run -v /app_logs

原文:K8s - Kubernetes使用详解8(使用Volume存储实现数据持久化)


原文:K8s - Kubernetes使用详解8(使用Volume存储实现数据持久化)


(6)由于 emptyDir 是 Host 上创建的临时目录,它不具备持久性。如果 Pod 不存在了,emptyDir 也就没有了。下面我们把 pod 删除再重新创建,可以发现前的数据已经被清除了。

1
2
3
kubectl delete -f app.yml
kubectl apply -f app.yml
kubectl logs emptydir-test log-collector

原文:K8s - Kubernetes使用详解8(使用Volume存储实现数据持久化)

3,hostPath

(1)基本介绍

  • hostPath 类型的 volume,是将主机上的目录 mount 给 pod 的容器。

  • 与 emptyDir 不同的是,即使 pod 被销毁了,hostPath 对应的目录数据也还会被保留。

注意:大部分应用都不会使用 hostPath Volume,因为这实际上增加了 Pod 与节点的耦合,限制了 Pod 的使用。不过那些需要访问 Kubernetes 或 Docker 内部数据(配置文件和二进制库)的应用则需要使用 hostPath


(2)这里我们同样以前面的日志写入、读取为例。只不过这次我们不再使用临时目录作为共享目录,而是用用主机上 /mylogs 这个目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apiVersion: v1
kind: Pod
metadata:
  name: hostpath-test
spec:
  containers:
  - image: busybox
    name: app
    volumeMounts:
    - mountPath: /logs
      name: shared-dir
    args:
    - /bin/sh
    - -c
    echo `date '+%H:%M:%S'` >> /logs/app.log; sleep 60
  - image: busybox
    name: log-collector
    volumeMounts:
    - mountPath: /app_logs
      name: shared-dir
    args:
    - /bin/sh
    - -c
    - cat /app_logs/app.log; sleep 60
  volumes:
  - name: shared-dir
    hostPath:
      path: /mylogs


(3)创建 pod 后可以看到 /mylogs 这个目录下确实已经生成了日志文件:

原文:K8s - Kubernetes使用详解8(使用Volume存储实现数据持久化)


4,NFS

(1)我们也可以 mount 一个NFS(网络数据卷)类型的 volume。即允许一块现有的网络硬盘在同一个 pod 内的容器间共享。

(2)还是以上面的日志写入、读取为例。只不过这次我们使用 NFS 目录作为为共享目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: v1
kind: Pod
metadata:
  name: nft-test
spec:
  containers:
  - image: busybox
    name: app
    volumeMounts:
    - mountPath: /logs
      name: shared-dir
    args:
    - /bin/sh
    - -c
    echo `date '+%H:%M:%S'` >> /logs/app.log; sleep 60
  - image: busybox
    name: log-collector
    volumeMounts:
    - mountPath: /app_logs
      name: shared-dir
    args:
    - /bin/sh
    - -c
    - cat /app_logs/app.log; sleep 60
  volumes:
  - name: shared-dir
    nfs:
     server: 192.168.20.47
     path: "/data/disk1"


5,外部存储

(1)如果 Kubernetes 部署在诸如 AWSGCEAzure 等公有云上,可以直接使用云硬盘作为 Volume,下面是 AWS Elastic Block Store 的例子:

要在 Pod 中使用 ESB volume,必须先在 AWS 中创建,然后通过 volume-id 引用。其他云硬盘的使用方法可参考各公有云厂商的官方文档。

原文:K8s - Kubernetes使用详解8(使用Volume存储实现数据持久化)

(2)Kubernetes Volume 也可以使用主流的分布式存,比如 CephGlusterFS 等。下面是一个 Ceph 例子:将 Ceph 文件系统的 /some/path/in/side/cephfs 目录被 mount 到容器路径 /test-ceph

原文:K8s - Kubernetes使用详解8(使用Volume存储实现数据持久化)


原文链接:https://www.hangge.com/blog/cache/detail_2437.html