课程:极客时间 - 深入剖析Kubernetes

知识图谱

最近在极客时间上发现了门好课程,正巧自己对Kubernetes相关技术非常感兴趣,此文是对原课程部分核心的内容的摘抄和凝练,同时也包括自己学习过程中的一些新的体会。

一、云计算领域近年来的风云变幻

2013年之前的云计算领域主要是以IaaS(Infrastructure-as-a-Service)项目为主,即将IT基础设施(CPU、内存、存储、网络等)作为服务提供给用户。但这种模式在用户在使用过程中有诸多的问题:

  • 本地开发环境和购买的虚拟机之间的不一致,进而导致调试、部署困难;
  • 不用应用之间可能在同一个虚拟机上,没有隔离;
  • 大规模的应用部署困难。

而正因为以上几点问题,出现了以Cloud Foundry为代表的开源PaaS(Platform-as-a-Service)项目,其最核心的组件是一套应用打包和分发机制,核心能力是基于Linux操作系统CgroupsNamespace机制实现的“沙盒”隔离环境,让各个应用进程互不干扰,实现了把多个用户的应用互不干涉地在虚拟机里批量地、自动地运行起来的目的。这里的”沙盒“也就是所谓的”容器“。

可是PaaS在实际使用过程中,用户发现其打包过程十分痛苦,需要投入大量人力来解决本地应用和远端PaaS的适配问题。因此便出现了Docker,其用Docker镜像来实现本地环境和云端环境的高度一致,解决了打包困难的问题,进而取代了Cloud Foundry这类PaaS项目中的“沙盒”。

Docker 项目给 PaaS 世界带来的“降维打击”,其实是提供了一种非常便利的打包机制。这种机制直接打包了应用运行所需要的整个操作系统,从而保证了本地环境和云端环境的高度一致,避免了用户通过“试错”来匹配两种不同运行环境之间差异的痛苦过程。

随着Docker的大规模应用,PaaS的定义也渐渐地变成了一套以Docker容器技术为核心,全新的”容器化“思路。

2014年,Docker公司也顺势发布了自己的PaaS项目Swarm。Swarm 的最大亮点,则是它完全使用 Docker 项目原本的容器管理 API 来完成集群管理,例如:

  • 单机 Docker 项目:
    $ docker run "我的容器"
    
  • 多机Docker项目"
    $ docker run -H "我的Swarm集群API地址" "我的容器"
    

这种简洁明了的操作方式导致Swarm一经发售便受到了已有Docker用户群热捧,这直接触犯了其他公司的利益,因此CoreOS与Docker决裂,推出了自己的rkt容器,Mesos发布了Marathon与Swarm竞争、Google公司也宣告Kubernetes诞生。

而Swarm 项目只是 Docker 公司重新定义“PaaS”的关键一环,在2015年,围绕着Docker迅速催生出了一个非常繁荣的生态,Docker公司也借助这波浪潮开始通过并购来完善自己的平台层能力,其中最成功的案例便是对Fig项目的收购,并将其更名为Compose。Fig项目在当时史无前例地提出了“容器编排”(Container Orchestration)的概念。

“编排”(Orchestration)主要是指用户如何通过某些工具或者配置来完成一组虚拟机以及关联资源的定义、配置、创建、删除等工作,然后由云计算平台按照这些指定的逻辑来完成的过程。

在容器时代,“编排”显然就是对Docker容器的一系列定义、配置和创建动作的管理。

Docker公司有了Docker,Swarm,Compose后,在容器商业生态具有很大的优势和话语权。为了竞争, Google、Redhat等基础设施领域的玩家们组建了CNCF(Cloud Native Computing Foundation)基金会,着手开始打造Kuberentes。

Kubernetes 项目的基础特性,并不是几个工程师突然“拍脑袋”想出来的东西,而是 Google 公司在容器化基础设施领域多年来实践经验的沉淀与升华。这,正是 Kubernetes 项目能够从一开始就避免同 Swarm 和 Mesos 社区同质化的重要手段。

Kubernetes并没有和Swarm展开同质化竞争,其通过让人耳目一新的设计理念和号召力,很快就构建出了一个与众不同的容器编排与管理的生态。就这样,Kubernetes很快远远将Swarm项目甩在身后。

为了与Kubernetes竞争“容器编排”领域,Docker公司放弃了Swarm项目,孤注一掷地将其内置到Docker项目中。

从工程角度来看,这种做法的风险很大。内置容器编排、集群管理和负载均衡能力,固然可以使得 Docker 项目的边界直接扩大到一个完整的 PaaS 项目的范畴,但这种变更带来的技术复杂度和维护难度,长远来看对 Docker 项目是不利的。

