Edera

Styrolite 介绍:从零开始构建一个 Linux Container Runtime

2025年3月26日

Edera Protect 是一套解决方案,旨在弥合现代云原生计算和基于虚拟化的安全技术之间的差距。为了支持这个平台,我们构建了自己的 container runtime,它被设计成一个微服务,允许以完全编程的方式运行容器,类似于 Kubernetes Container Runtime Interface (CRI) 如何通过微服务实现容器管理。

今天,我们很高兴地宣布,我们将开源我们的编程底层 container runtime——Styrolite,以便其他人可以从我们的工作中受益。

为什么要构建一个新的底层 container runtime?

将底层 container runtime 关注点分离到其自身的工具或微服务中的想法并不新鲜。除了 Kubernetes CRI(它将容器生命周期管理呈现为可插拔的微服务)之外,还有一些更简单的工具也提供了底层 container runtime,例如 util-linux 中的 unshare 实用程序,以及另一个名为 Bubblewrap 的工具。

但这些工具要么过于高级(如 Kubernetes CRI),要么旨在通过 shell 脚本使用:Bubblewrap 具有很高的可配置性,但只能通过非常复杂的 CLI 访问,并且很容易出错;而 util-linux 的 unshare 具有基本功能,但也隐藏在 CLI 之后。虽然 CLI 允许快速迭代,但我们需要一些不同的东西用于 Edera Protect:一个丰富的编程接口,用于精确地生成和管理容器。Styrolite 提供了两全其美的解决方案——一个可以直接从 Rust 使用的干净的 API,同时保留了 CLI 的快速迭代能力。

Styrolite 如何工作:Linux 容器的内部原理

重要的是,我们在设计 Styrolite 时充分意识到 Linux namespace 从未打算作为硬安全边界——这一事实解释了为什么容器逃逸漏洞不断出现。我们的方法承认这些限制,同时提供更强大的基础。

Linux 中的容器——与其他 容器化 努力 无关 ——建立在 Linux namespace 之上。Linux 中的 namespace 允许对给定类型的资源进行替代视图,例如:mount namespace 允许对挂载表进行替代视图,从而允许对根文件系统进行替代视图,而 PID namespace 允许对系统进程集进行替代视图。Container runtime 组合这些 namespace 以提供容器化环境,从而以更高的复杂性为代价实现了极大的灵活性。

所有 container runtime 的根源是 Linux unshare(2) syscall。这允许当前正在运行的进程从其一个或多个当前 namespace 解除关联到可以修改的 namespace 的 fork 版本中。通常,container runtime 默认情况下会 unshare 大多数 namespace,因为有必要这样做:

在 Edera Protect 平台上,所有这些 namespace 都在堆栈中的不同级别上 unshare。在 Edera Protect 平台内部使用时,Styrolite 主要负责处理 Mount、PID、IPC、User、Time 和 UTS namespace,而网络在平台的其他地方处理。

简单、可编程的接口

以下是 Styrolite 与传统方法相比如何简化容器创建的一个例子:

// 使用 Styrolite 创建一个基本容器let mut request = CreateRequestBuilder::new()
  .with_rootfs("/path/to/container/rootfs")
  .set_executable(“/bin/sh”)
  .set_arguments(vec![“-i”])
  .set_working_directory(“/”)
  .push_namespace(Namespace::User)
  .push_namespace(Namespace::Mount)
  .push_namespace(Namespace::Pid)
  .to_request();
// 在容器中启动一个进程let runner = Runner::new(“styrolite”);
runner.run(request)?;

这种简洁的接口使容器创建和管理更易于维护,并且比复杂的 CLI 命令或 shell 脚本更不容易出错。

实际应用

Styrolite 为几个重要的用例提供支持:

性能与安全

Styrolite 旨在以最小的开销运行,提供与传统 CLI 方法相当或更快的容器初始化时间,同时提供关于容器状态的更强的编程保证。

我们的安全优先设计承认了 Linux namespace 的固有局限性,同时通过仔细的默认设置和显式安全控制提供了更强大的基础。

加入社区

当我们决定构建一个底层容器化工具供我们在 Edera Protect 中使用时,我们立即知道它会对更大的 OSS 社区有其他好处。我们欢迎社区的贡献:

我们致力于 Styrolite 的持续开发,并期待看到社区如何使用它进行构建!

作者

Ariadne Conill