KubernetesはなぜDockerを捨てたのか? — 裏切りか、進化か 🐋

「Dockerは死んだ!」

2020年末、このニュースが広まると、コミュニティはパニックに陥りました。

しかし、実際に何が起こったのでしょうか?

>

🎯 この記事で扱うこと

  • KubernetesがDockerを除外した理由(本当の理由)
  • dockershimとは何か、なぜ問題になったのか
  • containerd、CRI-Oなどの代替ランタイムとは何か
  • Dockerイメージ(docker build)はまだ使えるのか
  • 開発者・運用者が実際に何を変更する必要があるのか

📌 導入 / 背景

2020年12月、Kubernetes公式ブログに爆弾のような記事が一つ投稿されました。

“Kubernetes is deprecating Docker as a container runtime.”

この一文がTwitter、Reddit、Slackチャンネルを炎上させました。Kubernetesの共同創設者であるJoe Bedaでさえ、Twitterにこう書き込みました。

“Fascinating how this docker/docker-shim deprecation has created mass confusion.”

多くの人々が「もうDockerは使えないのか?」「私のdocker buildで作ったイメージはすべて使えなくなるのか?」とパニックに陥りました。

結論から申し上げますと:パニックになる必要はありません。しかし、正確に何が起こったのかを知る必要があります。


🔍 dockershimとは何か?

Kubernetes初期:Dockerしかなかった

Kubernetesが初めて登場したとき(2014年頃)、コンテナランタイムはDocker Engine一つだけでした。そのため、KubernetesはDockerサポートをコードにハードコーディングしましたが、このコンポーネントをdockershimと呼びます。

shimとは、元々機械の組み立て時に2つの部品間の隙間を埋める薄いクサビを指します。ソフトウェアでも同様に、異なるAPI間を接続するアダプターの役割を果たします。

CRIの登場:標準化の始まり

時間が経つにつれて、rkt、CRI-O、containerdのような様々なコンテナランタイムが登場しました。Kubernetesはこれらすべてをサポートするために、CRI(Container Runtime Interface)という標準APIを作成しました。

問題は、DockerがこのCRIをサポートしていなかったことです。DockerがCRIよりも先に登場したことを考えると、これは当然のことでした。

そのため、呼び出しパスはこのようになりました:

kubelet → dockershim → Docker Daemon → containerd → runc → 컨테이너

実際には、Dockerはイメージのダウンロードやコンテナの起動を直接行いません。内部のcontainerdがその役割を果たします。つまり、Kubernetesはコンテナを実行するために、kubelet → dockershim → Docker → containerdという長い中間プロセスを経る必要がありました。


🔍 なぜDockerを排除したのか?本当の理由3つ

1️⃣ メンテナンスの負担が大きすぎた

dockershimは最初から一時的な解決策でした(名前の通り:shim)。メンテナンスの負担が大きくなるにつれて、Kubernetesのメンテナーたちは「CRI標準を実装しないDockerのために、この負担を背負い続ける必要があるのか?」という疑問を抱き始めました。

2️⃣ 不要な中間段階

Kubernetes開発者がDockerを排除したかった大きな理由の一つは、中間段階が多すぎたことです。一つのコンテナを起動するのに、あまりにも多くのメッセージがアプリからアプリへと伝達されていました。

containerdに直接接続すると、パスはこのように単純化されます:

kubelet → containerd (CRI plugin 내장) → runc → 컨테이너

コンテナ一つを起動するのに0.1秒ずつ節約するだけでも、数百のコンテナを扱う環境では体感性能に差が出ます。

3️⃣ 新しい技術との非互換性

cgroups v2、ユーザーネームスペース(user namespaces)のような新しい機能は、dockershimと概ね互換性がありませんでした。dockershimのサポートを削除することで、これらの領域での追加開発が可能になります。


🗓️ タイムライン:このすべてはいつ起こったのか?

時期 出来事
2016年 Kubernetes CRI仕様発表
2020年12月 Kubernetes v1.20: dockershim 非推奨を公式宣言
2021年 コミュニティの反発により削除スケジュールが一度延期
2022年4月 Kubernetes v1.24: dockershim 完全削除

v1.20で非推奨が公式化されましたが、告知が適切に行われなかったため、コミュニティにパニックが発生しました。「Dockerという会社がなくなるのか?」「Dockerで作ったイメージが実行できなくなるのか?」といった誤解から混乱の大部分が生じました。


