CRI-O: The OCI runtime bridge for Kubernetes clusters that want to skip the Docker layer
Open Container Initiative-based implementation of Kubernetes Container Runtime Interface.
At a glance
- What is it?
- CRI-O is a Kubernetes CRI implementation that talks directly to OCI runtimes like runc, skipping the Docker daemon. This review covers its scope, architecture, configuration, and the maintenance constraints that come with following Kubernetes release cycles.
- Who is it for?
- Adopt CRI-O if you run Kubernetes and want a minimal CRI implementation that talks directly to OCI runtimes, especially on OpenShift or in environments where you already use container-libs tools. Do not adopt it if you need a CLI for day-to-day container management, because the project explicitly does not guarantee backward compatibility for its test-only CLIs.
- 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 received new commits within the last day.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What CRI-O actually replaces
Kubernetes does not launch containers directly. It talks to a container runtime through the Container Runtime Interface, a gRPC API that the kubelet calls. CRI-O is one implementation of that interface. The README states that CRI-O provides an integration path between OCI conformant runtimes and the kubelet. In practice, that means CRI-O replaces the Docker daemon or containerd as the thing that pulls images, manages storage, and starts processes. The target user is a Kubernetes cluster operator who wants a runtime that is narrowly scoped to the CRI and nothing else. The project explicitly excludes building, signing, and pushing images, and it excludes providing a stable CLI. That is a sharper boundary than most runtimes draw.
How CRI-O is built: OCI runtimes and container-libs
The architecture is visible in the README's list of components. CRI-O uses runc, or any OCI runtime-spec implementation, to execute containers. It uses container-libs/image for image management and container-libs/storage for image layers and overlay filesystems. Networking goes through CNI. The data flow is straightforward: the kubelet sends a CRI request, CRI-O translates it into OCI runtime calls, and the runtime starts the container. The storage and image libraries come from the containers project, which is the same ecosystem that powers tools like Podman. That means CRI-O is not a from-scratch runtime. It is a thin CRI layer on top of shared container libraries. The README also mentions support for OCI hooks, which lets you run custom actions at container lifecycle events. The integration with the kubelet is the core, and everything else is delegated.
Getting it running: install and configuration
The README points to a packaging repository for installation, but the configuration section is the part that matters. CRI-O is configured through a TOML file, typically at /etc/crio/crio.conf. Key settings include the runtime path, the storage driver, and the network plugin. For a basic setup, you install the package, point the kubelet at the CRI-O socket, and start the service. The README gives commands for running Kubernetes with CRI-O, but the exact commands are in the truncated part of the material. What is clear is that CRI-O exposes an HTTP status API, metrics endpoints, and tracing support. These are the operational surfaces you need to monitor a runtime. The metrics endpoint is Prometheus-compatible, which is standard for Kubernetes components. The configuration file is the main thing you will edit, and it follows the conventions of the container-libs ecosystem.
The maintenance model: manual backports and version skew
The README is explicit about how releases work. CRI-O follows Kubernetes minor versions, so v1.36 corresponds to Kubernetes 1.36. Patch releases are not synchronized with Kubernetes patch releases. Kubernetes patches ship monthly, while CRI-O patches ship only when necessary. The README states that maintenance on release-1.x branches is manual and only bugfixes are backported. That is a real operational cost. If you run a Kubernetes cluster that is not on the latest minor version, you depend on the community deciding to backport a fix. The version skew policy matches Kubernetes n-2, meaning CRI-O supports the current and two previous minor Kubernetes versions. But the manual backport process means you cannot assume a fix will arrive in your branch. You have to track the release notes, which are hand-crafted and published on the GitHub Pages site.
What CRI-O does not do: the CLI and image building gap
The README is refreshingly honest about what is out of scope. CRI-O does not build, sign, or push images. That is not a gap; it is a design choice. But the CLI part is a limitation. Any CLI built as part of CRI-O is only for testing, and there is no backward compatibility guarantee. That means you cannot rely on a CRI-O command as part of your operational tooling. If you need to inspect containers, pull images, or debug runtime state, you have to use cri-tools (crictl) or Kubernetes itself. The project also does not provide a user-facing interface for interacting with CRI-O. This is the wrong tool if you want a runtime that doubles as a developer tool. The scope is strictly the CRI, and anything beyond that is left to other projects.
The alternative: containerd and the difference in approach
The main alternative to CRI-O is containerd, which is also a CRI implementation but takes a different architectural path. containerd is a full container runtime that includes its own image management, snapshotters, and a stable CLI (ctr). It originated from the Docker ecosystem and is now a CNCF project. CRI-O, by contrast, delegates image and storage handling to container-libs, which are shared with Podman and other tools. The practical difference is that containerd is a standalone runtime that you can use outside Kubernetes, while CRI-O is tightly coupled to the CRI and the kubelet. If you need a runtime that works for both Kubernetes and standalone container workflows, containerd is the more flexible choice. If you want a minimal CRI implementation that does not carry the Docker lineage, CRI-O is the cleaner fit. The README does not compare itself to containerd, but the scope statements make the difference clear.
Licence and operational considerations
CRI-O is licensed under Apache-2.0, which is permissive and compatible with most enterprise use. The README references a license scan and a FOSSA badge, indicating the project tracks dependency licenses. That matters if you are deploying in an environment that requires license compliance. The project is part of the Kubernetes community, with governance and a weekly meeting, so it is not a solo effort. The CI setup is split between GitHub Actions and OpenShift's Prow, which is a sign of the project's ties to OpenShift. That relationship is worth noting: Red Hat and OpenShift are heavy users of CRI-O, and the project's roadmap is shaped by that. If you are on OpenShift, CRI-O is the default runtime, so the maintenance cost is absorbed by a larger community. If you are on vanilla Kubernetes, you have to weigh the manual backport model against the convenience of a runtime that is updated in lockstep with Kubernetes.
Editorial conclusion
Adopt CRI-O if you run Kubernetes and want a minimal CRI implementation that talks directly to OCI runtimes, especially on OpenShift or in environments where you already use container-libs tools. Do not adopt it if you need a CLI for day-to-day container management, because the project explicitly does not guarantee backward compatibility for its test-only CLIs. Before adopting, verify that your Kubernetes version matches a supported CRI-O minor release, check the compatibility matrix, and confirm that your OCI runtime (like runc) meets the runtime-spec requirements. Also verify which patch releases are available for your chosen branch, since maintenance is manual and bugfixes are not backported automatically.
Community notes