k8s 存储之volume

目录

emptyDir(空的目录卷)

emptyDir 的用法

hostPath

hostPath的用法


docker有自己的持久化方案,我们的k8s集群中也有进行持久化的操作。

容器磁盘上的文件的生命周期是短暂的,这就使得在容器中运行重要应用时会出现一些问题。首先,当容器崩溃时,kubelet 会重启它,但是容器中的文件将丢失——容器以干净的状态(镜像最初的状态)重新启动。其次,在Pod 中同时运行多个容器时,这些容器之间通常需要共享文件。Kubernetes 中的 Volume 抽象就很好的解决了这些问题。

上面的跟我们在docker中还不一样哈,在docker中我们把启动命令加上一个restart always的话,那么docker重启之后并不会删除原有的数据,但是在k8s中,一旦崩溃,就会以一个干净的状态重新启动,因为如果不以干净的状态启动,我们的init C就无法启动。

Kubernetes 中的卷有明确的寿命 —— 与封装它的 Pod 相同。所f以,卷的生命比 Pod 中的所有容器都长,当这个容器重启时数据仍然得以保存。当然,当 Pod 不再存在时,卷也将不复存在。也许更重要的是,Kubernetes支持多种类型的卷,Pod 可以同时使用任意数量的卷。。。。

虽然我们的pod会重新启动,然后创建出新的容器,但是我们的volume卷一直没动,所以存储不会丢失。这个也是实现的原理。

volume卷的类型

Kubernetes 支持以下类型的卷:

下面介绍一些重要的,常用的卷进行分析:

emptyDir(空的目录卷)

当 Pod 被分配给节点时,首先创建 emptyDir 卷,并且只要该 Pod 在该节点上运行,该卷就会存在。正如卷的名字所述,它最初是空的。Pod 中的容器可以读取和写入 emptyDir 卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除 Pod 时, emptyDir 中的数据将被永久删除。注意容器崩溃不会从节点中移除pod,因此,emptyDir卷中的数据在容器崩溃时是安全的。

分析上图:当我们的pod确定要被运行的时候,它会先创建一个空的目录卷,空卷会与生成的Pause进行绑定,然后依次运行处C1和C2。(下面的示例有讲到,这个C1和C2数据共享)

emptyDir 的用法

1. 暂存空间,例如用于基于磁盘的合并排序

(也就是我们现在有很多的容器,它们有些数据要进行组合和合并的话,我们需要一个临时空间去存放这些数据)

2. 用作长时间计算崩溃恢复时的检查点

(比如说,我们有一些服务需要去运行,会有一些数据重载,这些数据可能在我们pod重启时发生重载,那么重载的时候如何进行数据的恢复呢,或者是有些数据不需要进行持久话的写入,或者是只恢复部分的数据)

3. Web服务器容器提供数据时,保存内容管理器容器提取的文件

(也就是我们的web服务器运行的时候,有一些文件需要存在,那么我们在初始化镜像的时候,从某个地方download一些文件放到我们当前的目录下,然后可以保存至空目录下去使用)

下面就是示例:

[root@master1 storge]# cat emptydir.yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx:alpine
    name: test-container
    volumeMounts:
    - mountPath: /cache    #挂载到容器的哪个目录下
      name: cache-volume   #通过哪个volume去挂载的
  volumes:
  - name: cache-volume
    emptyDir: {}
[root@master1 storge]# 
[root@master1 storge]# kubectl apply -f  emptydir.yaml
pod/test-pd created
[root@master1 storge]# kubectl get pod 
NAME      READY   STATUS    RESTARTS   AGE
test-pd   1/1     Running   0          17s
[root@master1 storge]# kubectl exec  -it test-pd -- sh 
/ # cd /cache/
/cache # ls -al 
total 0
drwxrwxrwx    2 root     root             6 Sep  4 13:52 .
drwxr-xr-x    1 root     root            64 Sep  4 13:52 ..
/cache # 

我们发现cache里面为空,其实我们常用的场景是一个pod里面多个容器共享emptyDir这个数据卷,下面我们演示两个容器的案例。

