Confluo: Distributed Monitoring and Diagnosis Stack for High-speed Networks

主要是在end-host对10Gbps以上的telemetry data的收集增加支持。

Programmable switches收集丰富的telemetry data,并将它们embed在packet headers里面。 为了收集这些packet header并使用它们监控和诊断,我们需要能支持以下三个需求的en-host stacks。

  • monitoring of rich telemetry data
  • low-overhead diagnosis
  • highly-concurrent low-overhead read-write operations

Confluo Overview

Motivation

现有的end-host stack并不能够同时满足上面提出的三个功能。但是实现这三个目标面临着两个挑战

  • Challenges with larger network bandwidth: 现有的end-host stack不足以支持10Gbps的数据包处理速度
  • Challenges with monitoring rich telemetry data: 上述streaming和时间序列数据处理系统的局限性促使定制设计的end-host monitoring stack。这些系统要么通过放弃在线监测(如FloSIS),要么通过仅对流量中的第一个数据包应用过滤器(如Trumpet)来实现如此高的性能。这些系统不再支持rich telemetry data。

Confluo Interface

Confluo对数据包头进行操作,每个头都与一些属性相关联,这些属性可能是协议特定的(例如,TCP头中的属性,如srcIP、dstIP、rwnd、ttl、seq、dup)或自定义定义的(例如,数据包轨迹,或队列长度、时间戳等)。 Confluo不要求数据包头是固定的;每个头可以包含任意数量的字段,而且每个数据包的字段数量可以不同。

Confluo使用类似于[8, 23]的匹配动作语言,有三个要素:过滤器、聚合和触发器。 过滤器是一个由关系和布尔运算符组成的表达式fExpression,覆盖任意的header属性子集,并识别与fExpression匹配的标题。 聚合是在一个属性上评估一个可计算的函数(表2),用于所有符合某个过滤器表达式的header。 最后,一个触发器是一个布尔条件(例如,<,>,=,等等),在一个聚合上进行评估。

Confluo Design Overview

Confluo包括一个central coordinator interface和每个end-host上都有的end-host module。

Coordinator Interface

Confluo的协调器接口通过将监测责任划分给Confluo的各个终端主机模块,并将各个模块的诊断信息提供给网络运营商,来降低对全网事件的监测和诊断。 操作员将由Confluo API调用组成的控制程序提交给协调器,协调器反过来联系相关的终端主机模块,并通过RPC协调Confluo API调用的执行。 协调器API还允许获得分布在终端主机上的遥测数据的分布式原子快照(§4)。

End-host Module

Confluo在hypervisor里面捕捉并且监测数据包。 并使用software switch在NICs和VMs之间传递数据包。 一个mirroring module负责把数据包头镜像到spray module里面。 spray module负责把这些headers写入多个ring buffers中的一个ring buffer里面。 Confluo currently uses DPDK to bypass the kernel stack, and Open vSwitch to implement the mirror and spray modules.

Confluo目前有两个重要的架构设计选择:

  1. 使用多个ring buffers来方便可能的multiple cores processing different packet streams。同时支持多个高速并行的Confluo Wirter对同一个Confluo Data Structures的写入
  2. 将从Atomic MultiLogs "读 "和 "写 "的线程分开。具体来说,Confluo中的读线程实现了监控功能和即时诊断功能。另一方面,写线程就是上述的Confluo writer。这一架构决定是由两个目标驱动的。
    1. 虽然分离读和写线程一般会导致更多的并发问题,但Atomic MultiLog提供了低开销的机制来实现高度一致的读和写。
    2. 分离读写线程也需要稍高的CPU开销(在我们的评估中,即使每个数据包有1000个触发器,也不到4%);然而,这是实现即时诊断的一个很好的权衡,因为当需要执行复杂的临时过滤器时,在一个线程中交错的读写可能导致数据包丢失(§3)。

Confluo可以保证所有与单个头相对应的读/写操作对应用程序来说都是原子化的。 然而,由于一些原因(例如,在数据包捕获期间,网卡上的队列长度不同,随机的CPU调度延迟等),在Atomic MultiLogs上可见的数据包的排序可能不一定与网卡上收到的数据包的排序相同。 克服这个问题的一个简单方法是使用入口/出口网卡的时间戳来排列Atomic MultiLog中的更新,以反映网卡上收到的数据包的顺序; 几乎所有当前的10Gbps及以上的网卡都支持线速的入口和出口数据包时间戳。

Distributed Diagnosis

使用分布在多个终端主机上的遥测数据进行诊断会导致分布式系统的经典一致性问题--除非所有记录(在我们的例子中是数据包)都经过一个中央排序器,否则不可能实现对系统状态的绝对完美观察。 Confluo并不试图解决这个经典问题,而是表明通过利用遥测数据的特性,有可能将经典的分布式原子快照算法简化为一个非常低开销的算法(§4)。

