关闭
当前位置:首页 - 国际国内新闻 - 正文

陆星材,怎么根据 Cilium 和 eBPF 打造可感知微服务的 Linux?-90后的空间,分享成长故事,有趣新闻发布

admin 2020-03-28 135°c

今日在这儿给咱们介绍 BPF(Berkeley Packet Filter),以及怎样依据 BPF 将 Linux 打 形成一个可感知微服务的操作体系。

在这次同享中,我将评论以下内容:

运用运转方法的演进 :

最早的年代是单任务年代。每个进程具有对机器的全部权限。我对这个年代没什么了解, 我仍是太年青了。
然后多任务年代,多个 CPU 分给不同进程运用,开端有了 MMU、虚拟内存等概念。Linux 便是从这个时分开端起飞的。你需求运申东旭行一个 Linux 发行版,办理运用的依靠。一个服务器上全部的运用会同享一些库,你需求确保库的版别的正确性。多任务年代仍是在物理服务器上跑运用的。
再之后,咱们就进入了虚拟化年代。突然间,全部的东西都开端跑在虚拟机内部。咱们将运用和操作体系打包到一同,基本上,每个运用都能够跑在不同的操作体系上,而你能够将这 些运用运转在同一台物理服务器(宿主机)上。然后咱们开端虚拟硬件,许多名词前面都开端加上 “虚拟”(“v”),例如虚拟交换机、虚拟网桥、虚拟设备。全部东西都变成了软件界说的。女同志本质上,这些都是曾经硬件上的功用,咱们用软件重做了 一遍,运转在虚拟机内部。
现在,咱们正在进入微服务和容器年代。本质上,咱们正在从头回到将运用跑在宿主机上的年代:咱们将不同运用直接跑在宿主机操作体系上,不再是每个运用一个虚拟机。这些运用需求通过宿主机操作体系、容器、Namespace等进行阻隔和资源办理,后面会介绍这些内容。
这对操作体系需求供给什么功用产生了巨大的影响。不再是“喔,我需求将网络包转发给 这个虚拟机。我需求做一些防火墙作业”。咱们实在需求考虑的是运用。相同的,这是一个 巨大的改变。这和单任务到多任务的改变还不相同。突然间,咱们开端有一些只会继续几 十秒的运用,这导致彻底不同的需求。别的,还有多租户体系,以及其他十分不同的场景。


微服务年代 Linux 内核的问题:

在这种状况下,Linux 内核有哪些问题?明显,它不是为这个年代规划的。

问题一:笼统

软件开发者都喜爱笼统。上面这张图仅仅网络相关的笼统,但它清楚地展现了 Linux 卤鸡爪的做法内核里 的笼统长什么姿态。假如咱们想用 Netfilter 做包过滤,那就必需求通过 socket 和 TCP协议栈。而假如从网卡往上看的话,包得通过网络设备笼统层、流量整形(Traffic shaping)、以太网层、IP 层等等才干抵达运用。上下都需求阅历协议栈。 
1.用户空间 API 强兼容性:例如,20 年前编译的可履行文件现在依然能作业。这太奇特了,十分巨大
2.使大部分内核代码不依靠硬件:我现已(作为内核开发者)作业 15 年了,但从来没写过一个驱动程序。我对硬件所知甚少(have no clue about hardware),但我写过许多底层代码(low level code),例如 IP、路由和防火墙相关的。关于实在的硬件, 我简直没有什么了解

1.巨大的功用开支(massive performance overhead):接下来咱们会看到为什么会 有这些功用开支,以及怎样处理这个问题
2.很难绕过(bypass)这些层:虽然有一些场景能够做到 bypass,但大部分都是 bypass 不掉的

问题二:每个子体系都有自己的API

这张图展现的是网络相关的(子体系),但关于存储和其他体系,问题都是相似的。我在图中列出了对这些子体系进行操作所需的东西。例如:
-装备以太网驱动或许网络设备需求运用 ethtool 指令
-装备路由运用 IP 指令
-装备过滤运用 seccom 指令
-装备 I超维大领主P 防火墙运用 iptables 指令,但假如你运用的是raw sockets,那有许多当地都会bypass,因而这并不是一个完好的防火墙
-装备流量整形运用 tc 指令
-抓包运用 tcpdump 指令,但相同的,它并没有展现出悉数信息, 由于宫宇灿它只重视了一层
-假如有虚拟交换机,那运用 brctl 或 ovsctl
所以咱们看到,每个子体系都有自己的 API,这意味着假如要自动化这些东西,有必要独自的 运用这些东西。有一些东西这样做了,但这种方法意味着咱们需求了解其间的每一层。

