Docker

Docker核心实现技术

2019-05-17  本文已影响0人  王勇1024

cgroups

cgroups是Linux内核的一个特性,主要用来对共享资源进行隔离、限制、审计等。只有能控制分配到容器的资源,才能避免多个容器同时运行时对宿主机的资源竞争。

cgroups提供:

安装 Docker 后,用户可以在 /sys/fs/cgroup/memory/docker 目录下看到对 Docker 组应用的各种限制项,包括:

$ ll /sys/fs/cgroup/memory/docker
总用量 0
-rw-r--r-- 1 root root 0 3月  11 18:18 cgroup.clone_children
--w--w--w- 1 root root 0 3月  11 18:18 cgroup.event_control
-rw-r--r-- 1 root root 0 3月  11 18:18 cgroup.procs
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.failcnt
--w------- 1 root root 0 3月  11 18:18 memory.force_empty
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.kmem.failcnt
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.kmem.limit_in_bytes
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.kmem.max_usage_in_bytes
-r--r--r-- 1 root root 0 3月  11 18:18 memory.kmem.slabinfo
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.kmem.tcp.failcnt
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.kmem.tcp.limit_in_bytes
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.kmem.tcp.max_usage_in_bytes
-r--r--r-- 1 root root 0 3月  11 18:18 memory.kmem.tcp.usage_in_bytes
-r--r--r-- 1 root root 0 3月  11 18:18 memory.kmem.usage_in_bytes
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.limit_in_bytes
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.max_usage_in_bytes
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.memsw.failcnt
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.memsw.limit_in_bytes
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.memsw.max_usage_in_bytes
-r--r--r-- 1 root root 0 3月  11 18:18 memory.memsw.usage_in_bytes
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.move_charge_at_immigrate
-r--r--r-- 1 root root 0 3月  11 18:18 memory.numa_stat
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.oom_control
---------- 1 root root 0 3月  11 18:18 memory.pressure_level
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.soft_limit_in_bytes
-r--r--r-- 1 root root 0 3月  11 18:18 memory.stat
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.swappiness
-r--r--r-- 1 root root 0 3月  11 18:18 memory.usage_in_bytes
-rw-r--r-- 1 root root 0 3月  11 18:18 memory.use_hierarchy
-rw-r--r-- 1 root root 0 3月  11 18:18 notify_on_release
-rw-r--r-- 1 root root 0 3月  11 18:18 tasks

可以在创建或启动容器时为每个容器指定资源的限制,例如使用-c|--cpu-shares[=0] 参数来调整容器使用 CPU 的权重;使用 -m|--memory[=MEMORY] 参数来调整容器使用内存的大小。

UnionFS

UnionFS是一种轻量级的高性能分层文件系统,它支持将文件系统的修改信息作为一次提交,并层层叠加,同时可以将不同目录挂载到同一个虚拟文件系统下,应用看到的是挂载的最终结果。
Docker镜像自身就是由多个文件层组成,每一层有唯一的编号(层ID)。
可以通过docker history查看一个镜像由哪些层组成:

$ sudo docker history 04060a9dfc39
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
04060a9dfc39        4 months ago        /bin/sh -c set -x  && apk add --no-cache   o…   98.2MB
<missing>           4 months ago        /bin/sh -c #(nop)  ENV JAVA_ALPINE_VERSION=8…   0B
<missing>           4 months ago        /bin/sh -c #(nop)  ENV JAVA_VERSION=8u181       0B
<missing>           4 months ago        /bin/sh -c #(nop)  ENV PATH=/usr/local/sbin:…   0B
<missing>           4 months ago        /bin/sh -c #(nop)  ENV JAVA_HOME=/usr/lib/jv…   0B
<missing>           4 months ago        /bin/sh -c {   echo '#!/bin/sh';   echo 'set…   87B
<missing>           4 months ago        /bin/sh -c #(nop)  ENV LANG=C.UTF-8             0B
<missing>           4 months ago        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           4 months ago        /bin/sh -c #(nop) ADD file:2ff00caea4e83dfad…   4.41MB

对于 Docker 镜像来说,这些层的内容都是不可修改、只读的。

当 Docker 利用镜像启动一个容器时,将在镜像文件系统的最顶端再挂载一个新的可读写的层给容器。容器中的内容更新将会发生在可读写层。

当所操作的对象位于较深的某层时,需要先复制到最上层的可读写层。当书记对象较大时,往往意味着IO性能较差,因此,一般推荐将容器修改的数据通过 volume 方式挂载,而不是直接修改镜像内的数据。

Docker 所有的存在都在 Docker 目录下,以 Ubuntu 为例,默认路径是 /var/lib/docker。

Linux 网络虚拟化

Docker 的本地网络实现其实就是利用了 Linux 上的网络命名空间和虚拟网络设备(特别是 vetch pair)。

  1. 基本原理


    Linux虚拟网络技术
  2. 网络创建过程
    一般情况下,Docker创建一个容器的时候,会具体执行如下操作:
    <1> 创建一对虚拟接口,分别放到本地主机和新容器的命名空间中;
    <2> 本地主机一端的虚拟接口连接到默认的 docker0 网桥或指定网桥上,并具有一个以 veth 开头的唯一名字;
    <3> 容器一端的虚拟接口将放到新创建的容器中,并修改名字为 eth0,这个接口只有容器的命名空间可见;
    <4> 从网桥可用地址段中获取一个空闲地址分配给容器的 eth0 (例如172.17.0.2/16),并配置默认网关为 docker0 网卡的内部接口 docker0 的IP地址。

下面是一个 docker0 和 vetch 的示例:

docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
        ether 02:42:34:34:1e:51  txqueuelen 0  (Ethernet)
        RX packets 1318068311  bytes 409028946152 (380.9 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1499669933  bytes 4630779421080 (4.2 TiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

veth117260f: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        ether 76:39:98:ab:32:33  txqueuelen 0  (Ethernet)
        RX packets 35847863  bytes 182779813303 (170.2 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 43562399  bytes 17982858256 (16.7 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

在使用docker run命令启动容器的时候,可以通过--net参数来指定容器的网络配置。
有5个可选值bridge、none、container、host 和 用户定义的网络:

上一篇 下一篇

猜你喜欢

热点阅读