logo

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.

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