课程链接:深入剖析 Kubernetes

# 01 - 04 Docker 的前世今生

Docker 出现之前,以 Cloud Foundry 为代表的 PaaS 项目是市场上的主流,其核心在于应用的打包与分发:将要执行的应用的可执行文件与启动脚本进行打包并分发到虚拟机上运行。

与容器一样,上述应用也运行在隔离的环境中,只是当时还没有容器的概念。

Docker 的核心竞争力在于镜像功能。在 Docker 出现之前,打包过程非常繁琐,最关键缺少一个通用的打包规范,Docker 的镜像机制很好地解决了此问题。

Docker

2013 年 3 月 dotCloud 公司发布了 Docker 项目。

2013 年 10 月,dotCloud 宣布公司更名为 Docker。

2014 年 10 月,Docker 在 DockerCon Europe 上发布了其容器编排 (Orchestration) 项目 Docker Machine, Docker Compose,以及其集群管理 (Clustering) 项目 Docker Swarm:Announcing Docker Machine, Swarm, and Compose for Orchestrating Distributed Apps

CoreOS

Docker 与 CoreOS 公司曾经合作过一段时间,但由于 Swarm 项目的出现,CoreOS 意识到 Docker 公司向平台层推进的野心,因此中断了与 Docker 的合作,并直接推出了自己研制的 Rocker (rkt) 容器项目。

Mesos

Mesosphere 公司的 Mesos 是与 Docker 同时期的,甚至比 Docker 经验更足的集群管理项目。

在 Kubernetes 出现之前 Docker 的鼎盛时期,Docker 的扩张非常顺利,不仅在容器层面形成事实标准,并且在 PaaS 平台领域压制了 CoreOS 的 Fleet 与 RedHat 的 OpenShift 等等竞争对手。

容器运行时 (container runtime) 标准

在拒绝了 Google 的有关推进中立的容器运行时标准库后不久, Docker 推出了自己的容器运行时标准库 Libcontainer。

Libcontainer 的中心化与倾向性,促使社区在 2015 年 6 月,逼迫 Docker 公司作出了妥协:成立中立的容器运行时和镜像标准基金会,Docker 将 Libcontainer 捐出,并更名为 RunC。

以 RunC 为蓝本,上述基金会制定了一套容器运行时和镜像实现标准 OCI (Open Container Initiative)。

OCI 使容器运行时和镜像实现从 Docker 中剥离出来,一定程度上改善了容器领域 Docker 一家独大的局面。

CNCF (Cloud Native Computing Foundation)

由于 Docker 在容器生态的事实标准这一事实,OCI 并没有能够发挥太大的作用。因此:

由 Google,RedHat 等开源基础设施领域玩家们,共同牵头发起了一个名为 CNCF (Cloud Native Computing Foundation) 的基金会,希望以 Kubernetes 项目为基础,建立一个开源基础设施领域厂商主导的、按照独立基金会方式运营的平台级社区,来对抗以 Docker 公司为核心的容器商业生态。

Google 与 RedHat 的合作推进使 CNCF 和 Kubernetes 项目获得了空前的影响力。在之后的一段时间,CNCF 社区就包含了包括 Prometheus,Fluentd,OpenTracing,CNI 在内的一系列容器相关项目。

面对 CNCF 社区的压力,2016 年,Docker 公司直接宣布将 Swarm 项目的所有功能集成到 Docker 项目当中。以此最大化 Swarm 项目与 Docker 无缝集成的优势。

Kubernetes

与 Docker 不同,Kubernetes 的设计非常开放:

从 API 到容器运行时的每一层,Kubernetes 项目都为开发者暴露出了可以扩展的插件机制,鼓励用户通过代码的方式介入到 Kubernetes 项目的每一个阶段。

在意识到其商业策略失败后, Docker 公司开始放弃其开源社区,转而专注于自己的商业转型。

2017 年 3 月,Docker 公司将 Docker 的容器运行时部分 Containerd 捐赠给 CNCF 社区:Docker to donate containerd to the Cloud Native Computing Foundation

2017 年 4 月,Docker 公司将 Docker 项目更名为 Moby,并交于社区维护:Introducing Moby Project: a new open-source project to advance the software containerization movement

2017 年 10 月,Docker 公司宣布将在 Docker 企业版中内置 Kubernetes。

2018 年 1 月,RedHat 斥资 2.5 亿美元收购 CoreOS。

# 05 - 06 容器的本质

容器的本质:到底什么是容器 (container): namespaces 和 cgroups

DOCKER基础技术:LINUX NAMESPACE(上)

"敏捷" 和 "高性能" 是容器相较于虚拟机最大的优势,也是它能够在 PaaS 这种更细粒度的资源管理平台上大行其道的重要原因。

隔离的实现:namespace。

限制的实现:cgroups (control group)。

# 07 镜像

Mount Namespace 的特殊性:它对容器进程视图的改变在挂载操作后才生效(默认是继承宿主机文件系统的)。

为避免上述问题造成的困扰,借助 pivot_root 或 chroot,容器实现了进程根目录的切换。

最终挂载在容器根目录上的、用来为容器进程提供隔离后执行环境的文件系统,就是所谓的 "容器镜像"。它还有一个更为专业的名字,叫作:rootfs(根文件系统)。

注意 rootfs 并不包含操作系统内核。

容器镜像实现的是对整个操作系统文件和目录的打包。因此得以很高程度地保持了本地和远端执行环境之间的一致性。

借助联合文件系统 (Union File System, or UnionFS),Docker 创造了层 (layer) 的概念,层有很多优点:

  1. 实现了文件系统的复用
  2. 缩小了镜像占用的空间

典型的容器 rootfs 由三部分层组成:

  1. 若干个只读层 (ro+wh)
  2. 一个 Init 层 (ro+wh)
  3. 一个可读写层 (rw)

只读层即镜像的文件系统,Init 层包括一些 Docker 引擎需要作修改的内容(如 /etc/hosts, /etc/resolv.conf),可读写层则是容器运行过程中对其下的基础作出修改的层。

对只读层的删除和修改以 whiteout 和 copy-on-write 实现,只读层中的内容并未消失,只是被隐藏,因此镜像的大小可能会比最终形成的大小大。

容器镜像会成为未来软件的主流发布方式。

# 08 容器

Dockerfile 与容器构建

Dockerfile reference

Best practices for writing Dockerfiles

docker exec

可以通过 setns() 系统调用,将一个进程加入一个现有的 namespace 中,这就是 docker exec 的实现原理。

Volume 实现

Docker Volume 的实现原理是,在 rootfs 准备好后,chroot 执行前,将要挂载的宿主机目录,挂载到指定的容器目录在宿主机上的目录。须知:整个容器的 rootfs 只是宿主机上的一个目录

这里指的挂载是 Linux 中常见的绑定挂载 (bind mount)。