初识Docker架构

167 阅读28分钟

初识Docker

基础介绍

image.png Container 即容器,平时生活中指的是可以装下其它物品的工具, 以方便人类归纳放置物品 、存储和异地运输 ,比如人类使用的衣柜 、行李箱、 背包等可以成为容器,Container 除了容器以外,另一个意思是集装箱, 很多码头工人将很多装有不同物品但却整齐划一的箱子装载到停靠在岸边大船,然后方便的运来运去。

image.png

为什么这些集装箱可以很方便的运来运去呢?因为它们大小一致标准化尺寸的箱子,并且可以安全的隔离开,所以当我们使用 Container 来形容容器的时候,就是我们想要让容器达到一个可以打包,符合标准的状态。

但今天我们所说的容器是一种 IT 技术。容器其实是一种沙盒技术。顾名思义,沙盒就是能够像一个集装箱一样,把你的应用装起来。这样,应用与应用之间就有了边界而不会相互干扰;同时装在沙盒里面的应用,也可以很方便的被搬来搬去,这也是 PaaS 想要的最理想的状态(可移植性,标准化,隔离性。)

容器是软件工业上的集装箱的技术,集装箱的标准化,减少了包装成本,大大提高货物运输和装卸效率,是传统运输行业的重大变革。早期的软件项目中软件更新,发布低效,开发测试发布周期很长,很难敏捷。有了容器技术,就可以利用其标准化的特点,大幅提高生产效率。

容器技术是虚拟化、云计算、大数据之后的一门新兴的并且是炙手可热的新技术, 容器技术提高了硬件资源利用率、 方便了企业的业务快速横向扩容(可以达到秒级快速扩容)、 实现了业务宕机自愈功能(配合K8S可以实现,但OpenStack无此功能),因此未来数年会是一个容器愈发流行的时代 ,这是 一个对于 IT 行业来说非常有影响和价值的技术,而对于IT行业的从业者来说, 熟练掌握容器技术无疑是一个很有前景的行业工作机会。

image.png

Docker 介绍

容器历史

虽然 docker 把容器技术推向了巅峰,但容器技术却不是从 docker 诞生的。实际上,容器技术连新技术都算不上,因为它的诞生和使用确实有些年头了。下面的一串名称可能有的你都没有听说过,但它们的确都是容器技术的应用:

1、Chroot Jail

就是我们常见的 chroot 命令的用法。它在 1979 年的时候就出现了,被认为是最早的容器化技术之一。它可以把一个进程的文件系统隔离起来。

2、The FreeBSD Jail

Freebsd Jail (监狱)实现了操作系统级别的虚拟化,它是操作系统级别虚拟化技术的先驱之一。2000年,伴随FreeBSD4.0版的发布

3、Linux VServer

使用添加到 Linux 内核的系统级别的虚拟化功能实现的专用虚拟服务器。允许创建许多独立的虚拟专用服务器(VPS),这些虚拟专用服务器在单个物理服务器上全速同时运行,从而有效地共享硬件资源。VPS提供与传统Linux服务器几乎相同的操作环境。可以在这样的VPS上启动所有服务(例如ssh,邮件,Web和数据库服务器),而无需(或者在特殊情况下只需进行很少的修改),就像在任何真实服务器上一样。每个VPS都有自己的用户帐户数据库和root密码,并且与其他虚拟服务器隔离,但它们共享相同的硬件资源

4、Solaris Containers

它也是操作系统级别的虚拟化技术,专为 X86 和 SPARC 系统设计。Solaris 容器是系统资源控制和通过"区域" 提供边界隔离的组合。

5、OpenVZ

OpenVZ 是一种 Linux 中操作系统级别的虚拟化技术。 它允许创建多个安全隔离的 Linux 容器,即VPS。

6、Process Containers

Process 容器由 Google 的工程师开发,一般被称为 cgroups。

7、LXC

LXC为Linux Container的简写。可以提供轻量级的虚拟化,以便隔离进程和资源,而且不需要提供指令解释机制以及全虚拟化的其他复杂性。容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求Linux Container提供了在单一可控主机节点上支持多个相互隔离的server container同时执行的机制。Linux Container有点像chroot,提供了一个拥有自己进程和网络空间的虚拟环境,但又有别于虚拟机,因为lxc是一种操作系统层次上的资源的虚拟化。

