一、Docker简介
1. 什么是容器
A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.
- 容器是一个软件的标准单元
- 包含应用代码及其依赖
- 可以方便可靠的从一个环境迁移到另外一个环境
- Docker容器是运行在Docker引擎之上的
2. Docker容器 VS 虚拟机
Containers and virtual machines have similar resource isolation and allocation benefits, but function differently because containers virtualize the operating system instead of hardware. Containers are more portable and efficient.
- 虚拟机和Docker容器都有类似资源隔离和分配功能
- Docker容器虚拟化了操作系统
- 虚拟机虚拟化了硬件
二、Docker的本质———一个有“边界”的进程
1. 容器是一个进程
1)虚拟机进程模型
在虚拟机中,宿主机与虚拟机与进程的关系如下图所示,宿主机能看到虚拟机进程,但是看不到虚拟机中的进程。在使用容器时,大部分人也是这么理解容器的,包括很多Docker资料也是引导我们这么理解的。可以实践一下是否真的如此。
2)Docker进程模型
实践
- 先启动一个容器,并在容器执行
ps -ef
- 在宿主机执行
ps -ef
可以看到,容器的启动进程/bin/sh
不仅可以被宿主机看到,而且是宿主机上的一个普通进程,唯一一点有困惑的地方就是在容器中看到/bin/sh
的进程号是1
,而在宿主机上看到的/bin/sh
的进程号是15790
,这种现象其实就是PID Namespace
在起作用,Docker为这个进程套上一层PID Namespace,使得这个进程及其子进程看不到Namespace之外的其他进程
Namespace
Linux中一共有六个Namespace,除了PID Namespace之外,还有Mount、UTS、IPC、Network、User这些Namespace,不难想到,/bin/sh
的子进程ifconfig看到的网络栈与宿主机不符是Network Namespace在起作用,/bin/sh
的子进程ls
看到的目录和宿主机不符是Mount Namespace在起作用
Docker实际进程模型
Docker容器只是一个抽象概念,Docker容器内的进程本质就是宿主机上被套上了Namespace的进程
2. Docker优劣势
有了上面的讲解,可以看到Docker是比虚拟机少一层封装的,所以"敏捷"和“高性能”是容器的最大优势。但是Namespace技术相比于虚拟化技术也有很多劣势,其中最大的问题就是隔离的不彻底
- 容器内进程只是宿主机上的一种特殊进程,所以不同的容器内的进程是共享宿主机内核的,所以低版本的宿主机内核运行不了高版本的Linux系统的容器
- 在Linux内核中,很多资源和对象是不能被Namespace化的,比如时间,所以使用虚拟机时我们可以随意折腾,但是在使用容器我们的知道什么能做什么不能做
三、如何限制Docker容器资源
容器内进程其实就是宿主机上的一个特殊进程,那么这些进程跑在同一个虚拟机上,势必会相互竞争资源,这虽然是容器相比虚拟机的一个劣势,但是却可以用Cgroups技术来解决。
Linux Cgroups 的全称是 Linux Control Group。它最主要的作用,就是限制一个进程组能够使用的资源上限,包括 CPU、内存、磁盘、网络带宽等等。
1. Cgroups实践
我们可以先看看Linux上都有哪些Cgroup
Linux中一切皆文件,我们可以在/sys/fs/cgroup
下看到这些Cgroups
那么Cgroups到底如何使用,我们可以进行一下简单的实践
- 我们启动一个死循环进程,并用
top
命令查看这个死循环进程,发现其CPU
使用率是100%,接下来我们使用Cgroup技术限制它的CPU使用率
- 在/sys/fs/cgroup/cpu创建
container
目录,并进入到其中查看到文件夹下自带这么多文件
- 我们修改
cpu.cfs_quota_us
文件,将其中的-1改成20000(us),表示在100000us的时间里,我们有20000us可以使用cpu
但是以上只是填写了限制参数,那么到底对哪个进程进行限制呢?因此我们还需要将被限制的进程号写入tasks文件,执行
echo 17242 > tasks
以上我们一共修改了两个文件分别是
cpu.cfs_quota_us
和tasks
- 进行了以上修改之后,我们就可以看到这个死循环的进程使用率降为
20000/100000
了
2. Docker容器实践
docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash
执行一个容器,并进行容器资源限制查看容器资源限制在Cgroup资源上的映射
3. 加上Cgroups后的Docker进程模型
四、总结
Docker的本质就是Linux容器技术,为容器内的进程套上Namespace,使其看不见宿主机上的真实情况,并为其配置Cgroups参数,使其只能使用有限的资源。