Iron: Isolating Network-based CPU in Container Environments

论文链接

容器共享底层操作系统(OS)的组件,所以OS为容器分配的资源(如CPU、磁盘、网络带宽和内存)提供资源隔离至关重要。目前,Linux中的cgroups通过在内核中分配、计量和实施资源使用来实现资源隔离。

1 问题

容器在发送或接收网络流量时可以利用比各自的cgroup分配的更多的CPU,从而有效地打破隔离: 处理中断所花费的时间通常不会被计算到容器发送或接收通信流上。

1.1 软中断的处理开销

  • 软件中断在硬件中断处理结束时或内核重新启用softirq处理时被进行检查。软件中断在进程上下文中运行。也就是说,无论哪个不幸的进程正在运行,都必须使用它的预定时间来服务softirq。在这里,当一个容器必须使用自己的CPU时间来处理另一个容器的流量时,隔离就会打破。

  • 内核试图通过限制softirq处理程序运行一段固定的时间或预算的数据包数量来最小化进程上下文中的softirq处理。当超出预算时,softirq停止执行,并计划运行ksoftirqd。Ksoftirqd是一个内核线程(它不在进程上下文中运行),为剩余的softirqs服务。每个处理器有一个ksoftirqd线程。因为ksoftirqd是一个内核线程,所以它处理数据包的时间不会计入任何容器。这通过限制调度其他容器的可用时间或允许用尽其组配额的容器获得更多处理资源来打破隔离。

1.2 收发消息情况分析

  • 数据包从其套接字穿过内核到达网卡,是在进程上下文中执行的,因此发送数据包所花费的时间被计入正确的容器中(和上文冲突),但有两种情况,隔离会被Break:

    • 当网卡完成数据包传输时,它会安排一个中断来释放数据包资源。这项工作是在softirq context完成的,因此可能会向没有发送流量的容器收费

    • 数据包在进程上下文中从套接字被带到缓冲区。然而,在缓冲数据包时,内核系统调用退出。然后,软件中断负责将数据包从缓冲区中取出,并将其移至网络堆栈中。

  • 接收数据包比发送数据包会产生更高的softirq开销。数据包从驱动程序的环形缓冲区一直移动到softirq上下文中的应用程序套接字。这种遍历可能需要与多个协议处理器(例如,IP、TCP)、NFVs、网卡卸载(例如GRO )接口,或者甚至发送新的数据包(例如,TCP ack或ICMP消息)。总之,整个接收链是在softirq context中执行的,因此可能有相当长的时间没有计入正确的容器。

