rk8s: a small Kubernetes-compatible runtime written in Rust
A lightweight Kubernetes-compatible container orchestration system written in Rust, implementing the Container Runtime Interface (CRI) with support for single containers, Kubernetes-style pods, and Docker Compose-style multi-container applications.
At a glance
- What is it?
- rk8s is a lightweight container orchestration system built on Youki, implementing the Container Runtime Interface in Rust and supporting three workload shapes, single containers, Kubernetes-style pods with pause containers for namespace sharing, and Docker Compose files translated internally into Kubernetes-compatible pods. It ships two deployment modes, a standalone CLI and a cluster mode with its own control plane, and the README says plainly that it is work in progress and should not be used in production.
- Who is it for?
- Adopt rk8s if you want a compact, readable Rust implementation of the Container Runtime Interface and the Kubernetes pod model to study or prototype against, especially if you are interested in the pause container namespace sharing, the Compose-to-Kubernetes translation, or the QUIC-based internal protocol.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 18 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What it is, and the warning in the second paragraph
rk8s is described as a lightweight, Kubernetes-compatible container orchestration system written in Rust, implementing the Container Runtime Interface with support for single containers, Kubernetes-style pods and Docker Compose-style multi-container applications. The subtitle of the README is a lite version of Kubernetes in Rust.
The foundation matters. It is built on top of Youki, which is the Rust implementation of the OCI runtime, and that choice explains the requirement for Docker in the prerequisites: Docker is listed as needed for creating OCI bundles, not because rk8s talks to a Docker daemon at runtime.
The project has academic and foundation backing. The README says it is initiated by the Web3 Infrastructure Foundation and developed with support from Associate Professor Feng Yang's lab at Nanjing University and the Institute of Software Chinese Academy of Sciences, through R2CN.
Then the warning, which deserves to be quoted rather than paraphrased: the project is currently in WIP stage and should not be used in production environments. That is unusually direct for a project with published releases, and it frames everything else below. The recent releases are v0.1.3 from 2026-04-26, v0.1.2 and v0.1.1 both from 2026-03-09, so this is a 0.x project with three releases in six weeks. The primary language is Rust, the licence is Apache-2.0, the default branch is main, the homepage is rk8s.dev, and the last push was on 2026-10-05 with the project not archived.
The four components and the two deployment modes
The architecture section describes a distributed design with both standalone and cluster modes, and names four components.
RKL is the Container Runtime Interface, the primary runtime component supporting CLI operations and daemon mode. RKS is the control plane, a Kubernetes-like control plane combining API server, scheduler and controller functionality into one piece. Xline is etcd-compatible distributed storage for cluster state. And Redfannel is a centralized Flannel network solution implemented in Rust.
The naming pattern is worth noting: three of the four take a Kubernetes component and reimplement it in Rust, Xline for etcd and Redfannel for Flannel, while RKS folds three Kubernetes roles into one binary. The pattern is consistent with the stated aim of a lite version, and it also means each of these areas is where a deliberate simplification has been made.
Local mode, or standalone, is direct CLI interaction with the local container runtime. No central control plane is required, container creation and management are immediate, and it is described as ideal for development and testing. The three bullets say more than the label does: no control plane means no scheduler and no API server, so the CLI is doing what the control plane would otherwise do.
Cluster mode is the full Kubernetes-like arrangement. An RKS control plane handles scheduling and state management, RKL daemons run on worker nodes, Xline holds distributed state, and communication between components is QUIC-based.
QUIC is an interesting choice for the internal protocol and it is the one architectural decision in the README that is not a Kubernetes parallel. It suits a control plane talking to many workers, since it multiplexes over UDP and handles connection migration, but it also means rk8s is not speaking Kubernetes' own gRPC API between components, so this cluster would not interoperate with kubelet or kube-proxy.
Three workload types, and the pause container
The workload model has three levels, and the middle one is the interesting one.
A single container specification has a name, an image, ports with container port, protocol, host port and host IP, args, and resource limits:
name: single-container-test
image: ./rk8s/project/test/bundles/busybox
ports:
- containerPort: 80
protocol: ""
hostPort: 0
hostIP: ""
args:
- sleep
- "100"
resources:
limits:
cpu: 500m
memory: 233MiThe pod model is the Kubernetes one, with apiVersion and kind, metadata carrying labels, and a spec with a container list:
apiVersion: v1
kind: Pod
metadata:
name: simple-container-task
labels:
app: my-app
bundle: ./rk8s/project/test/bundles/pause
spec:
containers:
- name: main-container1
image: ./rk8s/project/test/bundles/busybox
args:
- "dd"
- "if=/dev/zero"
- "of=/dev/null"
ports:
- containerPort: 80
resources:
limits:
cpu: "500m"
memory: "512Mi"
status:The pod architecture is where the effort went. A pause container establishes shared namespaces for PID, network, IPC and UTS, and the work containers join the pause container's namespaces. On top of that there is CRI-compliant pod sandbox management, plus resource limits and port mappings per container.
The pause container is the standard Kubernetes trick, and the reason it exists is that a pod is not a process. A pod is several containers that share one network namespace so that they can reach each other over localhost, and sharing a namespace requires a process to hold it open. The pause container is that process, and it is why the pod lifecycle is decoupled from any individual container's lifecycle.
Implementing it correctly is more work than it looks, because the pause container must start first, the work containers must join it, and the sandbox has to be torn down in the right order when the pod ends. The CRI-compliant pod sandbox management line in the README is what tells you that part is being taken seriously.
The third workload type is Docker Compose. The README is explicit about why it exists: the compose functionality represents rk8s's philosophy of providing familiar developer experiences while maintaining Kubernetes compatibility, and it bridges the gap between local development workflows and production Kubernetes deployments. The design philosophy is four bullets: developer familiarity using Docker Compose syntax that developers already know, Kubernetes compatibility by internally translating compose specifications to Kubernetes-compatible pod structures, a unified runtime where a single runtime handles both Kubernetes pods and Compose applications, and progressive complexity so you can start with simple compose files and migrate to full Kubernetes specs as needed.
A compose file, and what it maps onto
The compose example is the most approachable thing in the README, and it is worth reading in full because it shows what the translation layer accepts.
services:
backend:
container_name: back
image: ./project/test/bundles/busybox
command: ["sleep", "300"]
ports:
- "8080:8080"
networks:
- libra-net
volumes:
- ./tmp/mount/dir:/app/data
frontend:
container_name: front
command: ["sleep", "300"]
image: ./project/test/bundles/busybox
ports:
- "80:80"
networks:
libra-net:
driver: bridge
configs:
backend-config:
file: ./config.yamlThe services are backend and frontend, each with a container_name, an image pointing at a local bundle path, a command given as an inline list, ports in the familiar string form, and a network. The backend also mounts a volume from a host directory to a container path, and the file declares a networks block with a bridge driver and a configs block pointing at a file.
So the supported surface includes services, named volumes, networks with a driver, and configs. That is a subset of the Compose specification, and the fact that configs are included at all is a little unexpected, since they are among the less widely used parts of the format.
What is striking is that the compose file contains nothing Kubernetes-shaped. There is no apiVersion, no kind, no labels. The translation described in the design philosophy happens underneath, and the way you would migrate to full Kubernetes specs is described as progressive: start with the compose file and move to Kubernetes resources as the application needs them, without changing the runtime that executes them.
For a team whose local development already uses Docker Compose, that is the interesting part. The same compose file describes the application locally and in the cluster, and the same runtime runs both. The cost is that the compose subset you can use is bounded by what the translation supports, so a compose file relying on an unsupported key will not behave the way Compose behaves.
Building and running it, step by step
The prerequisites are a Rust toolchain of 1.70 or newer, root privileges for container operations, and Docker for creating OCI bundles.
Root privileges are worth flagging. Every example command in the README is prefixed with sudo, because the runtime needs to set up namespaces, mount filesystems and manage cgroups directly rather than through a daemon that already holds those privileges. That is the same requirement as any low-level container runtime, and it is also why the local mode needs no control plane: the CLI does the privileged work itself.
The build is two cargo commands, one per binary:
cd rk8s/project/
cargo build -p rkl
cargo build -p rksThen two preparation steps. The network configuration is copied into place as a CNI config list:
sudo cp test/test.conflist /etc/cni/net.dAnd the root filesystem for the container image is extracted from a Docker image:
mkdir -p rootfs
docker export $(docker create busybox) | tar -C rootfs -xvf -That second command is the clearest illustration of the Youki relationship. The image is not pulled by rk8s at all. You export a container from Docker and untar it into a rootfs directory, and rk8s then treats that directory as an OCI bundle. So Docker is a build-time convenience for producing filesystem bundles, and the runtime works on directories.
Running a single container takes three commands:
sudo project/target/debug/rkl container run single.yaml
sudo project/target/debug/rkl container list
sudo project/target/debug/rkl container exec single-container-test /bin/shThe binary path is project/target/debug/rkl, which is the debug build output of the rkl package, so these are development commands rather than install commands.
Pod management in standalone mode uses pod run, pod state and pod exec. Cluster mode uses a --cluster flag pointing at the control plane address:
# Create pod via RKS control plane
sudo project/target/debug/rkl pod create pod.yaml --cluster 127.0.0.1:50051
# List pods from RKS
sudo project/target/debug/rkl pod list --cluster 127.0.0.1:50051
# Delete pod via RKS
sudo project/target/debug/rkl pod delete simple-container-task --cluster 127.0.0.1:50051And the daemon mode runs the runtime as a work node for the control plane:
sudo RKL_ADDRESS=127.0.0.1:50051 project/target/debug/rkl pod daemon # Monitors /etc/rk8s/manifests/ and acts as work node of rksThat daemon watches /etc/rk8s/manifests/ and acts as a work node, which is a static-pod arrangement in the style of the kubelet's static pod handling.
The repository, and the build system is not Cargo alone
The top-level listing is worth reading because it reveals a build setup more unusual than the Rust toolchain alone.
There are both Cargo and Buck artefacts: a .buckconfig, a .buckroot, a BUCK file, a PACKAGE file and a buckal.snap. So the project can be built with Meta's Buck2 build system as well as with Cargo. There is also a flake.nix and a flake.lock, so Nix is a supported way to get the toolchain and dependencies. There is a .devcontainer/ directory, an .envrc, setup.sh and install.sh, and a .pre-commit-config.yaml for hooks.
There are also platforms/, toolchains/ and third-party/ directories, plus a LICENSE-APACHE, a LICENSE-MIT and a LICENSE-THIRD-PARTY, so the licensing is triple: the project itself is Apache-2.0, and the third-party directory carries its own terms.
The project structure diagram in the README shows the internal layout, and the rkl component is the part with the detail. Under project/rkl/src there are commands/ with compose/, container/ and pod/ subdirectories for the three workload types, cri/ for the CRI API definitions, daemon/ for daemon mode, task.rs for pod task orchestration, and main.rs as the CLI entry point. There is a tests/ directory for integration tests. Alongside that, project/rks/ is the control plane server and project/libnetwork/ is the Redfannel network.
The docs/ directory and the README's pointer to project/rks/README.md for the details of building a cluster with RKS and RKL suggest the documentation is split by component, which is the right arrangement for a system with two binaries and two deployment modes.
The one thing to note about the toolchain is that a Rust 1.70 floor is quite old by the standards of a project whose last push was in October 2026, and it constrains which language features and dependency versions are available. That is a deliberate choice for compatibility rather than an oversight, and it does mean some newer crates will not be usable.
How to evaluate it, and what it is actually for
There is a real question here about what this project is for, and the README does not quite answer it.
The honest answer is that it is educational and experimental. A WIP-stage system that says outright it should not be used in production, that carries a 0.x version number, and that implements a Kubernetes-compatible subset rather than the Kubernetes API, is not going to replace kubelet in anyone's cluster. The feature list is short: CRI compliance, Kubernetes compatibility for pod specifications and resource management, Docker Compose support, and namespace sharing through pause containers.
So the value is in the code and the design, and in what it demonstrates about a specific approach: implementing the CRI from scratch in Rust, rather than wrapping an existing runtime, and pairing that with a Rust reimplementation of the etcd-compatible storage layer and the Flannel networking layer. That is a coherent bet. A Kubernetes-shaped system that does not speak Kubernetes' own wire protocols is useful precisely because you can read all of it.
The parts worth studying. The pause container namespace sharing is the mechanism most implementations get subtly wrong, and here it is implemented properly with CRI-compliant sandbox management. The Compose-to-Kubernetes translation with a unified runtime underneath is a design pattern that many teams end up reinventing badly. And the QUIC-based internal protocol is a deliberate departure from Kubernetes' gRPC assumptions, which is the kind of choice that is worth seeing even if you would not make it.
For an evaluation, the practical checklist is short. You need Rust 1.70 or newer, Docker, and root, and the setup means exporting an image into a rootfs directory by hand rather than pulling one. The three workload types are the three things to try, and the standalone mode is the one to start with because it needs no control plane, no Xline and no quorum.
If you are looking for something to run in production, this is not it and the README says so. If you are looking for a compact, readable reference implementation of the container runtime interface and the pod model in Rust, with an academic group behind it and a documented WIP status, it is a good deal more useful than most blog posts on the subject.
Editorial conclusion
Adopt rk8s if you want a compact, readable Rust implementation of the Container Runtime Interface and the Kubernetes pod model to study or prototype against, especially if you are interested in the pause container namespace sharing, the Compose-to-Kubernetes translation, or the QUIC-based internal protocol. Do not adopt it for production, because the README says outright that it is WIP and should not be used in production environments, and do not expect it to interoperate with an existing Kubernetes cluster, since it implements the CRI rather than the Kubernetes API and uses its own storage and networking layers. Before you commit, start in standalone mode since it needs no control plane, Xline or quorum, remember that every command needs root, and read project/rks/README.md for the cluster details, because the root README covers the runtime far more fully than the control plane.
Frequently asked questions
What is rk8s?
It is a lightweight, Kubernetes-compatible container orchestration system written in Rust, built on top of Youki, implementing the Container Runtime Interface with support for single containers, Kubernetes-style pods and Docker Compose-style multi-container applications. It is Apache-2.0 licensed and the homepage is rk8s.dev.
Is rk8s ready for production use?
No. The README states that the project is currently in WIP stage and should not be used in production environments. The recent releases are v0.1.3 from 2026-04-26 and v0.1.2 and v0.1.1 from 2026-03-09, so it is an early 0.x project.
What are the main components of rk8s?
RKL is the Container Runtime Interface component supporting CLI operations and daemon mode, RKS is a control plane combining API server, scheduler and controller functionality, Xline is etcd-compatible distributed storage for cluster state, and Redfannel is a centralized Flannel network solution implemented in Rust.
How does rk8s implement the Kubernetes pod model?
With a pause container that establishes shared PID, network, IPC and UTS namespaces, and work containers that join the pause container's namespaces. On top of that it implements CRI-compliant pod sandbox management, with resource limits and port mappings per container.
How does the Docker Compose support work in rk8s?
You write ordinary Docker Compose syntax, and rk8s internally translates the compose specification into Kubernetes-compatible pod structures, with a single runtime handling both Kubernetes pods and Compose applications. The stated goal is to bridge the gap between local development workflows and production Kubernetes deployments.
What do I need to build and run rk8s?
A Rust toolchain of 1.70 or newer, root privileges for container operations, and Docker for creating OCI bundles. You build the two binaries with cargo build -p rkl and cargo build -p rks, copy a CNI config list into /etc/cni/net.d, and export a Docker image into a rootfs directory before running the CLI.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rk8s-dev-rk8s)Was this useful?