Docker 1.11+:Engine 已经建立在 runC 和 containerd 之上

Docker 公司最近为整个平台发布了全新的版本:Engine 升级到了 1.11 版,Swarm 升级到了 1.2 版,Compose 和 Machine 分别升级到 1.7 版本和 0.7 版本。Mac 和 Windows 版的 Docker 也联合发布了新的测试版。

这种 “冰山一角” 式的发布方式,让用户在几乎感受不到变动的情况下对 Engine 进行了大规模改动,成为首个完全兼容 OCI 标准的运行时。值得一提的是,Docker Engine 现在完全基于 runC 和 containerd。

thumbnail_0606_docker_1200

 

OCI,runC,containerd,这些都是个啥?

什么是开放式容器协议(OCI)?

OCI 发布于去年六月,旨在为容器运行时和格式制定行业标准。OCI 的宗旨是避免生态系统的混乱无序,确保容器能在不同的引擎上运行。因而实现容器的可移植性,非常必要。由于 Docker 是目前唯一可用的运行时,因而也就成为了行业标准。但是考虑到可用性(和适应性)及其它引擎的存在,有必要从技术上定义“容器是什么”,以便各方能达成一定的共识。

什么是 runC?

runC 是一种只专注于运行容器的轻量级工具。如果你了解 Docker Engine 的早期历史,你就知道它曾经用 LXC 来启动和管理容器;后来它演变为 “libcontainer”。“libcontainer” 是一段与 cgroup 和 namespace 这些 Linux 内核交互的代码,这些内核是容器构建的基石。

简言之,runC 基本上是一种无需进入 Docker Engine,直接控制 libcontainer 的小型命令行工具,是一种管理和运行 OCI 容器的单机二进制。欲知详情,可参阅 Solomon Hykes 的博文。

什么是 containerd?

containerd 是运用 runC(或者任何与 OCI 兼容的程序)来管理容器,通过 gRPC 暴露功能的简易守护进程。相比于 Docker Engine,暴露容器相关的 CRUD 接口使用成熟的 HTTP API,Docker Engine 不仅能暴露容器,还能暴露镜像、数据卷、网络、构建等。想要深入了解,可参阅 Michael Crosby 的博文。

如何集成?

如前所述,Docker Engine 现在完全兼容 runC 和 containerd。在 1.11 版之前,Engine 服务于 volume、网络、容器等。现在它的工作被分为四部分: Engine、containerd、runC 和介于 containerd 与 runC 之间的 containerd-shim。

docker1.11-1

Docker Engine 仍负责镜像管理,将镜像交付到 containerd 运行,containerd 使用 runC 来运行容器。

containerd 只需管理容器,包括容器的启动、停止、暂停和销毁。鉴于容器运行时与引擎隔离,Engine 能够重启和升级,无需重启容器。随着 Linux 专用代码被移除,能够在保持相同 Docker UI 命令的同时使用其它容器运行时(所有运行时在界面上一致)。

与单机 docker 二进制不同,四个组件各有一个对应的二进制,即 docker、 docker-containerd、 docker-containers-shim 和 docker-runc。用户能够使用 ps ax | grep docker 字符串在宿主机上检索 docker 进程的运行情况。下面是为 Docker 三周年开发的投票应用,它正在运行中,如果在宿主机上检索了所有 docker 进程,会看到前文描述的二进制。

docker1.11-2
docker1.11-3

如果使用 Docker for Mac/Windows,则可以在容器中运行 docker run -it — pid host -v /:/hostfs — net host alpine chroot /hostfs 和 run ps ax | grep docker 获取运行中的进程。由于 pid 主机实现了这一功能,所以容器使用主机的 PID namespace;与此类似,网络主机使用主机的 UTS namespace。想详细了解运行知识,请阅读 Engine 的参考资料。

深入查看 /var/run/docker/libcontainerd 能看到运行中的所有容器,以及 docker-containerd sock 文件。

docker1.11-4

其他改进

网络

网络也有改进。Engine 1.10 内置 DNS 服务器,使得每个容器能够将容器名称和网络别名映射到 IP 地址。遇到多个容器共享同一个网络别名,DNS 服务器会返回一条稳定的记录。在 1.11 版 Engine 中,DNS 服务器会乱序返回所有记录,因而可以把 DNS 轮询用作基础的负载均衡和失效备缓机制。如果对网络别名多次执行 ping 命令,则结果千变万化。所有流量可以能在同一容器上,可能均衡,也可能不均衡。记住,容器名称解析仅适用于使用  docker network create 创建的用户网络。在下面的例子中,两个 NGINX 容器运行在使用共享别名的网络上。

docker1.11-5

此外,网络(和 volume)也可以像镜像那样使用标签。

Compose 1.7

Compose 的改进主要包括直接从 env 文件中读取环境变量,无需使用命令行。

其次,通过 docker-compose up 能够实现并行,同时仍需考虑依赖顺序。譬如,使用 redis 查看 Docker compose 文件,一旦 redis 启动就能启动数据库、前端和 worker,确实它们同时启动。

对于 docker-compose 命令也有修改和增加。有两条新增命令: docker-compose up -build 和 docker-compose exec。以前在编辑 Docker 文件时,人们经常先运行 docker-compose build ,然后是 docker-compose up,为了简化这一过程,就把  — build  添加到了 up 上。exec 命令跟 Docker Engine 上的 exec 命令功能相同。除此之外,docker-compose logs 命令与 docker logs 命令相似:与之前显示容器的所有日志并串流不同,现在只显示日志。可以使用 docker-compose logs -f 来简化日志。docker-compose logs 现在可以检测出何时向应用添加新容器,并会在使用 docker-compose logs -f 时自动添加日志并简化。

Swarm 1.2

Swarm  1.1 版中,对容器重新调度的支持是实验性的,而到了 1.2 版,就不再是实验性的了。在 1.1 版本之前,如果你使用 Swarm,并启动一个有 10 个服务器的集群,运行 100 个网络前端示例,一旦有服务崩溃,没有任何应急措施。现在,容器可以针对节点崩溃进行重启。通过在容器上设置环境变量或标签,随着容器启动,服务即被监控。



负责追踪节点轨迹的 Swarm 管理器,会持续检测各个节点的心跳,一旦发现异常,就会尝试重启。如果节点上有根据重新排序原则运行的容器,则容器会在别的节点重新调度。这些状态都能通过日志,被 Swarm 管理器检查到,管理器也会有多个。

Registry

以前删除注册表的时候,仅仅删除了镜像的逻辑表示,全部数据仍被保留,只是无法引用。如果在编程时删除变量的时候并不会立刻删除数据,必须通过内存管理手动删除,否则会有垃圾数据堆积。这一问题已经得到解决。

Docker for Mac / Windows

上个月 Docker 发布了针对 Mac 和 Windows 的内测版本。这两个版本的 Docker 没有根本性改变,却大大优化了用户体验。它们提供了在 Linux 上运行 Docker 的类似体验,除非需要多个主机,否则都不需要 VirtualBox。要想了解 Docker for Mac 的使用体验,可以参考博文 “Say Hello to Docker for Mac”。

Docker 1.11 版增加了一些新功能。在 Docker for Mac 的 Beta 9 版本中,localhost 用于端口转发而非 docker.local,后者能提供正宗 Linux 体验。Beta 10 版本进行了改进,能够通过 SSL tunnel(HTTPS)进行 token 确认。Beta 11 版本升级了内核和 Compose。可以参考发布说明了解新功能、变更和问题。

(文章写于 5 月 17 日)

Leave a Reply

Your email address will not be published. Required fields are marked *