containerd の CLI ツール:ctr、nerdctl、crictl
3 つのコマンドラインツール、3 つの異なる役割:いつ、どれを使うか。
Docker がノード上でコンテナを実行しなくなると、そのノードでは docker ps や docker logs が使えなくなります。この穴を埋める 3 つのツールがあり、2 つの異なるコミュニティによって、2 つの異なる目的で作られています。ノード上で直接トラブルシューティングをするときに最も混乱しやすいのは、間違ったツールを選んでしまうことです。
3 つのツールの概要
| ツール | 開発元 | 通信先 | 目的 | Docker に近いか |
|---|---|---|---|---|
ctr | containerd プロジェクト | containerd に直接 | containerd 自体のデバッグ | いいえ。最小限で低レベル |
nerdctl | containerd プロジェクト | containerd に直接 | 汎用のコンテナ管理 | はい。docker によく似ている |
crictl | Kubernetes プロジェクト | CRI 互換の任意のランタイム | Kubernetes の視点からのランタイムのデバッグ | 部分的に。Pod を認識する |
ctr:同梱、最小限、デバッグ専用
ctr は containerd 自体に同梱されているため、containerd がある場所ならどこでも使えます。ただし、明示的にデバッグ用のツールであり、意図的に機能は少なく、日常的なコンテナ管理を想定したものではありません。
ctr images pull docker.io/library/redis:7
ctr run docker.io/library/redis:7 my-redis
ctr containers list
containerd プロジェクト自身が、containerd 自体の状態のデバッグと調査以外に ctr を使うことを推奨していません。ctr でデプロイをスクリプト化しようとしているなら、nerdctl に切り替えるべきサインです。
nerdctl:Docker 風の日常使いのツール
nerdctl は、同じく containerd プロジェクトの独立した CLI で、docker CLI によく似た動作をするように設計されています。ほとんどの docker コマンドは、バイナリ名を置き換えるだけで動作します。
nerdctl run -d -p 8080:80 nginx:1.25
nerdctl ps
nerdctl logs my-container
nerdctl build -t myapp:latest .
使い慣れた Docker のワークフローとの互換性に加えて、nerdctl は Docker にはない containerd ネイティブの機能を提供します。暗号化イメージ、lazy pulling、P2P イメージ配布、イメージの署名と検証、containerd 自身のデータモデルにおける Kubernetes の namespace との直接のやり取りなどです。containerd がインストールされていて Docker がないマシンでの汎用的なコンテナ作業には、nerdctl を使います。
crictl:Kubernetes の視点から
crictl は containerd ではなく Kubernetes プロジェクト自身が保守しており、containerd のネイティブ API ではなく、kubelet が使うのと同じ CRI で通信します。そのため、containerd、CRI-O、その他の CRI 準拠ランタイムのどれでも同じように動作し、ctr や nerdctl にはない Kubernetes の概念、特にコンテナだけでなく Pod を理解します。
crictl images
crictl ps
crictl pods
crictl exec -it CONTAINER_ID sh
crictl logs CONTAINER_ID
crictl pods に注目してください。ctr も nerdctl も、それ以前の Docker も、ネットワークとストレージを共有するコンテナのグループである Pod のネイティブな概念を持っていませんでした。これは Kubernetes 固有のものであり、crictl はそれを直接扱うために作られたツールです。
crictl は ctr と同様、ワークロードの作成ではなく、調査とデバッグのためのものです。Kubernetes が把握していないコンテナを起動すると、kubelet はそのコンテナの記録を持っていないため、気づいた時点で削除します。Kubernetes にとって、ノード上の予期しないコンテナは、保持すべきワークロードではなく、修正すべきドリフトだからです。
crictl が接続するエンドポイント
crictl はランタイムをまたいで動作するため、どれに接続するかを知る必要があります。設定がない場合、固定のデフォルトソケットのリストを順番に試します(歴史的には dockershim、次に containerd、次に CRI-O、その他)。現代のノードでは、ランタイムが 1 つだけインストールされているため、この曖昧さが問題になることはまれですが、複数ある場合や、ソケットパスの問題を調査するときには、明示的に設定します。
crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps
# または
export CONTAINER_RUNTIME_ENDPOINT=unix:///run/containerd/containerd.sock
どれを選ぶか
- Kubernetes 自身が見ているものの調査やトラブルシューティング、つまり
kubectl describe podが報告している内容と、ノード上で実際に実行されているものとの突き合わせには、crictlを使います。 - ノードやローカル開発での汎用的なコンテナ作業、たとえば何かをすばやく実行する、イメージをビルドする、ログを確認するといった場合には、
nerdctlを使います。 - containerd 自体の内部状態のデバッグ、つまりランタイムに依存しない CRI の視点ではなく containerd 固有の問題には、
ctrを使います。その際は、containerd のドキュメントを横に開いておく必要があると考えてください。