首页 > 数据库 > 数据库开发技术 > 每日一问题探索-简说docker
tip:
容器的大部分问题最终都会归结到LINUX操作系统
例如:
容器里进程被OOM kill了,OOM kill是linux里常见的内存保护机制容器使用的OverlayFS系统,看上去和linux常用的XFS,Ext4系统不同,但是它也是Linux内核维护的一种文件系统
linux操作系统不外乎是进程管理,内存管理,文件系统,网络协议栈,再加上一些安全管理。
除此之外容器有自己的特殊性:在linux内核原来的特性上加上Namespace与Cgroups
docker是利用linux的namespace,Cgroups和联合文件系统三大机制来保证的
原理:
使用namespace做主机名,网络,pid等资源的隔离使用cgroups对进程或进程组做资源(cpu,内存等)的限制联合文件系统用户镜像的构建与容器的运行环境
chroot是在Unix和Linux系统的一个操作,针对正在运行的软件进程和它的子系统,改变它的外显的根目录。一个运行在这个环境下,经由chroot设置根目录的程序,它不能够对这个指定目录之外的文件进行访问操作,不能读写其他目录的内容
Namespace是linux内核的一项功能,对内核资源进行隔离,使得容器内的进程都可以在单独的命名空间中运行,并且只可以访问当前容器命名空间的资源
隔离对象:进程ID,主机名,用户ID,文件名,网络访问和进程间通信等的相关资源
Docker 只使用了其中的前6 种,分别为Mount Namespace、PID Namespace、Net Namespace、IPC Namespace、UTS Namespace、User Namespace。
Mount Namespace 是 Linux 内核实现的第一个 Namespace,从内核的 2.4.19 版本开始加入。它可以用来隔离不同的进程或进程组看到的挂载点。通俗地说,就是可以实现在不同的进程中看到不同的挂载目录。使用 Mount Namespace 可以实现容器内只能看到自己的挂载信息,在容器内的挂载操作不会影响主机的挂载目录。
PID Namespace 的作用是用来隔离进程。在不同的 PID Namespace 中,进程可以拥有相同的 PID 号,利用 PID Namespace 可以实现每个容器的主进程为 1 号进程,而容器内的进程在主机上却拥有不同的PID。例如一个进程在主机上 PID 为 122,使用 PID Namespace 可以实现该进程在容器内看到的 PID 为 1。
UTS Namespace 主要是用来隔离主机名的,它允许每个 UTS Namespace 拥有一个独立的主机名。例如我们的主机名称为 docker,使用 UTS Namespace 可以实现在容器内的主机名称为 lagoudocker 或者其他任意自定义主机名。
IPC Namespace 主要是用来隔离进程间通信的。例如 PID Namespace 和 IPC Namespace 一起使用可以实现同一 IPC Namespace 内的进程彼此可以通信,不同 IPC Namespace 的进程却不能通信。
User Namespace 主要是用来隔离用户和用户组的。一个比较典型的应用场景就是在主机上以非 root 用户运行的进程可以在一个单独的 User Namespace 中映射成 root 用户。使用 User Namespace 可以实现进程在容器内拥有 root 权限,而在主机上却只是普通用户。
Net Namespace 是用来隔离网络设备、IP 地址和端口等信息的。Net Namespace 可以让每个进程拥有自己独立的 IP 地址,端口和网卡信息。例如主机 IP 地址为 172.16.4.1 ,容器内可以设置独立的 IP 地址为 192.168.1.1。
实例:

Linux 在创建容器的时候,就会建出一个 PID Namespace,PID 其实就是进程的编号。这个 PID Namespace,就是指每建立出一个 Namespace,就会单独对进程进行 PID 编号,每个 Namespace 的 PID 编号都从 1 开始。同时在这个 PID Namespace 中也只能看到 Namespace 中的进程,而且看不到其他 Namespace 里的进程。
Cgroups是linux内核功能,可以限制和隔离进程的资源使用情况(CPU,内存,磁盘IO,网络等)
Cgroups通过不同的子系统限制不同的资源,每个子系统限制一种资源。每个子系统限制资源的方式都是类似的,就是把相关的一组进程分配到一个控制组里,然后通过树结构进行管理
CPU子系统:
用来限制一个控制组(一组进程,可以理解为一个容器里所有的进程)可以使用的最大CPU
memory子系统:
用来限制一个控制组里最大的内存使用量
pids子系统:
用来限制一个控制组里最多可以运行多少个进程
cpuset子系统:
这个子系统来限制一个控制组里的进程可以在哪几个物理CPU上运行
cgroups功能的实现依赖于三个核心概念:
子系统、控制组、层级树
子系统(subsystem):是一个内核的组件,一个子系统代表一类资源调度控制器。例如内存子系统可以限制内存的使用量,CPU 子系统可以限制 CPU 的使用时间。
控制组(cgroup):表示一组进程和一组带有参数的子系统的关联关系。例如,一个进程使用了 CPU 子系统来限制 CPU 的使用时间,则这个进程和 CPU 子系统的关联关系称为控制组。
层级树(hierarchy):是由一系列的控制组按照树状结构排列组成的。这种排列方式可以使得控制组拥有父子关系,子控制组默认拥有父控制组的属性,也就是子控制组会继承于父控制组。比如,系统中定义了一个控制组 c1,限制了 CPU 可以使用 1 核,然后另外一个控制组 c2 想实现既限制 CPU 使用 1 核,同时限制内存使用 2G,那么 c2 就可以直接继承 c1,无须重复定义 CPU 限制。
资源限制:限制资源的使用量,例如我们可以通过限制某个业务的内存上限,从而保护主机其他业务的安全运行。优先级控制:不同的组可以有不同的资源( CPU 、磁盘 IO 等)使用优先级。审计:计算控制组的资源使用情况。控制:控制进程的挂起或恢复。
联合文件系统
联合文件系统(Union File System,Unionfs)是一种分层的轻量级文件系统,它可以把多个目录内容联合挂载到同一目录下,从而形成一个单一的文件系统,这种特性可以让使用者像是使用一个目录一样使用联合文件系统。
docker使用联合文件系统为容器提供构建层,使得容器可以实现写时复制已经镜像的分层构建和存储,常使用的联合文件系统有AUFS,Overlay和Devicemapper等
原文作者:五分钟学SRE;如有侵权,请联系管理员删除。