文章目录

  • Docker 资源控制
  • 1:对CPU的控制
  • (1)限制CPU使用速率
  • (2) 按比例分享CPU
  • (3) 限制CPU内核使用
  • 2: 对内存使用的限制
  • 3:对blkio的限制
  • Docker 网络通信操作
  • 1:端口映射
  • 2:容器互联


Docker 资源控制

Cgroup是Control group的简写,是Linux内核提供的一种限制所使用物理资源的机制,这些资源主要包括CPU、内存、blkio。下面就这三个方面来谈一下Docker是如何使用Cgroup机制进行管理的。

1:对CPU的控制

(1)限制CPU使用速率

在Docker中可以通过 --cpu-quota 选项来限制CPU的使用率,CPU的百分比是以1000为单位的

docker run --cpu-quota 20000 容器名  /bin/bash     //CPU的使用率限定为20%

docker运行时控制资源 docker控制cpu资源_docker


-i 表示让容器的输入保持打开

-t 表示让docker分配一个伪终端

-d 表示后台运行容器,并返回容器ID

进入容器,进行压力测试
用圆周率压测公式,进行满载压测,看CPU使用率的变化

[root@localhost ~]# docker exec -it 5e3fbaabff9e /bin/bash
[root@5e3fbaabff9e /]# yum -y install bc
[root@5e3fbaabff9e /]# echo "scale=5000; 4*a(1)" | bc -l -q
-l   --使用标准数学库
-q   --不输出在界面

另开一个终端,用top 命令查看CPU变化,可看到CPU 在20%左右徘徊

docker运行时控制资源 docker控制cpu资源_Docker_02


docker运行时控制资源 docker控制cpu资源_docker_03


在CentOS中还可以通过修改对应的Cgroup配置文件/sys/fs/cgroup/cpu/docker/容器编号/cpu.cfs_quota_us的值来实现,直接执行echo命令将设定值导入到此文件中就会立即生效。

echo 20000 >/sys/fe/cgroup/cpu/docker/572e6811c6b6c64b129a8ffOd6c7ac4f8 bee2f8e7d34470c2b634b698206a/cpu.cfs_quota_us

(2) 按比例分享CPU

当有多个容器任务运行时,很难计算CPU的使用率。为了使容器合理使用CPU 资源,可以通过 --cpu-share 选项设置CPU按比例共享CPU资源,这种方式还可以实现CPU使用率的动态调整。
如:运行2个容器A、B、占用CPU资源的比例为1:2,可以这样执行:

docker run --cpu-shares 512 容器A
docker run --cpu-shares 1024 容器B

创建两个容器为c1和c2,若只有这两个容器,设置容器的权重,使得c 1和c2的CPU资源占比为33.3%和66.7%

docker运行时控制资源 docker控制cpu资源_Docker_04


开两个终端,进入容器,2个容器同时进行压测,用stress工具满载4个线程

进入容器c1
# docker exec -it c1容器ID /bin/bash	
# yum -y install epel-release -y
# yum -y install stress
# stress -c 4

docker运行时控制资源 docker控制cpu资源_docker_05

进入容器c2
# docker exec -it c2容器ID /bin/bash	
# yum -y install epel-release -y
# yum -y install stress
# stress -c 4

docker运行时控制资源 docker控制cpu资源_docker运行时控制资源_06


再开一个终端,查看CPU使用率,可看到c1占1/3, c2占2/3

# docker stats    动态查看docker的资源

docker运行时控制资源 docker控制cpu资源_Docker_07

(3) 限制CPU内核使用

在Docker中可以使用 --cpuset-cpus 选项来使某些程序独享CPU内核,以便提高 其处理速度,对应的Cgroup配置文件为/sys/fs/cgroup/cpuset/docker/容器编号/cpuset.cpus。选项后直接跟参数0、1、2 …表示第1个内核、第2个内核、第3个内核, 与 /proc/cpuinfo 中的 CPU 编号(processor)相同。
如果服务器有16个核心,那么CPU编号为。0〜15,使容器绑定第2和4个内核使用,则:

