回顾:docker容器的本质是一种特殊的宿主机进程
其中NameSpace的作用隔离,只允许进程看到NameSpace内部的”世界”
其中Cgroups的作用是限制,给这个世界围上一圈看不见的“玻璃墙”

问题
1、我们可以在docker容器中更改操作系统的内核参数吗? 本博客已解答

关于容器的 “文件系统的隔离” 实现原理问题
2、linux的监狱策略chroot 和容器的文件系统的隔离有什么关系?本博客已解答
3、chroot怎样对linux的服务、命令来做监牢机制的呢?本博客已解答
4、容器镜像指的是什么?容器镜像的os和虚拟机的os有区别吗?本博客已解答
5、简述下Docker容器的隔离都是什么(文件系统的隔离,立体的隔离),Docker的对宿主机的限制又是如何实现的?本博客已解答
同样linux应用这个原理是不是可以实现服务的资源的占用限制呢?

关于容器镜像 “分层” 问题 以及 “分层的意义”

6、Docker的分层特性对于部署者和开发者来说,有什么益处?
这种分层结构的原理是什么?
7、linux的AUFS是什么?
8、目录联合挂载的时候,如果A目录中的x文件和B目录中的x文件内容不一样,怎样处理的呢?
解答:aufs是一层一层往上覆盖的,A里面的x会覆盖掉B里面的x

关于容器镜像的 ”细化分层” 问题

9、rootfs容器镜像的分层,以及每层的存放的文件的类型 ? 本博客已解答
10、只读层中 whiteout有什么作用? 本博客已经解答
11、删除只读层 增量的rootfs的原理 本博客已经解答
12、被whiteout遮挡的文件会被清除吗?用什么命令清除?不清除镜像是不是就膨胀了?
解答:镜像是会膨胀的,可以压缩镜像
13、为什么需要init层,只读层和读写层不能满足需求吗? 本博客已解答
14、既然容器的rootfs 是以只读方式挂载的,那么又如何在容器中修改系统镜像的内容呢?
解答:上面的读写层称为容器层 + 下面的只读层称为镜像层
所有的 增删改操作 都是作用在容器层
相同的文件,上层覆盖下层
对于镜像文件的修改,从上到下查找有没有这个文件,找到这个文件,就copy到容器层,进行修改,修改后的文件作用在下层 ,这种方式被称为copy-on-write

关于容器的使用问题:

15、使用Docker部署,在多次的部署以后,会导致磁盘占用空间急速增大,总是需要不断的扩容,
虽然对不使用的镜像已经定时做了删除,但是还是会出现磁盘空间占用大的问题,产生的文件不能在生产环境随便删除,只能清理容器和镜像?
解答:用K8S,打开GC功能,定时的清理

知识点1

容器里的进程看到的文件系统是什么样子?怎样让容器的进程有自己的文件系统不受宿主机和其他的容器的影响?
解:容器的进程所看到的文件系统 就是宿主机的文件系统

  创建进程时,除了声明mount NameSpace之外,还要告诉容器进程有哪些目录是需要重新挂载,于是在容器执行之前添加一步重新挂载目录的操作
  我们希望的是容器进程看到的文件系统就是一个独立的隔离环境,不是继承的宿主机的文件系统,我们可以在容器启动之前重新挂载整个目录/ ,
  由于mount NameSpace的存在,这个挂载对宿主机不可见,容器进程就有了自己的文件系统了

  linux中,想实现为 某一个进程设置属于自己的房间 ?chroot
change root file system :改变进程的根目录到指定的位置
  Docker中,实现的进程的文件系统的”隔离”,其实本质是使用的Mount NameSpace

Mount NameSpace的本质是基于linux的chroot监狱发明出来的
Mount NameSpace是操作系统中的第一个NameSpace
为了让容器更加的真实,一般会在容器的根目录下挂载一个完整操作系统的文件系统 ,注意仅仅挂载文件系统,不包含内核

(只是挂载躯体,不包括灵魂)

对于容器来说。它的灵魂就是宿主机的内核,所以如果涉及到更改内核参数,要注意内核参数对于宿主机上所有容器来说,是一个全局变量

知识点2