8、Warden

在最初阶段,Warden 使用 LXC 作为容器运行时。 如今已被 CloudFoundy 取代。

9、LMCTFY

LMCTY 是 Let me contain that for you 的缩写。它是 Google 的容器技术栈的开源版本。Google 的工程师一直在与 docker 的 libertainer 团队合作,并将 libertainer 的核心概念进行抽象并移植到此项目中。该项目的进展不明,估计会被 libcontainer 取代。

10、Docker

Docker 是一个可以将应用程序及其依赖打包到几乎可以在任何服务器上运行的容器的工具。

11、RKT

RKT 是 Rocket 的缩写,它是一个专注于安全和开放标准的应用程序容器引擎。综上所述正如我们所看到的,docker 并不是第一个容器化技术,但它的确是最知名的一个。

统一基础设施环境-docker环境

  • 硬件的组成配置
  • 操作系统的版本运行时环境的异构

统一程序打包(装箱)方式-docker镜像

  • java程序
  • python程序
  • nodejs程序

统一程序部署(运行)方式-docker容器

  • java-jar...→ docker run...
  • python manage.py runserver... → docker run...
  • npm run dev ... → docker run...

Docker 是什么

Docker (码头工人)是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司(后由于 Docker 开源后大受欢迎就将公司改名为 Docker Inc ,总部位于美国加州的旧金山)内部的一个开源的 PAAS 服 务 (Platform as a ServiceService )的业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。

Docker 是基于 linux 内核实现,Docker 最早采用 LXC 技术 ,LXC 是 Linux 原生支持的容器技术 ,可以提供轻量级的虚拟化 ,可以说 docker 就是基于 LXC 发展起来 的,提供 LXC 的高级封装,标准的配置方法,在LXC的基础之上,docker提供了一系列更强大的功能。而虚拟化技术 KVM(KernelKernel-based Virtual Machine Machine) 基于 模块实现, 后来Docker 改为自己研发并开源的 runc 技术运行容器,彻底抛弃了LXC。

Docker 相比虚拟机的交付速度更快,资源消耗更低,Docker 采用客户端/服务端架构,使用远程API来管理和创建容器,其可以轻松的创建一个轻量级的、可移植的、自给自足的容器,docker 的三大理念是build(构建)、ship(运输)、 run(运行),Docker遵从apache 2.0协议,并通过(namespace及cgroup等)来提供容器的资源隔离与安全保障等,所以Docke容器在运行时不需要类似虚拟机(空运行的虚拟机占用物理机6-8%性能)的额外资源开销,因此可以大幅提高资源利用率,总而言之Docker是一种用了新颖方式实现的轻量级虚拟机.类似于VM但是在原理和应用上和VM的差别还是很大的,并且docker的专业叫法是应用容器(Application Container)。

Docker 和虚拟机,物理主机

操作系统的的组成

  • Bootloader:它负责设备的启动过程。
  • Shell:Shell是一种编程语言,它可以控制其他文件,进程以及所有其他程序。
  • Kernel:它是操作系统的主要组件,管理内存,CPU和其他相关组件。
  • Desktop Environment:这是用户通常与之交互的环境。
  • Graphical server(图形服务器):它是操作系统的子系统,用于在屏幕上显示图形
  • Applications: 这些是执行不同用户任务(例如word,excel等)的程序集。
  • Daemons : 后台服务提供商。

什么是内核kernel 内核是操作系统的关键组件。 它借助进程间通信和系统调用,在硬件级别上充当应用程序和数据处理之间的桥梁。

每当将操作系统加载到内存中时,首先,将加载内核并将其保留在那里,直到操作系统关闭。 内核负责处理低级任务,例如任务管理,内存管理,风险管理等。

内核的任务

  • 用于应用程序执行的流程管理。
  • 内存和I / O(输入/输出)管理。
  • 系统调用控制(内核的核心行为)。
  • 借助设备驱动程序进行设备管理。

内核空间,用户空间是什么?

内核空间