问题三:开发进程

假如你需求改动 Linux 内核,那这项作业将是十分困难的。 
可是,先来看一些好的方面。Linux 内核是敞开和通明的,任何人都能够看到其他任何人的 改动,而且它的代码质量十分高。另 外,Linux 内核十分安稳,可能是现在最安稳的体系,而且获取它十分便当。一旦你将自己的改动合并到内核,每个运用内核的人都会用到你的改动,这简直彻底是厂商无关的( vendor-neutral)。
欠好的方面:欠好的方面太多了。
首要,内核是十分,十分难改。一般需求大喊大叫(Shouting is involved)。但这种状况也正在明显地改进。Linux 内核是一个十分庞大和复 杂的代码库,包含 12 million 行 C 和其他言语代码,其间一些代码现已 30 多岁高龄了 。向 upstream 提交代码很难,需求到达一致。假如你有特别的运用场景,而且没有发现其他人认同你的观念,那你的代码是无法合并进内核的。在这种状况下,你无脑婴儿只能 fork 一份内核,保护自己的 包含 12 million 行代码的内核分支。
视所运用的 Linux 内核发行版的不同,其他用户可 能得几年之后才干用到某个改动。一些人还在运转 10 年前的内核。
最大的问题可能是,每个人都在保护自己的内核 fork,许多时分触及到上千个 patch 需求 backport。假如你运转的是 Android,那你运转的是 Linux,具体的说是 Android Linux。假如你在运转 Rail,那你运转的是 Linux,具体的说是有 4 万个 patch 的 Linux。午时它们和上游的 Linconfidentux 仍是不太相同的,而仅仅上游的一个 fork。因而,咱们都在运转自己的 Linux。

问题四:Linux 感知不到容器

这也许是最严峻的问题:事实上内核感知不到容器的存在。

内核知道的是:

-进程和线程

-Cgroups

-Namespace

-IP 地址和端口号

-体系调用和 SELinux 上下文

Cgroups 是一个逻辑结构,你能够将进程相关到一个 group,然后指定这个 group 的资源约束,例如能够运用的 CPU、内存、IOPS 等等。

Namespace 是一种阻隔技能,例如给一个 group 的进程指定 Namespace 约束一个虚拟地址空间,使它们只能看到这个 Namespace 的进程。网络 Namespace 的网络设备只能看到这个 Namespace 内的网络设备。

内核知道 IP 地址和体系调用。因而运用建议体系调用时,内核能够对它进行盯梢和过滤。内核还知道 SELinux 上下文,因而有过滤网络安全相关的功用,例如操控进程是否/怎样与 其他进程通讯。听起来很有用。

这些都是多任务年代(multitasking age)的柱石。

内核不知道的是:

-容器或 Kubernetes Pod

-露出(到宿主机外面)的需求

-容器/Pod 之间的 API 调用

-Service Mesh

内核无法感知(作为一个全体的)容器。

你能够在 cgroup 文件中找到容器 ID,但内核自身并不了解一个容器是什么。它只能看到 Cgroups 里边的 Namespace。

内核了解运用是否需求露出给外部。在多任务年代,内核其实知道一个运用绑定了哪个 IP 和 port,以及是否对外露出。例如假如一个 Web Server 运转在 Localhost 的 80 端口,内核就了解它不应该被露出到外部。在容器年代,内核现已不清楚什么应该被露出, 什么不陆星材,怎样依据 Cilium 和 eBPF 打造可感知微服务的 Linux?-90后的空间,同享生长故事,风趣新闻发布应该被露出了。

别的一个大问题:曾经通过 IPC 或 Linux domain socket pipe 方法的通讯,现在换成 REST、GRPC 等方法了。内核无法感知到后者。内核知道的仅仅是网络包、端口号等, 内核会知道:“嘿,这儿有一个进程,它监听在 80 端口,运转在自己的 Namespace 内。” 除此之外的(更上层)东西,内核就不知道了,例如跑在这个端口上的是什么服务。在之前,内核还知道这是一个正在通过 IPC 和其他进程通讯的进程,这种状况是简略的进程到进程、服务到服务通讯。而 Service Mesh —— 我不知道在座有多少人正在重视 Service Mesh —— 内核无法感知到 Service Mesh。许多东西都是内核不知道的。

