谈谈k8s1.12新特性--Mount propagation(挂载命名空间的传播)
Mount propagation
挂载传播允许将Container挂载的卷共享到同一Pod中的其他Container,甚至可以共 享到同一节点上的其他Pod。
一个卷的挂载传播由Container.volumeMounts中的mountPropagation字段控制。它的值是:
- None 此卷挂载不会接收到任何后续挂载到该卷或是挂载到该卷的子目录下的挂载。以类似的方式,在主机上不会显示Container创建的装载。这是默认模式。
此模式等同于Linux内核文档中所述的 private 传播。
- HostToContainer 此卷挂载将会接收到任何后续挂载到该卷或是挂载到该卷的子目录下的挂载。
换句话说,如果主机在卷挂载中挂载任何内容,则Container将看到它挂载在那里。
类似地,如果任何具有 Bidirectional 挂载传播设置的Pod挂载到同一个卷中,那么具有HostToContainer挂载传播的Container将会看到它。
此模式等同于Linux内核文档中描述的rslave挂载传播。
- Bidirectional 此卷挂载的行为与HostToContainer挂载相同。此外,Container创建的所有卷挂载都将传播回主机和所有使用相同卷的Pod的所有容器。
此模式的典型用例是具有Flexvolume或CSI驱动程序的Pod需要使用hostPath 卷模式 在主机上挂载内容。
此模式等同于Linux内核文档中描述的rshared安装传播。
PS:
Bidirectional 挂载传播可能很危险。它可能会损坏主机操作系统,因此只允许在特权容器中使用它。强烈建议您熟悉Linux内核行为。此外,容器在容器中创建的任何卷装入必须在终止时由容器销毁(卸载)。
Bidirectional一些使用场景:
- 在不同的pod之间共享设备,其中挂载发生在pod中,但是在pod之间共享。
- 从容器内部附加设备。例如,从容器内部附加ISCSI设备。这时候因为如果容器死掉,主机将不能获得所需的信息(除非使用双向安装传播)来正确刷新写入和分离设备。
sample
deployment: containers: - image: gcr.io/google_containers/busybox:1.24 name: reader volume: - mount: /usr/test-pod store: local-vol propagation: bidirectional name: local-test-reader version: extensions/v1beta1 volumes: local-vol: pvc:example-local-claim
配置
在挂载传播可以在某些部署(CoreOS,RedHat / Centos,Ubuntu)上正常工作之前,必须在Docker中正确配置挂载共享,如下所示。
编辑Docker的systemdservice 文件。设置MountFlags如下:
MountFlags=shared
或者,如果存在,则删除MountFlags = slave。然后重启Docker守护进程:
$ sudo systemctl daemon-reload $ sudo systemctl restart docker
具体案例
之所以关注这块,是由于我们在实际使用k8s的过程中遇到了相关的问题。
我们容器业务日志的收集有很大一部分通过sidecar的方式,mount日志到主机某个目录。由于我们的日志量非常大,即使我们每个主机挂载了1T的硬盘,经常会写满这张盘。所以我们实现了一个log-tracer的项目,专门用于根据pod的日志挂载信息clear过期的日志。通过daemonset方式部署。
但是如果设置mount为private的话,缺乏广播通知。在实际新增pod后,有一部分的日志挂载是无法感测到,因而也无法彻底清理。
刨根问底
究其深层次分析,该特性并不是k8s或是docker实现的。本质上是mount namespace 的特性。
mount namespace通过隔离文件系统挂载点对隔离文件系统提供支持,它是历史上第一个Linux namespace,所以它的标识位比较特殊,就是CLONE_NEWNS。隔离后,不同mount namespace中的文件结构发生变化也互不影响。你可以通过/proc/[pid]/mounts查看到所有挂载在当前namespace中的文件系统,还可以通过/proc/[pid]/mountstats看到mount namespace中文件设备的统计信息,包括挂载文件的名字、文件系统类型、挂载位置等等。
进程在创建mount namespace时,会把当前的文件结构复制给新的namespace。新namespace中的所有mount操作都只影响自身的文件系统,而对外界不会产生任何影响。这样做非常严格地实现了隔离,但是某些情况可能并不适用。比如父节点namespace中的进程挂载了一张CD-ROM,这时子节点namespace拷贝的目录结构就无法自动挂载上这张CD-ROM,因为这种操作会影响到父节点的文件系统。
2006 年引入的挂载传播(mount propagation)解决了这个问题,挂载传播定义了挂载对象(mount object)之间的关系,系统用这些关系决定任何挂载对象中的挂载事件如何传播到其他挂载对象(参考自:http://www.ibm.com/developerw...)。所谓传播事件,是指由一个挂载对象的状态变化导致的其它挂载对象的挂载与解除挂载动作的事件。
- 共享关系(share relationship)。如果两个挂载对象具有共享关系,那么一个挂载对象中的挂载事件会传播到另一个挂载对象,反之亦然。
- 从属关系(slave relationship)。如果两个挂载对象形成从属关系,那么一个挂载对象中的挂载事件会传播到另一个挂载对象,但是反过来不行;在这种关系中,从属对象是事件的接收者。
一个挂载状态可能为如下的其中一种:
- 共享挂载(shared)
- 从属挂载(slave)
- 共享/从属挂载(shared and slave)
- 私有挂载(private)
- 不可绑定挂载(unbindable)
在默认情况下,所有挂载都是私有的。可以用以下命令将挂载对象显式地标为共享挂载:
mount --make-shared <mount-object>
例如,如果 / 上的挂载必须是共享的,那么执行以下命令:
mount --make-shared /
从共享挂载克隆的挂载对象也是共享的挂载;它们相互传播挂载事件。
通过执行以下命令,可以显式地将一个共享挂载转换为从属挂载:
mount --make-slave <shared-mount-object>
从从属挂载克隆的挂载对象也是从属的挂载,它也从属于原来的从属挂载的主挂载对象。
通过执行以下命令,可以将挂载对象标为私有的:
mount --make-private <mount-object>
通过执行以下命令,可以将挂载对象标为不可绑定的:
mount --make-unbindable <mount-object>
最后,这些设置都可以递归地应用,这意味着它们将应用于目标挂载之下的所有挂载。
mount --make-rshared /
将 / 之下的所有挂载转换为共享挂载。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
k8s与CICD--借助scp插件实现非容器项目的部署
前言 最近连续996加班,一直没有时间完成drone系列文章。drone-wechat插件实现了 一半,由于企业微信token申请比较麻烦,所以也没有进展。今天抽出时间,研究了一下scp插件,主要目的是实现非容器项目的部署。其实就是借助scp插件,将构建好的go项目可执行文件和配置文件发布到指定主机上。本项目依旧基于baa-cicd项目。 .drone.yml 直接上.drone.yml 文件 workspace: base: /go path: src/gogs.xxx.com/baa-cicd pipeline: build: image: golang:latest commands: - go build -o baa-cicd # publish: # image: plugins/docker # registry: registry.xxx.com # repo: registry.xxx.com/test/baa-cicd # tags: latest # secrets: [ docker_username, docker_password ] # insecure:...
- 下一篇
k8s与监控--改造telegraf的buffer实现
改造telegraf的buffer实现 前言 最近在使用telegraf的场景中,要求数据在程序意外终止的时候不丢失。按照telegraf最初的原始实现,在running_output内部维护了两个buffer,分别是metrics和failMetrics。这两个buffer是基于go中channel实现的。由于没 有持久化机制,在意外退出的时候,存在丢失数据的风险。所以这篇文章主要讲述之前telegraf保证数据安全的一些措施和我们对代码的一些优化。 telegraf关于数据安全的处理办法 关于两个buffer,定义在running_output.go的struct中。 // RunningOutput contains the output configuration type RunningOutput struct { Name string Output telegraf.Output Config *OutputConfig MetricBufferLimit int MetricBatchSize int MetricsFiltered selfstat.Stat Met...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS8编译安装MySQL8.0.19
- CentOS6,CentOS7官方镜像安装Oracle11G
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Docker安装Oracle12C,快速搭建Oracle学习环境