docker run --cpuset-cpus 1,3 容器名 /bin/bash

那么该容器内的进程只会在编号1、3的CPU上运行

如:

docker运行时控制资源 docker控制cpu资源_Docker_08


添加处理器里的CPU内核数量调为4

# docker run -itd --name test1 --cpuset-cpus 1,3 centos:7 /bin/bash
进入容器test1
# docker exec -it test1容器ID /bin/bash
# yum -y install epel-release -y
# yum -y install stress
# stress -c 4    满载4个线程进行压测

另开一个终端,查看CPU使用率

#top 看到cpu1 和cpu3的使用率在变化

docker运行时控制资源 docker控制cpu资源_docker_09

尽量使用绑定内核的方式分配CPU资源给容器进程使用,然后再配合–cpu-share 选项动态调整CPU使用资源的比例。

2: 对内存使用的限制

在Docker中可以通过docker run -m命令来限制容器内存使用量,相应的Cgroup 配置文件为/sys/fc/cgroup/memory/memory.limit_in_bytes 但是需要注意一旦容器 Cgroup使用的内存超过了限制的容量,Linux内核将会尝试收回这些内存,如果仍旧没法控制内存使用在限制范闱之内,进程就会被杀死。
例如:限制容器的内存为512M。

docker run -m 512m 容器名

docker运行时控制资源 docker控制cpu资源_docker运行时控制资源_10


docker运行时控制资源 docker控制cpu资源_docker_11

3:对blkio的限制

如果是在一台服务器上进行容器的混合部署,那么会出现同时有几个程序写磁盘 数据的情况,这时可以通–device-write-iops选项来限制写入的iops,相应的还有 -device-read-bps选项可以限制读取的iops。但是这种方法只能针对blkio限制的是设备(device),而不是分区。相应Cgroup写配置文件/sys/fs/cgroup/blkio/docker/容器ID/blkio.throttle.write_iops_device
例如:限制容器的/dev/sda1的写入ipos为1MB。

docker run --device-write-bps /dev/sda1:1mb 容器名

例如:限制容器的/dev/sda1的读入ipos为30MB。

docker run --device-write-bps /dev/sda:30M centos:7 /bin/bash

Docker 网络通信操作

安装docker时,会自动创建3个网络,bridge (创建容器默认连接到此网络)、none 、host
host : 容器将不会虚拟出自己的网卡、配置自己的IP等,而是使用宿主机的IP和端口。
Container: 创建的容器不会创建自己的网3,配置自己的IP,而是和一个指定的容器共享IP、端口范围。
None:该模式关闭了容器的网络功能。
Bridge: 此模式会为每一个容器分配、设置IP等, 并将容器连接到一个docker0虚拟网桥,通过docker0网桥以及Iptables nat表配置
以上都是不用动手的,真正需要配置的是自定义网络。

查看网络类型
#docker network ls

默认docker0是桥接模式,并且无法指定容器IP地址

如果不指定IP,是可以创建的
#docker run -itd --name test2 --network bridge centos:7 /bin/bash

# docker exec -it test容器ID /bin/bash	   进入容器
# yum -y install net-tools 
# ifconfig		
可以看到随机分配的地址eth0是同属docker网段的

# ping  docker0的IP地址	可以ping通

如果想要指定容器IP地址,可以自定义网络

创建 网段名为 mynet
# docker network create --subnet=172.18.0.0/16 mynet
# docker network ls	可看到mynet
# ifconfig   可看到这个网段

指定容器IP地址

# docker run -itd --name test2 --network mynetwork --ip 172.18.0.10 centos:7 /bin/bash

# docker ps -a   可看到test2

进入容器查看IP地址

# docker exec -it test2容器ID /bin/bash
# yum -y install net-tools 
# ifconfig		
可看到eth0是172.18.0.10

