Architectural Friction in OCI Runtimes: Linux Kernel Primitives and Go Runtime Constraints
Developing a custom container runtime highlights how OCI implementations like runc orchestrate kernel primitives while navigating fundamental mismatches in Go's execution model. The reliance on pre-runtime C modules, process self-execution workarounds, and userspace network stack reimplementations demonstrates the true underlying mechanics of container isolation.
Kernel Primitives and Process Isolation
Containers do not exist as a unified entity within the Linux kernel. Isolation is achieved by composing five distinct kernel features, primarily utilizing namespaces to restrict visibility, control groups (cgroups) to enforce resource limits, and dedicated network isolation mechanisms.
At the host level, container processes are standard Linux processes directly observable within the host `/proc` directory. Container images are localized host directory structures. The runtime isolates execution by placing the extracted image folder on disk and calling `chroot` or `pivot_root` to establish that directory as the process root prior to executing the target binary.
Go Runtime Conflicts in OCI Execution
The standard container runtime, `runc`, encounters structural friction due to its implementation in Go. Go utilizes a natively multithreaded runtime, whereas several Linux system calls required during container setup must execute within a single-threaded context.
To bypass this limitation, `runc` embeds a specialized C module that executes critical syscalls before the Go runtime initializes. Additionally, Go lacks a native `fork` system call wrapper because forking a multithreaded process creates concurrency hazards. To achieve the standard process setup pattern, `runc` re-executes `/proc/self/exe` with specific command-line arguments to simulate a child process fork, allowing it to apply isolation parameters before calling `exec` on the final workload binary.
Root Privileges and Userspace Networking Constraints
Many kernel APIs leveraged by container runtimes require root privileges, leading traditional architectures like the Docker daemon to run with elevated host permissions.
Executing runtimes in a rootless configuration presents significant engineering trade-offs, particularly within networking. Because rootless runtimes cannot manipulate elevated kernel networking interfaces directly, they must reimplement the entire network stack within userspace to deliver parity with root-level container networking features.