展示 HN: Kern – 容器与资源运行时,1.5 MB 二进制文件,无守护进程

Hacker News Top 工具

摘要

Kern 是一个极简、快速的容器与资源运行时,在一个 1.52 MB 的二进制文件中提供无根沙箱和资源管理,无需守护进程。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/08/24 19:50

getkern/kern 源代码:https://github.com/getkern/kern

kern: 为任意工作负载(包括不受信任和 AI 生成的代码)提供的快速、无 root 权限的沙箱及虚拟资源运行时。

一个真正的、内核强制的容器,启动约需 3.5 毫秒,仅由一个 1.52 MB 的二进制文件实现,无需守护进程。

静态时内存占用为 0 · 无守护进程、无套接字、无需启动任何服务 · 一个静态二进制文件,其唯一的 Rust 依赖是 libc

CI (https://github.com/getkern/kern/actions/workflows/ci.yml)
许可证:Apache-2.0
平台%20%C2%B7%20ARM%20开发板-informational.svg)

# 安装发行版二进制文件(静态,1.52 MB,脚本验证校验和)
curl -fsSL https://raw.githubusercontent.com/getkern/kern/main/install.sh | sh

# 在真实的 OCI 镜像中启动一个一次性 shell:无 root 权限、内核强制、耗时几毫秒
kern box dev --image alpine -it -- sh

不支持原生 Windows:请使用 WSL2。安装


kern 是什么

一个二进制文件管理资源,其中隔离是首要任务。 这就是为什么在比较表中 kern 没有单独的一行:它同时是一个容器运行时、一个沙箱、一个资源切片器和一个栈运行器,仅 1.52 MB,无需守护进程。

  • 一个真正的容器。 真实的 OCI 镜像:支持 pull、从 Dockerfile buildcommitpushsave/load。从镜像启动一个 box 约需 3.5 毫秒。
  • 一个沙箱,始终无 root 权限。 用户、PID、挂载点、网络、UTS 和 IPC 命名空间,overlay 或只读根文件系统作为根,一个默认拒绝的 seccomp 白名单和 cgroup v2 限制。一个标志 --security-profile untrusted 就是整个强化包。
  • 资源配置文件,而不仅仅是隔离。 CPU (vcpu:)、内存、磁盘 (vdisk:) 和设备 (vgpio:),在 kern.toml 中声明一次,然后按名称附加。kern run 可将相同的资源上限应用于宿主机上的进程,且完全无需沙箱。docs/RESOURCES.md
  • 栈,使用 kern 自有格式或 Docker 格式。 kern compose up 可接受 kern-compose.toml(使用上述资源文件的 [box.NAME] 表)或你已有的 docker-compose.yml,无需转换步骤。一个栈对应一个 Pod,服务之间可通过名称相互访问。
  • 配套工具。 pslogsexecstatsinspectwaittop(一个实时 TUI)、doctor,另外还有 Python 和 Node SDK 以及一个供智能体使用的 MCP 服务器。其完整的 Rust 依赖树仅有 libc:JSON 和 OCI 清单是手动解析的,pull 则通过 shell 调用系统已有的 curltar,而不是链接一个 TLS 栈。(1.52 MB 是优化后的发行版构建大小;从源代码直接执行 cargo install 生成的大小为 1.91 MB。)

kern 不是什么

  • 不是虚拟机管理程序。 边界是 Linux 内核,因此内核权限提升漏洞即可逃逸。Docker 和 Podman 同样存在此问题,这也是 gVisor 和 Firecracker 存在的原因。结合标语来理解,这是从两方面看的同一行文字:不受信任和 AI 生成的代码正是 kern 的目标用途,因为你选择运行它们并承担其影响范围(智能体工具调用、CI 任务、构建步骤、代码单元)。它不适用于来自陌生人的恶意代码、多租户环境,或者你用于服务其他租户的内核。kern 始终以无 root 权限启动,而 Docker 的无 root 模式是可选的。
  • 并非完全摆脱了用户命名空间的权衡。 其隔离构建于非特权用户命名空间之上,这是内核本地权限提升漏洞的一个主要来源。SECURITY.md 在任何声明之前都阐明了这一点。
  • 不是你挂载内容周围的围墙。 -v $HOME:/host 会将你的主目录提供给 box:挂载点是你做出的信任决策,而不是 kern 强制执行的边界。--net host--privileged 是明确的退出选项。(kern 拒绝绑定的唯一路径是其自身的运行时注册表。)
  • 不是 Docker 引擎的重实现。 它使用 Docker 的格式,而非其 API:没有 overlay 网络,没有插件,没有 Swarm。兼容矩阵:docs/DOCKER-COMPAT.md
  • 不是 Kubernetes 运行时。 没有 CRI。请使用 containerd 或 CRI-O。
  • 尚未提供 GPU 切片。路线图上,此版本中没有 GPU 相关代码,因此目前没有可信任或可攻击的内容。其未知或尚未完成的功能记录在 OPEN_ITEMS.md 中,而不是留待你自行发现。

