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 Works

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.

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

FeatureCRI-ODockercontainerd
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 or Podman for that.

Installation guide

1. Install CRI-O

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

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

On Ubuntu/Debian:

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

2. Check if CRI-O is Running

systemctl status crio

3. Use CRI-O with Kubernetes

Tell kubelet to use CRI-O instead of Docker:

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

4. Run a Container Using CRI-O

Use crictl (CRI-O’s CLI tool) to pull and run a container:

crictl pull alpine
crictl runp alpine.json

Common Issues and Fixes

Pods Stuck in ContainerCreating

Possible Cause: Kubelet is not configured to use CRI-O
Fix: Check if CRI-O is running and kubelet is using the correct CRI socket:

ps aux | grep kubelet

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

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/

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 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.