容器镜像 :这个就是mount NameSpace的操作系统文件系统的 容器,就是容器的镜像,也叫根文件系统 rootfs
  挂载在容器根目录上,用来为容器进程提供隔离后执行环境的文件系统,是容器镜像

疑问????? :对于容器我们都知道它们都已经使用了Mount NameSpace,实现了文件系统方面的隔离
但是,对于linux来说,有些服务、有些命令会做了chroot监狱隔离,我们拿到一个系统,我们怎么能知道这个系统中有多少个监狱呢?

现在回顾docker容器

:启用了NameSpace配置
设置了Cgroups参数
切换进程的根目录(Chang Root)

知识点3

容器的一致性 :打通了本地开发&远端执行之间的鸿沟
容器有一个很重要的特性,也是战胜Paas的一个特点就是 “一致性”
rootfs里面打包的不只是应用,而是整个操作系统的文件和目录
也就是说:应用以及他运行所需要的所有的依赖,都被封装在一起了
本质上说,应用的依赖不仅仅只是语言上的依赖,操作系统本身才是运行所需要的完整的依赖

知识点4:容器的分层性 — 联合文件系统 Aufs

问题:两个人基于rootfs拉下镜像,不同的更改使得产生两个不同的rootfs,结果就是随着时间的推移 极度的碎片化

如果想要两个人分别拉下镜像,所做的更改融合在一个rootfs,可以实现吗?

解答:Docker公司在实现Docker镜像时对Rootfs做了一个小创新

  联合文件系统:Docker在镜像的设计中,引入了层的概念,用户制作镜像的每一步骤,都会生成一个层,这个层就是增量的rootfs

  联合文件系统的本质就是:将多个不同位置的目录联合挂载到同一个目录下面

  docker image inspect ubuntu:latest 拉下来的rootfs,本来就是多层组成的:可以看到是5层 ,即5个增量的rootfs

容器进程级隔离 容器隔离原理_docker


  docker image inspect ubuntu:latest 拉下来的rootfs,本来就是多层组成的:可以看到是5层 ,即5个增量的rootfs

  • 每个rootfs都是操作系统文件&目录的一部分
  • 使用镜像的时候,所有rootfs联合挂载在统一的挂载点
      一般是:/var/lib/docker/aufs/mnt
      这个目录里面的所有rootfs共同组成一个完整的操作系统
  • 联合挂载是怎样实现的?
      挂在实现的记录在/sys/fs/aufs
      cat /proc/mounts |grep aufs :通过查看挂载点,找出Aufs的内部ID→SI
  • 使用这个SI可以/sys/fs/aufs 下查看被联合挂载在一起的rootfs层的具体信息

rootfs的基本信息:

镜像的增量rootfs层放置在/var/lib/docker/aufs/diff 联合挂载在/var/lib/docker/aufs/mnt

容器进程级隔离 容器隔离原理_容器进程级隔离_02


只读层:ro+wh readonly+whiteout

  只是包含了增量rootfs

容器进程级隔离 容器隔离原理_容器_03


读写层:rw read+write

  存放修改rootfs后产生的增量,增+删+改都发生在这里

  在没有写入文件的时候,这个目录是空的,一旦有了写操作,所修改的内容就会以增量的方式保存在这个目录中

  修改过容器后,可以docker commit && docker push,保存被修改过的可读写层 ,原来的只读层的内容不会发生变化

问题:如果想删除只读层里面的一个文件 ? whiteout的作用

  Aufs会在 读写层 新建一个whiteout文件,把只读层里面的文件遮挡住

  当 读写层和只读层 被联合挂载的时候,a文件就会被 .a.foo文件遮挡住,就起到了删除的效果

init层 :位于读写层和只读层之间 ,以-init结尾的层
  init层是Docker项目单独生成的一个内部层,主要是存放/etc/hosts /etc/resolv.conf
问题:为什么会需要init层 ?
/etc/hosts /etc/resolv.conf 这些文件本来是属于镜像的一部分
  但是用户需要往容器内写入一些特定的值 栗子:hostname
  这个时候我们需要在可读写层来进行更改
  当我们只想在当前的容器生效,不希望docker commit的时候,将这些信息和可读写层一起提交上去
  所以,在修改这些文件后,单独把这些 “特殊文件” 挂载出来
  Docker commit 只能提交读写层,不会提交init层