内核处于提升的系统状态,其中包括受保护的内存空间以及对设备硬件的完全访问权限。 此系统状态和内存空间统称为内核空间。 在内核空间内,对硬件和系统服务的核心访问进行管理,并作为服务提供给系统的其余部分。

用户空间

用户空间或用户域是在操作系统内核环境之外运行的代码,用户空间定义为操作系统用来与内核连接的各种应用程序或程序或库。

用户的应用程序是在用户空间中执行的,它们可以通过内核系统调用访问计算机可用资源的一部分。 通过使用内核提供的核心服务,可以创建用户级别的应用程序,例如游戏或办公软件。

image.png

  • 传统虚拟机是虚拟出一个主机硬件,并且运行一个完整的操作系统 ,然后在这个系统上安装和运行软件
  • 容器内的应用直接运行在宿主机的内核之上,容器并没有自己的内核,也不需要虚拟硬件,相当轻量化
  • 每个容器间是互相隔离,每个容器内都有一个属于自己的独立文件系统,独立的进程空间,网络空间,用户空间等,所以在同一个宿主机上的多个容器之间彼此不会相互影响

容器和虚拟机表现比较

  1. 资源利用率更高: 开销更小,不需要启动单独的虚拟机OS内核占用硬件资源,可以将服务器性能压榨至极致.虚拟机一般会有5-20%的损耗,容器运行基本无损耗,所以生产中一台物理机只能运行数十个虚拟机,但是一般可以运行数百个容器
  2. 启动速度更快: 可以在数秒内完成启动
  3. 占用空间更小: 容器一般占用的磁盘空间以MB为单位,而虚拟机以GB
  4. 集成性更好: 和CI/CD(持续集成/持续部署)相关技术结合性更好,实现打包镜像发布测试可以一键运行,做到自动化并快速的部署管理,实现高效的开发生命周期

使用虚拟机是为了更好的实现服务运行环境隔离,每个虚拟机都有独立的内核,虚拟化可以实现不同操作系统的虚拟机,但是通常一个虚拟机只运行一个服务,很明显资源利用率比较低且造成不必要的性能损耗,我们创建虚拟机的目的是为了运行应用程序,比如Nginx、PHP、Tomcat等web程序,使用虚拟机无疑带来了一些不必要的资源开销,但是容器技术则基于减少中间运行环节带来较大的性能提升。

根据实验,一个运行着CentOS的KVM虚拟机启动后,在不做优化的情况下,虚拟机自己就需要占用100~200 MB内存。此外,用户应用运行在虚拟机里面,它对宿主机操作系统的调用就不可避免地要经过虚拟化软件的拦截和处理,这本身又是一层性能损耗,尤其对计算资源、网络和磁盘I/O的损耗非常大。

比如: 一台96G内存的物理服务器,为了运行java程序的虚拟机一般需要分配8G内存/4核的资源,只能运行13台左右虚拟机,但是改为在docker容器上运行Java程序,每个容器只需要分配4G内存即可,同样的物理服务器就可以运行25个左右容器,运行数量相当于提高一倍,可以大幅节省IT支出,通常情况下至少可节约一半以上的物理设备。

Docker 的组成

docker 官网: www.docker.com

帮助文档链接: docs.docker.com/

docker 镜像: hub.docker.com/

docker 中文网站: www.docker.org.cn/

image.png

image.png

  • Docker 主机(Host): 一个物理机或虚拟机,用于运行Docker服务进程和容器,也称为宿主机,node节点
  • Docker 服务端(Server): Docker守护进程,运行docker容器
  • Docker 客户端(Client): 客户端使用 docker 命令或其他工具调用docker API
  • Docker 镜像(Images): 镜像可以理解为创建实例使用的模板,本质上就是一些程序文件的集合
  • Docker 仓库(Registry): 保存镜像的仓库,官方仓库: hub.docker.com/,可以搭建私有仓库harbor
  • Docker 容器(Container): 容器是从镜像生成对外提供服务的一个或一组服务,其本质就是将镜像中的程序启动后生成的进程

image.png

Namespace

image.png