即在同一个pod里面的两个不同的容器C1和C2数据共享

[root@master1 storge]# cat  emptydir.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx:alpine
    name: test-container
    volumeMounts:
    - mountPath: /cache    #挂载到容器的哪个目录下
      name: cache-volume   #通过哪个volume去挂载的
  - name: test-busybox
    image: busybox:alpine
    command: ["/bin/sh","-c","sleep 600s"]
    volumeMounts:
    - mountPath: /test    #挂载到容器的哪个目录下
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}
[root@master1 storge]# kubectl apply -f   emptydir.yaml 
pod/test-pd created
[root@master1 storge]# kubectl get pod 
NAME      READY   STATUS    RESTARTS   AGE
test-pd   2/2     Running   0          4s

不同的容器进行数据共享,上面的容器先是在挂载目录(cache)写入,然后下面的是另外的一个容器也可以读取到该容器挂载目录(test)的文件里面内容。

hostPath

hostPath 卷将主机节点的文件系统中的文件或目录挂载到集群中。。

hostPath 的用途如下:

1. 运行需要访问 Docker 内部的容器;使用 /var/lib/docker 的 hostPath。

意味着我们想要在本机获取容器内部的一些文件的话,可以使用该方案。

2. 在容器中运行 cAdvisor;使用 /dev/cgroups 的 hostPath。

3. 允许 pod 指定给定的 hostPath 是否应该在 pod 运行之前存在,是否应该创建,以及它应该以什么形式存在。

我们有一个nfs集群,然后我们把集群挂载至node节点的某个目录下,我们在启动pod的时候,我们让pod去挂载本机的那个目录。即只要存储服务能够挂载至我们的node节点,那么我们的pod可以通过hostPath方案实现外部存储的挂载。

除了所需的 path 属性之外,用户还可以为 hostPath 卷指定 type

使用这种卷类型是请注意,因为:

1. 由于每个节点上的文件都不同,具有相同配置(例如从 podTemplate 创建的)的 pod 在不同节点上的行为可能会有所不同。我们要确保每一个pod挂载到指定的本机哪个目录,因为pod会根据调度规则随机部署到node节点上,假如说,我们在yaml文件中指定了某个pod对应的目录,但是有些node节点没有这个目录,此时pod里面的内容就会发生变化。所以我们需要提前想好所有的节点(或者说pod对应的调度规则匹配的node)是否有符合yaml对应目录。

2. 当 Kubernetes 按照计划添加资源感知调度时,将无法考虑 hostPath 使用的资源。也就是hostPath本机的一些资源的动态是无法添加到我们的k8s资源管理器中去的。

3. 在底层主机上创建的文件或目录只能由 root 写入。您需要在特权容器中以 root 身份运行进程,或修改主机上的文件权限以便写入 hostPath 卷。也就意味着,在我们本机的某些文件或者目录上,如果是一些默认的权限的话,它是没有写入权的,这个时候可以把本机的某个目录调整为我们kubelete的权限即可。

hostPath的用法

[root@master1 storge]# mkdir /data
[root@master1 storge]# cat hostpath.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx:alpine
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
    # directory location on host
      path: /data
    # this field is optional
      type: Directory
[root@master1 storge]# 
[root@master1 storge]# kubectl apply -f  hostpath.yaml 
pod/test-pd created
[root@master1 storge]# kubectl get pod 
NAME      READY   STATUS    RESTARTS   AGE
test-pd   1/1     Running   0          3s

补充:对于上面的第一点如果还有点迷糊的话,像我们这里创建一个hostpath,挂载的宿主机目录是/data,由于我这里是单节点部署,所有只在master上面创建一个目录,如果是多节点的话,那么就得在其他节点上创建同样的目录。

下面看一下效果

同样我们互相写入数据也是能够在宿主机和pod里面看见的

总结:上面的这种方案有很大的灵活性,可以跟我们的任何存储进行对接,也就是开始讲的可以对接nfs集群。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值