一、Docker简介
1. 什么是容器
容器是一个标准的软件单元,它将代码及其所有的依赖关系打包,以便应用程序在一个计算环境中快速、可靠地运行。
- 容器是一个软件的标准单元
- 包含应用代码及其依赖
- 可以方便可靠的从一个环境迁移到另外一个环境
- Docker容器是运行在Docker引擎之上的
2. Docker容器 VS 虚拟机
容器和虚拟机有类似的资源隔离和分配优势,但功能不同,因为容器虚拟化了操作系统而不是硬件。容器的便携性和效率更高。
- 虚拟机和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参数,使其只能使用有限的资源。