
데몬 없이 밀리초 단위로 커널이 강제하는 OCI 이미지를 실행하는 루트리스 컨테이너 런타임 및 샌드박스로, 신뢰할 수 없는 코드와 AI가 생성한 코드를 위한 리소스 프로필, seccomp 허용 목록, compose 지원을 제공합니다.
kern: 신뢰할 수 없는 코드와 AI 생성 코드를 포함한 모든 워크로드를 위한 빠르고 루트리스인 샌드박스 및 가상 리소스 런타임.
데몬 없이 1.52 MB 바이너리 하나로 ~3.5 ms에 시작되는, 커널이 강제하는 진짜 컨테이너.
유휴 상태 RAM 0 · 데몬 없음, 소켓 없음, 시작할 것 없음 · 정적 바이너리 하나, 유일한 Rust 의존성은 libc
# install the release binary (static, 1.52 MB, checksum-verified by the script)
curl -fsSL https://raw.githubusercontent.com/getkern/kern/main/install.sh | sh
# a throwaway shell in a real OCI image: rootless, kernel-enforced, a few ms
kern box dev --image alpine -it -- sh
네이티브 Windows 없음: WSL2를 사용하세요. 설치.
리소스를 관리하는 단일 바이너리, 그중 첫 번째가 격리입니다. 그래서 비교 표에 kern을 위한 단일 행이 없습니다: 데몬 없이 1.52 MB로 컨테이너 런타임, 샌드박스, 리소스 슬라이서, 스택 러너가 동시에 있기 때문입니다.
pull, Dockerfile에서 build, commit, push,
save/load. 이미지에서 박스가 ~3.5 ms 만에 시작됩니다.--security-profile untrusted 플래그 하나가 강화된 번들 전체입니다.vcpu:), 메모리, 디스크(vdisk:) 및 장치(vgpio:)를
kern.toml에 한 번 선언하고 이름으로 붙입니다. kern run은 샌드박스 없이 호스트의
프로세스에 동일한 상한을 적용합니다. docs/RESOURCES.mdkern compose <file> up은
( 테이블, 위의 리소스 프로필 포함) 또는 이미 가지고 있는 을
있는 그대로 읽습니다. 하나의 스택은 하나의 포드로, 서비스는 이름으로 서로 도달합니다.Rust 의존성 트리 전체는 libc입니다: JSON 및 OCI 매니페스트는 직접 파싱하고, pull은 TLS
스택을 링크하는 대신 머신에 이미 있는 curl과 tar를 호출합니다. (1.52 MB는 크기 최적화된
릴리스 빌드이며, 소스에서 일반 cargo install 하면 1.91 MB입니다.)
하이퍼바이저가 아닙니다. 경계는 Linux 커널이므로, 커널 권한 상승 버그는 탈출로 이어집니다. Docker와 Podman도 같은 조건을 공유하며, 그래서 gVisor와 Firecracker가 존재합니다.
태그라인과 함께 읽으면, 이는 양면에서 보이는 한 줄입니다: 신뢰할 수 없는 코드와 AI 생성 코드는 kern이 FOR(위한) 대상입니다. 여러분이 그것을 실행하기로 선택하고 폭발 반경을 소유하기 때문입니다(에이전트 도구 호출, CI 작업, 빌드 단계, 코드 셀). kern이 FOR(위한) 대상이 아닌 것은 낯선 사람의 적대적 코드, 즉 다른 테넌트에 서비스하는 커널 위의 다중 테넌트입니다. kern은 Docker가 옵트인인 반면 항상 루트리스로 시작합니다.
userns 트레이드오프에서 자유롭지 않습니다. 격리는 커널 LPE 버그의 온상인 권한 없는 사용자 네임스페이스 위에 구축됩니다. SECURITY.md는 어떤 주장보다 먼저 이를 명시합니다.
마운트한 것을 둘러싼 벽이 아닙니다. -v $HOME:/host는 박스에 여러분의 홈 디렉터리를
줍니다: 마운트는 kern이 강제하는 경계가 아니라 여러분이 내리는 신뢰 결정입니다.
--net host와 --privileged는 이름 그대로 옵트아웃입니다. (kern이 바인드를 거부하는 유일한
경로는 자체 런타임 레지스트리입니다.)
Docker Engine 재구현이 아닙니다. 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_64 또는 aarch64를 자동으로 선택하고 ~/.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
소스에서가 다른 방법이며, 의존성 트리 전체가 하나의 크레이트(libc)이므로 짧습니다:
데스크톱(i7-14700KF)에서 clone, build, install에 36초가 걸렸고, 작은 ARM 보드에서는 더
걸립니다.
# if you do not have Rust yet
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이
발견되지 않으면 새 셸을 열거나 source "$HOME/.cargo/env"를 실행하세요).
릴리스에는 aarch64 바이너리, Windows .exe 심(shim) 및 사전 제작된 WSL rootfs도
포함되며, 각각 자체 .sha256이 있습니다. 태그는 GPG 서명되고 독립적으로 타임스탬프가
찍힙니다(provenance/).
kern doctor는 시도하기 전에 이곳에서 박스가 실행될 수 있는지 알려줍니다. 보드, WSL2 및
자세한 내용: docs/INSTALL.md. 자주 묻는 질문(Docker, bubblewrap, youki,
E2B, Windows, 위협 모델): docs/FAQ.md.
kern box dev --image alpine -it -- sh # a throwaway shell in a real OCI image
kern run --memory 256M --cpus 0.5 -- ./crunch # cap a process, no sandbox
kern box svc --image nginx:alpine -d -p 8080:80 \ # a service: published, restarted, health-checked
--restart --health-cmd 'wget -qO- localhost:80' -- nginx -g 'daemon off;'
kern ps # what is running, with PORTS and HEALTH
kern exec svc -it -- sh # shell into it
kern stop svc # its signal, its grace, then the code it exited with
kern top # live TUI: boxes, CPU/RAM, profiles, volumes
kern compose stack.toml up # a multi-box stack (examples/) or a compose.yml
kern compose stack.toml down # and take it down again
신뢰할 수 없는 코드, 번들에는 플래그 하나:
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를
추가하면 메모리/pids 상한이 실제로 적용되지 않으면 시작을 거부합니다. 요청하지 않는 한
네트워크 없음, 위험한 capabilities 제거, seccomp 항상 켜짐. 각각 한 가지 일을 하는 90개의
실행 가능한 예제: examples/.
모든 읽기 동사는 JSON으로도 응답하므로, 아무것도 표를 파싱할 필요가 없습니다:
kern ps --json | jq '.[] | select(.health == "unhealthy") | .name'
kern volume ls --json # ps · images · stats · inspect · builds · pod ls · config list · diff
kern은 docker-compose.yml을 이해합니다. 이미 가지고 있는 스택을 가리키면
kern compose up이 데몬과 Docker Desktop 없이 실행하며, Linux, WSL2 및 ARM 보드에서
동일합니다.
# compose.yaml - a real stack, unchanged
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에 도달하며, 포트는 호스트에
게시됩니다. 웜 상태(이미지 캐시됨)에서 웹 티어는 ~0.3 s에 서빙하며, 스택은 postgres와
adminer가 실제로 사용하는 만큼만(~66 MB) 비용이 들고 그 위에 데몬 0개입니다. 반면
Docker Desktop은 첫 번째 컨테이너를 띄우기 전부터 백그라운드 VM을 띄웁니다.
비-root 사용자로 전환하는 공식 이미지(postgres, redis 등)는 uidmap과 /etc/subuid 줄을
필요로 하고, 아웃바운드 이미지 pull은 pasta를 필요로 합니다. 둘 다 개발 머신에서
apt install 한 번이면 되며, kern doctor는 빠진 것이 있으면 이름을 알려줍니다. 이것은
로컬 개발 루프이지 프로덕션 오케스트레이터가 아닙니다: Swarm 없음, overlay 네트워크 없음.
자체 프로그램에서 에이전트 또는 LLM 생성 코드를
**kern-sandbox**로 실행하세요. 이는 kern 바이너리 위의
얇고 의존성 없는 래퍼입니다. 모든 호출은 새로운 격리 박스에서 실행됩니다: 네트워크 꺼짐,
메모리 및 pid 상한, capabilities 제거, 출력 제한, 그리고 바인딩 자체가 강제하는 타임아웃.
pip install kern-sandbox # PyPI · needs the `kern` binary above, on PATH or $KERN_BIN
npm install kern-sandbox # npm · same
from kern_sandbox import run_code
r = run_code("import platform; print(platform.python_version())")
print(r.stdout) # ran in a fresh box; a timeout / OOM / blocked escape is data on r.fault
Sandbox는 호출 간에 작업 공간을 유지하고, 웜 kernel()은 서브-밀리초 셀을 위해
인터프리터 하나를 유지합니다(선택에 따른 더 약한 격리).display() 및 matplotlib 그림이
노트북 셀처럼 캡처되어 돌아옵니다.kern-mcp)를 제공합니다: Claude Desktop, Cursor 또는 모든 MCP 클라이언트에
로컬 코드 인터프리터를 제공하는 의존성 없는 stdio 서버입니다. 클라이언트를 여기로
지정하세요:{ "mcpServers": { "kern": { "command": "kern-mcp" } } }
도구: run_code(python/bash/node), write_file, read_file, list_files. 각 호출은
네트워크가 꺼진 새로운 박스입니다. 파일은 디스크의 작업 공간에 호출 간에 유지됩니다.
설정 명령, 이미지 및 기타 옵션: bindings/python/README.md.
전체 API, Python 및 Node: bindings/python/README.md · bindings/node/README.md.
슬라이스는 ~/.config/kern/kern.toml에 한 번 선언되고, 이름으로 샌드박스 박스 또는 일반
프로세스에 동일한 토큰으로 붙습니다.
세 종류: vcpu:(CPU 및 메모리), vdisk:(크기 제한이 있는 스크래치 디스크),
vgpio:(장치 노드). 그중 둘과, 그것들이 잘려 나오는 앵커:
[[cpu]] # the host budget a slice is carved from
id = "cpu:0"
cores = 8.0
[[vcpu]] # 1.5 cores and 512 MiB -> attach as vcpu:heavy
name = "heavy"
backend = "cpu:0"
cpus = 1.5
memory = "512m"
[[gpio]] # a controller anchor
id = "gpio:0"
[[vgpio]] # exactly one device node -> attach as vgpio:sensor
name = "sensor"
backend = "gpio:0"
i2c = ["/dev/i2c-1"]
kern validate ~/.config/kern/kern.toml # check it before anything runs
kern box train --image alpine vcpu:heavy vdisk:scratch -- ./train.sh
kern run vcpu:heavy -- ./train.sh # the same slice, no sandbox
kern box iot --image alpine vgpio:sensor -- ls /dev
프로필은 조합됩니다: 여러 개가 하나의 박스에 붙을 수 있고, 명시적 플래그가 프로필 자체
값보다 우선합니다. 모든 키는 CLI 플래그처럼 표기되므로 cpus는 --cpus이고 memory는
--memory입니다. 선언된 풀이 없는 백엔드 이름은 박스가 실행될 때가 아니라 config를 읽을
때 거부됩니다. 필드별 스키마는 docs/RESOURCES.md에 있습니다.
vdisk:는 kern이 루트리스로 실행될 때 백엔드가 무엇을 말하든 RAM 기반 tmpfs이며,
권한(privileged)으로 실행될 때는 실제 할당량이 있는 ext4-on-loop 이미지입니다. kern은
여러분이 추측하게 두지 않고 프로필별로 어떤 것인지 알려줍니다. 크기 상한은 어느 쪽이든
적용됩니다.
vgpio:는 라인별이 아니라 칩 단위입니다. pins를 요청하면 /dev/gpiochipN 전체가
바인드되며, 그 캐릭터 디바이스는 해당 컨트롤러의 모든 라인을 노출합니다. pins = [17]은
박스를 라인 17로 제한하지 않습니다: 커널에는 라인별 마운트 경계가 없으므로, 핀 목록은
경계가 아니라 협력적 메타데이터입니다. 위의 i2c처럼 장치 노드를 이름으로 지정하면 그
노드만 부여되고 그 외에는 없습니다.
Intel i7-14700KF, Linux 7.0.0, 릴리스 바이너리, 직접 실행할 수 있는 스크립트 하나:
python3 examples/benchmark.py. 결과는 여러분의 CPU, 커널, 파일시스템에 따라 다를 것입니다.
3,000개를 동시에 실행하면 ~2.2 s가 걸리며, 실행 중인 박스 하나는 ~0.3 MB의 메모리를 사용합니다.
솔직한 메모 두 가지. 단발 레이턴시에서 완전히 이기는 사람은 없습니다: unshare +
exec의 하한은 1~2 ms이므로 최상위 계층 전체가 자체 노이즈 안에 있으며, bubblewrap은
이미지, 상한 또는 수명 주기가 없는 런처입니다. 의미 있는 격차는 두 자릿수 위에 있는
엔진들과의 차이입니다.
방법론, 단계별 분석, 보드 수치 및 모든 주의사항: BENCHMARKS.md.
네임스페이스, pivot_root, exec 전에 제거되는 16개의 위험한 capabilities, 기본적으로
항상 켜진 seccomp 허용 목록(moby의 기본 필터에서 kern의 35개 탈출 syscall을 뺀 것으로,
이들은 하드킬로 유지됩니다. 검증된 집합 밖의 syscall은 ENOSYS를 반환하며, 더 넓은 차단
목록은 KERN_SECCOMP=denylist를 통한 옵트아웃입니다), cgroup v2 제한(--require-limits는
실제로 바인드되지 않으면 시작을 거부), 그리고 기본 거부(deny-by-default) /dev. 경계가
커널이 강제하는 것이 아니라 협력적인 곳에서는 SECURITY.md가 그렇게 명시하고
우회 방법을 밝힙니다.
신뢰로 받아들일 필요가 없습니다: pentest/에는 kern 자체의 보고가 아니라 커널을 상대로 그러한 경계를 검증하는 네 개의 적대적(adversarial) 스위트가 있으며, 레지스트리 계정이나 네트워크 없이 실행됩니다.
sh pentest/run-with-local-registry.sh ./target/release/kern pentest/pentest-ports.sh
취약점은 GitHub Security Advisories 또는 [email protected]로 비공개로 신고해 주세요.
핵심은 완성되었습니다. 위의 모든 것이 오늘 동작합니다: 840개의 Rust, 78개의 Python 및
61개의 Node 테스트, clippy 클린, cargo-deny 클린, 실제 하드웨어에서: Linux, WSL2,
Raspberry Pi 5, Jetson Orin Nano, Arduino UNO Q. v0.7.0이 첫 번째 공개 릴리스입니다.
CLI 및 config 표면은 여전히 변경될 수 있으며, 변경 사항은 항상
CHANGELOG.md에 명시됩니다.
이슈와 풀 리퀘스트를 환영합니다. CONTRIBUTING.md에 워크플로와 게이트가 있으며, 기여는 CLA의 적용을 받습니다.
Alex, @realexhub. 커밋은 프로젝트의 커밋 아이덴티티인 @getkerndev에서 옵니다.
커밋은 서명되지 않았지만, 릴리스 TAG는 서명되었습니다. 검증할 대상은 바로 이것입니다:
provenance/의 키로 git verify-tag v0.7.0을 실행하세요. 해당 키의 지문은
SECURITY.md에 있습니다.
Apache-2.0. LICENSE 및 TRADEMARK.md를 참조하세요.
kern-compose.toml[box.NAME]docker-compose.ymlps, logs, exec, stats, inspect, wait, top(실시간 TUI),
doctor, 그리고 Python 및 Node SDK와 에이전트용 MCP 서버.| kern | Docker | Podman |
|---|
| 데몬 | 아니요 | 예 (dockerd + containerd) | 아니요 |
| 루트리스 | 예, 항상 | 옵트인 | 예 |
| 콜드 스타트, 빈 박스 | ~2.3 ms | ~297 ms | ~293 ms |
| 콜드 스타트, OCI 이미지에서 | ~3.5 ms | ~297 ms | ~293 ms |
| 서비스 중지 (init이 SIGTERM 처리) | ~1.9 ms | ~310 ms | ~380 ms |
| 상주 메모리, 실행 중인 것 없음 | 0 | 154~160 MB | 0 |
| 설치 공간 | 1.52 MB 바이너리 하나 | 데몬 스택 | 다중 바이너리 설치 |
| OCI 이미지, pull / build / push | 예 | 예 | 예 |
docker-compose.yml | 예, 그대로 읽음 | 예 | 부분적 |
| Overlay 네트워크, Swarm, CRI | 아니요 | 예 | 부분적 |
| GPU | 로드맵에 있음 | 예 | 예 |
| kern | bubblewrap | runc | podman | docker |
|---|
| 콜드 스타트 (빈 박스) | ~2.3 ms | ~2.3 ms | ~18.6 ms | ~293 ms | ~297 ms |
| 200개 박스 병렬 | ~0.11 s | ~0.16 s | ~0.35 s | ~44.8 s | ~16.2 s |
| 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 스키마, 볼륨 및 이그레스(egress) |
| docs/THREAT_MODEL.md · SECURITY.md · OPEN_ITEMS.md | 위협 모델(구조화되고, 그다음 메커니즘별), 그리고 알려진 격차 |
| BENCHMARKS.md · EDGE.md | 측정치, 그리고 Pi, Jetson 또는 UNO Q에서 실행 |
| examples/ · blog/ | 실행 가능한 스크립트 90개, 그리고 더 자세한 글 |
| bindings/python/README.md · bindings/node/README.md | kern-sandbox SDK: Python 또는 Node에 kern 임베드 |