云原生学习01:容器与镜像
前言:《云原生学习》系列主要记录从阿里云和CNCF联合推出的【云原生技术公开课】上学到的知识。
容器和镜像
容器出现背后的需求
如果我们有对进程或者说应用程序进行隔离的需求,在操作系统上我们会遇到这样的三个主要问题:
- 进程视角:进程能互相通信和可见。这意味着高级权限的进程可以攻击比其更低级的进程。
- 文件视角:进程之间使用的是同一个文件系统,这导致多个进程对文件的增删改查会冲突。同时,不同进程之间的依赖冲突也给运维增加了麻烦,例如appA需要jdk1.8,appB需要jdk11。
- 资源视角:进程使用同一个host上的资源,存在资源抢占问题。
那么,如何为进程提供一个独立的运行环境呢?
- 进程视角:使用Namespace技术可以实现进程在资源视图上隔离。
- 存储视角:使用chroot系统调用可以将子目录改成根目录,达到视图级别的隔离。进程在chroot支持下可以拥有独立的文件系统。
- 资源视角:使用Cgroup技术来限制资源使用率,设置使用的cpu和内存量。
容器的概念
容器的本质是一组进程集合,它将系统的其他资源隔离开来,具有自己独立的资源视图。
容器就是一个视图隔离、资源可限制、独立文件系统的进程集合。
容器具有一个独立的文件系统,不需要具备内核相关的代码或者工具,我们只需要提供容器所需的二进制文件、配置文件以及依赖即可。
容器运行时所需要的所有的文件集合称之为容器镜像,如下所示:
我们常使用Dockerfile来构建镜像,它可以帮助我们描述每一个构建步骤,每个构建步骤对文件系统内容的变化我们叫做changeset。changeset是分层的,支持复用的,这使得我们不用每次都下载这个镜像的每个组成。
容器的生命周期
我们通过docker run来运行容器时,会启动一个initial进程,这个进程的生命周期即容器的生命周期。当 initial 进程退出的时候,所有的子进程也会随之退出,这样也是为了防止资源的泄漏。
然而,这种情况下就需要引入数据卷的概念,因为app的数据如果随着容器退出而删除,那可不行。
数据卷的生命周期是独立于容器的生命周期的。我们会将数据卷挂载到容器内,这样一来容器就能够将数据写入到相应的目录里面了,而且容器的退出并不会导致数据的丢失。
数据卷有两种管理方式:
- bind方式,将host的目录挂到容器内。这种方式依赖host机器,当有很多host机器时,需要对所有host机器统一管理,有一定运维成本。
- 将目录管理交给容器运行引擎。
容器项目架构
moby 是目前最流行的容器管理引擎,其架构如下:
- moby daemon:对上提供有关于容器、镜像、网络以及 Volume的管理。
- containerd:容器运行时管理引擎,其独立于 moby daemon ,可以对上提供容器、镜像的相关管理。
- containerd shim模块:插件化设计,能够被containered动态接管,方便业务的升级。
容器和VM的差异
简单来说,VM会在host机器上建立一个Guest OS,每个Guest OS拥有一个独立的内核。
好处是:隔离效果好。坏处是:代价高。一方面需要将一部分计算资源交给虚拟化,另一方面需要占用大量磁盘。
容器则不然,容器是针对进程的,无需Guest OS,所有的文件隔离都是进程级别的。因此启动速度非常快,占用空间也很小。但是自然隔离效果会差一些,所以容器技术也在向着强隔离方向发展。
- 感谢你赐予我前进的力量