一个宿主机运行了N个容器,多个容器共用一个 OS,必然带来的以下问题:

  • 怎么样保证每个容器都有不同的文件系统并且能互不影响?
  • 一个docker主进程内的各个容器都是其子进程,那么如果实现同一个主进程下不同类型的子进程?各个容器子进程间能相互通信(内存数据)吗?
  • 每个容器怎么解决IP及端口分配的问题?
  • 多个容器的主机名能一样吗?
  • 每个容器都要不要有root用户?怎么解决账户重名问题

namespace是Linux系统的底层概念,在内核层实现,即有一些不同类型的命名空间被部署在核内,各个docker容器运行在同一个docker主进程并且共用同一个宿主机系统内核,各docker容器运行在宿主机的用户空间,每个容器都要有类似于虚拟机一样的相互隔离的运行空间,但是容器技术是在一个进程内实现运行指定服务的运行环境,并且还可以保护宿主机内核不受其他进程的干扰和影响,如文件系统空间、网络空间、进程空间等,目前主要通过以下技术实现容器运行空间的相互隔离:

隔离类型功能系统调用参数内核版本
MNT Namespace(mount)提供磁盘挂载点和文件系统的隔离能力CLONE_NEWNS2.4.19
IPC Namespace(Inter-Process Communication)提供进程间通信的隔离能力,包括信号量,消息队列和共享内存CLONE_NEWIPC2.6.19
UTS Namespace(UNIXTimesharing System)提供内核,主机名和域名隔离能力CLONE_NEWUTS2.6.19
PID Namespace(ProcessIdentification)提供进程隔离能力CLONE_NEWPID2.6.24
Net Namespace(network)提供网络隔离能力,包括网络设备,网络栈,端口等CLONE_NEWNET2.6.29
User Namespace(user)提供用户隔离能力,包括用户和组CLONE_NEWUSER3.8
TimeNamespace提供时间隔离能力CLONE_NEWTIME5.6
syslogNamespace提供syslog隔离能力syslognamespace是由华为工程师RuiXiang(瑞翔)提出的,但没有合并到linux内核中,后systemd在2020年2在2020年2 月实现了一个名为“journalnamespace”的类似功能
Controlgroup(cgroup)Namespace提供进程所属的控制组的身份隔离Linux4.6
MNT Namespace

image.png

每个容器都要有独立的根文件系统有独立的用户空间,以实现在容器里面启动服务并且使用容器的运行环境,即一个宿主机是ubuntu的服务器,可以在里面启动一个centos运行环境的容器并且在容器里面启动一个Nginx服务,此Nginx运行时使用的运行环境就是centos系统目录的运行环境,但是在容器里面是不能访问宿主机的资源,宿主机是使用了chroot技术把容器锁定到一个指定的运行目录里面。

例如:

/var/lib/containerd/io.containerd.runtime.v1.linux/moby/容器ID

根目录:

/var/lib/docker/overlay2/ID
IPC Namespace

一个容器内的进程间通信,

允许一个容器内的不同进程的(内存、缓存等)数据访问,但是不能跨容器直接访问其他容器的数据

image.png

UTS Namespace

UTS namespace(UNIX Timesharing System包含了运行内核的名称、版本、底层体系结构类型等信息)用于系统标识,

其中包含了

  • 主机名hostname
  • 域名domainname
  • 内核名称

它使得一个容器拥有属于自己主机名标识,这个主机名标识独立于宿主机系统和其上的其他容器。

image.png

PID Namespace

Linux系统中,有一个PID为1的进程(init/systemd)是其他所有进程的父进程, 那么在每个容器内也要有一个父进程来管理其下属的子进程, 那么多个容器的进程通过 PID namespace 进程隔离 比如:

  • PID编号重复
  • 容器内的主进程生成
  • 回收子进程

image.png

image.png

NET Namespace

每一个容器都类似于虚拟机一样有自己的网卡、监听端口、TCP/IP协议栈等,Docker使用network namespace启动一个vethX接口,这样你的容器将拥有它自己的桥接ip地址, 通常是docker0,而docker0实质就是Linux的虚拟网桥, 网桥是在OSI七层模型的数据链路层的网络设备,通过mac地址对网络进行划分,并且在不同网络直接传递数据。

image.png

