# CRI-O: The Lightweight Container Runtime for Kubernetes

CRI-O is an open-source container runtime designed to provide a lightweight and Kubernetes-native way to run containers. It adheres to Kubernetes' Container Runtime Interface (CRI), allowing Kubernetes to manage containers without needing Docker or other full-fledged container runtimes.

## **Purpose**

When Kubernetes first became popular, it relied on Docker as the default container runtime. However, Docker was built with a broader focus, including features Kubernetes didn’t need (such as image building and registry management). This led to inefficiencies, prompting the Kubernetes community to create CRI-O—a runtime that does only one thing: run and manage containers in Kubernetes.

Think of it as a lean and optimized engine, built specifically for Kubernetes, without the extra weight of Docker’s full toolset.

## **How Does it Work**

CRI-O acts as the middleman between Kubernetes and low-level container runtimes like **runc** (which actually runs the container process). Here’s how it fits into the ecosystem:

1. **Kubernetes API Server → Kubelet**  
   Kubernetes schedules workloads to nodes and tells the **kubelet** (node agent) to run a container.
2. **Kubelet → CRI-O (via CRI)**  
   Instead of talking to Docker, the kubelet communicates with CRI-O using the Container Runtime Interface (CRI).
3. **CRI-O → runc (or another OCI-compliant runtime)**  
   CRI-O then uses **runc** to actually launch the container.

This streamlined approach eliminates unnecessary layers, reducing **overhead, attack surface, and resource consumption**.

## **Key Features**

### **1. Lightweight and Kubernetes-Native**

CRI-O is built only for Kubernetes, making it smaller, faster, and more efficient than other container runtimes.

Example:

A typical Kubernetes cluster using Docker requires extra components like the Docker daemon. With CRI-O, this is unnecessary—everything is streamlined, reducing CPU and memory overhead.

### **2. Supports Open Container Initiative (OCI) Standards**

It supports any OCI-compliant container images and runtimes (such as runc and crun), making it flexible.

**Example:**  
You can run an OCI-compliant image from Docker Hub without modifying it.

```none
crictl pull nginx
crictl runp nginx.json
```

This pulls and runs an Nginx container without requiring Docker.

### **3. No Unnecessary Features (Unlike Docker)**

CRI-O removes features that Kubernetes doesn’t need, such as:

- Building images
- Managing registries
- Swarm orchestration

Instead, it focuses purely on running containers efficiently.

### **4. Security Enhancements**

CRI-O integrates seccomp, SELinux, and AppArmor for hardened security. Since it doesn’t require a long-running daemon (unlike Docker), it reduces the attack surface.

Example:

If a container escapes, the absence of a centralized Docker daemon makes it harder for an attacker to gain control over the host system.

### **5. Faster Pod Startups**

Since CRI-O is optimized for Kubernetes, it can launch pods faster than Docker.

Example:

In large clusters, switching from Docker to CRI-O can reduce pod startup times by 30-40%.

## **Comparing CRI-O with Docker and containerd**

| Feature | CRI-O | Docker | containerd |
| --- | --- | --- | --- |
| Kubernetes Focused | ✅ Yes | ❌ No (General-purpose) | ✅ Yes |
| Lightweight | ✅ Yes | ❌ No (Includes extra tools) | ✅ Yes |
| Supports Kubernetes CRI | ✅ Yes | ❌ No (Needs dockershim) | ✅ Yes |
| Security Hardened | ✅ Yes | ❌ No | ✅ Yes |
| Supports OCI Images | ✅ Yes | ✅ Yes | ✅ Yes |

## **Use Cases**

**Best choice for Kubernetes clusters**

- If you run Kubernetes, especially large-scale clusters, it improves **efficiency and performance**.

**Not for local development**

- Unlike Docker, CRI-O does not include image-building tools. You would still need **[Buildah](https://buildah.io/)** or **[Podman](https://podman.io/)** for that.

## **Installation guide**

### **1. Install CRI-O**

On a **RedHat-based system** (like CentOS, Fedora, RHEL):

```none
sudo dnf install cri-o
sudo systemctl enable --now crio
```

On **Ubuntu/Debian**:

```none
sudo apt-get update
sudo apt-get install cri-o
sudo systemctl enable --now crio
```

### **2. Check if CRI-O is Running**

```none
systemctl status crio
```

### **3. Use CRI-O with Kubernetes**

Tell kubelet to use CRI-O instead of Docker:

```none
kubeadm init --cri-socket=/var/run/crio/crio.sock
```

### **4. Run a Container Using CRI-O**

Use [crictl](https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md) (CRI-O’s CLI tool) to pull and run a container:

```none
crictl pull alpine
crictl runp alpine.json
```

## **Common Issues and Fixes**

### **Pods Stuck in ContainerCreating**

**Possible Cause:** [Kubelet](/content/finops-glossary/kubernetes-kubelet/index.html) is not configured to use CRI-O

**Fix:** Check if CRI-O is running and kubelet is using the correct CRI socket:

```none
ps aux | grep kubelet
```

If needed, restart kubelet with the CRI-O socket:

```none
systemctl restart kubelet
```

### **Can’t Pull Container Images**

**Possible Cause:** Registry authentication issue

**Fix:** Make sure your authentication credentials are set up in `/etc/crio/crio.conf.d/`

```none
cat /etc/crio/crio.conf.d/00-default
```

## **Future of CRI-O**

- With **Docker support removed from Kubernetes (since v1.20)**, **CRI-O and [containerd](/content/finops-glossary/containerd/index.html)** have become the standard choices.
- **Adoption is growing**, especially in RedHat OpenShift and other Kubernetes-focused environments.
- Continuous security enhancements and performance optimizations make CRI-O one of the best choices for running Kubernetes workloads.