安装

kern 需要支持非特权用户命名空间和 cgroup v2 的 Linux 内核。它可在 Linux、WSL2 和 ARM 开发板(Raspberry Pi · Jetson · Arduino UNO Q)上运行;没有原生 Windows 构建版本,请使用 WSL2(kern 提供预构建的 WSL rootfs)。

最快的方式是使用发行版二进制文件:一个静态文件,无需工具链,脚本会在安装前验证其 SHA256 校验和。

curl -fsSL https://raw.githubusercontent.com/getkern/kern/main/install.sh | sh

它会为你自动选择 x86_64aarch64,安装到 ~/.local/bin(以 root 身份则为 /usr/local/bin,或由 KERN_INSTALL_DIR 指定),并拒绝安装校验和不匹配的下载文件。

手动验证只需两行命令:

curl -fsSLO https://github.com/getkern/kern/releases/latest/download/kern-x86_64-unknown-linux-musl.tar.gz{,.sha256}
sha256sum -c kern-x86_64-unknown-linux-musl.tar.gz.sha256 && tar xzf kern-x86_64-unknown-linux-musl.tar.gz

从源代码构建是另一种方式,整个依赖树仅有一个 crate(libc),因此过程很短:在桌面机(i7-14700KF)上克隆、构建和安装耗时约 36 秒,在小型 ARM 开发板上则更长。

# 如果你还没有 Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

cargo install --git https://github.com/getkern/kern getkern --locked

这会将 kern 放入 ~/.cargo/bin,rustup 会将其添加到你的 PATH(如果找不到 kern,请打开新 shell 或执行 source "$HOME/.cargo/env")。

发行版还包括一个 aarch64 二进制文件、一个 Windows .exe 引导文件和一个预构建的 WSL rootfs,每个都有自己的 .sha256 校验和文件;标签经过 GPG 签名并带有独立时间戳(provenance/)。

kern doctor 可以在你尝试之前告诉你 box 是否能在这里运行。

开发板、WSL2 和完整说明:docs/INSTALL.md
常见问题(Docker、bubblewrap、youki、E2B、Windows、威胁模型):docs/FAQ.md

快速入门

kern box dev --image alpine -it -- sh                      # 在一个真实的 OCI 镜像中启动一次性 shell
kern run --memory 256M --cpus 0.5 -- ./crunch              # 对进程设置资源上限,无沙箱
kern box svc --image nginx:alpine -d -p 8080:80 \          # 一个服务:发布、重启、健康检查
  --restart --health-cmd 'wget -qO- localhost:80' -- nginx -g 'daemon off;'
kern ps                                                      # 查看运行状态,包括端口和健康状况
kern exec svc -it -- sh                                      # 连接到服务 shell
kern stop svc                                                # 发送信号,优雅等待,然后记录退出码
kern top                                                      # 实时 TUI:查看 box、CPU/内存、配置文件、卷
kern compose stack.toml up                                   # 启动一个多 box 栈(示例在 examples/ 目录)
kern compose stack.toml down                                 # 停止该栈

不受信任的代码,一个标志即整个安全包:

kern box job --image python:3.12-slim --security-profile untrusted --memory 256m \
  -v ./job:/w -- python3 /w/x.py

--security-profile untrusted 是 seccomp 白名单 + --cap-drop ALL + --read-only 的合一可选标志(如果你愿意,也可以手动列出);加上 --require-limits 可确保除非内存/进程限制确实生效,否则拒绝启动。除非请求,否则无网络,危险能力被丢弃,seccomp 始终开启。

九十个可运行的示例,每个做一件事:examples/

每个读取命令也支持 JSON 输出,无需解析表格:

kern ps --json | jq '.[] | select(.health == "unhealthy") | .name'
kern volume ls --json                                        # ps · images · stats · inspect · builds · pod ls · config list · diff

你的 Docker Compose 栈,无需 Docker Desktop