处理方法

面临这种状况,咱们该怎样办呢?有几种处理方法。 
第一种方法,针对第一个问题(内核完结的笼统和分层问题),咱们能够给用户空间程序拜访硬件的权限,彻底绕过内核。我是仔细的(I mean it will be fine),内核能够处理好这些作业。运用可壮阳补肾能也知道怎样运用硬件。这类用户空间程序陆星材,怎样依据 Cilium 和 eBPF 打造可感知微服务的 Linux?-90后的空间,同享生长故事,风趣新闻发布包含 DMA、DPDK 及相似结构。
第二种处理方法:Unikernel。Linus 错了,每个运用应该自带它们自己的操作体系, 这彻底可行(definitely feasible)。这类比如也许多,包含 ClickOS、MirageOS、 Rumprun 等等。每个运用自带自己的操作体系,而不是同享同一个操作体系。
第三种方法:将操作体系上移到用户空间。gVisor 是一个比如,现已好多年了。咱们能够将操作体系的大部分功用都跑在用户空间,只将最小的子集跑在内核空间,处理硬件等相关的作业。这样关于许多网络和存储问题,咱们就不需求和内核社区洽谈了(直接在 用户空间自己改)。这个主意十分棒,可是,价值是功用会有十分大的(massive)下降。
最终,咱们还有一种处理方法:从头来过,重写全部(rewrite everything)。明显, 这也是一种方法。我信任今日晚些时分 Brian 会同享怎样用 Rust 重写全部(高档黑 !)。我以为重写全部是十分大的一项工程,因而我去 Google 了一下重写 Linux 内核需求多少预算,这是给出的数字:$1,372,340,206。我不清楚核算所用的工资水平跟现在比是 否现已过期,但咱们现已看出来:重写 Linux 内核基本上是不可行的。

BPF 是什么?

BPF 是一个处理全部这些问题的计划。那什么是 BPF?

BPF 是 Linux 内核中的一个高功用沙盒虚拟机(sandbox virtual machine),它将内核变成了可编程的(programmable)。它由咱们团队是非帝国和 Fa高岭之花cebook 的一些工程师保护,别的还有许多 Google、RedHat、Netflix、Netronome 等工程师帮忙。BPF 生成的代码如上图所示,这使得开发者能够对内核进行编程(program the Linux Kernel),咱们接下来会看到这是怎样作业的。

要了解 BPF 首要要意识到:Linux 内核本质上是作业驱动的。 
在图中最上面,有进程进行体系调用,它们会连接到其他运用,写数据到磁盘,读写 socket,恳求定时器等等。这些都是作业驱动的。这些进程都是体系调用。
在图最下面,是硬件层。这些能够是实在的硬件,也能够是虚拟的硬件,它们会处理中止作业,例如:“嗨,我收到了一个网络包”,“嗨,你在这个设备上恳求的数据现在能够读了”, 等等泡面。因而,内核所作的全部作业都是作业驱动的。
在图中心,是 12 million 行巨型单体运用(Linux Kernel)的代码,这些代码处理各种作业。

BPF 给咱们供给了在作业发作时运转指定的 BPF 程序的才干。

例如,咱们能够在以下作业发作时运转咱们的 BPF 程序:

  • -运用建议 read/write/connect 等体系调用
  • -TCP 发作重传
  • -网络包到达网卡

因而,BPF 答应咱们在内核完结这陆星材,怎样依据 Cilium 和 eBPF 打造可感知微服务的 Linux?-90后的空间,同享生长故事,风趣新闻发布些逻辑,当发作特定的内核作业时做相应的处理。对全部的内核函数,能够通过 kprobes 做这些作业。也能够对 tracepoints 做这些作业。这些都是界说杰出的爱乐维复合维生素片、安稳的函数(名)。咱们乃至能够对用户空间函数做这些,陆星材,怎样依据 Cilium 和 eBPF 打造可感知微服务的 Linux?-90后的空间,同享生长故事,风趣新闻发布运用 Uprobe。这样当用户空间应陆星材,怎样依据 Cilium 和 eBPF 打造可感知微服务的 Linux?-90后的空间,同享生长故事,风趣新闻发布用调用到这些函数时,咱们就能够通过 Uprobe 和 BPF 程序捕 获。这便是那些依据 BPF 完结的 profiling 和 tracing 东西的作业原理。咱们在体系调用、 网络设备、socket 层交互乃至网卡驱动层(通过 DMA)等当地调用 BPF 程序,而且内核里的可 attach 点越来越多。