●docker network create
●docker network ls
●docker network inspect
●docker network connect
●docker network disconnect
●docker network rm

Docker也提供了映射容器端口到宿主机和容器互联机制来为容器提供网络服务。

1:端口映射

在启动容器的时候,如果不指定对应的端口,在容器外将无法通过网络来访问容器内的服务。Docker提供端口映射机制来将容器内的服务提供给外部网络访问,实质上就是将宿主机的端口映射到容器中,使得外部网络访问宿主机的端口便可访问容器内的服务。
实现端口映射,需要在运行docker run命令时使用-P (大写)选项实现随机映射, Docker会随机映射一个端口到容器内部开放的网络端口。 例如:

[root@localhost 〜]# docker run -d -P httpd:centos
34ec7fd9538ab0495ce504f79dd98f6415e7203a5154ae5a4cll 05a0d7cfl 30b

此时,使用docker ps命令可以看到,本机的32768端口被映射到了容器中的80端口。那么访问宿主机的32768端口即可访问到容器内web应用提供的界面。

[root@localhost 〜|# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 34ec7fd9538a httpdxentos "/run.sh" 9 seconds ago Up 7 seconds
0.0.0.0:32768->80/tcp happy almeida

还可以在运行docker run命令时使用-p (小写)选项指定要映射的端口,例如:

[root@localhost -]# docker run -d -p 49280:80 httpd:centos
c8b 185afl e92a04927a2a8e57a47183fd9745afce224c429736ecd084c4ae657

此时,将本机的49280端口映射到了容器中的80端口。

[roott@localhost 〜]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATEDSTATUS PORTS NAMES c8b 185afl c92 httpdxentos "/run.sh" 10 seconds ago Up 7 seconds
. 0.O.O.O:4928S8O/tcp backstabbing

2:容器互联

容器互联是通过容器的名称在容器间建立一条专门的网络通信隧道从而实现容器的互联。简单点说,就是会在源容器和接收容器之间建立一条隧道,接收容器可以看到源容器指定的信息。
在运行docker run命令时使用 --link 选项可以实现容器之间的互联通信。
格式–link name:alias
其中name是要连接的容器名称,alias是这个连接的别名。

容器互联是通过容器的名称来执行的,–name 选项可以给容器创建一个友好的名称,这个名称是唯一的。如果已经命名了一个相同名称的容器,当要再次使用这个名称的时候,需先使用docker rm命令来删除之前创建的同名容器。

下面是使用容器互联技术实现容器间通信的例子。
1.创建源容器
首先使用docker run命令建立容器A,使用-name指定容器名称为web1。

[root@localhost 〜]# docker run -d -P -name web1 httpd:centos 4ca528Bd96b6979ea41aafd4a730d4984d0ca36f65fI4625e7ef26655al2f38

2.创建接收容器
然后使用docker run命令建立容器B,使用–name指定容器名称为web2,使用–link指定连接容器以实现容器互联。

[root@localhost -]# docker run -d -P --name web2 -link web1:web1 httpd:centos
9fdd92 ld7d24e05c76e724b0b735546ef87cec8a99321614cef6024aa9fl105e

3.测试容器互联
最简单的检测方法是进入容器,使用ping命令查看容器是否能相互连通。

[root@localhost -]# docker exec -it web2 /bin/bash
[root@9fdd921d7d24 /]# ping web1
PING webl (172.17.0.7) 56(84) bytes of data.
64 bytes from webl (172.17.0.7): icmp_seq=l ttl=64 time=0.804 ms
64 bytes from webl (172.17.0.7): icmp_seq=2 ttl=64 time=0.340 ms
..............

此时,可以看到容器web2与容器web1已经建立互联关系。Docker在两个互联的 容器之间创建了一条安全隧道,而且不用映射它们的端口到宿主机上,从而避免暴露端口给外部网络