コンテナ標準化が進んでいる事は知りつつも、標準化された仕様の具体的な内容についてはあまり知らない事に気づいたので、この機会に調べてみました。個人向けメモとして残しておきます。
余力があれば、後でもう少し詳細をまとめる予定です(docker image を OCI Image Format に変換して眺めてみたり、runc や containerd などを実際に動かしてみたり、containerd や CRI-O などの Container Runtime の実装に目を通してみたりしたので、その辺りについてもいつかまとめたいと思ってます)。
追記: 手を動かして調べた内容は以下の2つのブログにまとめました。
以下、調査した内容をまとめたメモです。
コンテナ標準と Open Container Initiative (OCI) について
コンテナ標準は Open Container Initiative (OCI) と呼ばれる団体によって仕様策定が進められている。 image format, (low-level) runtime については既に標準が存在している(v1.0.0 をリリース済み)。distribution (container registry 周り) については仕様策定中の状態(2020年12月6日時点で GitHub の tag では v1.0.0-rc1 が出ている状態)。
以下、 OCI が定める各種標準仕様について簡単にまとめる。
OCI Image Format Specification
- Docker Image のような「container を記述する image format」の標準仕様。これは Docker Image の最新 format である Docker Image Manifest V2, Schema 2 をベースに標準化したもの。
- 以下が Docker 社からの公式声明。
Given this state of the world in late 2015, the OCI image specification work began in earnest with a strong group of collaborating independent and vendor-associated participants, using the Docker v2.2 image format as a starting point.
- cf. https://opencontainers.org/posts/blog/2018-10-11-oci-image-support-comes-to-open-source-docker-registry/
- Container Registry とのデータのやり取りも OCI Image Format(およびそれの元になった Docker Image Manifest V2, Schema2)に準拠する形で行われる。
- 後述する OCI Runtime Specification で利用される Filesystem Bundle を生成する Conversion 処理 についても仕様が策定されている。
OCI Runtime Specification
- Container 管理を行う Container Runtime の標準仕様。後述するが、Low-Level Container Runtime と呼ばれるものはこの仕様に準拠している。
- これは Docker 社が OCI に寄贈した “runC” とほぼ対応づくもの。
runc depends on and tracks the runtime-spec repository. We will try to make sure that runc and the OCI specification major versions stay in lockstep. This means that runc 1.0.0 should implement the 1.0 version of the specification.
- https://github.com/opencontainers/runc
- 「コンテナの configuration file およびコンテナの root filesystem をまとめたもの」である Filesystem Bundle や、OCI Runtime 準拠の Container Runtime で行える操作 について仕様を策定している。
OCI Distribution Specification
- Container Registry との通信における標準仕様。Docker Hub や Google Container Registry など各種 Container Registry が従っている Docker Registry HTTP API V2 をベースに仕様策定が進められている。最新は v1.0.0-rc1。
The spec is based on the specification for the Docker Registry HTTP API V2 protocol apdx-1.
- cf. https://github.com/opencontainers/distribution-spec/blob/master/spec.md
Container Runtime について
Container Runtime と呼ばれるものは複数存在するが、ものによって担当する layer が違う。以下、一例を紹介(注: 他にも Container Runtime と呼ばれるものはいくつかあるが、ここでは自分の理解のために調べた一部に限定している)。
runc
- 前述した OCI Runtime Specification を素朴に実装したもの。後述する containerd と対比して、Low-Level Container Runtime と紹介をされる例を見かける。
runc is a low-level container runtime, as it directly uses namespace and cgroups to create containers.
- https://insujang.github.io/2019-10-31/container-runtime
- Docker 社が「ツールとしての Docker」の一部を OSS として公開したのが出自。
And today we are spinning out runC as a standalone tool, to be used as plumbing by infrastructure plumbers everywhere.
- https://www.docker.com/blog/runc/
- OCI Runtime Specification で定められた Filesystem Bundle と呼ばれる「コンテナの configuration file およびコンテナの root filesystem をまとめたもの」を元に、コンテナの作成、削除、状態の取得などの操作が可能。
- README の Using runc を参照して動かしてみると動作がイメージできる。
containerd
- container registry からの image 取得、runc などの low-level container runtime を利用した container 起動(OCI Runtime Specification で定められた filesystem bundle 生成を含む)、container 管理などを行うもの。
- daemon として動作する。client からは
/run/containerd/containerd.sock
経由の gRPC API で通信を行い、container 作成や task 実行などの操作が可能。 - 後述する Container Runtime Interface (CRI) もサポートしている
- 「ツールとしての Docker」から利用されている。そもそも、Docker 社が CNCF へ寄贈したのが出自。
Today, Docker announced its intention to donate the containerd project to the Cloud Native Computing Foundation (CNCF).
- https://www.docker.com/blog/docker-donates-containerd-to-cncf/
CRI-O
- containerd とだいたい似たレイヤーを担当。「Kubernetes から利用されること(CRI に準拠していること)」を念頭に開発されてる。
Last year, the Kubernetes project introduced its Container Runtime Interface (CRI)
Building on that work, the CRI-O project (originally known as OCID) is ready to provide a lightweight runtime for Kubernetes.
- https://www.redhat.com/en/blog/introducing-cri-o-10
- runc を始めとして、いくつかのコンポーネントを組み合わせた実装になっている
The plan is to use OCI projects and best of breed libraries for different aspects:
- Runtime: runc (or any OCI runtime-spec implementation) and oci runtime tools
- Images: Image management using containers/image
- Storage: Storage and management of image layers using containers/storage
- Networking: Networking support through use of CNI
- https://github.com/cri-o/cri-o#what-is-not-in-scope-for-this-project
Kubernetes が定める Container Runtime Interface (CRI) について
- Kubernetes は Container Runtime Interface (CRI) と呼ばれる「独自で定義した API」を利用して、Container Runtime と通信を行う
- CRI は基本的には「protocol buffer で記述された gRPC API」。container を操作するために必要な操作が RPC として定義されている。
CRI consists of a protocol buffers and gRPC API, and libraries, with additional specifications and tools under active development
- cf. https://kubernetes.io/blog/2016/12/container-runtime-interface-cri-in-kubernetes/
- アクティブに開発されてる Container Runtime は、CRI を実装している。一例は以下(注: Docker については Kubernetes 開発者によって dockershim と呼ばれる CRI サポート用のツールが実装されていた)。
This page lists details for using several common container runtimes with Kubernetes, on Linux:
- containerd
- CRI-O
- Docker
- https://kubernetes.io/docs/setup/production-environment/container-runtimes/
- 先週、 Docker が Kubernetes の Container Runtime としては Deprecated になった ことが話題になったが、これは dockershim のメンテナンスを将来のバージョンで止めるというアナウンス。
- 自分が調べた限りでは、containerd, CRI-O などの Container Runtime はどれも複数の image format をサポートしていて、「docker build で生成した container image」は引き続き利用可能。
- “Docker Image Manifest V2, Schema 2” と “OCI Image Format Specification” はどちらもサポートされている。
- そもそもこれらは「ほぼ同一」ある(一部の mediaType が違うくらいで、1対1対応)
The OCI image manifest is also a registry image manifest that defines components that make up an image. The format is essentially the same as the Docker V2.2 format, with a few differences.
- mediaType - must be set to application/vnd.oci.image.manifest.v1+json
- config.mediaType - must be set to application/vnd.oci.image.config.v1+json
Each object in layers must have mediaType be either application/vnd.oci.image.layer.v1.tar+gzip or application/vnd.oci.image.layer.v1.tar.
- https://containers.gitbook.io/build-containers-the-hard-way/#registry-format-oci-image-manifest
- そもそもこれらは「ほぼ同一」ある(一部の mediaType が違うくらいで、1対1対応)
- “Docker Image Manifest V2, Schema 2” と “OCI Image Format Specification” はどちらもサポートされている。
- そのため、「docker build で作成した container image を container registry へ push して、k8s から利用する」という一連のワークフローに関していえば、containerd or CRI-O を使っても問題になる事は一切無い はず
- もちろん、以下の Blog で言及されてるように「Kuberrnetes 内で Docker 自体の機能に依存していた場合」は対応が必要