containerd containerd

Docker から containerd へ:Kubernetes ランタイムの簡単な歴史

Kubernetes がなぜ Docker と直接通信するのをやめたのか、そして containerd が Docker との関係で実際に何なのか。

9 min learn.level.初級

古い Kubernetes のチュートリアルは、Docker がコンテナランタイムであることを前提としています。新しいものは containerd を前提としています。どちらも間違ってはおらず、Kubernetes の歴史の異なる時点を説明しているだけです。何が変わったかを理解すると、ctr や crictl をめぐる混乱の大半や、クラスターノード上で docker ps が役に立つ情報を表示しなくなった理由が明らかになります。

Docker が先にあり、Kubernetes はそれを中心に作られた

Docker はコンテナを使えるものにしました。CLI、イメージ形式、すべてを実行するデーモンです。初期の Kubernetes は、Docker コンテナをオーケストレーションするために特別に作られ、両者は密接に結びついていました。Kubernetes が成長するにつれて、他のランタイム(rkt など)も統合を求めるようになり、Kubernetes は Docker の API に固定されるのではなく、複数のランタイムと連携できる方法が必要になりました。

CRI と OCI:インターフェースの標準化

Kubernetes の答えは Container Runtime Interface(CRI) でした。これは kubelet がインストールされたランタイムと通信するための gRPC API で、ランタイムごとの専用コードを必要としません。CRI を実装するランタイムなら、どれでも Kubernetes に接続できます。

CRI 自体は Open Container Initiative(OCI) の標準に依拠しています。OCI は、エコシステムが単一ベンダーの実装に依存しないよう、Docker が確立に貢献した仕様です。

  • image spec は、コンテナイメージの構造とアドレス指定の方法を定義し、あるツールで作成されたイメージを別のツールで実行できるようにします。
  • runtime spec は、ホスト上でコンテナを実際に作成して実行する方法を、namespace、マウント、プロセス設定のレベルまで定義します。
  • distribution spec(後から追加)は、レジストリからイメージを push および pull する方法を定義します。

CRI と OCI により、ランタイムとオーケストレーターが同じ製品である必要も、同じベンダーである必要もなくなりました。

Docker は CRI より前に作られたため、Kubernetes が橋渡しをする必要があった

Docker は CRI を話すようには作られていませんでした。Docker が作られた時点では CRI は存在せず、それでも Docker は支配的なランタイムであり続けました。Kubernetes の回避策が dockershim でした。これは CRI の呼び出しを Docker 自身の API に変換する互換レイヤーで、Docker 側を変更することなく、kubelet が Docker と連携できるようにしました。

containerd はもともと Docker の内部にあった

Docker は単なるランタイムではありませんでした。CLI、ビルドシステム、ボリュームとネットワークの管理、認証を含み、それらすべての下に、実際にコンテナを実行する部品である containerd というデーモンがありました。これは低レベルランタイムの runc の上に構築されています。containerd は独立したプロジェクトとして切り出されて CNCF に寄贈され、2019 年に graduated となりました。Docker のユーザー向けツールとは異なり、ネイティブに CRI を話します。関係を一文で言うと、containerd は常に Docker の内部にあったランタイムコンポーネントであり、今では単独で、CRI 互換のまま利用できるようになったものです。

dockershim の削除

1 つのランタイムのために変換レイヤーを維持することは、他のすべてのランタイムが直接 CRI を話すなかで、メリットが減る一方の継続的な負担でした。Kubernetes は 1.24 リリース(2022 年)で dockershim を削除し、それに伴い、Docker をクラスターのコンテナランタイムとして直接実行するサポートも終了しました。

これは既存のイメージを壊すものではありませんでした。Docker は OCI イメージ仕様に従ってイメージをビルドしていたため、すでにレジストリにあるものは、以前とまったく同じように containerd 上で動作します。動作しなくなったのは、ノード上で実際にコンテナを実行するものとして Docker Engine 自体を使うことでした。クラスターは、containerd や CRI-O のような CRI ネイティブのランタイムに移行する必要がありました。

今日ノード上にいるときに意味すること

現代のノードで docker ps を実行しても、存在しないか、関連する情報が何も表示されません。Docker がコンテナを実行しているわけではないからです。そのためのツールは crictl、ctr、nerdctl で、このシリーズの次のガイドで、それぞれをいつ使うかを説明します。コンテナイメージ自体、つまりアプリケーションの実際のレイヤーは、この歴史のどれからも影響を受けません。変わったのは、その下の仕組みだけです。

人気のガイド