研究人员已经开发了隔离CPU和网络带宽的方案``todo`。但隔离基于网络的处理的研究非常有限

2 贡献

Iron实现了一组细内核检测工具,集成了Linux cgroup调度器,在维持保持内核中中断处理的效率和响应性,获得细粒度的处理数据包的成本,来为容器的流量收费,并实现了一种基于硬件的丢包机制,将数据包丢弃到已耗尽其分配的容器中。

2.1 现有方案的不足

Iron’s contributions are put in context.

  • Resource containers:通过一个特殊的活形成一个抽象,捕获、计费系统资源;当一个进程被调度时,一个接收系统调用延迟调用内核中的协议处理,因此处理数据包所花费的时间被正确地计入一个进程。但是很低效,因为要给每个接受进程分配一个per-socket线程。

    所以Iron遵循softirq handler集中处理所有进程中断的原则,旨在减小带来的额外开销(尤其是上述的多线程)和复杂性

  • Redesigning the OS:一些系统库将网络协议处理转移到用户态,包处理直接从网卡copy到application,这样就可以直接计费了;但这同样会带来额外开销,并且会让用户使用门槛变高,管理难度加大;

2.2 实验:网络拥塞带来的影响

引入惩罚因子这个概念,通过一些数据证明现象的存在

3 设计

基本思路:计算在softirq context中处理数据包所花费的时间。在获得包成本后,Iron与Linux调度程序集成,为softirq处理对容器进行计费。当容器的运行时间耗尽时,Iron通过限制容器并通过基于硬件的方法丢弃传入的数据包来实施强化隔离。

3.1 计费方案

如何计费以及将数据包分配给容器,并描述了用于计费的状态

3.1.1 接收端

接收数据的时候,堆栈中低层的会嵌套调用堆栈高层的函数,可以通过从堆栈中低层的接收函数结束时间中减去函数开始时间来获得处理数据包所花费的时间。

Iron使用 netif_receive_skb获取每个包成本,它是第一个在驱动程序之外处理单个数据包的功能,与传输协议无关。获取时间差并不是准确的,因为内核是可抢占的,调用树中的函数可以随时中断。

为了确保只捕获处理数据包所花费的时间,Iron依赖于调度程序数据。调度器保存线程已经运行的累计执行时间(cumtime),以及线程最后被换入的时间(swaptime),结合本地时钟(now),开始和结束时间可以计算为:time = cumtime+(now-swaptime)。此外,进入处理硬件中断(do_IRQ)的函数、处理softirqs和执行skb垃圾收集都有开销,这些开销被集中在一起,并以加权的方式分配:

在Linux中,由softirq处理程序(do softirq)处理六种类型的soft_IRQ:HI、TX、RX、TIMER、SCSI和TASKLET。对于每个中断,我们获得总的do_IRQ成本,表示为​;以及处理每个特定softirq的成本(表示为​等)。注意软件中断是在硬件中断结束时处理的,所以​ ,与处理中断相关的开销定义为:​,该中断内recv overhead的公平份额为​ 。最后,​在给定do softirq调用中处理的数据包之间平均分配,以获得添加到每个数据包的固定费用。

3.1.2 发送端

与接收器类似,使用net_tx_action操作获得发送批处理的开始和结束时间,然后平均分配到每个包。而固定开销​也会平均分配。开销是按每个内核计算的。

3.1.3 映射到容器

Iron必须识别一个包所属的容器。在sender,当一个skb在qdisc层排队时,它与它的cgroup相关联。在接收器上,Iron维护一个IP地址hashtable,在将数据包复制到套接字时填充该hashtable。

此外,每个进程都维护一个在softirq context中处理的数据包的列表及其各自的开销(每个内核)。每个进程的结构最终被合并成一个全局的per-cgroup的结构。Iron在调度器获得全局锁时合并状态(减少了新建锁的开销),每个cgroup结构维护一个变量(​),该变量指示一个cgroup是否应该被记入网络处理。

3.2 隔离方案

通过将计费数据与Linux的CFS(完全公平调度器)中的CPU分配 集成,并在容器受到限制时丢弃数据包来实现的。

3.2.1 集成scheduler

scheduler 通过一个混合方案来实现Cgroup的CPU分配,该方案同时保持local(即每个核)和globle状态:容器被允许在一段​内运行给定的​。scheduler通过在细粒度级别更新local state和在粗粒度级别更新globle state来最小化锁定开销。

  • 在globle level,​在一个CPU周期开始时被设置为​。scheduler从​中减去一个​,并将其分配给一个核。​逐渐递减,直到=0或周期结束。无论如何,在一个周期结束时,​会被重新填充到配额​。

  • 在local level,从全局​中提取的​分配给一个​变量。scheduler会随着cgroup占用CPU而减少​,当​为零时,scheduler会试图从全局poo中获取一个​,如果不够了,就等下一个周期

3.2.1.1 globle level填充run_time

Iron:周期结束时的全局​补充算法

1: if gained > 0 then
2:   runtime ← runtime + gained
3:   gained ← 0
4: end if
5: if cgroup_idled() and runtime > 0 then  
6:   runtime ← 0
7: end if
8: runtime ← quota + runtime
9: set_timer(now + period)</pre>
  • 1-4行:在Iron中,一个全局变量​跟踪一个容器应该拿回的时间(也就是它用来处理了另一个容器的softirqs);

  • 5-7行:如果容器受到其需求的限制没有使用其先前的分配,也就是处于idle状态(空闲状态),那么需要额外补给​的份额置零(保留CFS策略,该策略不允许累积未使用的周期用于后续周期。)

  • 8-9行:分配的​来填充​并更新时间

3.2.1.2 local level填充rt_remain

Iron:re_remain<0时触发的向globle runtime请求算法

1: amount ← 0
2: min_amount ← slice - rt_remain
3: if cpuusage > 0 then
4:   if cpuusage > gained then
5:           runtime ← runtime - (cpuusage - gained)
6:           gained ← 0
7:   else
8:           gained ← gained - cpuusage
9:   end if
10: else
11:  gained ← gained + abs(cpuusage)
12: end if
13: cpuusage ← 0
14: if runtime = 0 and gained > 0 then
15:      refill ← min(min_amount, gained)
16:      runtime ← refill
17:      gained ← gained - refill
18: end if
19: if runtime > 0 then
20:      amount ← min(runtime, min_amount)
21:      runtime ← runtime - amount
22: end if
23: rt_remain ← rt_remain + amount</pre>

引入​变量是为了维护local level计费:

  • 2-9:>0表示容器需要为未计算的网络周期付费

  • 10-12:<0表示容器可以拿回被别的容器占用的资源

  • 14-18:globle runtime耗尽但是有gained可以填充runtime

  • 19-22:正常的run_time分配

3.2.2 丢包减少影响

丢弃receiver端多余的数据包更为重要,因为受限制的reciver可能会继续接收流量,从而破坏隔离。

现代系统用NAPI管理网络中断。收到新数据包后,NAPI会禁用硬件中断,并通知OS用轮询方法来检索数据包。同时,网卡将额外接收的包简单地放入环形缓冲区。当内核轮询网卡时,它会从环形缓冲区中删除尽可能多的数据包。当移除的数据包数量少于预算时,NAPI轮询退出,中断驱动接收恢复。

基于硬件的丢包的工作原理如下

  • 假设网卡每个容器有一个队列。Iron使用从队列到其容器(即cgroup)的映射来扩展NAPI队列结构。

  • 当调度程序限制一个容器时,它会修改任务组中的一个布尔值。

  • 不同于原生NAPI,Iron不会从容器被限制的队列中轮询数据包。

    • 从内核的角度来看,队列是从轮询列表中剥离出来的,这样它就不会不断地被重新填充。

    • 从网卡的角度来看,内核不会轮询队列中的数据包,因此它会保持轮询模式,并保持硬件中断禁用。

  • 如果收到新的数据包,只需将它们插入环形缓冲区。这种技术有效地减轻了接收开销,因为内核不会被中断或者被要求代表节流容器做任何工作。当调度程序释放一个容器时,它重置它的布尔值,并调度一个softirq来处理可能在排队的数据包。

此外还有一个轻微的优化,Iron还可以在容器被限制之前丢弃数据包。也就是说,如果一个容器正在接收大量流量,并且该容器在其配额的​%以内,则可以丢包。这允许容器使用一些剩余的运行时间来阻止大量的传入数据包。

Iron可以为每个内核分配固定数量的队列,然后将有问题的容器动态映射到自己的队列中。而对于没有过重流量负担的容器可以通过使用一种通过实现__netif_receive_skb来基于软件的丢包。这种动态分配方案从SENIC中得到启发,SENIC使用类似的方法来调整基于网卡的速率限制器。或者,可以根据预先购买的带宽分配将容器映射到队列。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容