您的位置:首页 > 理论基础 > 计算机网络

kubernetes集群pod使用tc进行网络资源限额

2016-08-30 13:59 881 查看
       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-
4000
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息