- Docker容器和LXC容器在实现上很相似,所提供的安全特性也基本–致。当用dockerrun启动一个容器时,Docker 将在后台为容器创建一个独立的命名空间。
命名空间提供了最基础也是最直接的隔离,在容器中运行的进程不会被运行在本地主机上的进程和其他容器通过正常渠道发现和影响。
例如,通过命名空间机制,每个容器都有自己独有的网络栈,意味着它们不能访问其他容器的套接字( sockets)或接口。当然,容器默认可以与本地主机网络连通,如果主机系统上做了相应的交换设置,容器可以像跟主机交互一样的和其他容器交互。启动容器时,指定公共端口或使用连接系统,容器可以相互通信了(用户可以根据配置来限制通信的策略)。- 从网络架构的角度来看,所有的容器实际上是通过本地主机的网桥接口(Docker0)进行相互通信,就像物理机器通过物理交换机通信一样。
那么,Linux内核中实现命名空间(特别是网络命名空间)的机制是否足够成熟呢?
Linux内核从2.6.15版本(2008年7月发布)开始引人命名空间,至今经历了数年的演化和改进,并应用于诸多大型生产系统中。
实际上,命名空间的想法和设计提出的时间要更早,最初是OpenVZ项目的重要特性。OpenVZ项目早在2005年就已经正式发布,其设计和实现更加成熟。
当然,与虚拟机方式相比,通过命名空间来实现的隔离并不是那么绝对。运行在容器中的应用可以直接访问系统内核和部分系统文件。因此,用户必须保证容器中应用是安全可信的(这跟保证运行在系统中的软件是可信的一一个道理),否则本地系统将可能受到威胁。实际上,Docker自1.30版本起对镜像管理引人了签名系统,用户可以通过签名来验证镜像的完整性和正确性。
具体可参看:Docker 使用 Linux namespace 隔离容器的运行环境
- 控制组是Linux容器机制中的另外一个关键组件,它负责实现资源的审计和限制。当用dockerrun启动一个容器时,Docker将在后台为容器创建一个独立的控制组策略集合。
它提供了很多有用的特性;以及确保各个容器可以公平地分享主机的内存、CPU、磁盘O等资源;当然,更重要的是,控制组确保了当发生在容器内的资源压力不会影响到本地主机系统和其他容器。
尽管控制组不负责隔离容器之间相互访问、处理数据和进程,但是它在防止拒绝服务攻击(DDoS)方面是必不可少的。尤其是在多用户的平台(比如公有或私有的PaaS)上,控制组十分重要。例如,当某些应用容器出现异常的时候,可以保证本地系统和其他容器正常运行而不受影响。- 在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 中生成的数据包。
[root@server1 cgroup]# cd memory/
[root@server1 memory]# ls
[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
可通过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
可通过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 # 进行查看
可通过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 冻结进程
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)