コンテナ標準化が進んでいる事は知りつつも、標準化された仕様の具体的な内容についてはあまり知らない事に気づいたので、この機会に調べてみました。個人向けメモとして残しておきます。

余力があれば、後でもう少し詳細をまとめる予定です(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 社からの公式声明。
  • 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 Runtime について

Container Runtime と呼ばれるものは複数存在するが、ものによって担当する layer が違う。以下、一例を紹介(注: 他にも Container Runtime と呼ばれるものはいくつかあるが、ここでは自分の理解のために調べた一部に限定している)。

runc

  • 前述した OCI Runtime Specification を素朴に実装したもの。後述する containerd と対比して、Low-Level Container Runtime と紹介をされる例を見かける。
  • Docker 社が「ツールとしての Docker」の一部を OSS として公開したのが出自。
  • 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 へ寄贈したのが出自。

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 として定義されている。
  • アクティブに開発されてる Container Runtime は、CRI を実装している。一例は以下(注: Docker については Kubernetes 開発者によって dockershim と呼ばれる CRI サポート用のツールが実装されていた)。
  • 先週、 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
  • そのため、「docker build で作成した container image を container registry へ push して、k8s から利用する」という一連のワークフローに関していえば、containerd or CRI-O を使っても問題になる事は一切無い はず