docker底层原理介绍

2018-09-07  本文已影响1190人  编码前线

1.docker介绍

1.1什么是docker

Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。

Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上。

1.2docker能解决什么问题

1.2.1高效有序利用资源

1.2.2一次编译,到处运行

1.2.docker底层原理介绍

1.2.1Linux的namespace和cgroup简单理解

namespace:类似于JAVA的命名空间

controll groups : controll (system resource) (for) (process)groups

1.2.2Linux中的namespace

在Linux系统中,可以同时存在多用户多进程,那么对他们的运行协调管理,通过进程调度和进度管理可以解决,但是,整体资源是有限的,怎么把有限的资源(进程号、网络资源等等)合理分配给各个用户所在的进程?

image

Linux Namespaces机制提供一种资源隔离方案。PID,IPC,Network等系统资源不再是全局性的,而是属于某个特定的Namespace。每个namespace下的资源对于其他namespace下的资源都是透明,不可见的。因此在操作系统层面上看,就会出现多个相同pid的进程。系统中可以同时存在两个进程号为0,1,2的进程,由于属于不同的namespace,所以它们之间并不冲突。而在用户层面上只能看到属于用户自己namespace下的资源,例如使用ps命令只能列出自己namespace下的进程。这样每个namespace看上去就像一个单独的Linux系统。

image

命名空间建立系统的不同视图, 对于每一个命名空间,从用户看起来,应该像一台单独的Linux计算机一样,有自己的init进程(PID为0),其他进程的PID依次递增,A和B空间都有PID为0的init进程,子容器的进程映射到父容器的进程上,父容器可以知道每一个子容器的运行状态,而子容器与子容器之间是隔离的。

<colgroup style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"><col style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"><col style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"><col style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"><col style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important;"></colgroup>
|

namespace

|

引入的相关内核版本

|

被隔离的全局系统资源

|

在容器语境下的隔离效果

|
| --- | --- | --- | --- |
| Mount namespaces | Linux 2.4.19 | 文件系统挂接点 |

将一个文件系统的顶层目录挂到另一个文件系统的子目录上,使它们成为一个整体,称为挂载。把该子目录称为挂载点。

Mount namespace用来隔离文件系统的挂载点, 使得不同的mount namespace拥有自己独立的挂载点信息,不同的namespace之间不会相互影响,这对于构建用户或者容器自己的文件系统目录非常有用。

|
| UTS namespaces | Linux 2.6.19 | nodename 和 domainname |

UTS,UNIX Time-sharing System namespace提供了主机名和域名的隔离。能够使得子进程有独立的主机名和域名(hostname),这一特性在Docker容器技术中被用到,使得docker容器在网络上被视作一个独立的节点,而不仅仅是宿主机上的一个进程。

|
| IPC namespaces | Linux 2.6.19 | 特定的进程间通信资源,包括System V IPC 和 POSIX message queues |

IPC全称 Inter-Process Communication,是Unix/Linux下进程间通信的一种方式,IPC有共享内存、信号量、消息队列等方法。所以,为了隔离,我们也需要把IPC给隔离开来,这样,只有在同一个Namespace下的进程才能相互通信。如果你熟悉IPC的原理的话,你会知道,IPC需要有一个全局的ID,即然是全局的,那么就意味着我们的Namespace需要对这个ID隔离,不能让别的Namespace的进程看到。

|
| PID namespaces | Linux 2.6.24 | 进程 ID 数字空间 (process ID number space) |

PID namespaces用来隔离进程的ID空间,使得不同pid namespace里的进程ID可以重复且相互之间不影响。

PID namespace可以嵌套,也就是说有父子关系,在当前namespace里面创建的所有新的namespace都是当前namespace的子namespace。父namespace里面可以看到所有子孙后代namespace里的进程信息,而子namespace里看不到祖先或者兄弟namespace里的进程信息。

|
| Network namespaces | 始于Linux 2.6.24 完成于 Linux 2.6.29 | 网络相关的系统资源 | 每个容器用有其独立的网络设备,IP 地址,IP 路由表,/proc/net 目录,端口号等等。这也使得一个 host 上多个容器内的同一个应用都绑定到各自容器的 80 端口上。 |
| User namespaces | 始于 Linux 2.6.23 完成于 Linux 3.8) | 用户和组 ID 空间 |

User namespace用来隔离user权限相关的Linux资源,包括user IDs and group IDs。

这是目前实现的namespace中最复杂的一个,因为user和权限息息相关,而权限又事关容器的安全,所以稍有不慎,就会出安全问题。

在不同的user namespace中,同样一个用户的user ID 和group ID可以不一样,换句话说,一个用户可以在父user namespace中是普通用户,在子user namespace中是超级用户

|

1.2.3linux cgroup介绍

(1)有了namespace为什么还要cgroup:

Docker 容器使用 linux namespace 来隔离其运行环境,使得容器中的进程看起来就像一个独立环境中运行一样。但是,光有运行环境隔离还不够,因为这些进程还是可以不受限制地使用系统资源,比如网络、磁盘、CPU以及内存 等。关于其目的,一方面,是为了防止它占用了太多的资源而影响到其它进程;另一方面,在系统资源耗尽的时候,linux 内核会触发 OOM,这会让一些被杀掉的进程成了无辜的替死鬼。因此,为了让容器中的进程更加可控,Docker 使用 Linux cgroups 来限制容器中的进程允许使用的系统资源。

(2)原理

Linux Cgroup 可为系统中所运行任务(进程)的用户定义组群分配资源 — 比如 CPU 时间、系统内存、网络带宽或者这些资源的组合。可以监控管理员配置的 cgroup,拒绝 cgroup 访问某些资源,甚至在运行的系统中动态配置 cgroup。所以,可以将 controll groups 理解为 controller (system resource) (for) (process)groups,也就是是说它以一组进程为目标进行系统资源分配和控制。它主要提供了如下功能:

使用 cgroup,系统管理员可更具体地控制对系统资源的分配、优先顺序、拒绝、管理和监控。可更好地根据任务和用户分配硬件资源,提高总体效率。

在实践中,系统管理员一般会利用CGroup做下面这些事:

1.3docker与虚拟机的区别

1.3.1虚拟机结构介绍

image

1.3.2docker结构介绍

image

Docker守护进程可以直接与主操作系统进行通信,为各个Docker容器分配资源;它还可以将容器与主操作系统隔离,并将各个容器互相隔离。虚拟机启动需要数分钟,而Docker容器可以在数毫秒内启动。由于没有臃肿的从操作系统,Docker可以节省大量的磁盘空间以及其他系统资源;虚拟机更擅长于资源的完全隔离。

上一篇下一篇

猜你喜欢

热点阅读