前言:《云原生学习》系列主要记录从阿里云和CNCF联合推出的【云原生技术公开课】上学到的知识。

容器和镜像

容器出现背后的需求

如果我们有对进程或者说应用程序进行隔离的需求,在操作系统上我们会遇到这样的三个主要问题:

  1. 进程视角:进程能互相通信和可见。这意味着高级权限的进程可以攻击比其更低级的进程。
  2. 文件视角:进程之间使用的是同一个文件系统,这导致多个进程对文件的增删改查会冲突。同时,不同进程之间的依赖冲突也给运维增加了麻烦,例如appA需要jdk1.8,appB需要jdk11。
  3. 资源视角:进程使用同一个host上的资源,存在资源抢占问题。

那么,如何为进程提供一个独立的运行环境呢?

  1. 进程视角:使用Namespace技术可以实现进程在资源视图上隔离。
  2. 存储视角:使用chroot系统调用可以将子目录改成根目录,达到视图级别的隔离。进程在chroot支持下可以拥有独立的文件系统。
  3. 资源视角:使用Cgroup技术来限制资源使用率,设置使用的cpu和内存量。

image-rgc1.png

容器的概念

容器的本质是一组进程集合,它将系统的其他资源隔离开来,具有自己独立的资源视图。

​容器就是一个视图隔离、资源可限制、独立文件系统的进程集合。​

容器具有一个独立的文件系统,不需要具备内核相关的代码或者工具,我们只需要提供容器所需的二进制文件、配置文件以及依赖即可。

容器运行时所需要的所有的文件集合称之为容器镜像,如下所示:

image-nqb5.png

我们常使用Dockerfile来构建镜像,它可以帮助我们描述每一个构建步骤,每个构建步骤对文件系统内容的变化我们叫做changeset。changeset是分层的,支持复用的,这使得我们不用每次都下载这个镜像的每个组成。

容器的生命周期

我们通过docker run来运行容器时,会启动一个initial进程,这个进程的生命周期即容器的生命周期。当 initial 进程退出的时候,所有的子进程也会随之退出,这样也是为了防止资源的泄漏。

然而,这种情况下就需要引入数据卷的概念,因为app的数据如果随着容器退出而删除,那可不行。

数据卷的生命周期是独立于容器的生命周期的。我们会将数据卷挂载到容器内,这样一来容器就能够将数据写入到相应的目录里面了,而且容器的退出并不会导致数据的丢失。

数据卷有两种管理方式:

  1. bind方式,将host的目录挂到容器内。这种方式依赖host机器,当有很多host机器时,需要对所有host机器统一管理,有一定运维成本。
  2. 将目录管理交给容器运行引擎。

容器项目架构

moby 是目前最流行的容器管理引擎,其架构如下:

  • moby daemon:对上提供有关于容器、镜像、网络以及 Volume的管理。
  • containerd:容器运行时管理引擎,其独立于 moby daemon ,可以对上提供容器、镜像的相关管理。
  • containerd shim模块:插件化设计,能够被containered动态接管,方便业务的升级。

image-rms2.png

容器和VM的差异

简单来说,VM会在host机器上建立一个Guest OS,每个Guest OS拥有一个独立的内核。

好处是:隔离效果好。坏处是:代价高。一方面需要将一部分计算资源交给虚拟化,另一方面需要占用大量磁盘。

容器则不然,容器是针对进程的,无需Guest OS,所有的文件隔离都是进程级别的。因此启动速度非常快,占用空间也很小。但是自然隔离效果会差一些,所以容器技术也在向着强隔离方向发展。

image-5co4.png