由于官方的warden独立安装要涉及到一系列手动操作,可能要自己搭虚拟机,配环境,稍显麻烦。 github上找到一个warden集成安装的项目vagrant-warden,就是一键安装虚拟机和warden。本文后半部分的warden使用就是基于vagrant-warden。与官方warden的使用其实就是直接登录虚拟机,和通过vagrant登录虚拟机的区别。
有兴趣的同学了解下vagrant,它是利用virtualbox自动安装vm,只要本地安装了virtualbox,就可以利用vagrant来安装虚拟机了,自己不需要操作系统iso镜像,vagrant会自动帮你找到合适的操作系统自动完成安装。vagrant-warden,从字面上就可以理解,它帮你装完vm,还帮你在vm装warden,而这一切都是自动的。
vagrant-warden的安装比较详细:
github地址: https://github.com/silas/vagrant-warden
网上的一篇:http://silas.sewell.org/blog/2012/10/06/getting-started-with-cloud-foundrys-warden/
要记得前提:安装virtualbox!
首先要启动虚拟机,登录到虚拟机,启动虚拟机上的warden服务,命令分别是:
vagrant up # 在vagrant warden目录下
vagrant ssh
sudo warden-server
warden启动之后,需要命令行来操作它,创建管理container。命令分别是:
vagrant ssh
sudo warden-repl
这样就到命令行模式下,键入help,就会看到命令清单:
解释看英文吧。最重要的几个,create 创建,copy_in将文件拷备进去,info查看某个container的详情,list 查看当前有几个container,run命令运行在container里的应用。几个limit是限制disk、bandwidth和memory。
练习几个命令:
list
create
info --handle container标识
不懂如何操作的,加上--help,比如create --help
这节是结合例子一步步剖析warden原理,如何创建使用容器,容器如何做到资源隔离,访问限制。并做一些简单测试。
首先,warden命令行里list一下,是nil,说明还没有创建任何容器,创建一个吧。
grace_time要设得大一点,默认是300秒,也就是说300秒没请求,container就被回收。基本设上一天,方便测试。可以看到创建后返回一个handle标识。
查看下这个容器的参数:
warden> info --handle 16h7sfkuoa8
state : active
host_ip : 10.254.0.1
container_ip : 10.254.0.2
container_path : /opt/warden/warden/data/containers/16h7sfkuoa8
memory_stat.cache : 802816
memory_stat.rss : 24576
memory_stat.mapped_file : 0
memory_stat.pgpgin : 917
memory_stat.pgpgout : 715
memory_stat.swap : 0
memory_stat.pgfault : 3987
memory_stat.pgmajfault : 10
memory_stat.inactive_anon : 0
memory_stat.active_anon : 24576
memory_stat.inactive_file : 565248
memory_stat.active_file : 237568
memory_stat.unevictable : 0
memory_stat.hierarchical_memory_limit : 9223372036854775807
memory_stat.hierarchical_memsw_limit : 9223372036854775807
memory_stat.total_cache : 802816
memory_stat.total_rss : 24576
memory_stat.total_mapped_file : 0
memory_stat.total_pgpgin : 917
memory_stat.total_pgpgout : 715
memory_stat.total_swap : 0
memory_stat.total_pgfault : 3987
memory_stat.total_pgmajfault : 10
memory_stat.total_inactive_anon : 0
memory_stat.total_active_anon : 24576
memory_stat.total_inactive_file : 565248
memory_stat.total_active_file : 237568
memory_stat.total_unevictable : 0
cpu_stat.usage : 31116450
cpu_stat.user : 0
cpu_stat.system : 0
disk_stat.bytes_used : 40960
disk_stat.inodes_used : 10
bandwidth_stat.in_rate : 4294967295
bandwidth_stat.in_burst : 4294967295
bandwidth_stat.out_rate : 4294967295
bandwidth_stat.out_burst : 4294967295
容器信息包含了状态,ip地址,容器的路径,以及内存,cpu,磁盘,和带宽信息。
先看ip信息,多了俩ip,host_id和container_id。host_id是用来连接这个container的,container ip不知道有什么作用。 ifconfig一下发现多了个虚拟网卡,是create的时候生成的。
w-16h7sfkuoa8-0 Link encap:Ethernet HWaddr 46:47:48:69:3b:04
inet addr:10.254.0.1 Bcast:10.254.0.3 Mask:255.255.255.252
inet6 addr: fe80::4447:48ff:fe69:3b04/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:468 (468.0 B) TX bytes:468 (468.0 B)
虚拟机上除了eth0,多了个虚拟网卡 w-16h7sfkuoa8-0,命名很有意思,一看就知道是哪个container的。ping 10.254.0.1 没问题。这个证明了这个container,虚拟网卡有了,可以实现网络功能了。
==========================================
接着看container路径:/opt/warden/warden/data/containers/16h7sfkuoa8 ,ll下:
drwxr-xr-x 2 root root 4096 Dec 20 02:02 bin/
-rwxr-xr-x 1 root root 771 Dec 20 02:02 destroy.sh*
drwxr-xr-x 2 root root 4096 Dec 20 02:02 etc/
drwxr-xr-x 2 root root 4096 Dec 20 02:02 jobs/
drwxr-xr-x 2 root root 4096 Dec 20 02:02 lib/
drwxr-xr-x 2 root root 4096 Dec 20 02:02 mnt/
-rwxr-xr-x 1 root root 1195 Dec 20 02:02 net_rate.sh*
-rwxr-xr-x 1 root root 3371 Dec 20 02:02 net.sh*
drwxr-xr-x 2 root root 4096 Dec 20 02:02 run/
-rwxr-xr-x 1 root root 1925 Dec 20 02:02 setup.sh*
-rw-r--r-- 1 root root 154 Dec 20 02:02 snapshot.json
-rwxr-xr-x 1 root root 297 Dec 20 02:02 start.sh*
-rwxr-xr-x 1 root root 958 Dec 20 02:02 stop.sh*
drwxr-xr-x 3 root root 4096 Dec 20 02:02 tmp/
像destroy.sh,net_rate.sh,start.sh等,命令行操作时候执行的脚本。有个疑问,container应该起码像个操作系统才对,怎么是这样,重点关注下tmp目录。里面有个rootfs目录,这个就是操作系统了。
进去看看,包括了dev etc home var四个目录,是个简易的操作系统,能实现一些基本的操作,包括sh, ls之类的,在部署一个应用的时候,够用了。
cd home看看
是一个默认的用户,叫vcap,它的创建者与组群是“10000”,好诡异。这个大有文章,下面会讲到。
这里我们了解到container文件夹的结构,它拥有简易操作系统的目录。是root权限,但是/home/vcap的用户组是“10000”。在这里我们只能看到这么多。
实际上在安装warden的时候,它就安装了一个rootfs的模板,在/tmp/warden目录下。每次用户create的时候,就copy一份,并将/home/vcap的用户组改改。安装的时候还有,重启电脑后/tmp/warden没了
create时rootfs哪里取的,这个不太清楚,可以再研究下setup的过程。相对来说不是很重要,这里先略过。
到目前为止,我们知道有一个虚拟网卡对应这个类似操作系统的目录。其实这个操作系统就可以用了,怎么用呢,chroot!
动手练练吧,这个操作系统对于用户来说是透明的,我们试试用命令行传个文件,看看保存在什么地方。
回顾下系统关系,宿主机--->vm--->warden。就是宿主机上用vagrant装了vm,vagrant又在vm上装了warden。
但是先解决一个问题,文件从哪里来。环境是ubuntu 12.04利用vagrant-warden创建一个ubuntu12.04虚拟机,并在vm上装了warden服务。宿主机,vm,以及warden上的container。
要传一个文件,得从vm传给warden container。两种方法:1.宿主机与vm做个NFS共享,2.vm直接从网络上wget东西。我用的是前一种。因为很多东西,包括应用都在宿主机上。部署container比较方便。
warden> copy_in --handle 16h7sfkuoa8 --src_path /tmp/nfs_share --dst_path /tmp
发现tmp目录在rootfs下,说明rootfs才是用户操作的根目录,验证了warden是用chroot。
drwxr-xr-x 3 root root 4096 Dec 20 02:02 ../
drwxr-xr-x 3 root root 4096 Dec 20 02:02 dev/
drwxr-xr-x 3 root root 4096 Dec 20 02:02 etc/
drwxr-xr-x 3 root root 4096 Dec 20 02:02 home/
drwxrwxrwt 3 root root 4096 Dec 20 08:44 tmp/
drwxr-xr-x 5 root root 4096 Dec 18 05:14 var/
接下来我要部署一个应用,因为cloudfoundry打包的时候,会把相关编译运行环境,web server都打包,这里没法模拟。先试试行不行,把tomcat扔进去,启服务,看能不能访问。
warden> copy_in --handle 16h7sfkuoa8 --src_path /tmp/nfs_share/apache-tomcat-6.0.36 --dst_path /home/vcap
放在用户vcap下,相信dea_ng结合warden使用时,也是将包扔在vcap下。好了,启动服务:
warden> run --handle 16h7sfkuoa8 --script 'cd /home/vcap/apache-tomcat-6.0.36/bin && sh ./startup.sh'
报错了:
Neither the JAVA_HOME nor the JRE_HOME environment variable is defined
At least one of these environment variable is needed to run this program
意思是说没有tomcat所需要的java环境,这个恰恰说明部署成功了,因为container里确实没有java环境。vm里装了个java环境,也没用。也说明做到资源隔离。
再试下这个:
warden> run --handle 16h7sfkuoa8 --script 'cd ~/apache-tomcat-6.0.36/bin && sh ./startup.sh'
得到的结果一样,又证实了用户用的是这个目录。
=================================================
到这里为止,warden装上了,也可以用。该测试下资源隔离了,这才是warden的核心功能。
cloudfoundry多租户的核心就是资源隔离,假设应用之间没有做到相互隔离,随便一个应用都可以占满cpu,跑满内存,写满磁盘甚至耗尽带宽。那这个PAAS就没法用了。
分为四大块,cpu,memory,disk,bandwidth 。 看源码得知,分别用到了Linux的cgroup 、quota以及tc(traffic control)。
看下warden工程的目录,其中图所示这几个文件就是负责资源隔离与监控的代码了。
cgroup.rb主要是命令行info时读取cgroup中container的memory和cpu信息
mem_limit.rb 是负责配置内存限制,写入cgroup中,并提供oom,就是内存溢出时的行为。
net.rb ,负责container的网络I/O,通过调用 net_rate.sh来配置tc(traffic control)的。
quato.rb,负责container的磁盘份额。
下面会进一步讲到代码。
最常用的就是内存限制了。warden的内存限制与监控,反馈,委托给linux 的cgroup。关于cgroup的概念仅用法参看:http://en.wikipedia.org/wiki/Cgroups
它是control group,就是控制组,是个树形结构,每个root管理着自己下面所有的分支,而且分支共享着root的资源。由各个子系统控制与监控这些组群。最新linux内核(3.2.6)提供了丰富的cgroup
子系统:cpu,cpuset,cpuacct,memory,devices,blkio,net_cls,freezer
cgroup的系统目录位于 /sys/fs/cgroup,可以看到cgroup下有四个子系统:cpu,memory,devices,cpuacct,可能与linux 内核版本有关。内核3.2.0
这一节讲memory,重点看一下memory目录:
-rw-r--r-- 1 root root 0 Dec 21 01:05 cgroup.clone_children
--w--w--w- 1 root root 0 Dec 21 01:05 cgroup.event_control
-rw-r--r-- 1 root root 0 Dec 21 01:05 cgroup.procs
drwxr-xr-x 2 root root 0 Dec 21 01:17 instance-16haaer1lpc/
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.failcnt
--w------- 1 root root 0 Dec 21 01:05 memory.force_empty
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.limit_in_bytes
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.max_usage_in_bytes
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.memsw.failcnt
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.memsw.limit_in_bytes
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.memsw.max_usage_in_bytes
-r--r--r-- 1 root root 0 Dec 21 01:05 memory.memsw.usage_in_bytes
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.move_charge_at_immigrate
-r--r--r-- 1 root root 0 Dec 21 01:05 memory.numa_stat
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.oom_control
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.soft_limit_in_bytes
-r--r--r-- 1 root root 0 Dec 21 01:05 memory.stat
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.swappiness
-r--r--r-- 1 root root 0 Dec 21 01:05 memory.usage_in_bytes
-rw-r--r-- 1 root root 0 Dec 21 01:05 memory.use_hierarchy
-rw-r--r-- 1 root root 0 Dec 21 01:05 notify_on_release
-rw-r--r-- 1 root root 0 Dec 21 01:05 release_agent
-rw-r--r-- 1 root root 0 Dec 21 01:05 tasks
看到一堆文件,前面几个是cgroup的控制文件,然后是instance-16haaer1lpc,新创建的容器,已经加入到memory的控制组群了。后面是一些memory的参数,最后一个tasks,就是存放要监控的进程IDID
重点看两个文件,也是跟warden配置相关的,一个是memory.limit_in_byes,限制最大内存。一个是memory.memsw.limit_in_bytes,连同swap也一起限制。
vagrant@precise64:/sys/fs/cgroup/memory$ cat memory.limit_in_bytes
9223372036854775807
vagrant@precise64:/sys/fs/cgroup/memory$ cat memory.memsw.limit_in_bytes
9223372036854775807
单位是字节,这个值9223372036854775807刚好是long型最大值,所以默认是没有限制的。可以理解为无限大,你可以使用vm上的所有内存资源。
memory目录下的这些参数可以理解为树的root资源,有个分支,就是instance-16haaer1lpc,此目录下的各文件参数与root一样,默认是无限制的。我们可以做个限制。限制两个limit参数。
root@precise64:/sys/fs/cgroup/memory/instance-16haaer1lpc# echo 100M >> memory.limit_in_bytes
root@precise64:/sys/fs/cgroup/memory/instance-16haaer1lpc# cat memory.limit_in_bytes
104857600
会自动转化为字节,这样warden容器16haaer1lpc最大只能用这么大的内存了,memory.memsw.limit_in_bytes一个道理。
我们大概知道了,warden其实是将container委托给cgroup来管理,监控,以及反馈的。 那就是创建container时,warden负责把container挂到cgroup的memory组群的内存树上,这样用户通过warden提供的命令行修改memory时, 也是warden负责修改cgroup组群上的相应container的memory.limit_in_bytes和memory.memsw.limit_in_bytes。具体我们来看一下命令行。
先查下默认的值,一堆memory参数,重点看memory_stat.hierarchical_memory_limit 和 memory_stat.hierarchical_memsw_limit,是不是long最大值9223372036854775807
info --handle 16haaer1lpc
warden> limit_memory --help
command: limit_memory
description: Set or get the memory limit for the container.
usage: limit_memory [options]
[options] can be one of the following:
--handle (string) # required
[--limit_in_bytes (uint64)] # optional
warden> limit_memory --handle 16haaer1lpc --limit_in_bytes 104857600
limit_in_bytes : 104857600
操作前先--help看下用法。现在 info --handle 16haaer1lpc 发现两个值变了。
warden> info --handle 16haaer1lpc
state : active
host_ip : 10.254.0.1
container_ip : 10.254.0.2
container_path : /opt/warden/warden/data/containers/16haaer1lpc
...
memory_stat.hierarchical_memory_limit : 104857600
memory_stat.hierarchical_memsw_limit : 104857600
....
这时候查看 /sys/fs/cgroup/memory/instance-16haaer1lpc 目录下,两个文件的值同时被修改了,说明warden通过命令行,只修改这两个值。
root@precise64:/sys/fs/cgroup/memory/instance-16haaer1lpc# cat memory.limit_in_bytes
104857600
root@precise64:/sys/fs/cgroup/memory/instance-16haaer1lpc# cat memory.memsw.limit_in_bytes
104857600
mem_limit.rb中的do_limit_memory方法有这么两句,就是往cgroup中写值了。
["memory.limit_in_bytes", "memory.memsw.limit_in_bytes"].each do |path|
File.open(File.join(cgroup_path(:memory), path), 'w') do |f|
f.write(request.limit_in_bytes.to_s)
end
end
没有测试过应用,有兴趣的可以测试下,把进程号放进对应的taks文件中就可以。
先抛出一个问题:cpu隔离什么呢。 使用时间? 指定哪一个cpu核? 独占某个cpu? 限制cpu使用比例?
说下几个cgroup的cpu相关子系统的功能:
cpu子系统负责分配进程间的cpu的使用比例
cpuset子系统可以让某个进程使用哪些cpu和内存资源。比如指定8核cpu的哪几核等。
cpuacct子系统统计cpu使用情况。
看看 /sys/fs/cgroup中,只有cpu和cpuacct子系统。可以知道warden起码只用到了这两个子系统。再看看warden命令行的help命令,查看指令发现,哇,没有limit_cpu这一项。没有设置入口。
同时info --handle 16haaer1lpc时,又有cpu的信息。说明:1.无法设置cpu,2.cpu的信息是从cpuacct是取得的。可以查看cgroup.rb中的do_info方法:
def do_info(request, response)
super(request, response)
begin
fields = read_memory_stats
response.memory_stat = Protocol::InfoResponse::MemoryStat.new(fields)
rescue => e
raise WardenError.new("Failed getting memory usage: #{e}")
end
begin
fields = read_cpu_stats
response.cpu_stat = Protocol::InfoResponse::CpuStat.new(fields)
rescue => e
raise WardenError.new("Failed getting cpu stats: #{e}")
end
nil
end
这么说难道cpu没有做到资源隔离,一个无限创建线程的程序就可以跑满cpu。事实是这样的吗?来验证一下:
1. 本地vcap环境,是没有warden的,一跑程序,果然超过cpu 100%。
2. 自己也没架起cf-release集群,扔到cloudfoundry.com上试试。url测试,一会儿就报错了,不像本地,浏览器无限等待。同时在部署在cloundfoundry.com上的其他应用不受影响。
结论:
1. 本地跑满cpu,是因为没有warden,没有container,没有交给cgroup管理。
2. cloudfoundry.com应用了warden,代码里没看到有cpu设置。但貌似可以做到隔离,其他应用不受影响。
简单把container交给cgroup,而不做设置,就可以做到应用之间不相互受影响吗,答案是肯定的,由cgroup的cpu子系统的分配机制相关。刚才提到cpu子系统是负责分配进程间的cpu使用比例。
看下 /sys/fs/cgroup/cpu目录
-rw-r--r-- 1 root root 0 Dec 21 01:05 cgroup.clone_children
--w--w--w- 1 root root 0 Dec 21 01:05 cgroup.event_control
-rw-r--r-- 1 root root 0 Dec 21 01:05 cgroup.procs
-rw-r--r-- 1 root root 0 Dec 21 01:05 cpu.cfs_period_us
-rw-r--r-- 1 root root 0 Dec 21 01:05 cpu.cfs_quota_us
-rw-r--r-- 1 root root 0 Dec 21 01:05 cpu.rt_period_us
-rw-r--r-- 1 root root 0 Dec 21 01:05 cpu.rt_runtime_us
-rw-r--r-- 1 root root 0 Dec 21 01:05 cpu.shares
-r--r--r-- 1 root root 0 Dec 21 01:05 cpu.stat
drwxr-xr-x 2 root root 0 Dec 21 01:17 instance-16haaer1lpc/
-rw-r--r-- 1 root root 0 Dec 21 01:05 notify_on_release
-rw-r--r-- 1 root root 0 Dec 21 01:05 release_agent
-rw-r--r-- 1 root root 0 Dec 21 01:05 tasks
同样有instance-16haaer1lpc这一目录。cpu子系统最重要看cpu.shares。里面的默认值是1024。只是一个值。看instance-16haaer1lpc目录下的cpu.shares,也是1024。
说明目前cpu子系统只管理着一个进程,没人跟你抢。如果再来一个container,可以看到cpu.shares也是1024。那么两个container的cpu.shares的比例就是1:1,他们分别最多可以占用cpu的50%的使用率
如果container继续增加,他们就以同等比例分享cpu资源了。这样就可以做到不影响其他应用。所以cpu资源交给cgroup之后,其实不用做什么配置,所以就可以理解warden没有配置cpu命令的原因了。
接着说磁盘配额,warden使用linux的quota特性来限制磁盘使用量的。quota可以限制硬盘某一分区下用户组或用户的磁盘使用量,并进行监控。关于quota的概念和使用可以上网查查。这里只做简单说明。
命令行查看如何设置disk:
warden> limit_disk --help
command: limit_disk
description: set or get the disk limit for the container.
usage: limit_disk [options]
[options] can be one of the following:
--handle (string) # required
[--block_limit (uint32)] # optional
[--block (uint64)] # optional
[--block_soft (uint64)] # optional
[--block_hard (uint64)] # optional
[--inode_limit (uint32)] # optional
[--inode (uint64)] # optional
[--inode_soft (uint64)] # optional
[--inode_hard (uint64)] # optional
[--byte_limit (uint32)] # optional
[--byte <byte> (uint64)] # optional
[--byte_soft (uint64)] # optional
[--byte_hard (uint64)] # optional
好多可选项,查看quota.rb的do_limit_disk方法,发现quota要设置好多参数,而必选入参其实只有byte_limit。单位是byte
说明下参数:
block是块,就是与byte有个换算关系,所以只需要设置byte_limit,inode我们一般配置不了,也控制不了。 测试一下。 首先查看当前container的磁盘使用量,才16K,其实就是看vcap下的磁盘使用情况。 注意到为什么要ll来查看目录,vcap的用户组是10000,文章刚开始就提到过,这个有说法。quota正是根据用户组来控制磁盘的,不同的container有不同的用户组,再创建一个container,用户组就是10001,往下累加。查看下当前所有用户的磁盘使用情况。
soft值就是超过了有警告,并被要求在一定时间内返回soft值以下,hard就是硬指标,不能超过。一般softroot@precise64:/opt/warden/warden/data/containers/16haaer1lpc/tmp/rootfs/home# ll
total 12
drwxr-xr-x 3 root root 4096 Dec 21 01:17 ./
drwxr-xr-x 6 root root 4096 Dec 21 01:17 ../
drwxr-xr-x 2 10000 10000 4096 Dec 21 01:17 vcap/
root@precise64:/opt/warden/warden/data/containers/16haaer1lpc/tmp/rootfs/home# cd vcap
root@precise64:/opt/warden/warden/data/containers/16haaer1lpc/tmp/rootfs/home/vcap# du -sh
16K .
/dev/mapper/precise64-root 分区下所有用户的磁盘使用情况。值为0说明没有限制。看到10000用户使用了264M,没有限制最大值。
warden>limit_disk --handle 16haaer1lpc 102457600
设置100M 然后再查看 repquota -auvs。接着copy_in一个大于100m的文件,就会报错。这里就不再演示了。
命令行设置会调用net.rb的do_limit_bandwidth方法。
def do_limit_bandwidth(request, response)
sh File.join(container_path, "net_rate.sh"), :env => {
"BURST" => request.burst,
"RATE" => request.rate * 8, # Bytes to bits
}
response.rate = request.rate
response.burst = request.burst
end
它调用net_rate.sh ,传入RATE和BURST参数。
看下net_rate.sh
# clear rule if exist
# delete root egress tc qdisc
tc qdisc del dev ${network_host_iface} root 2> /dev/null || true
# delete root ingress tc qdisc
tc qdisc del dev ${network_host_iface} ingress 2> /dev/null || true
# set inbound(outside -> eth0 -> w--0 -> w--1) rule with tc's tbf(token bucket filter) qdisc
# rate is the bandwidth
# burst is the burst size
# latency is the maxium time the packet wait to enqueue while no token left
tc qdisc add dev ${network_host_iface} root tbf rate ${RATE}bit burst ${BURST} latency 25ms
# set outbound(w--1 -> w--0 -> eth0 -> outside) rule
tc qdisc add dev ${network_host_iface} ingress handle ffff:
# use u32 filter with target(0.0.0.0) mask (0) to filter all the ingress packets
tc filter add dev ${network_host_iface} parent ffff: protocol ip prio 1 u32 match ip src 0.0.0.0/0 police rate ${RATE}bit burst ${BURST} drop flowid :1
大概意思是先删掉先前的设置,再创建新的,利用tc 的 tbf 过滤器,就是令牌桶。RATE指定速率,BURST 指定了最大能有多少个桶。tc就是监控create container时创建的虚拟网卡。
每个输入输出数据都要经过这一tc 队列,每个请求数据通过一个桶,桶的速率是rate。最大有burst/rate个桶。可以允许超过burst限制,但不能太多。
大概就是这个意思,详细tc可以上网查查。
而warden的实现是集成了cgroup,quota以及tc(traffic control) ,分别控制cpu,mem,disk以及网络I/O。