Docker入门——namespace 隔离容器的运行环境,cgroups 限制容器使用的资源

1. namespace 隔离容器的运行环境

  • Docker容器和LXC容器在实现上很相似,所提供的安全特性也基本–致。当用dockerrun启动一个容器时,Docker 将在后台为容器创建一个独立的命名空间。
    命名空间提供了最基础也是最直接的隔离,在容器中运行的进程不会被运行在本地主机上的进程和其他容器通过正常渠道发现和影响。
    例如,通过命名空间机制,每个容器都有自己独有的网络栈,意味着它们不能访问其他容器的套接字( sockets)或接口。当然,容器默认可以与本地主机网络连通,如果主机系统上做了相应的交换设置,容器可以像跟主机交互一样的和其他容器交互。启动容器时,指定公共端口或使用连接系统,容器可以相互通信了(用户可以根据配置来限制通信的策略)。
  • 从网络架构的角度来看,所有的容器实际上是通过本地主机的网桥接口(Docker0)进行相互通信,就像物理机器通过物理交换机通信一样。
    那么,Linux内核中实现命名空间(特别是网络命名空间)的机制是否足够成熟呢?
    Linux内核从2.6.15版本(2008年7月发布)开始引人命名空间,至今经历了数年的演化和改进,并应用于诸多大型生产系统中。
    实际上,命名空间的想法和设计提出的时间要更早,最初是OpenVZ项目的重要特性。OpenVZ项目早在2005年就已经正式发布,其设计和实现更加成熟。
    当然,与虚拟机方式相比,通过命名空间来实现的隔离并不是那么绝对。运行在容器中的应用可以直接访问系统内核和部分系统文件。因此,用户必须保证容器中应用是安全可信的(这跟保证运行在系统中的软件是可信的一一个道理),否则本地系统将可能受到威胁。实际上,Docker自1.30版本起对镜像管理引人了签名系统,用户可以通过签名来验证镜像的完整性和正确性。
    具体可参看:Docker 使用 Linux namespace 隔离容器的运行环境

2. 控制组资源控制的安全

  • 控制组是Linux容器机制中的另外一个关键组件,它负责实现资源的审计和限制。当用dockerrun启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。
    它提供了很多有用的特性;以及确保各个容器可以公平地分享主机的内存、CPU、磁盘O等资源;当然,更重要的是,控制组确保了当发生在容器内的资源压力不会影响到本地主机系统和其他容器。
    尽管控制组不负责隔离容器之间相互访问、处理数据和进程,但是它在防止拒绝服务攻击(DDoS)方面是必不可少的。尤其是在多用户的平台(比如公有或私有的PaaS)上,控制组十分重要。例如,当某些应用容器出现异常的时候,可以保证本地系统和其他容器正常运行而不受影响。
  • 在docker中的体现:
    • 默认情况下,Docker 启动一个容器后,会在 /sys/fs/cgroup 目录下的各个资源目录下生成以容器 ID 为名字的目录(group),比如:
      容器信息
      这里写图片描述
      /sys/fs/cgroup 中对应的信息:
      这里写图片描述
      下面以cgroup第资源的控制,来解释docker 容器对资源的限制

通过linux cgroup来进行说明
实验拓扑:linux rhel6.5 机器,安装libcgroup.x86_64 来进行实验

 [root@server1 ~]# /etc/init.d/cgconfig start
 Starting cgconfig service:                                 [  OK  ]
 # 进入此目录
 [root@server1 ~]# cd /cgroup/
 [root@server1 cgroup]# ls
 blkio  cpu  cpuacct  cpuset  devices  freezer  memory  net_cls
