普通虚拟化——完全性解耦
docker虚拟化——半解耦
耦合就是发生矛盾,冲突
解耦就是解决矛盾,冲突
举个栗子:比如你在淘宝买了一个栗子,赶巧你在公司上班,快递小哥儿给你打电话让你下来取,你呢<><>,正好也走不开,于是你说:“你放到楼下的小花超市吧”,小哥儿答应了,你们两个谁都没有耽误谁,很好的处理了这件事,这就是解耦。
传统虚拟机以VMware或kvm为例,我们需要给虚拟机分配CPU,内存,硬盘等资源,宿主机必须支持CPU虚拟化才可以,而且极其占用宿主机性能等等缺陷,而docker不会, docker容器内的应用程序是直接运行于宿主的内核,容器没有自己的内核,更加不会对硬件进行虚拟。这就是我们所见的centos4G的镜像到docker里面就200MB的原因,因此docker容器比传统的虚拟机更为轻便。
主要对比如下:
从这图里面可以看出来,KVM虚拟化基于Hypervisor实现的宿主机虚拟化,流程如下:
docker与虚拟机对比如下
特性 | docker容器 | kvm虚拟机 |
---|---|---|
启动速度 | 秒级 | 分钟级 |
计算机消耗 | 几乎无 | 50%左右 |
性能 | 接近原生 | 弱 |
系统支持量 | 上千个 | 几万个 |
隔离性 | 容器之间互相隔离,与宿主机隔离 | 完全隔离 |
docker容器本质是宿主机的进程,docker通过namespace实现资源的隔离;
namespace | 隔离内容 |
---|---|
MNT | 挂载点 |
PID | 进程编号 |
USER | 用户组,组 |
NET | 网络栈,网络设备 |
UTS | 主机名,域名 |
IPC | 共享内存,消息队列 |
Cgroups实现的是资源限制;Cgroups可以将任意的一个进程进行分组化管理的Linux内核系统,可以对CPU,内存,I/O进行限制。
Cgroups 提供了一个 Cgroups 虚拟文件系统,作为进行分组管理和各子系统设置的用户接口。要使用 Cgroups,必须挂载 Cgroups 文件系统。这时通过挂载选项指定使用哪个子系统 。
位置在:
[root@docker01 ~]# cd /sys/fs/Cgroups/
[root@docker01 Cgroups]# ls
blkio cpuacct cpuset freezer memory net_cls,net_prio perf_event systemd
cpu cpu,cpuacct devices hugetlb net_cls net_prio pids
cpuacct – 这个子系统自动生成 Cgroups 中任务所使用的 CPU 报告。
cpuset – 这个子系统为 Cgroups 中的任务分配独立 CPU(在多核系统)和内存节点。
devices – 这个子系统可允许或者拒绝 Cgroups 中的任务访问设备。
freezer – 这个子系统挂起或者恢复 Cgroups 中的任务。
net_cls – 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 Cgroups 中生成的数据包
容器内存包括两个部分:物理内存和swap
可以通过参数控制容器内存的使用量:
新建一个容器,创建的时候分配内存限制
[root@docker01 ~]# docker run -itd --name dc02 -m 200MB --memory-swap 300MB centos:7
60b389243c1799565db8ac0cb256701a5b318ed5c5a7bbd457e51f92e87811e1
查看限制
[root@docker01 ~]# cd /sys/fs/Cgroups/memory/docker/ && ls
448896a705bcc5a22af3cc3887db45c0e9446efbdb4e66fef96f77efda5e04d1
60b389243c1799565db8ac0cb256701a5b318ed5c5a7bbd457e51f92e87811e1
......
#找到与你的容器对应的id号为准,进入
[root@docker01 docker]# cd 60b389243c1799565db8ac0cb256701a5b318ed5c5a7bbd457e51f92e87811e1
[root@docker01 60b389243c1799565db8ac0cb256701a5b318ed5c5a7bbd457e51f92e87811e1]# cat memory.limit_in_bytes
209715200
新建dc03,分配权重
[root@docker01 ~]# docker run -itd --name dc03 -c 512 centos:7
查看限制
[root@docker01 docker]# cd /sys/fs/Cgroups/cpu/docker
#找到与你的容器对应的id号为准,进入
[root@docker01 docker]# cd 06dc9224c00f8619f9551d7fea0646cfb537c3f1a565534d9c99d4beb3149ed7/
[root@docker01 06dc9224c00f8619f9551d7fea0646cfb537c3f1a565534d9c99d4beb3149ed7]# pwd
/sys/fs/Cgroups/cpu/docker/06dc9224c00f8619f9551d7fea0646cfb537c3f1a565534d9c99d4beb3149ed7
[root@docker01 06dc9224c00f8619f9551d7fea0646cfb537c3f1a565534d9c99d4beb3149ed7]# cat cpu.shares
512
默认情况下,所有容器都能够平等的读写磁盘,速率取决于你宿主机的磁盘度读写速率
–device-read-bps: 显示读取某个设备的bps
–device-write-bps: 显示写入某个设备的bps
–device-read-iops: 显示读取某个设备的iops
–device-write-iops: 显示写入某个设备的iops
新建dc04,配置写入速率为30MB/s
[root@docker01 ~]# docker run -itd --name dc04 --device-write-bps /dev/sda:30MB centos:7
ebcfc480d48e641bf77645b0c45ab663907aef2cb85593a3f4b7d45ced34fe60
[root@docker01 ~]#
[root@docker01 ~]# docker attach dc04
[root@ebcfc480d48e /]# 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.6239 s, 31.5 MB/s
real 0m26.644s
user 0m0.000s
sys 0m0.568s
在运行一个测试不做任何限制
进入dc03
测试发现不做限制取决于你的磁盘读写速率
[root@docker01 ~]# docker attach dc03
[root@06dc9224c00f /]#
[root@06dc9224c00f /]# 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, 1.02023 s, 822 MB/s
real 0m1.023s
user 0m0.000s
sys 0m0.833s
长话短说,dd主要用在测试硬盘的读写速度
命令格式如下:
dd if=输入文件名 of=输出文件名 bs=block_size count=number_of_blocks iflag(oflag)=FLAGS
常用的选项:
if=file 输入文件名,缺省为标准输入。
of=file 输出文件名,缺省为标准输出。
bs=bytes/MB 同时设置读写块的大小为 bytes/MB
count=num 设置读写的次数
conv=conversion 用指定的参数转换文件。
iflag=FLAGS 指定读的方式FLAGS,参见“FLAGS参数说明”
oflag=FLAGS 指定写的方式FLAGS,参见“FLAGS参数说明”
FLAGS说明
direct 读写数据采用直接IO方式;
directory 读写失败除非是directory;
dsync 读写数据采用同步IO;
sync 同上,但是针对是元数据
fullblock 堆积满block(accumulate full blocks of input )(iflag only);
nonblock 读写数据采用非阻塞IO方式
noatime 读写数据不更新访问时间
注释:
time+dd 测磁盘读写速度
1、先熟悉两个特殊的设备及一些相关参数:
/dev/zero是一个伪设备,它只产生空字符流,对它不会产生IO ,
/test是一个实体文件,需要写入就产生IO
time dd if=/dev/zero of=/test bs=1M count=1024 oflag=direct
/dev/null也是一个伪设备,所以写入时不会产生IO,相当于黑洞
/root/test是一个实体文件,读取时会产生IO
time time dd if=/root/test of=/dev/null bs=1M count=1024 iflag=direct
一个是物理分区,一个是实际的文件,对它们的读写都会产生IO(对/dev/sda是读,对/test01是写)
time dd if=/dev/sda of=/test01 bs=1M count=1024
测试单纯读取性能
/dev/null也是一个伪设备,所以写入时不会产生IO,相当于黑洞
/root/test是一个实体文件,读取时会产生IO
time time dd if=/root/test of=/dev/null bs=1M count=1024 iflag=direct
一个是物理分区,一个是实际的文件,对它们的读写都会产生IO(对/dev/sda是读,对/test01是写)
time dd if=/dev/sda of=/test01 bs=1M count=1024