容器技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个边界。
Cgroups技术是用来制造约束的主要手段,Namespaces技术则是用来修改进程视图的主要方法。
Mount Namespace用于让被隔离进程只看到当前Namespace里的挂在点信息;Network Namespace
用于让被隔离进程看到当前Namespace里的网络设备和配置。
容器就是一种特殊的进程而已。
虚拟机通过硬件虚拟化功能,模拟出运行一个操作系统需要的各种硬件,然后在虚拟硬件上安装了一个
新的操作系统。
容器的弊端:隔离的不彻底。
容器是运行在宿主机上的一种特殊的进程,那么多个容器之间使用的就是还是同一个宿主机的操作系统内核。
在linux内核中,有很多资源和对象是不能被Namespace化的。
Linux下的/proc目录存储是记录当前内核运行状态的一系列特殊文件,/proc文件系统不了解Cgroups限制的存在。
Mount Namespace修改的是,是容器进程对文件系统挂在点的认知。在挂载操作发生之后,进程的视图才会被改变。
Mount Namespace于其他Namespace的区别:它对容器进行视图的改变,一定是伴随着挂载操作才能生效。
chroot命令就是改变进程的根目录到指定的位置。
挂载在容器根目录上、用来为容器进行提供隔离后执行环境的文件系统,就是所谓的容器镜像,也可以成为rootfs(根文件系统)。
rootfs这是一个操作系统所包含的文件、配置和目录,不包括操作系统内核。在Linux操作系统中,这两部分是分开存放的,
操作系统只有在开机启动时才会加载指定版本的内核镜像。
同一台机器上的所有容器,都共享宿主机操作系统的内核。
容器相对于虚拟机的缺陷:虚拟机不仅可以模拟出来的硬件机器充当沙盒,而且每个沙盒里还运行着一个完成的guest os给应用随便折腾。
由于rootfs里打包的不只是应用,而是整个操作系统的文件和目录。
Union File System是将多个不同位置的目录联合挂载到同一个目录下。
镜像的层都是放置在/var/lib/docker/aufs/diff目录下,然后被联合挂载在/var/lib/docker/aufs/mnt里面。
rootfs有三个部分组成:只读层(镜像基础的文件层)、可读可写层(自定义的安装软件、增加文件等操作,增加的的rootfs)、
init层(内部层,专门存放/etc/hosts, /etc/resolv.conf等信息)。
docker commit只提交可读写层。
Docker会提供一个隐含的entrypoint,即 /bin/bash -c。
Linux Namespace创建的隔离空间虽然看不见摸不着,
但一个进程的Namespace信息在宿主机上是确确实实存在的,并且是以一个文件的方式存在。
查看容器的进程号:
docker inspect --format '{{ .State.Pid }}' 容器id
ls -l /proc/{pid}/ns # 连接到一个真实的Namespace文件上。
一个进程,可以选择加入到某个进程已有的Namespace当中,从而达到进入这个进程所在容器的目录,这正式docker exec的实现原理。
在设置网路的过程中,如果不使用host模式,就是使用容器自己的进程号,于/bin/bash的进程的网络指向同一个net。
rootfs的最上层是一个可读写层,它以copy-on-write的方式存放任何对只读层的修改,容器生命的volume挂载点,也出现在这一层。
docker commit 会将创建的文件提交上去,而不会外挂的文件提交上去。
网友评论