BPF 程序之间能够通讯,它们能够运用 BPF maps 保存状况信息。
BPF maps 数据能够通过 BPF 程序拜访,也能够从用户空间拜访。因而能够在 BPF 程序中向 BPF map旋风十一人s 写数据,然后从用户空间读取,例如导出一些收集数据。或许,能够将装备信息写入 maps,然后从 BPF 程序读取装备。
BPF maps 支撑哈希表、数组、LRU、Ring Buffer、Stack trace、LPM 等等。其间一些支撑 per-CPU variant,功用更高。

能够调用 BPF 辅佐函数。例如 BPF 程序自身不知道怎样操作一个网络包,而咱们能够通过调用 helper 函数完结。这些 helper 函数都是安稳的 API。这使得 BPF 程序能够通过 Linux 内核了解的、已有的功用来和内核交互。

咱们能够做尾调用(tail call);能够从一个程序调用另一个程序;能够完结逻辑程序链 (chains of logical programs),依据此能够完结函数调用。这使得能够构建一个小程序,按次序顺次调用他们。

咱们有一个 JIT (Just-In-Time)编译器。当加载通用的、CPU 无关的字节码之后,内核会接收,验证它的合法性,然后将它编译成 CPU 相关的代码,例如 x86。能够看到现在支撑的 CPU 类型,现在首要支撑的是 64 位 CPU。

BPF 的奉献者有哪些?以上是现在的列表,这个列表还在增加,这儿展现的仅仅是 TOP 10。这是曩昔两年给 BPF 内核侧奉献过代码的开发者。Daniel 和 Alexei 现在一同保护 BPF。然后有来自 Facebook、Reddit、Netronome 等公司的奉献者。我印象中大概有 186 位。BPF 是现在内核最活泼的子体系之一。

Use case 1:Facebook
Facebook 用 BPF 重写了他们的大部分基础设施。
11 月 12 号的 BPF 峰会上,他们会介绍 Facebook 怎样用 BPF 替换了 iptables 和 network filter。这个同享肯定会在线直播的。假如你对此感兴趣,届时能够在线收听。他们会供给很多的细节和功用数据。Facebook 基本上现已将他们的负载均衡器从 IPVS 换成了 BPF。他们现已将 BPF 用在流量优化(traffic optimizationcommition),在同享中,它们也将会介绍他们在网络安全方面的作业。
Use case 2:Go丹尼尔惠灵顿ogle
G起点大神的纲要模板oogle 现已开端用 BPF 做 profiling,找出在分布式体系中运用耗费多少 CPU。而且,他 们也开端将 BPF 的运用范围扩展到流量优化和网络安全。
Use case 3:Redhat
Redhat 正在开发一个叫 bpffilter 的上游项目,将来会替换掉内核里的 iptables,也便是说,内核里依据 iptables做包过滤的功用,今后都会用 BPF 替换。别的还有一些论文 和项目,关于 XDP 和 BPF+NFV的场景。
Use case 4:Netflix
假如你听说过 DPF,那你估量是看过 Brendan Gregg 的同享。他介绍了怎样在大规模出产 环境中运用 BPF 定位 CPU 耗费问题,这个问题用传统方法是很难做的,需求特别轻量级的东西。他依据 BPF 收集信息然后画出所谓的火焰图(flame graphs),协助定位功用问题。最近他开源了一个 BPF trace 的项目,能够协助排查功用问题。
别的还有很多的与 BPF 相关的项目。

BPF 程序长什么样?

以上是一个(至少对我来说)简略的 BPF 程序。

BPF 程序运用高档言语编写,例如 C 言语。以上这个比如中,每次体系调用回来时,就会履行这个 BPF 程序。程序会获取进程的 PID 和程序名,将信息脑血栓先兆送到用户空间。这样你就能够监控你的体系。十分十分简略的比如,但这便是依据 BPF 的 profiling 和 monitoring 体系的作业原理。

Cilium 是什么?

以上便是关于 BPF 的介绍,十分的底层,那么,有必要得了解全部这些细节才干运用 BPF 吗 ?不,这便是咱们创立 Cilium 项意图原因。