User Namespace

各个容器内可能会出现重名的用户和用户组名称,或重复的用户UID或者GID,那么怎么隔离各个容器内的用户空间呢?

User Namespace允许在各个宿主机的各个容器空间内创建相同的用户名以及相同的用户UID和GID,只是会把用户的作用范围限制在每个容器内,即A容器和B容器可以有相同的用户名称和ID的账户,但是此用户的有效范围仅是当前容器内,不能访问另外一个容器内的文件系统,即相互隔离、互不影响、永不相见。

image.png

Control groups

Linux Cgroups的全称是Linux Control Groups,是Linux内核的一个功能.最早是由Google的工程师(主要是Paul Menage和Rohit Seth)在2006年发起,最早的名称为进程容器(process containers)。在2007年时,因为在Linux内核中,容器(container)这个名词有许多不同的意义,为避免混乱,被重命名为cgroup,并且被合并到2.6.24版的内核中去。自那以后,又添加了很多功能。

如果不对一个容器做任何资源限制,则宿主机会允许其占用无限大的内存空间,有时候会因为代码bug程序会一直申请内存,直到把宿主机内存占完,为了避免此类的问题出现,宿主机有必要对容器进行资源分配限制,比如CPU、内存等

Cgroups 最主要的作用,就是限制一个进程组能够使用的资源上限,包括CPU、内存、磁盘、网络带宽等等。此外,还能够对进程进行优先级设置,资源的计量以及资源的控制(比如:将进程挂起和恢复等操作)

image.png

验证系统 cgroups

Cgroups在内核层默认已经开启,从CentOS 和 Ubuntu 不同版本对比,显然内核较新的支持的功能更多。

Centos 7.6 cgroups:

[root@localhost overlay2]#grep CGROUP /boot/config-3.10.0-693.el7.x86_64 
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_HUGETLB=y
CONFIG_CGROUP_PERF=y
CONFIG_CGROUP_SCHED=y
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_NETFILTER_XT_MATCH_CGROUP=m
CONFIG_NET_CLS_CGROUP=y
CONFIG_NETPRIO_CGROUP=y
cgroups 具体实现
  • blkio: 块设备IO限制
  • cpu: 使用调度程序为 cgroup 任务提供 cpu 的访问
  • cpuacct: 产生 cgroup 任务的 cpu 资源报告
  • cpuset: 如果是多核心的 cpu,这个子系统会为 cgroup 任务分配单独的 cpu 和内存
  • devices: 允许或拒绝 cgroup 任务对设备的访问
  • freezer: 暂停和恢复 cgroup 任务
  • memory: 设置每个 cgroup 的内存限制以及产生内存资源报告
  • net_cls: 标记每个网络包以供 cgroup 方便使用
  • ns: 命名空间子系统
  • perf_event: 增加了对每 group 的监测跟踪的能力,可以监测属于某个特定的 group 的所有线程以及运行在特定CPU上的线程

容器管理工具

有了以上的chroot、namespace、cgroups就具备了基础的容器运行环境,但是还需要有相应的容器创建与删除的管理工具、以及怎么样把容器运行起来、容器数据怎么处理、怎么进行启动与关闭等问题需要解决,于是容器管理技术出现了。目前主要是使用docker,早期使用 LXC

lxc Linux Container

淘汰

Docker

相当于增强版的LXC,功能更为强大和易用,也是当前最主流的容器前端管理工具Docker 先启动一个容器也需要一个外部模板,也称为镜像,docke的镜像可以保存在一个公共的地方共享使用,只要把镜像下载下来就可以使用,最主要的是可以在镜像基础之上做自定义配置并且可以再把其提交为一个镜像,一个镜像可以被启动为多个容器。

pouch

Pouch (小袋子)起源于 2011 年,并于2017年11月19日上午,在中国开源年会现场,阿里巴巴正式开源了基于 Apache 2.0 协议的容器技术 Pouch。Pouch 是一款轻量级的容器技术,拥有快速高效、可移植性高、资源占用少等特性,主要帮助阿里更快的做到内部业务的交付,同时提高超大规模下数据中心的物理资源利用率

Podman

image.png

