docker底层原理

文章目录

    • docker虚拟化和普通虚拟化得区别
        • 区别——解耦方式不同
        • 耦合?解耦?
    • Namespace与Cgroups
        • namespace的六项隔离
        • Cgroups子系统介绍
    • Cgroups可以做的限制
    • Cgroups的资源限制
        • 内存限制(大小)
        • cpu限制(大小)
        • 磁盘I/O限制(速率)
    • 附加回顾:dd用法
        • 单纯测试写入能力
        • 测试单纯读取性能
        • 同时测试读写性能
        • 同时测试读写性能

docker虚拟化和普通虚拟化得区别

区别——解耦方式不同

普通虚拟化——完全性解耦
docker虚拟化——半解耦

耦合?解耦?

耦合就是发生矛盾,冲突
解耦就是解决矛盾,冲突
举个栗子:比如你在淘宝买了一个栗子,赶巧你在公司上班,快递小哥儿给你打电话让你下来取,你呢<><>,正好也走不开,于是你说:“你放到楼下的小花超市吧”,小哥儿答应了,你们两个谁都没有耽误谁,很好的处理了这件事,这就是解耦。

传统虚拟机以VMware或kvm为例,我们需要给虚拟机分配CPU,内存,硬盘等资源,宿主机必须支持CPU虚拟化才可以,而且极其占用宿主机性能等等缺陷,而docker不会, docker容器内的应用程序是直接运行于宿主的内核,容器没有自己的内核,更加不会对硬件进行虚拟。这就是我们所见的centos4G的镜像到docker里面就200MB的原因,因此docker容器比传统的虚拟机更为轻便。

主要对比如下:

docker底层原理_第1张图片

从这图里面可以看出来,KVM虚拟化基于Hypervisor实现的宿主机虚拟化,流程如下:

docker与虚拟机对比如下

特性 docker容器 kvm虚拟机
启动速度 秒级 分钟级
计算机消耗 几乎无 50%左右
性能 接近原生
系统支持量 上千个 几万个
隔离性 容器之间互相隔离,与宿主机隔离 完全隔离

Namespace与Cgroups

docker容器本质是宿主机的进程,docker通过namespace实现资源的隔离;

namespace的六项隔离

namespace 隔离内容
MNT 挂载点
PID 进程编号
USER 用户组,组
NET 网络栈,网络设备
UTS 主机名,域名
IPC 共享内存,消息队列

Cgroups实现的是资源限制;Cgroups可以将任意的一个进程进行分组化管理的Linux内核系统,可以对CPU,内存,I/O进行限制。

Cgroups子系统介绍

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
  • blkio – 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等等)
  • cpu – 这个子系统使用调度程序提供对 CPU 的 Cgroups 任务访问
  • memory – 这个子系统设定 Cgroups 中任务使用的内存限制,并自动生成由那些任务使用的内存资源报告

cpuacct – 这个子系统自动生成 Cgroups 中任务所使用的 CPU 报告。

cpuset – 这个子系统为 Cgroups 中的任务分配独立 CPU(在多核系统)和内存节点。

devices – 这个子系统可允许或者拒绝 Cgroups 中的任务访问设备。

freezer – 这个子系统挂起或者恢复 Cgroups 中的任务。

net_cls – 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 Cgroups 中生成的数据包

Cgroups可以做的限制

  • 资源限制:Cgroups可以对进程组使用的资源总额进行限制
  • 优先级分配:通过分配的cpu时间片数量以及硬盘IO带宽大小,实际 上相当于控制了进程运行的优先级别
  • 资源统计:Cgroups可以统计系统资源使用 量
  • 进程控制:可以对进程组执行挂起、恢复等操作

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

cpu限制(大小)

新建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

磁盘I/O限制(速率)

默认情况下,所有容器都能够平等的读写磁盘,速率取决于你宿主机的磁盘度读写速率

–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主要用在测试硬盘的读写速度

命令格式如下:

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、先熟悉两个特殊的设备及一些相关参数:

  1. time有计时作用,dd用于复制,从if读出,写到of;
  1. bs是每次读或写的大小,即一个块的大小,count是读写块的数量

单纯测试写入能力

/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

你可能感兴趣的:(docker)