1、整体架构
在 Linux 环境中,docker的整体架构
容器管理工具(例如 Docker)是基于一组更精细的容器工具构建的: runc和containerd。
Linux 上的 Docker 体系结构
1.1 操作系统(底层技术)
1.1.1 Control Groups:对资源分配和限制
cgroup将限制应用程序使用一组特定的资源。cgroup允许Docker引擎将可用的硬件资源共享给容器,并有选择地实施限制和约束。例如,可以限制特定容器可用的内存。Cgroups 是Linux 内核提供的一种机制,这种机制可以根据需求把一系列系统任务及其子任务整合(或分割)到按资源划分等级的不同组内,从而为系统资源管理提供一个统一的框架。
Cgroups可以限制、记录任务组使用的物理资源(cpu、memory 、io等),主要作用如下:
- 资源限制:对任务使用的资源总额进行限制
- 优先级分配:控制任务运行的优先级
- 资源统计:统计系统资源的使用量
- 任务控制:对任务执行挂起、恢复等操作
1.1.2 Namespace:对系统资源的封装隔离
Docker使用namespace技术为容器提供隔离,在运行容器时,Docker将会为其创建一个namespace集合。这些namespace为容器提供隔离层,容器的每个方面都在单独的namespace中运行,并且其访问仅限于该namespace。
Namespace是对全局系统资源的一种封装隔离,使得处于不同namespace的进程拥有独立的全局系统资源,改变一个namespace中的系统资源只会影响当前namespace里的进程,对其他namespace
中的进程没有影响。而Docker其实就通过 Linux 的Namespaces对不同的容器实现了资源隔离。
在Linux内核中提供了多种namesapce隔离系统调用,如下所示:
- pid: 进程隔离(PID: Process ID).
- net: 隔离网络接 (NET: Networking).
- ipc: 隔离IPC资源访问 (IPC: InterProcess Communication).
- mnt: 隔离文件系统挂接点 (MNT: Mount).
- uts: 隔离内核和版本标识 (UTS: Unix Timesharing System).
1.1.3 Layer Capabilities:
联合文件系统或UnionFS是通过创建层进行操作的文件系统,使其非常轻便且快速。Docker引擎使用UnionFS为容器提供构建模块。Docker引擎可以使用多个UnionFS变体,包括AUFS,btrfs,vfs、overlay、overlay2、zfs、brtfs和DeviceMapper等。
2 控制器
1.2.1 runc:
是一种 Linux 命令行工具,用于根据OCI 容器运行时规范创建和运行容器。runc是容器标准化的产物,为了避免docker垄断容器标准,成立了opencontainers组织,定义了容器,镜像和仓库的标准,runc就是该标准的一个实现,通过runc可以完成容器的启停等操作。
1.2.2 containerd shim
一个容器的启动就是一个进程的启动,而containerd-shim就是容器所在的进程。容器运行的真正载体,一个容器对应一个containerd-shim进程。容器运行时通过调用oci的一个标准实现runc来完成对应容器的启停过程,但是容器的管理都托管于容器的shim进程。
shim主要是作为容器进程的父进程,与containerd解耦,可以实现containerd挂掉的时候容器依然运行;shim的设计允许runc执行后即可退出,runc非常驻内存操作。另外shim用于收集容器状态以及向containerd报告容器状态。shim设计的第二个目的,主要是避免runc运行占用过多的内存,go语言默认的是静态编译,如果一个机器上运行N个容器,就需要占用N*runc消耗内存,shim可以减缓,但是不能完全消除。至于runc为何不使用动态编译的原因,猜测是为了尽可能减少部署的麻烦。
1.2.3 containerd:
containerd是一个守护程序,它管理容器生命周期,从下载容器到容器映像并将其解压缩到容器执行和监督。然而containerd并不直接做此事,而是交给runC来运行container。而Docker Engine则依然需要负责管理image,至于image的运行(container)则交给containerd组件来完成。docker engine的守护进程,接收docker client的请求,完成镜像、容器、容器网络、容器存储、swarm集群的管理。其中容器的管理通过rpc调用containerd进行管理。
containerd是一个工业级别的容器运行时,强调简单,健壮和可移植。它宿主机上容器的完成声明周期,主要提供如下功能:镜像的传输和存储,容器的运行和管理,底层的存储和网络等。containerd被设计成可以集成进入大型系统中,而不是直接被开发或者终端用户使用的。从containerd可以单独作为k8s的容器运行时即可看出。在docker内,实现了dockerd和cotainerd的解耦,可以容器不停,完成dockerd升级操作。需要docker的live-restore配置支持。
4 容器引擎
Docker Engine Components Flow
在架构中,Docker Engine是客户端-服务器模式的应用程序:
- 守护程序:服务器是在宿主机中长期运行的程序,作为容器的守护程序( dockerd 命令)。
- API接口:REST API,它指定程序可以用来与守护程序进行通信并指示其操作的接口。
- 客户端:命令行界面(CLI)客户端(docker 命令)。
CLI使用Docker REST API通过脚本或直接CLI命令控制或与Docker守护程序交互。许多其他Docker应用程序都使用基础API和CLI。守护程序负责创建和管理Docker 对象,例如镜像,容器,网络和数据卷。
4.1 libcontainer
Docker引擎将名称空间,控制组和UnionFS组合到一个称为容器格式的封装器中。默认的容器格式为libcontainer。Libcontainer 是Docker中用于容器管理的包,它基于Go语言实现,通过管理namespaces、cgroups、capabilities以及文件系统来进行容器控制。可以使用Libcontainer创建容器,并对容器进行生命周期管理。
4.2 libnetwork
Libnetwork是Docker团队将Docker的网络功能从Docker核心代码中分离出去,形成一个单独的库。 Libnetwork通过插件的形式为Docker提供网络功能。 使得用户可以根据自己的需求实现自己的Driver来提供不同的网络功能。
官方目前计划实现以下Driver:
- Bridge : 这个Driver就是Docker现有网络Bridge模式的实现。
- Null : Driver的空实现,类似于Docker 容器的None模式。
- Overlay : 隧道模式实现多主机通信的方案。
“Libnetwork所要实现的网络模型(网络拓扑结构)基本是这样的: 用户可以创建一个或多个网络(一个网络就是一个网桥或者一个VLAN ),一个容器可以加入一个或多个网络。 同一个网络中容器可以通信,不同网络中的容器隔离。”我觉得这才是将网络从docker分离出去的真正含义,即在创建容器之前,我们可以先创建网络(即创建容器与创建网络是分开的),然后决定让容器加入哪个网络。
4.3 graph
graph driver主要用于管理和维护镜像,包括把镜像从仓库下载下来,到运行时把镜像挂载起来可以被容器访问等,都是graph driver做的。
4.4 plugins
Docker插件是增强Docker引擎功能的进程外扩展。这就表示,插件不会运行在Docker daemon中。你可以随时随地(如果需要可以在另一台主机上)启动你的插件。只需要通过Plugin Discovery通知Docker daemon这儿有一个新的插件可用即可。
4.5 REST Interface
REST API指定程序可以用来与守护程序进行通信并指示其操作的接口。
- Registry API:提供了与来存储Docker镜像的Docker Registry集成的功能。
- Docker Hub API:提供了与Docker HUB集成的功能
- Docker Remote API:提供与Docker守护进程进行集成的功能
作者简介:季向远,本文版权归原作者所有。微博:ik8s
登录后评论
立即登录 注册