背景
2018 年可以说是 docker 容器技术 最火热的一年,各大厂商,互联网公司都开始构建自己的容器化平台,CI/CD 工具
那么为什么 docker 会这么火,以及 **docker 技术内涵是什么?**,这篇文章,我将以一个学习者的身份详细解析 docker 容器化技术
为什么选择 docker
在容器化时代到来之前,AWS
以及 OpenStack
可谓盛极一时,与此同时还有以 Cloud Foundry
为代表的开源 PaaS
项目。
PaaS 开源项目火热的主要原因主要是它提供了一种应用托管 的能力。各个国内外技术厂商都在进行上云体验。
具体的操作就是:Cloud Foundry
为每种主流编程语言都定义了一种打包格式,类似 cf push app
的操作就是将 app 的可执行文件和启动命令
打包进一个压缩包中,上传到 Cloud Foundry 的存储中。然后 Cloud Foundry 会通过调度器选择一个可以运行这个应用的虚拟机
,然后通过这个机器上的 agent 将应用压缩包下载下来启动。
对于一个虚拟机来说,需要在其上启动很多个来自不同用户的应用,Cloud Foundry 会调用操作系统 Cgroups
和 Namespace
机制为每个应用单独创建一个
称作沙盒
的隔离环境,然后在沙盒
环境中启动这些应用,这样就形成了一个个隔离的环境运行多个应用。
以上就是 PaaS 项目的核心的功能,也就是容器化技术。
也正是和 docker 项目相同的技术核心,通过 Cgroups
和 Namespace
来构建一个资源和边界,实现沙盒环境。
那么为什么 docker 技术为何在短短几个月就风靡全世界了?
- 实则正是
docker image
对于 Paas 项目而言,将项目运行的文件打包是一件极其麻烦的事情,对于每种语言,每种框架,每个版本都需要维护一个打好的包。
docker image 可以基于你所需要的系统文件,构建一个可以基于云端环境运行的压缩包。
容器化技术的发展
在以上的文章中,介绍了 docker 技术为何火热的原因。
对于一个大型的业务应用来说,从前端,后端,到数据库系统,文件系统等,往往是需要多个容器的,那么就存在着,如何能够优雅的在云端环境有序地运行。
于是,docker 公司便开发出了一个容器编排化的工具
, docker Swarm 项目
与此同时,Mesos 社区也开发出了一个类似的工具Marathon
, 它虽然不能像 Swarm 那样提供原生的 Docker API, 但是其却拥有一个独特的核心竞争力:
- 超大规模集群的管理经验
也就在这个时候,google 公司根据公司多年的发展经验和借助成熟的内部项目Borg
系统,宣布了 Kubernetes
项目的诞生。
而也是仅仅在两年之前,各个国内外的互联网厂商开始将自己的项目接入 k8s,宣布了 k8s 时代的到来。
本文仅仅讨论 docker 容器化技术
,对于容器化编排
不做过多的介绍。
容器到底是怎么一回事?
在上述的文章中,已经简单介绍了几个概念:
虚拟器
容器
容器化技术
镜像
我们可以总结一下:容器其实就是一种沙盒技术,使用 Cgroups
和Namespace
技术,将你的应用通过限制和隔离的技术在指定的环境中,良好的运行起来
先说结论,容器其实就是一种特殊的进程
而已
隔离技术 - Namespace
那么隔离技术是如何实现的?
首先创建一个容器:
1 | docker run -it --name=ubuntu-test ubuntu:18.04 /bin/sh |
1 | ps |
我们可以看到这个容器中,一共有两个进程,通过 ps 可以看到 sh ,就是这个容器内部的第 1 号进程(PID=1)。
这是为什么呢?
本来,当我们在宿主机上运行了一个 /bin/sh 程序的时候,我们的操作系统都会给其分配一个进程编号,例如 PID=100。但是通过 docker run
命令时,docker
就会在当前的进程时,调整其 namespace 相关参数,将其变为在这个 docker 中的 1 号进程。
这种技术就是Linux 里面的 Namespace 机制。
我们知道,在 Linux 系统中创建进程的系统调用是 clone():
1 | int pid = clone(main_function, stack_size, SIGCHID, NUll); |
通过指定 CLONE_NEWPID
参数,而每个 Namespace
里的应用进程,都会认为自己是当前容器里的第一号进程。
1 | int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL) |
在 Linux 操作系统中,还提供了 Mount
、UTS
、IPC
、Network
、User
这些 Namespace,用来对各种不同的进程
上下文进行”障眼法”操作。
限制技术 - Cgroups
Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等
在 Linux 中,Cgroups 给用户暴露出来的操作接口是文件系统,即它以文件和目录的方式组织在操作系统的 /sys/fs/cgroup 路径下。
1 |
|
其中,例如 cpuset
、cpu
、memory
这样的子目录,也叫子系统。这些都是可以被 Cgroups
进行限制的资源种类。
现在我们看一下子系统中关于 CPU 的相关配置文件
1 | ls /sys/fs/cgroup/cpu |
这些输出配置中,可以看到 cpu.cfs_period_us
和 cpu.cfs_quota_us
,这两个参数需要组合使用,可以用来限制进程在长度cfs_period
的一段时间内,
只能被分配到总量为 cfs_quota
的 CPU 时间。
另开一个终端,输入:
1 | while : ; do : ; done & |
键入:
1 | top |
可以看到 CPU 的使用率已经 100% 了, quota 还没有任何限制(-1)
1 | cat /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us |
在现在的默认配置中,在 100 ms 中的 cpu 时间中,使用 100ms 的 CPU 时间,也就是 100 %。
现在调整为 20%:
1 | echo 20000 > /sys/fs/cgroup/cpu/container/cpu.cfs_quota_us |
然后将限制的进程 PID 写入 container 组里的 tasks 文件:
1 |
|
然后使用 top
指令查看:
1 | Cpu0 : 20.3 us, 0.0 sy, 0.0 ni, 79.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st |
现在可以看到已经为 20%
左右了
其他关于 blkio
,cpuset
,memory
可以自行尝试
docker 运行时的限制参数
1 | docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu:18.04 /bin/bash |
这个配置就会将对应的值写入到 docker-container 的配置文件中,这个 Docker 容器,只能使用到 20% 的 CPU 带宽。
虚拟机和容器对比
虚拟机的工作原理,通过硬件虚拟化功能,模拟出了运行一个操作系统需要的各种硬件,例如 CPU、内存、I/O 设备等等。
docker 项目帮助用户启动的,还是原来的应用进程,但是 Docker 会为它们加上了各种各样的 Namespace 参数。
所以,”敏捷” 和 “高性能” 是容器相较于虚拟机最大的优势,也是它能够在 PaaS 这种更细粒度的资源管理平台上大行其道的重要原因。