kern 说 docker-compose.yml 语言。将其指向你已有的栈,kern compose up 即可运行它,无需守护进程,无需 Docker Desktop,在 Linux、WSL2 和 ARM 开板上体验一致。

# compose.yaml - 一个真实的栈,无需修改
services:
  db:
    image: postgres:alpine
    environment: { POSTGRES_PASSWORD: secret, POSTGRES_DB: app }
  web:
    image: adminer
    ports: ["8080:8080"]
    depends_on: [db]
kern compose compose.yaml up

两个官方镜像启动,web 通过服务名访问 db,端口发布到宿主机。预热(镜像已缓存)后,Web 层在 ~0.3 秒内就绪,栈仅消耗 postgres 和 adminer 实际使用的资源(此处约 66 MB),零守护进程开销,而 Docker Desktop 在启动第一个容器前就需要一个后台虚拟机。

使用非 root 用户运行的官方镜像(postgres、redis 等)需要 uidmap/etc/subuid 中的一行配置;出站镜像拉取需要 pasta;这两者在开发机上通过 apt install 即可安装,kern doctor 会指出缺少哪个。

这是本地开发循环,而非生产编排器:没有 Swarm,没有 overlay 网络。

嵌入使用:Python 与 Node

从你自己的程序中运行智能体或 LLM 生成的代码,可使用 kern-sandbox,这是对 kern 二进制文件的轻量、无依赖封装。每次调用都在一个全新的隔离 box 中运行:网络关闭、内存和 pid 限制、能力丢弃、输出有界,并且封装本身强制执行超时。

pip install kern-sandbox                                     # PyPI · 需要上述 `kern` 二进制文件在 PATH 或 $KERN_BIN 中
npm install kern-sandbox                                     # npm · 同理
from kern_sandbox import run_code

r = run_code("import platform; print(platform.python_version())")
print(r.stdout)                                              # 在全新 box 中运行;超时/内存不足/阻塞的逃逸信息在 r.fault 中
  • 故障是数据,而非异常:超时、内存不足终止或阻塞系统调用是结果的一个字段,而非抛出异常。
  • 默认每次调用使用全新 box;Sandbox 可在调用间保持工作空间,预热的 kernel() 则保持一个解释器用于亚毫秒级单元(隔离性较弱,但这是可选的)。
  • 无需 Jupyter 内核即可获得丰富结果:最后一个表达式、display() 调用和 matplotlib 图形都会被捕获并返回,如同笔记本单元格。

附带一个 MCP 服务器kern-mcp):一个无依赖的 stdio 服务器,为 Claude Desktop、Cursor 或任何 MCP 客户端提供本地代码解释器。将客户端指向它:

{
  "mcpServers": {
    "kern": {
      "command": "kern-mcp"
    }
  }
}

工具:run_code(python/bash/node)、write_fileread_filelist_files。每次调用都是一个网络关闭的新 box;文件在磁盘上的工作空间中跨调用持久化。设置命令、镜像和其他选项:bindings/python/README.md
完整 API,Python 与 Node:bindings/python/README.md · bindings/node/README.md

资源配置文件

资源切片在 ~/.config/kern/kern.toml 中声明一次,然后按名称附加到沙箱化的 box 或裸进程,使用相同的令牌。三种类型:vcpu:(CPU 和内存)、vdisk:(大小受限的临时磁盘)和 vgpio:(设备节点)。以下是其中两种及其基准来源:

[[cpu]]                    # 用于切片的主机预算
id = "cpu:0"
cores = 8.0

[[vcpu]]                   # 1.5 核 512 MiB -> 附加为 vcpu:heavy
name = "heavy"
backend = "cpu:0"
cpus = 1.5
memory = "512m"

[[gpio]]                   # 控制器基准
id = "gpio:0"

[[vgpio]]                  # 精确一个设备节点 -> 附加为 vgpio:sensor
name = "sensor"
backend = "gpio:0"
i2c = ["/dev/i2c-1"]
kern validate ~/.config/kern/kern.toml          # 在运行任何程序前验证配置
kern box train --image alpine vcpu:heavy vdisk:scratch -- ./train.sh
kern run vcpu:heavy -- ./train.sh               # 同样的切片,无沙箱
kern box iot --image alpine vgpio:sensor -- ls /dev

配置文件可组合:多个可附加到一个 box,显式标志优先于配置文件自身的值。每个键的命名与其 CLI 标志一致,因此 cpus 对应 --cpusmemory 对应 --memory。如果配置中引用了未声明的池,会在读取配置时拒绝,而非在 box 运行时。