Cilium 是一个开源项目,方针是为微服务环境供给网络、负载均衡、安全功用,首要定位是容器渠道。这个项目自身并不需求容器环境,但现在咱们供给的是容器化的装置方法。Cilium 依据 BPF。

目华为x1标

首要是让 BPF 更易上手运用(approachable)。BPF 自身很奇特、灵敏、功用十分高,但对内核不了解的话,要运用起来十分困难。而毫无疑问,大部分人并不想自己写 BPF 程序 ,但想运用 BPF 来完结一些作业。因而,咱们需求自动化 BPF 代码生成、自动化 BPF 办理等等。这是第一个方针。 
第二个方针是运用 BPF 的灵敏性使内核感知到 Cloud Native 运用,咱们后面会具体打开。
第三个方针是安全,通过 BPF 使内核能够感知到 API 层。内核能够了解:“嗨,你有两个运用相互通讯,它们之间调用了哪些 API?”使内核能够为 API 调用供给安全确保。构建一个依据身份认证(identity-based)机制使服务通陆星材,怎样依据 Cilium 和 eBPF 打造可感知微服务的 Linux?-90后的空间,同享生长故事,风趣新闻发布信更安全。因而不同于曾经简略的 IP + Port 过滤,现在内核能够了解什么是一个微服务,微服务的 labels 有哪些,这个微服务的安全性是怎样样的。
进程等级的上下文 enforcement。运用 BPF 的强壮功用使内核了解一个可履行文件是什么,一个容器里的进程正在进行什么 API 调用。这十分有用。例如,咱们都知道 kubectl exec 能够到一个容器里去履行指令,可是,谁来确保这个通讯进程的安全?明显不是服务自身。那你怎样确保这个通讯进程的安全呢,确保指令不会发送到过错的当地?
最终一点便是 BPF 的功用。

Cilium Use Cases

首要咱们供给了 CNI 和 CNM Plugin,你能够运用 Cilium 作为容器的网络计划。支撑 IPv4/IPv6、NAT46、负载均衡等等。 
咱们供给了微服务安全(microservice security),依据 identity 做安全,而不是传统的依据 IP 和端口。咱们给服务指定 identity,答应依据 service label 界说安全战略。例如答应我的前端和后端通讯,咱们是在网络层做这种战略的。咱们有增强的 API 安全支撑,例如答应部分 REST API 调用,或许只答应拜访 Kafka 集群,而且只能出产或消费特定的 topic 等等。
咱们有 DNS 服务器战略。下一个版别会支撑 SSL。

最终是 Service Mesh 的加快。这儿我介绍的略微具体一点,由于我感觉这是许多人感兴趣的当地。 
上面左面这张图便是 Service Mesh 中常见的两个服务通讯的场景。两个服务并不是直接和互相通讯,而是通过各自的 sidecar。看起来十分简略和简练。
右边是它实践的、在数据传输层的姿态。服务出来的恳求通过协议栈和 iptables 规矩进入到 sidecar 的监听 socket,这个 TCP 连接到这儿便是终点了。sidecar 会将恳求收进来,查看 HTTP 头和其他一些信息,做一些它自己的处理,然后再将恳求发送出去。这个进程并不高效。加上这一层 sidecar 会有 10x 的功用丢失。这并不是 sidecar 自身的功用形成的(我这儿放的图是 Envoy,现已很高效了),而是 sidecar 署理的作业方法形成的。

这儿为什么要运用 TCP?TCP 是为有质量差、有丢包的网络规划的。假如服务和 sidecar 永远都是在一台宿主机内部,咱们为什么还要用 TCP?

咱们能够绕过 TCP,将两个 socket 以短路方法连接到一同。假如服务和 sidecar 永远在一台宿主机上,咱们能够直接在两个 socket 之间复制数据。咱们实践丈量,假如以 RPS (每分钟恳求数)衡量,功用能够陆星材,怎样依据 Cilium 和 eBPF 打造可感知微服务的 Linux?-90后的空间,同享生长故事,风趣新闻发布 3x ~ 4x。因而,这便是 Cilium 和 BPF 使 Linux 内核可感知微服务的一个比如。Cilium/BPF 的意图便是为服务化年代供给便当和所需的功用。

其他一些 BPF 相关的项目。

标签: 未定义标签
admin 14文章 0评论 主页

  用户登录