Confluo Design

Background

介绍了两个概念

  • Atomic Hardware Primitives:现代大部分CPU都支持一些类似的指令
  • Concurrent Logs:很多高效、无锁的并发日志都利用append-only nature来实现高吞吐写。这些日志系统都维护一个writeTail。每个新增加的操作都增加writeTail,然后再写入日志。使用上述的原子硬件操作能够很方便地对writeTail进行修改,

Atomic MultiLog

基于这两个基本的properties

  • Property 1: Packet headers, once processed by the stack, are not updated and only aggregated over long time scales.
  • Property 2: Each packet header attribute has a fixed size (number of bits used to represent the attribute)

HeaderLog

这个并发的append-only的日志存储了Confluo中所有捕获的数据包头的原始数据。 HeaderLog中的每个数据包头都有一个偏移量,它被用作Atomic MultiLog中所有数据结构中对数据包的唯一引用。

IndexLog

Atomic MultiLog为每个indexed packet attribute(如srcIP、dstPort)存储一个IndexLog,它将每个独特的属性值(如srcIP=10.0.0.1或dstPort=80)映射到Header-Log中的相应数据包头。 IndexLogs利用两个main ideas有效地支持并发的、无锁的输入和查找。

数据包头中协议定义的固定属性宽度允许IndexLogs使用完美的k-ary树在新数据到达时进行高吞吐量的插入。 使用完美的k-ary树大大简化了写入路径。 一个k-ary树节点中的所有子指针最初都指向NULL。

当一个新的数据包属性值(例如,srcIP=10.0.0.1)被索引时,沿着属性值对应的路径的所有未分配的节点都被分配。 这就是IndexLog使用第二个想法的地方-- 因为工作负载是append-only的,所以属性值到数据包头映射的HeaderLog偏移量也是append-only的; 因此,传统的无锁并发日志可以用来在k-ary树的叶子上存储这种映射关系。

并发属性索引节点和日志分配之间的冲突使用CompareAndSwap指令来解决,从而减轻了对锁的需求。具有相同属性值的后续数据包头的索引是通过穿越树到相关的叶子,并将数据包头的偏移量附加到日志上。为了评估对索引的范围查询,Confluo确定了与属性范围相对应的子树(例如10.0.0.0/24);然后,最终结果是子树叶中的日志的头偏移量的联合。

FilterLog

FilterLog是一个简单的过滤表达式(例如,srcIP==10.0.0.1 && dstPort==80),以及一个以时间为索引的日志集合,存储对符合表达式的头的引用(按照用户指定的时间间隔分桶)。 对应于不同时间间隔的日志使用完美的k-ary树进行索引,类似于IndexLogs。

AggregateLog

与FilterLogs类似,AggregateLog采用完美的k-ary树来索引在用户指定的时间段内与过滤器表达式相匹配的总量(例如SUM(pktSize))。 然而,对聚集值的原子更新稍有挑战性--它需要读取最新的版本,对其进行修改,并将其写回。为聚合体维护一个并发的日志需要处理复杂的竞赛条件以保证原子性。 Confluo则维护了一个线程本地日志的集合,每个写作者线程都在自己的聚合日志上执行读取-修改-写入操作。集合的最新版本是通过合并各个日志的最新线程-本地集合值获得的。 我们注意到,线程本地日志的使用限制了聚合的关联性和交换性操作,这足以实现网络工作的监控和诊断功能。

Atomic Operations on Collection of Logs

End-to-end Atomic MultiLog operations可能需要updating multiple logs across HeaderLog, IndexLogs and FilterLogs。 即使单个日志支持原子操作,端到端的原子多日志操作在默认情况下也不能保证是原子的。幸运的是,可以扩展并发日志的读尾/写尾机制,以保证原子多日志操作的原子性;然而,这需要解决两个难题。

首先,为了保证Atomic MultiLog操作的总顺序,其组件日志必须同意一个排序方案。 第二个挑战是保持Confluo聚合操作的原子性,因为它们与位于globalReadTail之内或之外的任何单个数据包头没有关联。

具体操作比较复杂,具体看文章。

虽然上述操作使原子多日志操作实现了端到端的原子性,但我们注意到,原子多日志中每个单独的日志的readTail的更新可能会增加一个非显著的开销(图6)。

Monitro & Diagnoser Modules

Monitor Module

这个模块负责通过一个专门的监控线程对Confluo触发器进行在线评估。

Diagnoser Module

Confluo的诊断器模块对Atomic MultiLog捕获的数据包头进行特别查询。 从表1可以看出,Confluo允许诊断查询提供一个过滤器表达式fExpression和一个时间范围。

Archival Module

Distributed Diagnosis