文章归档

netfilter + cgroup实现容器的带宽隔离

我们知道内核提供了一种机制,我们可以通过编写netfilter内核模块来实现对tcp数据包的处理,iptables的原理亦是如此:

那么,通过这种方案,能否实现进程的带宽控制呢?答案是肯定的。带宽控制的目的就是要隔离不同容器的网络需求,避免一个容器因为占用过多的网络带宽导致另一个容器饿死的现象。

尤其是在线离线混部的情况下,如果离线作业占用了过多的带宽资源,就会影响到在线服务的可用性。

实现方案如下:

  1. 扩展一个cgroup模块,或者实现一个新的cgroup子系统
  2. cgroup子系统在初始化的时候,注册netfilter钩子函数,截获所有的数据包
  3. 网络传输出发钩子函数,找到数据包所在的进程pid,找到pid相应的cgroup控制组,从而得到当前进程所在控制组的网络配额
  4. 使用类似与滑动窗口思想的算法实现带宽的限制

但是需要注意以下几个问题:

软限/硬限/整机阈值

对于每一个数据包,先检查是否到达软限,如果还没达到,则允许数据包通过。否则继续检查是否达到硬限,如果超过了硬限,则丢弃数据包。但是如果超过了软限,但是还没有超过硬限,怎么办?仍然需要判断单击带宽的物理阈值是多少。不能超过整机的网络带宽。

注意一旦超过了整机的阈值带宽,一定要先于网卡之前丢包,因为网卡无法区分此数据包是哪个容器的,超出负载后一律丢包。极端情况下:网卡丢的总是被抢占的一方的带宽资源

但是如果我们在netfilter钩子函数里判断以下当前整机带宽是否打满,提前丢包,就可以避免这种情况。

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>