OCI vs CRI
TL;DR
- OCI: Open Container Initiative (https://www.opencontainers.org/)
- low-level specs: standarizes container images, runtimes, and registries.
- NOT specific to kubernetes.
- CRI: Container Runtime Interface
- high-level specs: enables
kubelet
to talk to any OCI compliant container runtimes. - specific to Kubernetes.
- high-level specs: enables
The relationship can be illustrated as in this diagram:
Registry kubelet
| |
| v
(OCI distribution-spec) (CRI)
| |
| v
Containerfile -> Images -> Container Runtime -> Containers
Dockerfile (OCI image-spec) (OCI runtime-spec)
OCI: Open Container Initiative
OCI defines 3 important specs:
- the Runtime Specification(runtime-spec): standardizes container runtimes.
- the Image Specification(image-spec): what does an image look like.
- the Distribution Specification(distribution-spec): how images can be pulled.
OCI Image (image-spec)
Benefits:
- Deduplication of layers of images in releases; saving space.
- File verification thru SHA digests stored in Index and Manifests against file corruption.
- Listing Image Manifest of the bundle (before storing); full transparency to the customer.
Structure:
- OCI Image can be nested.
- A
oci-layout
file specifying the layout version:"imageLayoutVersion": "1.0.0"
- Root level must have:
index.json
MediaType
is either one of:- index:
application/vnd.oci.image.index.v1+json
- manifest:
application/vnd.oci.image.manifest.v1+json
- index:
- Artifacts are stored in
oci/blobs/<alg>/<digest>
, e.g.oci/blobs/sha256/XXXXXXXXXXX
MediaType is flexible
(Some are JSON some are binary)application/vnd.oci.image.config.v1+json
application/vnd.oci.image.layer.v1.tar+gzip
- References are all done by digest
- "file whose digest is
sha256:cdce9e...
" - instead of "file whose name is
layer.tar.gz
"
- "file whose digest is
- Merkle DAG (Directed Acyclic Graph)
- content dedup by digest
- immutable - tamper proof
- no circular dependency
Docker images will use application/vnd.docker.*
instead of application/vnd.oci.*
in mediaType
.
OCI Runtime Bundle (runtime-spec)
runc
doesn't recognize images; runc
is runtime-spec
compliant, so it expects an OCI Runtime Bundle, which is basically a root filesystem and a config.json
file.
OCI Image => (OCI converter / OCI Runtime Bundle Generator) => OCI Runtime Bundle => (runc) => container
OCI Runtime Bundle = a root filesystem + config.json
bundle/
|- config.json
|- rootfs/
The process:
- Start with an OCI Image.
- Apply the filesystem layers in the order specified in manifest.
- Generate
config.json
. - OCI Runtime Spec bundle is formed,
runc
now has enough information to run. - apply cgroup / namespace etc on Linux host.
OCI Registries (distribution-spec)
Docker Registry v2 API is a well known specification for any Docker registry (docker.io, gcr.io, Harbor etc.). Any time you’re doing docker pull
(or other Docker commands), the Docker client is interacting with the Docker registry using a protocol defined in Docker Registry v2 API specification.
OCI Distribution Specification is an effort to standardize the Docker Registry v2 API, which is largely the same as Docker Registry v2 API (intentional). Most of the Docker registry on the market nowadays supports it in addition to the Docker Registry v2 API support.
distribution-spec
allows other "artifacts" (e.g. Helm charts) to be stored in OCI registries.
You can store charts, images, and other artifacts in a single OCI registry.
CRI: Container Runtime Interface
Defines an API between Kubernetes (kubelet
) and the container runtime (defined by OCI).
- defines the main gRPC protocol for the communication between the cluster components
kubelet
and container runtime. - CRI =
RuntimeService
+ImageService
: https://github.com/kubernetes/cri-api/blob/master/pkg/apis/runtime/v1/api.proto - The
kubelet
acts as a client when connecting to the container runtime via gRPC. The runtime and image service endpoints have to be available in the container runtime.