blkio — 这​​​个​​​子​​​系​​​统​​​为​​​块​​​设​​​备​​​设​​​定​​​输​​​入​​​/输​​​出​​​限​​​制​​​,比​​​如​​​物​​​理​​​设​​​备​​​(磁​​​盘​​​,固​​​态​​​硬​​​盘​​​,USB 等​​​等​​​)。
cpu — 这​​​个​​​子​​​系​​​统​​​使​​​用​​​调​​​度​​​程​​​序​​​提​​​供​​​对​​​ CPU 的​​​ cgroup 任​​​务​​​访​​​问​​​。​​​
cpuacct — 这​​​个​​​子​​​系​​​统​​​自​​​动​​​生​​​成​​​ cgroup 中​​​任​​​务​​​所​​​使​​​用​​​的​​​ CPU 报​​​告​​​。​​​
cpuset — 这​​​个​​​子​​​系​​​统​​​为​​​ cgroup 中​​​的​​​任​​​务​​​分​​​配​​​独​​​立​​​ CPU(在​​​多​​​核​​​系​​​统​​​)和​​​内​​​存​​​节​​​点​​​。​​​
devices — 这​​​个​​​子​​​系​​​统​​​可​​​允​​​许​​​或​​​者​​​拒​​​绝​​​ cgroup 中​​​的​​​任​​​务​​​访​​​问​​​设​​​备​​​。​​​
freezer — 这​​​个​​​子​​​系​​​统​​​挂​​​起​​​或​​​者​​​恢​​​复​​​ cgroup 中​​​的​​​任​​​务​​​。​​​
memory — 这​​​个​​​子​​​系​​​统​​​设​​​定​​​ cgroup 中​​​任​​​务​​​使​​​用​​​的​​​内​​​存​​​限​​​制​​​,并​​​自​​​动​​​生​​​成​​​​​内​​​存​​​资​​​源使用​​​报​​​告​​​。​​​
net_cls — 这​​​个​​​子​​​系​​​统​​​使​​​用​​​等​​​级​​​识​​​别​​​符​​​(classid)标​​​记​​​网​​​络​​​数​​​据​​​包​​​,可​​​允​​​许​​​ Linux 流​​​量​​​控​​​制​​​程​​​序​​​(tc)识​​​别​​​从​​​具​​​体​​​ cgroup 中​​​生​​​成​​​的​​​数​​​据​​​包​​​。​​​

1. 进行内存的限制

 [root@server1 cgroup]# cd memory/
 [root@server1 memory]# ls

Docker入门——namespace 隔离容器的运行环境,cgroups 限制容器使用的资源_第1张图片
编辑/etc/cgconfig.conf,进行限制

 [root@server1 memory]# vim /etc/cgconfig.conf
 group test1 {
         memory {
                 memory.limit_in_bytes = 209715200;   # 限制为200M
                 memory.memsw.limit_in_bytes = 209715200;
         }
 }
 编辑完成,重启服务 
 [root@server1 ~]# /etc/init.d/cgconfig restart

进行限制测试:
介绍一下 /dev/shm

  • /dev/shm/是一个使用就是tmpfs文件系统的设备,其实就是一个特殊的文件系统。redhat中默认大小为物理内存的一半,使用时不用mkfs格式化。
    tmpfs是Linux/Unix系统上的一种基于内存的虚拟文件系统。tmpfs可以使用您的内存或swap分区来存储文件(即它的存储空间在virtual memory 中, VM由real memory和swap组成)。由此可见,tmpfs主要存储暂存的文件。它有如下2个优势 : 1. 动态文件系统的大小。2. tmpfs 使用VM建的文件系统,速度当然快。3.重启后数据丢失。
    当删除tmpfs中的文件时,tmpfs会动态减少文件系统并释放VM资源,LINUX中可以把一些程序的临时文件放置在tmpfs中,利用tmpfs比硬盘速度快的特点提升系统性能。实际应用中,为应用的特定需求设定此文件系统,可以提升应用读写性能,如将squid 缓存目录放在/tmp, php session 文件放在/tmp, socket文件放在/tmp, 或者使用/tmp作为其它应用的缓存设备
    上面的内存限制,限制的就是此目录下
 [root@server1 shm]# cgexec -g memory:test1 dd if=/dev/zero of=file bs=1M count=300       # 超过200M的内存截取不出
 Killed
 [root@server1 shm]# cgexec -g memory:test1 dd if=/dev/zero of=file bs=1M count=190       # 小于200M则可以截取
 190+0 records in
 190+0 records out
 199229440 bytes (199 MB) copied, 0.0559904 s, 3.6 GB/s

2. 进行进程CPU的限制

