【docker容器技术】Linux容器架构

1、整体架构

在 Linux 环境中,docker的整体架构

容器管理工具(例如 Docker)是基于一组更精细的容器工具构建的: runccontainerd

Linux 上的 Docker 体系结构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 FlowDocker 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:

  1.  Bridge : 这个Driver就是Docker现有网络Bridge模式的实现。
  2.  Null : Driver的空实现,类似于Docker 容器的None模式。
  3.  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​​​​

K8S中文社区微信公众号

评论 抢沙发

登录后评论

立即登录