🔍 では、今は何を使うのか?

containerd — 事実上の標準

containerdは、元々Dockerが開発し、その後CNCF(Cloud Native Computing Foundation)に寄贈された汎用コンテナランタイムです。コンテナのライフサイクルを管理し、Kubernetesの内部および外部の両方で使用可能です。

AWS EKS、Azure AKS、Google GKEのような主要なマネージドKubernetesサービスは、すでにcontainerdをデフォルトのランタイムとして使用しています。もしAzureを使用しているなら、AKSノードはすでにcontainerdが稼働しています。

CRI-O — Kubernetes専用の軽量ランタイム

Red Hatが主導するプロジェクトで、Kubernetesでのみ使用するために作られた軽量ランタイムです。OpenShift環境で主に見られます。

cri-dockerd — Dockerを使い続けたい場合

MirantisとDockerは、dockershimがKubernetesから削除された後も、これを独立したオープンソースのCRIインターフェースとして維持管理することに合意しました。cri-dockerdをインストールすれば、依然としてDockerをランタイムとして使用できますが、追加のインストール負担が生じます。


💻 実際に何が変わったのか?(運用者視点)

コンテナ確認コマンドの変化

# ❌ 今、ノードでこれを実行しても何も表示されません
docker ps

# ✅ containerd環境ではこれを使うべきです
crictl ps

# ✅ または名前空間を指定して
ctr -n k8s.io containers list

ランタイム確認方法

# ノードで使用中のランタイムを確認
kubectl get node -o wide
# CONTAINER-RUNTIME列で確認可能
# 例: containerd://1.7.x

containerdのインストールと基本設定(Ubuntu基準)

# containerdをインストール
sudo apt-get update
sudo apt-get install -y containerd

# デフォルト設定ファイルを生成
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# systemd cgroupドライバーを有効化 (Kubernetes推奨)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' 
  /etc/containerd/config.toml

sudo systemctl restart containerd
sudo systemctl enable containerd

イメージビルドは依然としてDockerで行ってもよい ✅

# これは依然として完全に有効です
docker build -t myapp:v1.0 .
docker push myregistry.io/myapp:v1.0

# Kubernetesにデプロイする際のイメージ形式は同じ
kubectl apply -f deployment.yaml

⚠️ 注意事項 / よくある間違い

1. docker psでPodをデバッグしようとしない

containerdを使用するノードでdocker psを実行しても、Podコンテナは表示されません。containerdのような他のランタイムを使用する場合、docker psやdocker inspectコマンドでコンテナ情報を取得することはできません。kubectl exec、kubectl logs、crictl psを活用してください。

2. Dockerデーモンに依存するツールを確認する必要がある

Kubernetesインフラストラクチャの外部でDockerコマンドを実行するスクリプトやデーモン、例えば監視エージェントやセキュリティエージェントがインストールされている場合は、確認が必要です。

3. プライベートレジストリの設定場所が異なる

Dockerでdaemon.jsonで管理していたプライベートレジストリミラーの設定は、containerdでは/etc/containerd/config.tomlで行う必要があります。

# /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."myregistry.io"]
      endpoint = ["https://myregistry.io"]

✅ まとめ / 締めくくり

Dockerは死んでいません。役割が分離されただけです。

役割 ツール ステータス
イメージビルド docker build ✅ 依然として有効
イメージプッシュ docker push ✅ 依然として有効
ローカル開発 Docker Desktop ✅ 依然として有効
K8sコンテナランタイム containerd / CRI-O ✅ 現在の標準
dockershim 削除済み ❌ v1.24以降なし

Dockerは、開発作業中に人間が非常に簡単に操作できるようにする多くのUX改善機能を提供します。しかし、Kubernetesは人間ではないため、それらのUX改善機能は必要ありません。そのため、KubernetesはDockerのコアエンジンであるcontainerdと直接対話する道を選んだのです。

次のステップとして推奨される内容:

  • 現在稼働中のKubernetesクラスターのランタイムを確認する: kubectl get node -o wide
  • crictlコマンドを習得する(containerd環境のデバッグに必須)
  • AKS/EKS/GKE使用時のランタイムデフォルト設定ドキュメントを確認する

Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です