博文大纲:

docker虚拟化与传统虚拟化的区别
NameSpace和Cgroup,隔离容器及控制资源
容器的Block IO(磁盘读写)

一、 docker虚拟化与传统虚拟化的区别:

Docker相比较传统虚拟化轻便、灵活,存储大小镜像小,便于存储与传输。与宿主机共用,从而节省更多的硬件资源,docker容器除了运行其中的应用之外,基本不消耗额外的系统资源,这样能保证性能的同时,减小系统开销。Dcoker中一个进程就可以模拟一个新的系统,运行容器后,只是占用了宿主机中的一个进程。
传统的虚拟化宿主机OS上运行虚拟机OS,镜像庞大,消耗宿主机系统额外的CPU、内存消耗。

docker宿主服务 docker和宿主机 操作系统不同_虚拟化

但是如果虚拟机中安装的服务对内核版本有要求,这个服务就不太适合用docker来实现了。可以使用KVM、OpenStack来实现。

二、 NameSpace和Cgroup。

在docker中镜像的概念主要就是把运行环境和代码进行打包,镜像层都是只读,不能往里写数据,需要在镜像的基础上启动一个容器,进行运行镜像。
在镜像的多个层中,有一个Busybox层,可以理解为欺骗层。用来模拟一些系统所依赖的目录,如果容器中的操作系统与宿主机不同,busybox就会模拟容器中的操作系统所依赖的目录。
上述说到一个进程就是一个新的系统,那么怎么解决宿主机与虚拟机、虚拟机与虚拟机之间的耦合问题呢。传统虚拟机是直接重新安装一台虚拟机来完全解耦的。Dockers呢?

1、 NameSpace

字面理解为名称空间,它就是用来隔离容器的。
Docker技术通过内核实现六种Namespace:

IPC

共享内存、消息列队

MNT

挂载点、文件系统

NET

网络栈,网络设备

PID

进程编号

USER

用户、组

UTS

主机名、域名

Namespace是将内核的全局资源做封装,使得每个Namespace都有一份独立的资源,因此不同的进程在各自的Namespace内对同一种资源的使用不会互相干扰。实际上,Linux内核实现namespace的主要目的就是为了实现轻量级虚拟化(容器)服务。在同一个namespace下的进程可以感知彼此的变化,而对外界的进程一无所知。这样就可以让容器中的进程产生错觉,仿佛自己置身于一个独立的系统环境中,以此达到独立和隔离的目的。

在/proc中就可以看到隔离项:

[root@localhost ~]# cd /proc/
[root@localhost proc]# echo $$
6844		#当前的PID编号。内存里的数据。
进入当前的PID编号目录:
[root@localhost ns]# pwd
[root@localhost ns]# pwd
/proc/6844/ns

docker宿主服务 docker和宿主机 操作系统不同_docker_02


进入容器查看:

[root@localhost ns]# docker run -it --name test centos:7 
[root@71d70634bee6 /]# cd /proc/
[root@71d70634bee6 proc]# echo $$
1
[root@71d70634bee6 ns]# pwd
/proc/1/ns

docker宿主服务 docker和宿主机 操作系统不同_虚拟化_03

2、 Cgroup

防止容器占用大量系统资源。 Cgroup:控制组。限制容器对资源的占用。
Cgroup更具体地控制对系统资源的分配、优先顺序、拒绝、管理和监控。可更好地根据任务和用户分配硬件资源,提高总体的效率,这样可以在docker容器中的服务受到外部干扰时,可以将其限制在容器之中,而不会影响宿主机或其他容器的运行,提高了安全性。
Cgroup的作用: 四大功能:
1.资源限制:cgroup可以对进程组使用的资源总额进行限制。
2.优先级分配:通过分配的cpu时间片数量以及硬盘IO带宽大小,实际上相当于控制了进程运行的优先级别。
3.资源统计:cgroup可以统计系统资源使用量,比如cpu使用时间,内存使用量等,用于按量计费。同时还支持挂起功能,也就是说通过cgroup把所有资源限制起来,对资源都不能使用,注意这并不是说我们的程序不能使用了,只是不能使用资源,处于等待状态。
4.进程控制:可以对进程组执行挂起、恢复等操作。

可在/sys下查看限制。

(1)内存限额: 容器内存包括两个部分:物理内存和swap 可以通过参数控制容器内存的使用量:
-m或–memory:设置内存的使用限额。 --memory-swap:设置内存+swap的使用限额。

例子:
运行一个容器,并且限制该容器最多使用200M内存和100M的swap。

[root@localhost ~]# docker run -it -m 200M --memory-swap 300M centos:7
[root@7e6d6362127d /]# cat /sys/fs/cgroup/memory/memory.limit_in_bytes 
209715200		#查看内存使用限制,单位字节。
[root@7e6d6362127d memory]# cat memory.memsw.limit_in_bytes 
314572800		#查看内存+交换分区的使用限制。单位字节。

对比一个没有限制的容器,我们会发现,如果运行容器之后不限制内存的话,意味着没有限制。

(2)CPU使用 通过-c或者–cpu-shares设置容器使用cpu的权重。如果不设置默认为1024。

例子:
没有限制:1024

[root@localhost ~]# docker run -it --name containerA centos:7 
[root@e223e567a4b5 /]# cd /sys/fs/cgroup/cpu
[root@e223e567a4b5 cpu]# cat cpu.shares 
1024

限制CPU使用权重为512

[root@localhost ~]# docker run -it --name containerB -c 512 centos:7 
[root@664ccadb34e5 /]# cd /sys/fs/cgroup/cpu
[root@664ccadb34e5 cpu]# cat cpu.shares 
512

(3)容器的Block IO 磁盘的读写。 docker中可以通过设置权重,限制bps和iops的方式控制容器读写磁盘的IO。
bps:每秒读写的数据量 byte per second iops:每秒IO的次数 io per second
默认情况下,所有容器都能够平等的读写磁盘,也可以通过–blkio-weight参数改变容器的blockIO的优先级。
–device-read-bps:显示读取某个设备的bps。
–devic-write-bps:显示写入某个设备的bps。
–device-read-iops:显示读取某个设备的iops。
–device-write-iops:显示写入某个设备的iops。

例子:
限制testA这个容器,写入/dev/sda这块磁盘的bps为30MB

[root@localhost ~]# docker run -it --name testA --device-write-bps /dev/sda:30MB centos:7

测试:从/dev/zero输入,然后输出到test.out文件中,每次大小为1M,总共800次,oflag=direct用来指定directIO方式写文件,这样才会使–device-write-bps生效。

[root@0d1d8785c8b3 /]# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
800+0 records in
800+0 records out
838860800 bytes (839 MB) copied, 26.6206 s, 31.5 MB/s

real	0m26.627s
user	0m0.000s
sys	0m0.581s
[root@0d1d8785c8b3 /]# du -h test.out 
800M	test.out

没做任何限制。

[root@localhost ~]# docker run -it --name testB  centos:7 
[root@a35026421532 /]# time dd if=/dev/zero of=test.out bs=1M count=800 oflag=direct
800+0 records in
800+0 records out
838860800 bytes (839 MB) copied, 0.821591 s, 1.0 GB/s	#这里的写入速度与磁盘读写性能有关。

real	0m0.823s
user	0m0.000s
sys	0m0.688s

本博文结束,感谢观看。