kubernetes集群pod使用tc进行网络资源限额
Docker容器可以实现CPU,内存,磁盘的IO限额,但是没有实现网络IO的限额。主要原因是在实际使用中,构建的网络环境是往超级复杂的大型网络。这样的网络机构,如何管理每一个容器的带宽本身就是一个挑战,对一台主机来说,你已经限制了带宽,然后你想更细颗粒度的管理里面的容器带宽,而且容器的种类特别多,而且不能一刀切解决的,所以这是非常大的挑战。所以Docker没有实现网络资源的限制,把这部分工作交给第三方工具实现。
但是在实际的使用过程中,对网络带宽要求不一样的容器进行网络带宽的限额是非常由必要的。本文就是根据此目标进行的一些调研和实践的总结。
一. kubernetes集群docker容器cpu,内存资源限额介绍
因docker容器中用cgroup实现了cpu,内存等资源的限额,所以最开始考虑能不能通过cgroup对容器的网络资源进行限额。
Linux CGroup全称Linux Control Group, 是Linux内核的一个功能,用来限制,控制与分离一个进程组群的资源(如CPU、内存、磁盘输入输出等)。这个项目最早是由Google的工程师在2006年发起(主要是Paul Menage和Rohit Seth),最早的名称为进程容器(process containers)。在2007年时,因为在Linux内核中,容器这个名词太过广泛,为避免混乱,被重命名为cgroup,并且被合并到2.6.24版的内核中去。然后,其它开始了他的发展。
cgroup主要提供了如下功能:
Resource limitation: 限制资源使用,比如内存使用上限以及文件系统的缓存限制。
Prioritization: 优先级控制,比如:CPU利用和磁盘IO吞吐。
Accounting: 一些审计或一些统计,主要目的是为了计费。
Control: 挂起进程,恢复执行进程。
cgroup实现成了一个file system,你可以mount。在我的Ubuntu 14.04下,你输入以下命令你就可以看到cgroup已为你mount好了
wade@wade-ThinkCentre-E73:~$ mount -t cgroup
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,relatime,cpuset)
cgroup on /sys/fs/cgroup/cpu type cgroup (rw,relatime,cpu)
cgroup on /sys/fs/cgroup/cpuacct type cgroup (rw,relatime,cpuacct)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,relatime,memory)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,relatime,devices)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,relatime,freezer)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,relatime,net_cls)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,relatime,blkio)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,relatime,perf_event)
cgroup on /sys/fs/cgroup/net_prio type cgroup (rw,relatime,net_prio)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,relatime,hugetlb)
systemd on /sys/fs/cgroup/systemd type cgroup (rw,noexec,nosuid,nodev,none,name=systemd)
你可以到/sys/fs/cgroup的各个子目录下去make个dir,你会发现,一旦你创建了一个子目录,这个子目录里又有很多文件了。
先来看看control group有哪些子系统:
blkio — 这个子系统为块设备设定输入/输出限制,比如物理设备(磁盘,固态硬盘,USB 等等)。
cpu — 这个子系统使用调度程序提供对 CPU 的 cgroup 任务访问。
cpuacct — 这个子系统自动生成 cgroup 中任务所使用的 CPU 报告。
cpuset — 这个子系统为 cgroup 中的任务分配独立 CPU(在多核系统)和内存节点。
devices — 这个子系统可允许或者拒绝 cgroup 中的任务访问设备。
freezer — 这个子系统挂起或者恢复 cgroup 中的任务。
memory — 这个子系统设定 cgroup 中任务使用的内存限制,并自动生成内存资源使用报告。
net_cls — 这个子系统使用等级识别符(classid)标记网络数据包,可允许 Linux 流量控制程序(tc)识别从具体 cgroup 中生成的数据包。
net_prio — 这个子系统用来设计网络流量的优先级
hugetlb — 这个子系统主要针对于HugeTLB系统进行限制,这是一个大页文件系统。
二. cgroup+tc对网络带宽限额尝试
可以查看到net_cls子系统包含了docker目录,并且docker目录下面是个容器的id,各个容器目录下面task文件已经包含了该docker容器的所有进程ID。
wade@wade-ThinkCentre-E73:/sys/fs/cgroup/net_cls$ ll
总用量 0
dr-xr-xr-x 4 root root 0 8月 30 10:25 ./
drwxr-xr-x 14 root root 280 8月 30 10:25 ../
-rw-r--r-- 1 root root 0 8月 30 14:24 cgroup.clone_children
-rw-r--r-- 1 root root 0 8月 30 14:24 cgroup.procs
-r--r--r-- 1 root root 0 8月 30 14:24 cgroup.sane_behavior
drwxr-xr-x 22 root root 0 8月 30 10:34 docker/
-rw-r--r-- 1 root root 0 8月 30 14:24 net_cls.classid
-rw-r--r-- 1 root root 0 8月 30 14:24 notify_on_release
-rw-r--r-- 1 root root 0 8月 30 14:24 release_agent
-rw-r--r-- 1 root root 0 8月 30 14:24 tasks
drwxr-xr-x 3 root root 0 8月 30 10:25 user/
所以首先想到是是否可以通过cgroup+tc实现容器网络的限额。
首先用tc工具对eth0进行htb算法的限额,并用cgroup进行流量的分类
tc qdisc del dev eth0 root
tc qdisc add dev eth0 root handle 1: htb
tc class add dev eth0 parent 1: classid 1: htb rate 1000mbit ceil 1000mbit
tc class add dev eth0 parent 1: classid 1:3 htb rate 10mbit
tc class add dev eth0 parent 1: classid 1:4 htb rate 10kbit
tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 1: cgroup
把相应分类写入要限额容器的net_cls.classid中
echo '0x10004' > /cgroup/net_cls/docker/id/net_cls.classid
最后进行实验的时候发现完全没有达到网络限额的效果。
然后同理对docker0进行限额。最后实验发现对所有的容器的网络进行了限额。不能对单个容器实现限额。
而容器默认使用veth方式创建虚拟机网络的,veth就是要把从一个网络用户空间(network namespace )发出的数据包转发到另一个用户空间。veth 设备是成对的(veth pair),一个是容器之中,另一个在容器之外,即在真实机器上能看到的。在容器内部看到的是eth0,容器外部就是一个veth device绑定到docker0虚拟网桥上. 因此设置在eth0上的限制,以及对于包的标记是都不管用的。
三. tc对veth限额实现kubernetes中pod级别的网络限额
kubernetes中每个pod对应一个veth
1.首先需要找到kubernetes中pod对应的vethname。
#!/bin/bash
#filename:getveth.sh
#author:wade
container_name=$1
if [ -z $1 ] ; then
echo "Usage: ./getveth.sh container_name"
exit 1
fi
if [ `docker inspect -f "{{.State.Pid}}" ${container_name} &>>/dev/null && echo 0 || echo 1` -eq 1 ];then
echo "no this container:${container_name}"
exit 1
fi
pid=`docker inspect -f "{{.State.Pid}}" ${container_name}`
mkdir -p /var/run/netns
ln -sf /proc/$pid/ns/net "/var/run/netns/${container_name}"
index=`ip netns exec "${container_name}" ip link show eth0 | head -n1 | sed s/:.*//`
let index=index+1
vethname=`ip link show | grep "^${index}:" | sed "s/${index}: (.*):.*/1/"`
echo $vethname
rm -f "/var/run/netns/${container_name}"
docker容器下载流量限额
在node节点上用tc设置对应veth的流量带宽
tc qdisc add dev vethname root tbf rate 10mbit latency 50ms burst 10000 mpu 64 mtu 15000
docker容器上传流量限额
在容器内使用tc设置eth0设备的流量带宽
(注意:因为要配置容器的网络设备eth0,所以kubelet,kube-apiserver的启动时候需要添加--allow-privileged=true 参数,或者pod的yaml文件中spec.containers[0].securityContext.privileged:true)
tc qdisc add dev eth0 root tbf rate 10mbit latency 50ms burst 10000 mpu 64 mtu 15000
通过测试发现实现了kubernetes中pod的网络带宽限额。
四. 若有朋友的docker网络没有使用默认bridge,而是绑定了openvswitch的bridge,并使用pipework提供网络,可以通过openvswitch基于port来进行网络资源的限制。
详细请移步以下链接
http://dl528888.blog.51cto.com/2382721/1641569
---------------------
作者:ptmozhu
来源:CSDN
原文:https://blog.csdn.net/ptmozhu/article/details/52368681
版权声明:本文为博主原创文章,转载请附上博文链接!