博文大纲:
docker虚拟化与传统虚拟化的区别
NameSpace和Cgroup,隔离容器及控制资源
容器的Block IO(磁盘读写)
一、 docker虚拟化与传统虚拟化的区别:
Docker相比较传统虚拟化轻便、灵活,存储大小镜像小,便于存储与传输。与宿主机共用,从而节省更多的硬件资源,docker容器除了运行其中的应用之外,基本不消耗额外的系统资源,这样能保证性能的同时,减小系统开销。Dcoker中一个进程就可以模拟一个新的系统,运行容器后,只是占用了宿主机中的一个进程。
传统的虚拟化宿主机OS上运行虚拟机OS,镜像庞大,消耗宿主机系统额外的CPU、内存消耗。
但是如果虚拟机中安装的服务对内核版本有要求,这个服务就不太适合用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
进入容器查看:
[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
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
本博文结束,感谢观看。