namespace本质
它其实只是 Linux 创建新进程clone()的一个可选参数
namespace类型
除了我们刚刚用到的 PID Namespace,Linux 操作系统还提供了 Mount、UTS、IPC、Network 和 User 这些 Namespace,用来对各种不同的进程上下文进行“障眼法”操作。
所有容器共享内核
尽管你可以在容器里通过 Mount Namespace 单独挂载其他不同版本的操作系统文件,比如 CentOS 或者 Ubuntu,但这并不能改变共享宿主机内核的事实。
所有的资源都可以namespace化吗?
在 Linux 内核中,有很多资源和对象是不能被 Namespace 化的,最典型的例子就是:时间。
namespace和cgroup各自的功能是什么?
namespace完成隔离,cgroup完成限制
Cgroups 技术是用来制造约束的主要手段,而 Namespace 技术则是用来修改进程视图的主要方法。
cgroup主要作用是什么?
它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。
cgroup如何起作用?如何使用?
- 在 /sys/fs/cgroup 下面有很多诸如 cpuset、cpu、 memory 这样的子目录,也叫子系统
- 子系统下的一系列配置文件实现了容器资源限制
- Cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下
容器是如何利用cgroup的?
容器创建的时候,在cgroup的子系统下比如sys/fs/cgroup/cpu下创建一个子目录container, container里会自动生成和cpu目录下一致的配置文件,改变这些配置文件里的值,然后把被限制的进程(即容器进程)的PID写入tasks即可。 这些配置文件的值一般是docker run的时候指定的
cgroup缺点?
- 众所周知,Linux 下的 /proc 目录存储的是记录当前内核运行状态的一系列特殊文件,用户可以通过访问这些文件,查看系统以及当前正在运行的进程的信息,比如 CPU 使用情况、内存占用率等,这些文件也是 top 指令查看系统信息的主要数据来源。
- 你如果在容器里执行 top 指令,就会发现,它显示的信息居然是宿主机的 CPU 和内存数据,而不是当前容器的数据。因为/proc 文件系统并不知道用户通过 Cgroups 给这个容器做了什么样的资源限制,即:/proc 文件系统不了解 Cgroups 限制的存在。
如何克服/proc问题?
把宿主机的 /var/lib/lxcfs/proc/* 文件挂载到容器的/proc/*
为什么容器最好不要同时运行两个进程?
- 容器是一个“单进程”模型。由于一个容器的本质就是一个进程,用户的应用进程实际上就是容器里 PID=1 的进程,也是其他后续创建的所有进程的父进程。这就意味着,在一个容器中,你没办法同时运行两个不同的应用,除非你能事先找到一个公共的 PID=1 的程序来充当两个不同应用的父进程,这也是为什么很多人都会用 systemd 或者 supervisord 这样的软件来代替应用本身作为容器的启动进程。
- 因为PID=1的进程就是容器中其他进程的父进程,退出后容器也退出了,其他进程也退出了。
mount namespace问题
mount namespace默认继承宿主机的文件系统,必须执行mount操作之后,才能看到不同的文件系统
容器怎么完成mount namespace挂载的?难不成一个个mount()
- 不是,只挂载本身的根目录即可,通过chroot可以一次挂载。
- 容器会把自己的进程根目录通过 chroot完成切根。
- chroot就是一个linux命令,作用是修改视图
- chroot $HOME/test /bin/bash
容器根目录会挂载什么?
- 一般会在容器的根目录下挂载一个完整os的fs, 而这个挂载在容器根目录上、用来为容器进程提供隔离后执行环境的文件系统, 就是所谓的容器镜像, 也叫rootfs
- 那么每开发/升级完一个应用,都要重复只做一次rootfs吗?引入层, 用户制作镜像的每一步操作,都会生成一个层,也就是一个增量rootfs,然后通过UnionFS把多个不同位置的目录联合挂载到同一个目录下。
unionFS是如何挂载的?
- unionFS一个实例,aufs,其关键目录结构在
/var/lib/docker/aufs/diff
目录下,diff下是一个个层 - 镜像的层都放置在 /var/lib/docker/aufs/diff 目录下,然后被联合挂载在
/var/lib/docker/aufs/mnt
里面。 - 查看mnt下的子目录,果然是一个完整的ubuntu os
如何查看aufs挂载信息?
cat /proc/mounts| grep aufs
找到挂载目录对应的aufs内部id:si- 通过
cat /sys/fs/aufs/si_972c6d361e6b32ba/br[0-9]*
查到联合挂载的层目录,然后发现这些层分成三种:容器层、init层、只读层 - docker init可用作 docker commit只提交容器层,不提init层。 init层:etc/hosts这些用户专属值