可通过cgroup来限制进程cpu的占用率

 [root@server1 ~]# vim /etc/cgconfig.conf
 编辑/etc/cgconfig.conf

 group test2 {
         cpu {
                 cpu.shares = 100;   # 限制cpu占用率为1/10
         }
 }

 执行如下命令,然后查看cpu 占有率 : (此测试需要注意cpu的核数,若是4核,则需要建立8各项目,来进行cpu占有的压测试)
 限制过的
 [root@server1 ~]# cgexec -g cpu:test2 dd if=/dev/zero of=/dev/null &
 [1] 4123
 未限制的
 [root@server1 ~]# dd if=/dev/zero of=/dev/null &
 [2] 4124
 通过top 命令,动态检测cpu占有率
 [root@server1 ~]# top

Docker入门——namespace 隔离容器的运行环境,cgroups 限制容器使用的资源_第2张图片

3. 进程 I/O 的限制

可通过cgroup来限制进程I/O

  # 查看设备编号
 [root@server1 blkio]# ll /dev/vda 
 brw-rw---- 1 root disk 252, 0 Aug 21 22:24 /dev/vda

 [root@server1 ~]# vim /etc/cgconfig.conf
 group test3 {
         blkio {
                 blkio.throttle.read_iops_device = "252:0 1000000";
                               # 限制进程I/O的磁盘读速率为100M
                               # 252:0 为设备编号
         }
 }
 [root@server1 ~]# /etc/init.d/cgconfig restart 
                 # 重启服务 

进行测试

 切取文件,查看磁盘读写速率
 [root@server1 ~]# cgexec -g blkio:test3 dd if=/dev/zero of=/dev/null &
 [3] 13663
 [root@server1 ~]# iotop # 进行查看

Docker入门——namespace 隔离容器的运行环境,cgroups 限制容器使用的资源_第3张图片

4. 进程的限制

可通过cgroup来限制进程的状态


 [root@server1 ~]# vim /etc/cgconfig.conf
 group test4 {
        freezer {

 }
 }
 [root@server1 ~]# /etc/init.d/cgconfig restart
                 # 重启服务

进行测试

 [root@server1 ~]# cgexec -g freezer:test4 dd if=/dev/zero of=/dev/null &
 [1] 5299
 [root@server1 ~]# cd /cgroup/freezer/
 [root@server1 freezer]# ls
 cgroup.event_control  cgroup.procs  notify_on_release  release_agent   tasks  test4
 [root@server1 freezer]# cd test4/
 [root@server1 test4]# ls
 cgroup.event_control  cgroup.procs  freezer.state  notify_on_release   tasks
 [root@server1 test4]# echo 5299 > tasks # 将进程号写入tasks中
 [root@server1 test4]# cat freezer.state 
 THAWED         # 解冻
 [root@server1 test4]# echo FROZEN > freezer.state # 冻结task中的进程
                # FROZEN 冻结进程

冻结前进程状态
这里写图片描述
冻结后进程状态
这里写图片描述

5. Docker run 命令中 cgroups 相关命令

block IO:
      --blkio-weight value Block IO (relative weight), between 10 and 1000       --blkio-weight-device value Block IO weight (relative device weight) (default [])       --cgroup-parent string Optional parent cgroup for the container CPU:
      --cpu-percent int CPU percent (Windows only)       --cpu-period int Limit CPU CFS (Completely Fair Scheduler) period       --cpu-quota int Limit CPU CFS (Completely Fair Scheduler) quota   -c, --cpu-shares int CPU shares (relative weight)       --cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)       --cpuset-mems string MEMs in which to allow execution (0-3, 0,1) Device:    
      --device value Add a host device to the container (default [])       --device-read-bps value Limit read rate (bytes per second) from a device (default [])       --device-read-iops value Limit read rate (IO per second) from a device (default [])       --device-write-bps value Limit write rate (bytes per second) to a device (default [])       --device-write-iops value Limit write rate (IO per second) to a device (default []) Memory:      
      --kernel-memory string Kernel memory limit   -m, --memory string Memory limit       --memory-reservation string Memory soft limit       --memory-swap string Swap limit equal to memory plus swap: '-1' to enable unlimited swap       --memory-swappiness int Tune container memory swappiness (0 to 100) (default -1)

你可能感兴趣的:(Docker入门——namespace 隔离容器的运行环境,cgroups 限制容器使用的资源)