Kubernetes与Rust:安全之舟的云原生实践

本文深入探讨DeisLabs团队使用Rust语言开发Krustlet工具的经验,重点分析Rust在Kubernetes生态中的安全优势,包括内存安全、并发保护机制,以及如何通过编译期检查避免常见云原生应用漏洞。

安全之舟:Kubernetes与Rust

我们的团队DeisLabs最近发布了一款名为Krustlet的新软件,这是一个在流行的开源容器管理工具Kubernetes上运行WebAssembly模块的工具。Kubernetes被广泛用于在许多供应商和公司的云软件运行,主要使用Go编程语言编写。虽然有很多关于使用Rust进行系统级编程的故事,但很少听到关于用Rust编写云软件或Kubernetes软件的故事。因此,我们想解释为什么我们做出了这样的选择。

WASM来了?

首先,让我们从一些重要的背景开始。WebAssembly(缩写为WASM)最初设计用于在浏览器中运行。WASM是一种编译后的二进制文件,可以在任何浏览器中下载和运行。这使得高性能应用程序可以在浏览器内部运行,目前被许多主要的Web应用程序使用。最近的工作使得编译后的WASM二进制文件(称为模块)可以在任何系统上运行。Rust是为数不多的原生支持构建这些二进制文件的语言之一。因此,许多运行WASM模块的项目也用Rust编写,这使我们能够将它们嵌入到我们的项目中。这是我们选择Rust的主要动机之一。

安全与保障

我们选择Rust的另一个原因是其强大的安全保障。像大多数Rust新手一样,我们开始咒骂Rust的借用检查器(它静态地强制执行Rust的许多安全保证),有时与之斗争数小时。但当我们开始更好地理解如何编写代码时,我们意识到编译器为我们避免了多少错误和问题。它阻止我们暴露可能的空指针、线程安全问题和其他被忽视的错误。整个学习过程花了我们大约一个月的时间。在第一周左右,我们花了很多时间学习借用是如何工作的。大约两周后,我们的效率恢复到与使用Go编写时相比的50%。一个月后,我们都足够熟练,效率恢复到满负荷(就我们能编写的代码量而言)。然而,我们注意到我们在生产力方面有所提升,因为我们不必花那么多时间手动检查特定条件,如空指针,或者不必调试那么多问题(我将在下面进一步讨论)。偶尔,我们会遇到更复杂的情况,需要比使用其他语言更长的时间来解决。然而,随着时间推移和我们经验的积累,这种情况发生的频率在减少。

一个具体的例子是Rust编译器如何保护我们免受各种并发错误的影响。Krustlet负责并行运行任意数量的WASM模块。当我们编写管理运行模块的代码时,借用检查器捕获了我们在线程之间传递数据结构的情况,这些情况可能导致不安全或并发数据访问问题。它还阻止我们使用可能已被代码先前部分访问的对象。

尽管我们有时会怀念拥有垃圾收集器,这样我们就不必担心克隆、借用、所有权等,但由于Rust编译器的严格规则而避免的痛苦是无法估量的。作为比较,上周我们在另一个我们维护的名为Helm(用Go编写)的Kubernetes相关项目中捕获了一个严重的竞态条件,这个错误已经存在了一年或更长时间,并且通过了Go的竞态检查器。这个错误永远不会逃过Rust编译器,从而从一开始就防止了该错误的存在。

由于大量的定制(至少在Kubernetes中)涉及自定义数据类型和云计算的分布式特性,在编译器级别拥有这些保护和安全保证使我们对编写的代码充满信心。这绝不是消除所有错误,但它确实从一开始就帮助我们避免了许多常见的并发错误。此外,拥有一个强大的类型系统,同时仍然允许扩展性(以特质的形式,Rust文档将其描述为“以抽象方式定义共享行为”并将泛型参数绑定到该行为的能力),对于需要以类似方式处理多个自定义数据类型的项目来说,是非常有用和灵活的。

简而言之,Rust的灵活性、安全性和保障性超过了必须遵循严格的生命周期、借用和其他编译器规则甚至缺乏垃圾收集器所带来的任何不便。这些功能是云软件项目急需的补充,将有助于避免其中常见的许多错误。

需要注意的事项

仅仅因为我们喜欢Rust的许多方面,并不意味着一切都很美好。我们也学到了一些需要注意的问题,我们认为在决定是否将Rust用于新的云软件项目时指出这些问题是重要的。

最大的问题之一是异步运行时仍然有些不明朗。目前有两个不同的选项可供选择,每个都有其自身的权衡和问题。此外,许多实现细节与特定的运行时绑定,这意味着如果你有一个依赖项使用一个运行时而不是另一个,你通常会被锁定在该运行时选择中。Rust在过去一年中在其异步故事方面取得了巨大进展,但仍有一些问题正在解决中。

另一个需要注意的问题是学习曲线。需要几周的艰苦努力学习如何正确地在Rust中编码,学习曲线才会趋于平缓。然而,由于上述的安全特性,前期的艰苦努力会带来丰厚的回报。我们还注意到,一旦开发者度过了最初的曲线,他们就能够像使用任何其他语言一样轻松地为代码做出贡献。只是要意识到会有一些最初的痛苦。

如果你愿意处理这些当前的问题,那么没有理由不在下一个项目中至少考虑使用Rust。所有语言都有其权衡,但我们觉得获得的益处超过了这些痛点。

结论

我们看到Rust在云软件中的光明未来。在不久的将来,我们计划继续将其用于任何适合的项目。鉴于Rust带来的特性,即使它缺乏一些熟悉的特性(如垃圾收集),我们强烈推荐它作为你下一个云软件项目的选项。

作者:Taylor Thomas,DeisLabs高级软件工程师,Azure

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计