四、Docker Daemon 中NewDaemon的实现(摘自《Docker源码分析》)

1、NewDaemon 作用简介

在 Docker 架构中有很多重要的概念,如:graph,graphdriver,execdriver,networkdriver,volumes,Docker containers 等。Docker 在实现过程中,需要将以上实体进行统一化管理,而 Docker Daemon 中的 daemon 实例就是设计用来完成这一任务的实体。

2、NewDaemon 介绍

NewDaemon 函数的执行完成了 Docker Daemon 创建并加载 daemon 的任务,最终实现统一管理 Docker Daemon 的资源。

NewDaemon的执行流程主要包括12个独立步骤:

1)、处理配置信息
2)、检测系统支持及用户权限
3)、配置工作路径
4)、加载并配置 graphdriver
5)、创建 Docker Daemon 网络环境
6)、创建并初始化 graphdb
7)、创建 execdriver
8)、创建 daemon 实例
9)、检测 DNS 配置
10)、加载已有 container
11)、设置 shutdown 处理方法
12)、以及返回 daemon 实例

2.1 应用配置信息

配置信息的主要功能是:供用户自由配置 Docker 的可选功能,使得 Docker 的运行更贴近用户期待的运行场景。

配置信息的处理包含 4 部分:

1)配置 Docker 容器的 MTU——config 信息中的 Mtu 应用于容器网络的最大传输单元(MTU)特性
2)检测网桥配置信息——检测 config 中 BridgeIface 和 BridgeIP 这两个信息
3)查验容器通信配置——主要是针对 config 中的 EnableIptables 和 InterContainerCommunication 这两个属性。EnableIptables 属性的作用是启用 Docker 对 iptables 规则的添加功能;InterContainerCommunication 的作用是启用 Docker container 之间互相通信的功能。
4)处理 PID 文件配置——主要工作是:为 Docker Daemon 进程运行时的 PID 号创建一个 PID 文件,文件的路径即为 config 中的 Pidfile 属性。并且为 Docker Daemon 的 shutdown 操作添加一个删除该 Pidfile 的函数,以便在 Docker Daemon 退出的时候,可以在第一时间删除该 Pidfile

2.2 检测系统支持及用户权限

处理完 Docker 的配置信息之后,Docker 对自身运行的环境进行了一系列的检测,主要包括三个方面:
1)操作系统类型对 Docker Daemon 的支持
2)用户权限的级别
3)内核版本与处理器的支持

2.3 配置工作路径

主要是创建 Docker Daemon 运行中所在的工作目录。
主要步骤如下:
(1) 使用规范路径创建一个 TempDir,路径名为 tmp;
(2) 通过 tmp,创建一个指向 tmp 的文件符号连接 realTmp;
(3) 使用 realTemp 的值,创建并赋值给环境变量 TMPDIR;
(4) 处理 config 的属性 EnableSelinuxSupport;
(5) 将 realRoot 重新赋值于 config.Root,并创建 Docker Daemon 的工作根目录。

2.4 加载并配置 graphdriver

加载并配置存储驱动 graphdriver,目的在于:使得 Docker Daemon 创建 Docker 镜像管理所需的驱动环境。

Graphdriver 用于完成 Docker 容器镜像的管理,包括存储与获取,主要工作是:在文件系统中指定的 root 目录下,实例化一个全新的 graph 对象,作用为:存储所有标记的文件系统镜像,并记录镜像之间的关系。

1)创建 volumesdriver 以及 volumes graph
Docker 中 volume 的概念是:可以从 Docker 宿主机上挂载到 Docker 容器内部的特定目录。一个 volume 可以被多个 Docker 容器挂载,从而 Docker 容器可以实现互相共享数据等。在实现 volumes 时,Docker 需要使用 driver 来管理它,又由于 volumes 的管理不会像容器文件系统管理那么复杂,故 Docker 采用 vfs 驱动实现 volumes 的管理。

2)创建 TagStore
主要是用于存储镜像的仓库列表(repository list)

·TagStore 类型中的多个属性的含义:
·path:TagStore 中记录镜像仓库的文件所在路径;
·graph:相应的 Graph 实例对象;
·Repositories:记录具体的镜像仓库的 map 数据结构;
·sync.Mutex:TagStore 的互斥锁
·pullingPool :记录池,记录有哪些镜像正在被下载,若某一个镜像正在被下载,则驳回其他 Docker Client 发起下载该镜像的请求;
·pushingPool:记录池,记录有哪些镜像正在被上传,若某一个镜像正在被上传,则驳回其他 Docker Client 发起上传该镜像的请求;

2.5 创建 Docker Daemon 网络环境

创建网络环境是极为重要的一个部分,这不仅关系着容器对外的通信,同样也关系着容器间的通信。
bridge.InitDriver 函数作用为:
·获取为 Docker 服务的网络设备的地址;
·创建指定 IP 地址的网桥;
·启用 Iptables 功能并配置;
·另外还为 eng 实例注册了 4 个 Handler, 如 ”allocate_interface”, ”release_interface”, ”allocate_port”,”link”。
1)创建网桥名为:docker0
2)启用 iptables 包括 container 容器之间所需要的 link 操作提供支持,为 host 主机上所有的对外对内流量制定传输规则等
假设网桥设备名为 docker0,网桥网络地址为 docker0_ip, 设置 iptables 规则,操作步骤如下:
(1) 使用 iptables 工具开启新建网桥的 NAT 功能,使用命令如下:

iptables -I POSTROUTING -t nat -s docker0_ip ! -o docker0 -j MASQUERADE