docs/RESOURCES.md 有逐字段的模式说明。

当 kern 以无 root 权限运行时,vdisk: 是基于 RAM 的 tmpfs,无论其 backend 如何声明;当以特权模式运行时,则是带有真实配额的 ext4-on-loop 镜像。kern 会告知你每个配置文件实际得到的是哪种类型,而非让你猜测,并且无论哪种情况都会强制执行大小限制。

vgpio: 是芯片粒度的,而非按行。 请求 pins 会绑定整个 /dev/gpiochipN,该字符设备暴露该控制器的所有行。pins = [17] 并不将 box 限制在第 17 行:内核没有按行的挂载边界,因此引脚列表是协作性元数据,而非边界。命名一个设备节点,如上面的 i2c 所示,则只授予该节点而非其他。

kern 对比 Docker 对比 Podman

kernDockerPodman
守护进程是(dockerd + containerd
无 root 权限,始终可选
冷启动,裸 box~2.3 ms~297 ms~293 ms
冷启动,从 OCI 镜像~3.5 ms~297 ms~293 ms
停止服务(init 处理 SIGTERM)~1.9 ms~310 ms~380 ms
常驻内存,无运行任务0154 至 160 MB0
占用空间一个 1.52 MB 二进制文件守护进程堆栈多二进制安装
OCI 镜像,pull / build / push
docker-compose.yml是,直接读取部分支持
Overlay 网络、Swarm、CRI部分支持
GPU在路线图上

性能

Intel i7-14700KF,Linux 7.0.0,发行版二进制文件,运行你也可执行的脚本:python3 examples/benchmark.py。你的结果会因 CPU、内核和文件系统而异。

kernbubblewrapruncpodmandocker
冷启动(裸 box)~2.3 ms~2.3 ms~18.6 ms~293 ms~297 ms
并行启动 200 个 box~0.11 s~0.16 s~0.35 s~44.8 s~16.2 s

同时启动三千个约需 2.2 秒,一个运行中的 box 内存占用约 0.3 MB。

两点说明。 没有人能在单次启动延迟上绝对胜出unshare + exec 的底层极限是 1 到 2 毫秒,因此整个顶级梯队都在自身的噪声范围内,而 bubblewrap 是一个没有镜像、能力或生命周期的启动器。有意义的差距在于与引擎相比,它们高出了两个数量级。

方法、分阶段分解、开发板数据及所有注意事项:BENCHMARKS.md

安全

命名空间、一个 pivot_root、在 exec 前丢弃 16 种危险能力、一个始终开启的 seccomp 白名单(默认采用 moby 自身的默认过滤器,减去 kern 的 35 个逃逸系统调用,这些调用被硬性终止;集合外的系统调用返回 ENOSYS,更广泛的拒绝列表可通过 KERN_SECCOMP=denylist 选择退出)、cgroup v2 限制(--require-limits 确保除非绑定否则拒绝启动),以及一个默认拒绝的 /dev

在边界是协作性而非内核强制的地方,SECURITY.md 会说明并指出绕过方式。你无需盲目信任:pentest/ 包含四套对抗性测试套件,用于针对内核(而非 kern 自身报告)断言这些边界,并且无需注册表账户或网络即可运行。

sh pentest/run-with-local-registry.sh ./target/release/kern
pentest/pentest-ports.sh

通过 GitHub Security Advisories 或 [email protected] 私下报告漏洞。

文档

| | |—|—|—| | docs/INSTALL.md | 在 Linux、WSL2 和 ARM 开发板上安装(从源代码) | | docs/DOCKER-COMPAT.md | Docker 哪些能用,哪些不能,以及差异之处 | | docs/RESOURCES.md · docs/CONFIG.md · docs/STORAGE.md · docs/EGRESS.md | 双动词模型、kern.toml 模式、卷和出口 | | docs/THREAT_MODEL.md · SECURITY.md · OPEN_ITEMS.md | 威胁模型(结构化,然后按机制),以及已知缺口 | | BENCHMARKS.md · EDGE.md | 测量数据,以及在 Pi、Jetson 或 UNO Q 上运行 | | examples/ · blog/ | 九十个可运行脚本,以及更长的文章 | | bindings/python/README.md · bindings/node/README.md | kern-sandbox SDK:将 kern 嵌入 Python 或 Node |

状态

相似文章

仅运行NES模拟器的内核

Lobsters Hottest

一个旨在无需任何操作系统的情况下运行NES模拟器的最小化内核,并附带像Mandelbrot分形可视化这样的额外程序。