而Kubernetes 的应对策略则是反其道而行之,开始在整个社区推进“民主化”架构,就这样,在这种鼓励二次创新的整体氛围当中,Kubernetes 社区在 2016 年之后得到了空前的发展。更重要的是,不同于之前局限于“打包、发布”这样的 PaaS 化路线,这一次容器社区的繁荣,是一次完全以 Kubernetes 项目为核心的“百家争鸣”。

最终在2017年,Docker公司将 Docker 项目改名为 Moby,交给社区自行维护,并在自己的主打产品Docker企业版中内置Kubernetes项目,这标志着“编排之争”落地帷幕。容器化社区以Kuberentes为核心愈加繁荣。

二、容器技术概念入门

2.1 虚拟机和容器

图1 虚拟机和容器的对比图

上图是虚拟机和容器的工作原理图,我们可以很容易的看出,虚拟机是通过硬件虚拟化技术,模拟出了运行一个操作系统需要的各种硬件并在这些虚拟硬件上安装了一个新的操作系统,这样自然实现了不同应用进程之间的隔离;而右图Docker容器中的应用虽然各自看起来像是互相隔离的,但实际上还是跑在同一个操作系统上的。

2.2 容器技术原理

容器技术的核心功能,就是通过约束和修改进程的动态表现,从而为其创造出一个“边界”。

一个“容器”,实际上是一个由 Linux Namespace实现的隔离、Linux Cgroups实现的“限制” 和 rootfs的文件系统 三种技术构建出来的进程的隔离环境。

图2 Docker容器全景图

隔离

其核心的实现原理是通过Linux提供的Namespace机制,用来对各种不同的进程上下文进行“障眼法”操作。例如:

  • PID Namespace用于让被隔离进程只看到当前Namespace里的进程被重新计算的pid信息;
  • Mount Namespace用于让被隔离进程只看到当前Namespace里的挂载点信息;
  • Network Namespace,用于让被隔离进程看到当前 Namespace 里的网络设备和配置。

Linux还提供了UTS、IPC、Network和User这些Namespace。因此可以说容器就是一种特殊的进程。
而我们在使用Docker过程中,其实并没有一个真正的“Docker容器”运行在宿主机上,Docker只是在帮助用户创建进程时,为其加上了各种各样的Namespace参数。而在进程看来,自己是各自PID Namespace的一号进程,只能看到各自Mount Namespace里挂在的目录和文件,只能访问各自Namespace里的网络设备等等。就像运行在一个个的容器(container)当中一样。(在目前最新的Docker项目默认会为用户启动Mount、PID、User、Network、IPC Namespace。)

限制

Linux Cgroups(Linux Control Group)是 Linux 内核中用来为进程设置资源限制的一个重要功能,可以限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。并且还能够对进程进行优先级设置、审计,以及将进程挂起和恢复等操作。

Cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。可以使用mount指令把它们展示出来:

$ mount -t cgroup

Linux Cgroups简单粗暴地理解,其就是一个子系统目录加上一组资源限制文件的组合。

文件系统

Linux 容器文件系统的实现方式就是我们经常提到的容器镜像,也叫作:rootfs。它只是一个操作系统的所有文件和目录,并不包含内核,最多也就几百兆。通过使用Mount Namespace和rootfs,容器就能够为进程构建出一个完善的文件系统隔离环境,当然这还有chroot和 pivot_root这两个系统调用切换进程根目录的参与。

在此基础上,Docker公司又提出了“层”的概念,即:使用多个增量rootfs联合挂载一个完整rootfs。这种“分层镜像”的设计极大便利了基于容器镜像的团队协作,将不同背景的技术人员紧密地联系到了一起。只要你发布了自己的镜像,其他地方的人就可以拉去获得一摸一样的完整容器环境,这就是容器技术的“强一致性”。

下图为Docker容器的rootfs结构图:

图2 Docker容器的rootfs结构图

  • 只读层:容器最下面的层,以增量的方式分别包含了 Ubuntu 操作系统的一部分;
  • 可读写层:容器最上面的层,专门用来存放修改rootfs后产生的增量,无论是增、删、改,都发生在这里;
  • Init 层:夹在只读层和读写层之间,用于挂载一些仅对当前容器生效的文件,例如/etc/hosts、/etc/resolv.conf 等文件。

容器镜像的发明,不仅打通了“开发 - 测试 - 部署”流程的每一个环节,更重要的是容器镜像将会成为未来软件的主流发布方式。

未完待续......

三、Kubernetes集群搭建与实践

四、容器编排与Kubernetes作业管理

五、Kubernetes容器持久化存储


Try and fail, but don't fail to try.