(2) 通过 icc 参数,决定是否允许 container 间通信,并制定相应 iptables 的 Forward 链。Container 之间通信,说明数据包从 container 内发出后,经过 docker0,并且还需要在 docker0 处发往 docker0,最终转向指定的 container。换言之,从 docker0 出来的数据包,如果需要继续发往 docker0,则说明是 container 的通信数据包。命令使用如下:

iptables -I FORWARD -i docker0 -o docker0 -j ACCEPT

(3) 允许接受从 container 发出,且不是发往其他 container 数据包。换言之,允许所有从 docker0 发出且不是继续发向 docker0 的数据包,使用命令如下:

iptables -I FORWARD -i docker0 ! -o docker0 -j ACCEPT

(4) 对于发往 docker0,并且属于已经建立的连接的数据包,Docker 无条件接受这些数据包,使用命令如下:


iptables -I FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

3)启用系统数据包转发功能
在 Linux 系统上,数据包转发功能是被默认禁止的。数据包转发,就是当 host 主机存在多块网卡的时,如果其中一块网卡接收到数据包,并需要将其转发给另外的网卡。通过修改 /proc/sys/net/ipv4/ip_forward 的值,将其置为 1,则可以保证系统内数据包可以实现转发功能

cat /proc/sys/net/ipv4/ip_forward
1

4)创建 DOCKER 链
在网桥设备上创建一条名为 DOCKER 的链,该链的作用是在创建 Docker container 并设置端口映射时使用。
5) 注册 Handler 至 Engine (引擎)
在创建完网桥,并配置完基本的 iptables 规则之后,Docker Daemon 在网络方面还在 Engine 中注册了 4 个 Handler,这些 Handler 的名称与作用如下:
·allocate_interface:为 Docker container 分配一个专属网卡;
·realease_interface:释放网络设备资源;
·allocate_port:为 Docker container 分配一个端口;
·link:实现 Docker container 间的 link 操作。
6)创建 graphdb 并初始化
Graphdb 是一个构建在 SQLite 之上的图形数据库,通常用来记录节点命名以及节点之间的关联。Docker Daemon 使用 graphdb 来记录镜像之间的关联。
7)创建 execdriver
Execdriver 是 Docker 中用来执行 Docker container 任务的驱动。创建并初始化 graphdb 之后,Docker Daemon 随即创建了 execdriver,在创建 execdriver 的时候,需要 4 部分的信息,以下简要介绍这 4 部分信息:

  • config.ExecDriver:Docker 运行时中指定使用的 exec 驱动类别,在默认配置文件中默认使用”native”, 也可以将这个值改为”lxc”,则使用 lxc 接口执行 Docker container 内部的操作 ;
  • config.Root:Docker 运行时的 root 路径,默认配置文件中为”/var/lib/docker”;
  • sysInitPath: 系统上存放 dockerinit 二进制文件的路径,一般为”/var/lib/docker/init/dockerinit-1.2.0”;
  • sysInfo: 系统功能信息,包括:容器的内存限制功能,交换区内存限制功能,数据转发功能,以及 AppArmor 安全功能等。

8)创建 daemon 实例
分析 Daemon 类型的属性:

属性名
作用
repository
部署所有 Docker 容器的路径
containers
用于存储具体 Docker 容器信息的对象
graph
存储 Docker 镜像的 graph 对象
repositories
存储 Docker 镜像元数据的文件
idIndex
用于通过简短有效的字符串前缀定位唯一的镜像
sysInfo
系统功能信息
volumes
管理 host 主机上 volumes 内容的 graphdriver,默认为 vfs 类型
config
Config.go 文件中的配置信息,以及执行产生的配置 DisableNetwork
containerGraph
存放 Docker 镜像关系的 graphdb
driver
管理 Docker 镜像的驱动 graphdriver,默认为 aufs 类型
sysInitPath
系统 dockerinit 二进制文件所在的路径
execDriver
Docker Daemon 的 exec 驱动,默认为 native 类型
eng
Docker 的执行引擎 Engine 类型实例
9) 检测 DNS 配置
获取 /etc/resolv.conf 中的 DNS 服务器信息。若本地 DNS 文件中有 127.0.0.1,而 Docker container 不能使用该地址,故采用默认外在 DNS 服务器,为 8.8.8.8,8.8.4.4,并将其赋值给 config 文件中的 Dns 属性。
10)启动时加载已有 Docker containers
当 Docker Daemon 启动时,会去查看在 daemon.repository,也就是在 /var/lib/docker/containers 中的内容。若有存在 Docker container 的话,则让 Docker Daemon 加载这部分容器,将容器信息收集,并做相应的维护。
11)设置 shutdown 的处理方法
加载完已有 Docker container 之后,Docker Daemon 设置了多项在 shutdown 操作中需要执行的 handler。也就是说:当 Docker Daemon 接收到特定信号,需要执行 shutdown 操作时,先执行这些 handler 完成善后工作,最终再实现 shutdown。

eng 对象 shutdown 操作执行时主要完成 4 部分的操作:

  • 运行 daemon 对象的 shutdown 函数,做 daemon 方面的善后工作;
  • 通过 portallocator.ReleaseAll(),释放所有之前占用的端口资源;
  • 通过 daemon.driver.Cleanup(),通过 graphdriver 实现 unmount 所有 layers 中的挂载点;
  • 通过 daemon.containerGraph.Close() 关闭 graphdb 的连接。

12)返回 daemon 对象实例

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,552评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,666评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,519评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,180评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,205评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,344评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,781评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,449评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,635评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,467评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,515评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,217评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,775评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,851评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,084评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,637评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,204评论 2 341

推荐阅读更多精彩内容