虽然目前 Docker 是管理 Linux 容器最好的工具,注意没有之一,但是podman的横空出现即将改变这一点

什么是Podman?

Podman即Pod Manager tool,从名称上可以看出和kubernets的pod的密切联系,不过就其功能来说,简而言之: alias docker = podman ,是CentOS 8 新集成的功能,或许不久的未来会代替dockerPodman是一个 为 Kubernetes 而生的开源的容器管理工具,原来是 CRI-O(即容器运行时接口CRI 和开放容器计划OCI) 项目的一部分,后来被分离成一个单独的项目叫 libpod。其可在大多数Linux平台上使用,它是一种无守护程序的容器引擎,用于在Linux系统上开发,管理和运行任何符合Open Container Initiative(OCI)标准的容器和容器镜像。Podman 提供了一个与Docker兼容的命令行前端,Podman 里面87%的指令都和Docker CLI 相同,因此可以简单地为Docker CLI别名,即“ alias docker = podman”,事实上,podman使用的一些库也是docker的一部分。

Podman 和docker不同之处

  • docker 需要在系统上运行一个守护进程(docker daemon),这会产生一定的开销,而podman 不需要

  • 启动容器的方式不同:

    docker cli 命令通过API跟 Docker Engine(引擎) 交互告诉它我想创建一个container,然后

    docker Engine 才会调用 OCI container runtime(runc) 来启动一个container。这代表

    container的process(进程)不会是 Docker CLI 的 child process(子进程) ,而是 Docker

    Engine 的 child process 。

    Podman 是直接给 OCI containner runtime(runc) 进行交互来创建container的,所以

    container process 直接是 podman 的 child process 。

  • 因为docke有docker daemon,所以docker启动的容器支持 --restart 策略,但是podman不支持

  • docker需要使用root用户来创建容器。 这可能会产生安全风险,尤其是当用户知道docker run命令的--privileged选项时。podman既可以由root用户运行,也可以由非特权用户运行

  • docker在Linux上作为守护进程运行扼杀了容器社区的创新。 如果要更改容器的工作方式,则需要更改docker守护程序并将这些更改推送到上游。 没有守护进程,容器基础结构更加模块化,更容易进行更改。 podman的无守护进程架构更加灵活和安全。

Docker 的优势

  • 快速部署: 短时间内可以部署成百上千个应用,更快速交付到线上
  • 高效虚拟化: 不需要额外hypervisor支持,基于linux内核实现应用虚拟化,相比虚拟机大幅提高性能和效率
  • 节省开支: 提高服务器利用率,降低IT支出
  • 简化配置: 将运行环境打包保存至容器,使用时直接启动即可
  • 环境统一: 将开发,测试,生产的应用运行环境进行标准化和统一,减少环境不一样带来的各种问题
  • 快速迁移和扩展: 可实现跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台
  • 更好的实现面向服务的架构,推荐一个容器只运行一个应用,实现分布的应用模型,可以方便的进行横向扩展,符合开发中高内聚,低耦合的要求,减少不同服务之间的相互影响

1.1.9 Docker 的缺点

  • 多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底
  • 由于和宿主机之间的进程也是隔离的,需要进入容器查看和调试容器内进程等资源,变得比较困难和繁琐
  • 如果容器内进程需要查看和调试,需要在每个容器内都需要安装相应的工具,这也造成存储空间的重复浪费

1.1.10 容器的核心技术

image.png

OCI 官网:opencontainers.org/

容器规范

容器技术除了的docker之外,还有coreOS的rkt,还有阿里的Pouch,为了保证容器生态的标准性和健康可持续发展,包括Linux 基金会、Docker、微软、红帽谷歌和、IBM、等公司在2015年6月共同成立了一个叫Open Container Initiative(OCI)的组织,其目的就是制定开放的标准的容器规范,目前OCI一共发布了三个规范,分别是runtime spec和 image format spec distribution-spec ,有了这三个规范,不同的容器公司开发的容器只要兼容这三个规范,就可以保证容器的可移植性和相互可操作性。

  • runtime spec
  • image format spec
  • distribution-spec

github.com/opencontain…

image.png

容器 runtime

