《docker 容器与容器云》读书笔记 part 1
这篇书评可能有关键情节透露
起源
docker基于go语言开发,apache 2.0协议。2013年正式发布开源版本。
docker优势:
* 持续部署和测试
* 跨云平台支持
* 环境标准化和版本控制
* 高资源利用率和隔离
* 容器跨平台性与镜像
* 易用
* 应用镜像仓库
前提
* 64位 cpu
* Linux内核版本为3.10+
* Linux内核开启cgroups和namespace
核心原理
通过namespace实现了资源隔离,通过cgroups实现了资源限制。
namespace 资源隔离
namespace的API包括clone()、setns()以及unshare(),还有/proc下的部分文件。
1.UTS(UNIX Time-sharing System)namespace提供了主机名和域名的隔离。
2.IPC namespace实现了容器与宿主机、容器与容器之间的IPC隔离。
3.PID namespace隔离对进程PID重新标号,即两个不同namespace下的进程可以 有相同的PID。
4.mount namespace通过隔离文件系统挂载点对隔离文件系统提供支持。
* master-slave为单箭头,表示传播方向
* share为双箭头,表示互相影响
* private为横线,表示隔离
* unbindable为叉,表示禁止绑定
5.network namespace主要提供了关于网络资源的隔离,包括网络设备、IPv4和IPv6协议栈、IP 路由表、防火墙、/proc/net目录、/sys/class/net目录、套接字(socket)等。
容器的经典做法就 是创建一个veth pair,一端放置在新的namespace中,通常命名为eth0,一端放在原先的namespace 中连接物理网络设备,再通过把多个设备接入网桥或者进行路由转发,来实现通信的目的。
6.user namespace主要隔离了安全相关的标识符(identifier)和属性(attribute),包括用户ID、 用户组ID、root目录、key(指密钥)以及特殊权限。
cgroups 资源限制
control groups可以限制、记录任务组所使用的物理资源(包括CPU、Memory、IO等)。
* 资源限制
* 优先级分配
* 资源统计
* 任务控制
mount -t group 查看子系统。
在/sys/fs/cgroup的cpu子目录下创建控制组,控制组目录创建成后,它下面就会有很多类似的文件。
tree cgroup/cpu/docker 查看docker控制组层级。
Docker使用了传统的client-server架构模式,用户通过Docker client与 Docker daemon建立通信,并将请求发送给后者。而Docker的后端是松耦合结构,不同模块各司其职。
libcontainer是对cgroups和namespace的二次封装,execdriver是通过libcontainer来实现对容器的具体管理,包括利用UTS、IPC、PID、Network、Mount、User等namespace实现容器之间的资源隔 离和利用cgroups实现对容器的资源限制。
Docker通过distribution、registry、layer、image、reference等模块实现了Docker镜像的管理。
* execdriver是对Linux操作系统的namespaces、cgroups、apparmor、SELinux等容器运行所 需的系统操作进行的一层二次封装。execdriver最主要的实现,是Docker官方编写的libcontainer库。
* volumedriver是volume数据卷存储操作的最终执行者,负责volume的增删改查,屏蔽不同驱动实现的区别,为上层调用者提供一个统一的接口。Docker中作为默认实现的 volumedriver是local,默认将文件存储于Docker根目录下的volume文件夹里。
* graphdriver是所有与容器镜像相关操作的最终执行者。在Linux环境下,目前Docker已经支持的graphdriver包括aufs、btrfs、zfs、devicemapper、overlay和vfs。
docker命令的两种模式:client模式和daemon模式。
docker [OPTIONS] COMMAND [arg...]
如果子命令为daemon,Docker就会创建一个运行在宿主机的daemon进程(docker/daemon. go#mainDaemon),即执行daemon模式。其余子命令都会执行client模式。
docker daemon会启动一个api server接收client的请求。Docker daemon运行中所在的工作目录,默认为 /var/lib/docker。
需要注意,目前vfs在Docker中是用来管理volume的,并不作为镜像存储使用。另外,由于目前在overlay文件系统上运行的Docker容器不兼容SELinux,因此当config中配置信息需要启用 SELinux并且driver的类型为overlay时,该过程就会报错。
libnetwork实现了host、null、 bridge和overlay的驱动。其中,bridge driver为默认驱动。bridge driver并不提供跨主机通信的能力,overlay driver则适用于多主机环境。
execdriver是Docker中用来管理Docker容器的驱动。
容器是一个与宿主机系统共享内核但与系统中的其他进程资源相隔离的执行环境。
libcontainer对Docker容器做了一层更高级的抽象,定义了Process和Container 来对应Linux中“进程”与“容器”的关系。
libcontainer实现原理:
(1) Docker daemon进程进行“用Facotry创建逻辑容器Container”“启动逻辑容器Container” 等准备工作,构建ParentProcess对象,然后利用它创建容器内的第一个进程dockerinit。
(2) dockerinit利用reexec.init()执行StartInitialization()。这里dockerinit会将自己加入 到用户指定的namespace(如果指定了的话),然后再开始进行容器内部的各项初始化工作。
(3) StartInitialization()使用execv系统调用执行容器配置中的Args指定的命令,即Entry- Point和docker run的[COMMAND]参数
子进程感知内存中写入了新数据:
Docker选择的方式是管道——文件和文件描述符方式。
Docker镜像的文件内容以及一些运行Docker容器的配置文件组成了Docker容器的静态文件系统运行环境——rootfs。
镜像的特点:分层,copy on write,内容寻址,联合挂载。
联合挂载是用于将多个镜像层的文件系统挂载到一个挂载点来实现一个统一文件系统视图 的途径,是下层存储驱动(如aufs、overlay等)实现分层合并的方式。
registry是repository的集合,repository是镜像的集合。
docker push 通过线上Docker Hub的方式迁移,而docker save则是通过线下包分发的方式迁移。
GraphDriver中主要定义了Driver和ProtoDriver两个接口,所有的存储驱动通过实现Driver 接口提供相应的功能,而ProtoDriver接口则负责定义其中的基本功能。
Docker中的任何存储驱动都需要实现上述Driver接口。
常用存储驱动有aufs、devicemapper以及overlay。
镜像层或者容器层在存储驱动中拥有一个标示ID,在镜像层(roLayer)中称为cacheID,容器层(mountedLayer)中为mountID。
Docker容器的文件系统有3层:可读写层(将来被commit的内容)、init层和 只读层。
1 aufs(advanced multi layered unification filesystem)是一种支持联合挂载的文件系统,支持将不同目录挂载到同一个目录下。
2 Device Mapper是Linux 2.6内核中提供的一种从逻辑设备到物理设备的映射框架机制。
Device Mapper包括3个概念:映射设备、映射表和目标设备。
3 OverlayFS是一种新型联合文件系统(union filesystem),允许用户将一个文件系统与另一 个文件系统重叠(overlay),在上层的文件系统中记录更改,而下层的文件系统保持不变。相比于aufs,OverlayFS在设计上更简单,理论上性能更好。
OverlayFS使用4类目录:
* 被联合挂载的两个目录lower和upper
* 作为统一视图联合挂载点的merged目录
* 作为辅助功能的work目录
docker volume create创建volume。
在创建volume时会在宿主机/var/lib/docker/volume/创建一个以volume ID为名的目录,volume中的内容存储在_data目录。
$ sudo docker run -v /host/dir:/container/dir ubuntu /bin/bash
共享volume (--volumes-from)
// 将宿主机上的volume_id目录绑定挂载到rootfs中指定的挂载点/data上
mount(“/var/lib/docker/volumes/volume_id/_data”, “rootfs/data”, “none”, MS_BIND, NULL)
// 将宿主机上的/var/log目录绑定挂载到rootfs中指定的挂载点/data上
mount(“/var/log”, “rootfs/data”, “none”, MS_BIND, NULL)
五大网络驱动:
* bridge 桥接
* host 共享宿主机网络空间
* overlay VXLAN
* remote 插件化
* null 配置为空,需要进一步定义
docker的安全机制:
* daemon安全:unix套接字本地连接,tls的TCP连接
* 镜像安全:registry
* 内核安全:cgroups,namespace
* 容器网络安全 —icc标志
* 容器能力限制(docker run 参数)
* seccomp(安全计算模式)