# runc in Kubernetes

runc is a lightweight, portable container runtime that serves as the reference implementation of the Open Container Initiative (OCI) runtime specification. In Kubernetes, runc is the low-level tool responsible for actually creating and running containers, often behind the scenes of higher-level container runtimes like containerd or CRI-O.

## History and Context

Containers in Kubernetes go through a layered runtime model:

1. Kubernetes (kubelet) delegates container tasks to a Container Runtime Interface (CRI)-compliant runtime.
2. That runtime further delegates container execution to **runc**, which uses Linux primitives like cgroups and namespaces to start containers.

Originally, [Docker](/content/finops-glossary/docker-and-containerization-a-complete-guide/index.html) used `runc` internally, and over time, the Kubernetes ecosystem moved toward **modular runtimes** like containerd, still relying on `runc` underneath to perform the actual syscall-heavy lifting.

## Why `runc` Matters

Even though it rarely gets direct attention, `runc` is the last stop before a container becomes a running Linux process. It’s responsible for:

- Setting up **Linux namespaces** (for isolation)
- Creating **control groups (cgroups)** for resource limits
- Executing the container process in a **minimalist environment**
- Mounting the container filesystem
- Managing **standard input/output** streams
- Running the container process as PID 1 inside the namespace

If Kubernetes were a restaurant, `runc` is the chef — not the one taking the order (that’s the kubelet), or even the head chef organizing tasks (containerd), but the actual person cooking your meal on the stove.

## Example: The Container Lifecycle with `runc`

Let’s say you deploy a pod to your Kubernetes cluster. Here’s a simplified lifecycle:

1. `kubelet` sees the pod and calls the CRI runtime (like containerd).
2. [Containerd](/content/finops-glossary/containerd/index.html) pulls the container image and unpacks it.
3. Containerd calls `runc` to start the container.
4. `runc`:
   - Sets up namespaces (PID, net, mount, etc.)
   - Applies resource constraints with cgroups
   - Mounts the root filesystem
   - Spawns the user process inside the container

At this point, the container is live, running as a Linux process, isolated by `runc`.

You can even test this yourself:

```none
runc run my-container-id
```

Or inspect an already running container:

```none
runc list
runc exec my-container-id ps aux
```

Note: In Kubernetes, these are typically abstracted by higher-level runtimes. You’d rarely run `runc` directly — but it’s still the core engine under the hood.

## Technical Details and Features

- **Written in Go** and highly portable
- Based on the [OCI Runtime Specification](https://github.com/opencontainers/runtime-spec)
- Lightweight and **stateless** — all state is passed at runtime
- Supports Linux **cgroups v1 and v2**
- Works on most modern Linux distributions

## Security Considerations

Because `runc` interacts with the Linux kernel directly, it’s part of your **trusted computing base (TCB)**. A vulnerability in `runc` can potentially allow container breakout or privilege escalation.

One such example:

> **CVE-2019-5736**: A flaw in `runc` allowed containers to overwrite the binary and execute code on the host. It was patched quickly, but it highlighted how deep control `runc` has.

**Best Practice**: Regularly update your runtime stack (containerd, runc, CRI-O) and monitor advisories from Kubernetes or your Linux distribution.

## Relation to Other Tools

| Tool | Role |
| --- | --- |
| `kubelet` | Talks to container runtime via CRI |
| `containerd` | CRI-compatible runtime that manages image + lifecycle |
| `runc` | Executes container processes with Linux namespaces |
| CRI-O | Another CRI-compatible runtime, also uses `runc` |

Other alternatives to `runc` include:

- **gVisor** (sandboxed containers for security)
- **Kata Containers** (lightweight VMs for isolation)
- **youki** (written in Rust, up-and-coming OCI runtime)

## When You Might Interact with `runc`

Most Kubernetes users **never touch `runc` directly** — and that’s okay. But here’s when it might matter:

- **Troubleshooting runtime failures**: If containers fail to start and logs from containerd or CRI-O don’t help, you might inspect the actual `runc` call.
- **Building custom Kubernetes runtimes**: If you’re developing an alternative runtime, `runc` might be the component you wrap or replace.
- **Low-level debugging**: Inspecting namespaces, cgroups, or processes inside a container.

## Real-World Use Case: Debugging Stuck Pods

Let’s say your pod is stuck in `ContainerCreating` and you’ve ruled out networking and image pull issues. You SSH into the node and run:

```none
sudo runc list
```

You find a container that’s “created” but not “running”. You can try:

```none
sudo runc exec <container-id> bash
```

This helps you get inside the container (if it’s partially created), check environment variables, mounted volumes, or why a process failed to launch.

## Summary

> **`runc` is the silent workhorse of the container world.** It’s not flashy, but it’s critical — responsible for turning container definitions into actual Linux processes with isolation, security, and performance. Every time you deploy a pod, `runc` is the one that actually makes it come alive.
