コンテナランタイム比較:containerd vs CRI-O vs Docker Engine でKubernetesを動かす
オープンソースラボ編集部 ・ 2026年6月14日
コンテナランタイム比較:containerd vs CRI-O vs Docker Engine でKubernetesを動かす
Kubernetes 1.24以降でDockerShimが削除され、CRI(Container Runtime Interface)準拠のコンテナランタイムを直接選ぶ必要があります。containerd(CNCF卒業プロジェクト・最も普及)・CRI-O(RedHat製・Kubernetes専用)・Docker Engine(Dockerfileは使えるが本番Kubernetesでは非推奨)の違いを理解して正しいランタイムを選びましょう。
コンテナランタイムを選ぶ理由
- Kubernetes 1.24以降:
dockershimが削除されてDocker EngineはCRIなしでは使用不可 - パフォーマンス: containerdとCRI-Oは中間レイヤーが少ない分軽量・高速
- セキュリティ: runC(OCI)・gVisor・Kata Containersなど代替ランタイムに切り替え可能
- 管理コスト: kubeadm/RKE2/k3sのデフォルトがcontainerdに変更済み(設定不要で使える)
主要ランタイムの概要
containerd
2016年公開、Go製のOSSです。GitHubスター18k+。CNCFの卒業プロジェクトで最も広く使われているCRI準拠ランタイムです。Docker Engineの中でも使われており、AWS EKS・GKE・AKSのデフォルトランタイムです。crictl・ctr・nerdctl(Dockerコンパチ)でコンテナを操作できます。
# containerd インストール(Ubuntu/Debian)
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
# Docker公式リポジトリからcontainerdをインストール
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y containerd.io
# デフォルト設定を生成してsystemdに対応
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 enable --now containerd
sudo systemctl status containerd
# /etc/containerd/config.toml - 主要設定項目
version = 2
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.k8s.io/pause:3.9"
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true # Kubernetes必須
# gVisorランタイム追加(セキュリティ強化)
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
runtime_type = "io.containerd.runsc.v1"
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io"]
# プライベートレジストリ設定
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.yourcompany.com"]
endpoint = ["https://registry.yourcompany.com"]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."registry.yourcompany.com".auth]
username = "robot_user"
password = "token_value"
# nerdctl: Docker CLI互換のcontainerdクライアント
# Docker移行時にdockerコマンドをnerdctlに置き換えるだけで使える
# nerdctlインストール
NERDCTL_VERSION=2.0.2
curl -Lo /tmp/nerdctl.tar.gz "https://github.com/containerd/nerdctl/releases/download/v${NERDCTL_VERSION}/nerdctl-${NERDCTL_VERSION}-linux-amd64.tar.gz"
sudo tar Cxzf /usr/local/bin /tmp/nerdctl.tar.gz nerdctl
# Docker互換コマンド
nerdctl pull nginx:alpine
nerdctl run -d -p 8080:80 --name web nginx:alpine
nerdctl ps
nerdctl exec -it web sh
nerdctl build -t myapp:v1 .
nerdctl push registry.yourcompany.com/myapp:v1
# crictl でKubernetes環境のコンテナを操作
sudo crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps
sudo crictl images
sudo crictl pods
CRI-O
2016年公開、Go製のOSSです。GitHubスター2.5k+。Kubernetes専用に設計されたCRI準拠ランタイムで、Kubernetesが使う機能のみを実装した最小構成です。OpenShift(RedHat)のデフォルトランタイムです。
# CRI-O インストール(Kubernetes 1.30向け)
export KUBERNETES_VERSION=v1.30
export PROJECT_PATH=prerelease:/main
# OBS(Open Build Service)からインストール
curl -fsSL https://pkgs.k8s.io/addons:/cri-o:/${PROJECT_PATH}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/cri-o-apt-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/cri-o-apt-keyring.gpg] https://pkgs.k8s.io/addons:/cri-o:/${PROJECT_PATH}/deb/ /" | sudo tee /etc/apt/sources.list.d/cri-o.list
sudo apt-get update
sudo apt-get install -y cri-o
sudo systemctl enable --now crio
sudo systemctl status crio
# kubeadmでCRI-Oを使うクラスター初期化
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --cri-socket=unix:///var/run/crio/crio.sock
# /etc/crio/crio.conf.d/10-runtime.conf
[crio.runtime]
# デフォルトランタイム
default_runtime = "runc"
[crio.runtime.runtimes.runc]
runtime_path = "/usr/bin/runc"
runtime_type = "oci"
# Kata Containers(VM分離ランタイム)
[crio.runtime.runtimes.kata-containers]
runtime_path = "/usr/bin/kata-runtime"
runtime_type = "vm"
[crio.image]
# 使用するレジストリを制限(セキュリティ強化)
registries = ["registry.access.redhat.com", "docker.io", "registry.yourcompany.com"]
Docker Engine(参考)
Docker Engineは現在もローカル開発・CI環境で最も使われています。Kubernetes本番環境ではcri-dockerd(Mirantis製シム)を経由して使えますが、containerd/CRI-Oが推奨です。
# Docker Engine インストール(ローカル開発用)
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER # sudoなしでdockerを実行
# kubeadmでDocker Engineを使う場合(非推奨・レガシー)
# cri-dockerdが必要
sudo apt-get install -y cri-dockerd
sudo kubeadm init --cri-socket unix:///var/run/cri-dockerd.sock
機能比較表
| 比較項目 | containerd | CRI-O | Docker Engine |
|---|---|---|---|
| CRI準拠 | ✅ | ✅ | cri-dockerd必要 |
| Kubernetes推奨度 | ✅ | ✅ | △(レガシー) |
| OpenShift対応 | ✅ | ✅(デフォルト) | △ |
| nerdctl/crictl | ✅ | crictl | docker CLI |
| メモリフットプリント | 小 | 最小 | 大 |
コンテナランタイムはDevOpsカテゴリ/categories/devopsのKubernetes・Helm・ArgoCD構成と密接に連携します。セキュリティカテゴリ/categories/securityのgVisor・Kata ContainersをcontainerdのRuntimeClassとして設定してサンドボックス分離を実現できます。
FAQ
Q. DockerからcontainerdにKubernetes環境を移行するには?
A. ノードのランタイムをcontainerdに変更する手順は: ①対象ノードをcordon/drainしてPodを退避②dockershim設定を削除③containerdをインストールして設定(SystemdCgroup=true)④kubeletの--container-runtime-endpointをunix:///run/containerd/containerd.sockに変更⑤ノードをuncordonして復帰。既存のDockerイメージはそのままcontainerdで使用できます(OCIイメージ形式の互換性)。kubeadm環境ではkubeadm upgrade後に設定を変更するのが最も安全です。
Q. containerdとCRI-Oのどちらを選ぶべきですか?
A. マネージドKubernetes(EKS/GKE/AKS)や汎用用途ならcontainerd、OpenShiftやRHEL系でKubernetes専用ならCRI-Oが向いています。実際の違いは小さく、設定はほぼ同じでcrictlコマンドは両方で使えます。k3s・RKE2・k0sはデフォルトでcontainerdを使用しています。新規クラスター構築ではよりエコシステムが大きいcontainerdを選ぶことが多いです。
Q. gVisorをcontainerdで使うにはどうしますか?
A. ①gVisorをインストール(apt-get install runsc)②containerd設定にrunscランタイムを追加③KubernetesのRuntimeClassリソースでhandler: runscを定義④PodSpecのruntimeClassName: gvisorでサンドボックスPodを作成。gVisorの制約: ①/procへのアクセスが制限される(一部のLinuxシステムコールをエミュレート)②パフォーマンスはrunCより10〜20%低下③インターネット向けのAPIサーバー・マルチテナント環境・機密データ処理Podに最適。
Q. コンテナランタイムのセキュリティベストプラクティスは?
A. ①rootlessコンテナ: containerd+rootlesskit(rootユーザーなしでコンテナを実行)②読み取り専用rootfs: PodSecurityContextでreadOnlyRootFilesystem: true③SeccompProfile: RuntimeDefaultプロファイルを適用してシステムコールを制限④AppArmor/SELinux: ノードのMACポリシーをコンテナに適用⑤イメージ署名検証: Cosign + Policy Controller(Sigstore)でサプライチェーン攻撃を防止⑥distrolessイメージ: Google Container Toolsのdistrolessベースイメージでシェル・パッケージマネージャーを含まない最小イメージを使用。
まとめ
| ユースケース | 推奨ランタイム |
|---|---|
| マネージドK8s・汎用Kubernetes | containerd |
| OpenShift・RHEL・Kubernetes専用 | CRI-O |
| ローカル開発・CI環境 | Docker Engine |