runtime是真正运行容器的地方,因此为了运行不同的容器runtime需要和操作系统内核紧密合作相互在支持,以便为容器提供相应的运行环境

runtime 类型:

  • Lxc: linux上早期的runtime,在 2013 年 Docker 刚发布的时候,就是采用lxc作为runtime, Docker把 LXC 复杂的容器创建与使用方式简化为 Docker 自己的一套命令体系。随着Docker的发展,原有的LXC不能满足Docker的需求,比如跨平台功能
  • Libcontainer: 随着 Docker 的不断发展,重新定义容器的实现标准,将底层实现都抽象化到Libcontainer 的接口。这就意味着,底层容器的实现方式变成了一种可变的方案,无论是使用namespace、cgroups 技术抑或是使用 systemd 等其他方案,只要实现了 Libcontainer 定义的一组接口,Docker 都可以运行。这也为 Docker 实现全面的跨平台带来了可能。
  • runc: 早期libcontainer是Docker公司控制的一个开源项目,OCI的成立后,Docker把libcontainer项目移交给了OCI组织,runC就是在libcontainer的基础上进化而来,目前Docker默认的runtime,runc遵守OCI规范
  • crun: 红帽推出的 运行时基于C语言开发,集成在podman内部
  • rkt: 是CoreOS开发的容器runtime,也符合OCI规范,所以使用rktruntime也可以运行Docker容器

image.png

低级容器运行时与高级容器运行时

  • High-Level:高级运行时提供基于API的远程管理操作,客户端可以通过高级别运行时管理容器的整个生命周期(创建、删除、重启、停止),高级别运行时并不真正直接运行容器,而是调用低级别运行时运行,比如dockerd、containerd都是高级别运行时。
  • Low-Level:接受高级别运行时的指令,按照相应的指令运行容器,因此低级别运行时真是运行容器的地方,例如runc

image.png

容器管理工具

管理工具连接runtime与用户,对用户提供图形或命令方式操作,然后管理工具将用户操作传递给

runtime执行。

lxc 是lxd 的管理工具

Runc的管理工具是docker engine,docker engine包含后台deamon和cli两部分,大家经常提到

的Docker就是指的docker engine

Rkt的管理工具是rkt cli

容器定义工具

容器定义工具允许用户定义容器的属性和内容,以方便容器能够被保存、共享和重建。Docker image: 是docker 容器的模板,runtime依据docker image创建容器Dockerfile: 包含N个命令的文本文件,通过dockerfile创建出docker imageACI(App container image): 与docker image类似,是CoreOS开发的rkt容器的镜像格式。

镜像仓库 Registry

统一保存镜像而且是多个不同镜像版本的地方,叫做镜像仓库

  • Docker hub: docker官方的公共仓库,已经保存了大量的常用镜像,可以方便大家直接使用
  • 阿里云,网易等第三方镜像的公共仓库
  • Image registry: docker 官方提供的私有仓库部署工具,无web管理界面,目前使用较少
  • Harbor: vmware 提供的自带web界面自带认证功能的镜像私有仓库,目前有很多公司使用

容器编排工具

当多个容器在多个主机运行的时候,单独管理容器是相当复杂而且很容易出错,而且也无法实现某一台

主机宕机后容器自动迁移到其他主机从而实现高可用的目的,也无法实现动态伸缩的功能,因此需要有

一种工具可以实现统一管理、动态伸缩、故障自愈、批量执行等功能,这就是容器编排引擎

容器编排通常包括容器管理、调度、集群定义和服务发现等功能

  • Docker compose : docker 官方实现单机的容器的编排工具
  • Docker swarm: docker 官方开发的容器编排引擎,支持overlay network
  • Mesos+Marathon: Mesos是Apache下的开源分布式资源管理框架,它被称为是分布式系统的内核。Mesos最初是由加州大学伯克利分校的AMPLab开发的,后在Twitter得到广泛使用。通用的集群组员调度平台,mesos(资源分配)与marathon(容器编排平台)一起提供容器编排引擎功能
  • Kubernetes: google领导开发的容器编排引擎,内部项目为Borg,且其同时支持 docker 和
  • CoreOS,当前已成为容器编排工具事实上的标准