# 简介

运行多个进程时,隔离它们的运行环境有利于管理。常见的几种隔离方式:

  • 运行多个物理主机
    • 缺点:冗余大,不方便通过软件管理
  • 在物理机上运行多个虚拟机
  • 在主机上运行多个容器,每个容器内包含一组进程

# 虚拟机

:Hypervisor ,又称为 VMM(Virtual Machine Monitor ,虚拟机监视器)

  • 原理:
    • 在计算机硬件与操作系统之间隔离出一个中间层,用于运行虚拟化的操作系统。
  • 优点:
    • 实现了对整个操作系统的隔离。
  • 缺点:
    • 重量级
      • 运行虚拟机软件,大概消耗 10% 的系统资源。
      • 每个虚拟机要运行一个完整的操作系统,但应用程序一般只需要用到其中少量的功能服务、系统资源,因此冗余较多。
      • 部署一个应用程序时,需要先创建一个虚拟机、安装操作系统,再配置运行环境、拷贝应用程序,耗时为几小时。
  • 创建虚拟机的软件举例:
    • Xen
      • 2003 年发布。
    • OpenVZ
      • 2005 年发布。
      • 在底层操作系统上运行多个虚拟操作系统,共用一个内核。
      • 只支持 Linux 系统。
    • KVM(Kernel-based Virtual Machine)
      • 2006 年发布。
      • 每个虚拟操作系统使用一个独立的内核,因此可采用不同的操作系统。
      • OpenVZ 属于半虚拟化,而 KVM 属于全虚拟化,开销更大。
    • VirtualBox
    • VMwareWorkstation
    • Windows Hyper-V

# 容器

:Container ,新一代的虚拟化技术。

  • 原理:
    • 在应用程序与操作系统之间隔离出一个中间层,用于运行容器。
    • 以镜像作为模板,在主机上创建容器并保持运行。
      • 运行容器的主机称为宿主机,可以是物理机或虚拟机。
  • 优点:
    • 能隔离进程的运行环境
      • 隔离程度比虚拟机低,比如容器会共享宿主机内核,但足够满足一般项目的需求。
    • 便于管理进程
      • 包含了进程管理工具的功能,比如启动、停止、自动重启。
      • 进程及其子进程都运行在容器中,不会游离到容器外。
    • 轻量级
      • 运行容器引擎,大概只消耗 5% 的系统资源。
      • 部署一个应用时,直接启动一个容器即可,耗时为几秒。
    • 兼容性好
      • 同一个镜像可以拷贝到不同平台上,创建容器,只需系统内核相同。
      • 便于将应用迁移部署到其它主机。
  • 总之,容器能在一般场景下模拟虚拟机,更轻量级,但不能完全替代虚拟机。

# 相关历史

  • 1979 年,Unix 系统加入了 chroot() 函数(change root directory),用于更改正在运行的进程的根目录。
    • 比如将一个进程的根目录改为 /tmp ,此时该进程执行 cd / 相当于其它进程执行 cd /tmp ,该进程只能看到该目录下的文件,不能通过 cd .. 命令跳到该目录之外。
    • 这不会修改进程的工作目录。
    • 更改根目录时,需要事先拷贝 /lib 等库文件到新的根目录下,供进程调用,否则进程不能正常运行。
  • 2002 年,Linux 系统加入了 namespace 技术,用于隔离进程可见、可用的系统资源。
  • 2008 年,Linux 系统加入了 Control group 技术,简称为 Cgroup ,用于限制进程占用的 CPU、内存等系统资源。
  • 2008 年,Linux 系统加入了 LXC 工具,用于控制 namespace 和 Cgroup 。
  • 2013 年,dotCloud 公司发布 Docker 软件,使得容器技术流行、普及,公司也改名为 Docker 公司。

# 容器引擎

  • 容器引擎(Container Engine):通常是一个复杂的软件,负责与用户交互、管理镜像、管理容器。
  • 容器引擎举例:
    • LXC(Linux Container)
    • Docker
    • Podman :兼容 Docker CLI 的大部分命令。
    • Windows Hyper-V Containers

# 容器运行时

  • 容器运行时(Container Runtime):通常是一个 CLI 程序,用于创建、运行、管理容器。

    • 有的容器引擎会直接管理容器,而有的容器引擎会调用容器运行时来管理容器。
    • 早期版本的 Docker 引擎是通过 LXC 来控制 namespace、Cgroup ,实现容器化。从 0.9 版本开始,弃用 LXC ,改用 libcontainer 等自研的 Golang 库,后来演变为 runC 组件。
      • 2016 年,Docker 引擎将其底层组件 runC、containerd 抽离出来,成为独立的容器运行时项目。
      • 此后,Docker 引擎会调用 containerd 来管理容器,而 containerd 会调用 runc 命令来管理容器。
  • OCI(Open Container Initiative ,开放容器倡议)

    • :定义了容器的镜像规范、容器运行时规范。
    • 2015 年,Docker 公司将 OCI 规范捐赠给 CNCF 基金会。
    • 如果一个镜像符合 OCI 规范,则可以被符合 OCI 标准的容器运行时用于创建容器。
  • 底层的容器运行时:

    • runC
      • 只支持 Linux 系统。
    • crun
    • rkt(CoreOS Rocket)
      • 由 CoreOS 公司发布,以 Pod 为单位管理容器。但不符合 OCI 规范,已被弃用。
    • kata-containers
      • 在一个轻量级虚拟机中运行容器,不共享宿主机的内核,隔离程度更高。
  • 高层的容器运行时:基于 runC 等底层的容器运行时来管理容器。例如:

    • containerd (opens new window)
      • 是对 OCI 规范的标准实现,支持 k8s 的 CRI 接口。
      • 支持 Linux、Windows 系统。
    • CRI-O
      • 是对 k8s CRI 接口的标准实现,符合 OCI 规范。

# 容器编排工具

当容器数量较多时,手动管理很麻烦,需要使用容器编排工具,例如:

  • Docker Compose :由 Docker 公司发布,只能管理当前宿主机上的容器,不能管理服务器集群。
  • Docker Swarm :由 Docker 公司发布,在 docker 软件包中自带,可以管理多台宿主机上的容器。
  • Mesos :由 ASF 基金会管理。
  • k8s :由 Google 公司发布,能管理大量主机上的大量容器,功能多也复杂,已成为容器编排领域的事实标准。