ステータス:ドラフト(2026-10-17)、一部実測。 基準バージョン:containerd/containerd v2.3.5(コミット 1294c24a7da8)、kubernetes/cri-api v0.34.0(コミット 9b3ce5ec4798)。 1.7 との比較は、containerd v1.7.27(コミット 05044ec0a9a7)も併せて開き、ソースコードで確認できた内容のみを記載しています。実測は 2026-10-17 に小規模クラスターで 読み取りのみ を行いました(ノード一覧の読み取り、2台のワーカーへの一般ユーザーでの ssh による
ps·mount設定ファイルの読み取り、sudo なし)。 作成規則:実測データを基本とし、測定できなかったものは「未測定」、確認できなかったものは「未確認」と表記します。
目次
- 1. 1行要約:発注書フォーマットと厨房
- 2. 構成図
- 3. コードマップ
- 4. コアパスを辿る
- 5. コントリビューションへの繋がり
- 6. 実測:1.7 ワーカーと 2.3 ワーカーを権限なしで読む
- 7. どこから読むべきか
- 8. 初めてのコントリビューションにおすすめの場所
- 9. 制限事項
- 参考
1. 1行要約:発注書フォーマットと厨房
kubelet はコンテナを直接作成しません。「このポッドのサンドボックスを用意しろ」、「このイメージでコンテナを作れ」、「起動しろ」といった注文を CRI(Container Runtime Interface) という決められたフォーマットで送信しているだけです。発注書のフォーマットが決まっているため、厨房(ランタイム)は containerd であろうと CRI-O であろうと変更できます。containerd はその注文を受け取り、材料(イメージレイヤー)を取り出して下ごしらえし(スナップショット)、テーブルごとに担当スタッフ(shim)を配置し、実際に火を点ける作業は調理師(runc)に任せます。調理師は料理をコンテナに据え付けるとすぐに退勤し、その後の世話は担当スタッフが引き受けます。
| 構成要素 | 役割 | 稼働場所 |
|---|---|---|
| kubelet | ポッド仕様を CRI 呼び出しに変換して送信 | ノードごとの systemd サービス |
| CRI(cri-api) | RuntimeService・ImageService の2つの gRPC サービスの規約 | api.proto 1つのファイル |
| containerd CRI プラグイン | CRI リクエストを受け取りコアサービス・CNI を呼び出す | containerd プロセス内 |
| containerd コアサービス | コンテナメタデータ・タスク・イメージ・コンテンツ・スナップショット・リース(lease) | containerd プロセス内 |
| containerd-shim-runc-v2 | ポッドあたりのコンテナプロセスを保護し、終了コードを受け取る | ポッドごとに1プロセス |
| runc | OCI バンドルで名前空間・cgroup を作成しプロセスを起動する | 実行後すぐに終了 |
| CNI プラグイン | ポッドのネットワーク名前空間にインターフェース・IP を付与する | containerd が実行するバイナリ |
2. 構成図
- 上から下へと1回のポッド作成処理が流れます。kubelet と containerd の間のみ gRPC(ユニックスソケット)であり、CRI プラグインとコアサービスの間は 同一プロセス内の関数呼び出しです。
- 3つの円柱はディスクに残る状態です。
meta.db(bolt メタデータ)、blobs/sha256(コンテンツストア)、snapshots/N(overlayfs スナップショットター)です。 - containerd と shim の間は ttrpc(gRPC を軽量化したプロトコル)です。shim はポッドごとに1つ存在し、runc は仕事を終えると消滅します。
- CNI は containerd の外側のバイナリであるため、オレンジ色で別個に描いています。
- 左側のグループは overlayfs スナップショットターの
snapshots/<번호>/fsディレクトリです。下の3つがコミットされた読み取り専用レイヤー、一番上がコンテナごとに新しく作成した書き込みレイヤーです。 - 右側の ①〜④ は、セクション 4.4 で追跡する関数の順序です。
3. コードマップ
containerd 2.x のリポジトリは1つの Go モジュール(github.com/containerd/containerd/v2)です。最初に見るべき重要な部分のみを抽出しました。
| パス | 内容 | 最初に読むべきファイル |
|---|---|---|
cmd/containerd/ |
デーモンのエントリーポイント、組み込みプラグイン一覧、プラグインのロード | builtins/builtins.go, server/server.go |
plugins/ |
プラグインレジストリ。サービス、スナップショットター、コンテンツ、CRI、GC など | types.go, cri/cri.go |
internal/cri/ |
CRI 実装本体(サーバー、サンドボックスコントローラー、イメージサービス、設定) | server/sandbox_run.go |
core/ |
ドメインロジック:メタデータ(bolt)、runtime v2、アンパック、トランスファー | runtime/v2/shim_manager.go |
client/ |
Go 클라이언트. CRI 플러그인도 이것을 「메모리 안」으로 씀 | container.go |
cmd/containerd-shim-runc-v2/ |
runc 用 shim | manager/manager_linux.go |
api/ |
containerd 独自の gRPC・ttrpc プロト | services/tasks/v1/tasks.proto |
kubernetes/cri-api はほぼ1つのファイルです。 pkg/apis/runtime/v1/api.proto
に 35 個の RPC とメッセージのすべてが含まれており、残りは生成された Go コードです。
1.7 と 2.x の違い(ソースコードで確認できたもののみ)
- CRI の位置づけ。 1.7.27 では
pkg/cri/の下に実装が2系統ありました。デフォルトのserver/(Go ファイル 108個)と実験用のsbserver/(98個)であり、環境変数ENABLE_CRI_SANDBOXESで選択していました (pkg/cri/cri.go:102)。2.x ではサンドボックス側の実装を基本としてinternal/cri/へ移行し、プラグインも3つに分割されました。gRPC を受け取るio.containerd.grpc.v1.cri、およびそれが依存するio.containerd.cri.v1.runtime·io.containerd.cri.v1.imagesです(cmd/containerd/builtins/cri.go). - pause を起動する主体。 1.7 の
RunPodSandboxは、1つの関数内で pause コンテナを作成し(sandbox_run.go:178)、CNI を呼び出し(338行目)、タスクを開始します(481行目)。2.x ではネットワーク処理までを CRI サーバーが行い、pause はpodsandboxという サンドボックスコントローラープラグインに委譲します(セクション 4.2)。 - 設定バージョン。 2.x の設定バージョンは 4 です(
version/version.go:41)。バージョン 2 の設定も読み込みますが、起動の都度バージョン 3・4 に変換して適用します(config.go:48のmigrations)。バージョン 4 はサーバーのプロパティ([grpc]·[ttrpc]など)をio.containerd.server.v1.*プラグインの設定に移行したバージョンです。
4. コアパスを辿る
4.1 デーモンはプラグイングラフで組み立てられる
containerd のほぼすべての機能はプラグインです。各パッケージが init() で registry.Register に自身を登録し、
builtins.go はそれらのパッケージをブランクインポート(_)で取り込んでいるだけです。ビルドに含めるかどうかは、インポートの1行で決まります。
- プラグインは タイプと ID によって識別されます。タイプは
io.containerd.grpc.v1,io.containerd.snapshotter.v1,io.containerd.cri.v1のような文字列です(plugins/types.go:35付近)。設定ファイルの[plugins."io.containerd.cri.v1.images"]は、「タイプ.ID」をそのまま記述したものです。 - 登録には
Requires(必要なタイプのリスト)が存在します。CRI gRPC プラグインは、CRI サービス、サンドボックスコントローラー、NRI、イベント、lease、transfer、shim など11種類のタイプを要求します(plugins/cri/cri.go:46init). - デーモンは
LoadPluginsでregistry.Graph(...)を使用して依存関係の順序に並べ替え(386行目)、Newのループ(161行目)で1つずつp.Initを実行します(189行目)。グラフソート自体は別モジュールであるgithub.com/containerd/pluginv1.1.0 に存在するため、このリポジトリには含まれていません。 - サービスは基本的に 2層構造になっています。実際に処理を行う
io.containerd.service.v1タイプの「local」実装(plugins/services/tasks/local.go:92)と、それを gRPC として外部に公開する薄いio.containerd.grpc.v1ラッパー(containers/service.go:34)です。
なぜ2層構造になっているのでしょうか?CRI プラグインがその答えです。 initCRIService は containerd クライアントを作成しますが、 containerd.WithInMemoryServices(ic)(121行目)を渡します。外部の ctr や nerdctl はソケットを経由して gRPC ラッパーを呼び出し、同一プロセス内の CRI は local 実装を直接呼び出します。シリアライズのオーバーヘッドを1回分削減しつつも、 クライアントコードを一つに 維持するための設計です。CRI リクエストが使用するネームスペースもこの時に k8s.io に固定されます。そのため、 ctr -n k8s.io を指定して確認しないと Kubernetes のコンテナは見えません。
4.2 RunPodSandbox:ネットワークが先、pause はコントローラーが
CRI 規約の最初の RPC は RunPodSandbox です。「成功すればサンドボックスが ready でなければならない」という1行が契約のすべてであり、サンドボックスとは何かについてはランタイム側が定義します。containerd の答えは「ネットワーク名前空間 + それを保持する pause コンテナ」です。
criService.RunPodSandboxはまずサンドボックス ID 用の lease を作成します(97行目)。この lease が存続している間、サンドボックスが使用するコンテンツおよびスナップショットは GC の対象外になります。hostNetworkではない場合、netns.NewNetNSにより/var/run/netns/の下に名前付きのネットワーク名前空間を作成します(209行目)。- 続いて
setupPodNetworkが CNI のSetupを呼び出します(496行目)。 コンテナが1つも起動する前に ネットワークが先に取り付けられる形になります。取得した IP はサンドボックスの状態にキャッシュしておき、PodSandboxStatusのたびに名前空間を探索しなくて済むようにします。 - その次にサンドボックスサービスの
CreateSandbox(281行目)とStartSandbox(299行目)を呼び出します。ここで実際の処理を行うのがサンドボックスコントローラーです。 - デフォルトのコントローラー
podsandboxのStartは、pause イメージを検索し(86行目)、そのイメージの上にスナップショットを準備してコンテナを作成し(209行目)、標準入出力なしでタスクを作成し(253行目)、終了監視(Wait、270行目)を設定した上で起動します(295行目)。
なぜこのように分割されているのでしょうか?サンドボックスを「pause コンテナ」に固定しないためです。コントローラーがプラグイン化されているため、VM ベースのランタイムのようにサンドボックスが仮想マシンである実装も、同じ CRI サーバの下に組み込むことができます。pause イメージ名が設定ファイルにおいて sandbox_image という1行ではなく、
pinned_images テーブルの sandbox 項目に変更されたのも(設定構造体 config.go:307)、同じ流れによるものです。コメントではこれを「CRI クライアントが削除してはならないイメージ群」と定義し、他のプラグインがキーとして参照できるようにしています。pause はその中の1つに過ぎません。
4.3 CreateContainer·StartContainer → tasks → shim → runc
CreateContainerは CRI のContainerConfigを OCI ランタイム仕様に変換し、WithNewSnapshot(378行目)を介してイメージ上の書き込みレイヤーを準備した上で、client.NewContainer(462行目)を呼び出します。この段階では メタデータのみ が作成されます。プロセスはまだ存在しません。StartContainerは、サンドボックスがタスク API のアドレスを保持している場合にそれをオプションとして付与し(197行目)、container.NewTask(206行目)→task.Start(247行目)を呼び出します。- クライアントの
NewTaskは、handleMounts(328行目)でスナップショットターのMountsを受け取り、rootfsのマウント一覧をリクエストに載せます。tasksサービスのlocal.Createがこれを受け取り、runtime v2のTaskManager.Createに渡します。 ShimManager.Startとbinary.Startがshimバイナリをstartサブコマンドとして実行します。shimは自身のttrpcソケットアドレスを返してデーモンから切り離されます。- shim側の
manager.Startには、この記事で最も重要な数行があります。
grouping := id
spec, err := readSpec()
...
for _, group := range groupLabels {
if groupID, ok := spec.Annotations[group]; ok {
grouping = groupID
break
}
}
...
s, err := newShimSocket(ctx, socketDir, opts.GetContainerdGrpcAddress(), grouping, false)
if err != nil {
if errdefs.IsAlreadyExists(err) {
params.Address = s.addr
return ¶ms, nil
出典: containerd v2.3.5 cmd/containerd-shim-runc-v2/manager/manager_linux.go, Apache-2.0
groupLabels には io.kubernetes.cri.sandbox-id があります(67行目)。同じPodのコンテナは同じサンドボックスIDで同じソケット名を取得し、
ソケットがすでに存在する場合は 新しいshimを起動せず既存のアドレスを返します。 そのため、shimはコンテナごとではなくPodごとに1つとなります。
第6節の実測値がこれをそのまま示しています。
6. shimの service.Create は
runc.NewContainer で
バンドル下の rootfs にoverlayを shimが直接マウントし(120行目)、 Init.Create
が runc create を実行します(149行目)。 Start は start で runc start です。
なぜshimを別々に分けるのでしょうか?コンテナプロセスの親がcontainerdである場合、containerdを再起動したりアップグレードしたりすると、すべてのコンテナが一緒に影響を受けます。 shimが親の役割(終了コードの回収、標準入出力の維持)を引き受ければ、デーモンはいつでも停止して起動し直し、ソケットで再接続できます。 runcを常駐させないのも同じ理由です。長生きするプロセスが少ないほど、アップグレードが容易になります。
4.4 イメージプルとスナップショット:レイヤーがrootfsになるまで
- CRIの
PullImageはCRIImageService.PullImageに届きます。 2.1からのデフォルトは transferサービスであり、use_local_image_pullを有効にすると従来のclient.Pullパスを使用します(184行目)。 transferのパスはpullImageWithTransferService→Transfer(326行目)→localTransferService.pullです。 - ダウンロードされたマニフェスト・設定・レイヤーはすべて コンテンツアドレス指定ストレージに入ります。パスはダイジェストそのものの
blobs/sha256/<hex>です(blobPath)。 同じレイヤーを使用するイメージが複数あっても、ディスク上には一度だけ存在します。 - プルの展開は
Unpacker.unpackがレイヤーごとに スナップショットターPrepare(415行目)→ diffサービスApply(tarを展開して格納、542行目)→Commit(494行目)を繰り返します。コミットされたスナップショットの名前は そのレイヤーまでの chainID であるため、同じレイヤーチェーンはイメージが異なっていても1度だけ展開されます。 - コンテナを作成する際、
WithNewSnapshotはこの一番上の chainIDを親としてPrepareにし、空のアクティブスナップショットを作成します(276行目)。イメージがまだ展開されていない場合、CRI側のラッパーがunpackImageでプルして再試行します。 - 最後にoverlayfsスナップショットターの
mountsがマウントオプションを作成します。
if s.Kind == snapshots.KindActive {
options = append(options,
fmt.Sprintf("workdir=%s", o.workPath(s.ID)),
fmt.Sprintf("upperdir=%s", o.upperPath(s.ID)),
)
}
...
parentPaths := make([]string, len(s.ParentIDs))
for i := range s.ParentIDs {
parentPaths[i] = o.upperPath(s.ParentIDs[i])
}
options = append(options, fmt.Sprintf("lowerdir=%s", strings.Join(parentPaths, ":")))
出典: containerd v2.3.5 plugins/snapshots/overlay/overlay.go, Apache-2.0
親スナップショットたちの fs ディレクトリがそのまま lowerdir になり、自分の fs·work が upperdir·workdir になります。コンテナが使用する
ファイルはすべてupperにのみ蓄積されるため、同じイメージを使用する100個のコンテナも下層を共有します。同じ発想をVMディスクに適用した話は
学生VMが起動するまで4にあります。
これらすべてをつなぐ台帳がbolt DBです。ネームスペースの下にイメージ・コンテナ・スナップショット・コンテンツ・leaseバケットがあり
(buckets.go:60 のコメント図)、
GarbageCollect はどのイメージ・コンテナ・leaseからも
参照されないコンテンツとスナップショットを削除します。プルの途中のレイヤーが削除されないのは、その作業がleaseを保持しているためです。
「参照がなければ削除する」を基本とし、実行中の作業のみleaseで例外とする設計です。
5. ユーザーコントリビューションとの連携
筆者は2026-10-17現在、containerdとkubernetes/cri-apiに提出したPRはありません。コントリビューション台帳には「コンテナランタイム低水準(containerd・CRI-O・runcなど)」を 調査中の分野として記載しており、この記事はその準備運動です。8節の候補は、この記事を書く過程でソースコードから直接見つけたものです。
1点あらかじめ記載しておきます。kubernetes/cri-apiはkubernetes/kubernetesの staging/src/k8s.io/cri-api をボットが移行するリポジトリであるため、
このリポジトリに直接送信されたPRは無視されます(リポジトリのCONTRIBUTINGを参照)。CRI側の修正はkubernetes/kubernetesに送信する必要があり、その場合はKubernetesの
AI使用ルール(PR本文での告知、AIが作成したコミットメッセージ・共同執筆者の表記の禁止)に従う必要があります。
6. 実測:1.7ワーカーと2.3ワーカーの権限なし読み取り
2026-10-17、小規模クラスター(ノード8台)で読み取りのみを行いました。ノードランタイムの分布は kubectl get nodes -o custom-columns=...containerRuntimeVersion
であり、ノード内は一般ユーザーのsshで ps·mount·/etc/containerd/config.toml のみを読み取りました。 /run/containerd·/var/lib/containerd は
権限がないため一覧を読み取れず(sudoは使用せず)、 crictl はインストールされていませんでした。
| 項目 | ワーカーA(containerd 1.7.27) | ワーカーB(containerd 2.3.5) |
|---|---|---|
| 同バージョンのノード数 | 4台 | 4台 |
| runc | 1.2.5 | 1.5.1 |
| 実行中のPod(うちhostNetwork) | 22 (10) | 31 (6) |
| アプリコンテナ数 | 28 | 42 |
containerd-shim-runc-v2 プロセス |
22 | 31 |
pause プロセス |
22 | 31 |
| タスクディレクトリ数(ディレクトリのハードリンク数 − 2) | 50 = 22 + 28 | 74 |
| overlayマウント | 50 | 74 |
| うち1層(lowerdirが1つ) | 22 | 33 |
| 最も深いlowerdir | 42層 | 52層 |
/var/run/netns 項目 |
12 = 22 − 10 | 25 = 31 − 6 |
| shim RSS平均 / containerd RSS | 15.7 MiB / 74 MiB | 12.6 MiB / 153 MiB |
| 設定バージョン | version = 2 |
version = 4 |
| CRI設定ブロック | io.containerd.grpc.v1.cri つ |
io.containerd.cri.v1.images·.runtime に分かれる |
| pauseイメージ | sandbox_image = pause:3.8 |
pinned_images.sandbox = pause:3.10.2 |
| snapshotter / cgroup | overlayfs / SystemdCgroup = true |
overlayfs / SystemdCgroup = true |
shimの1行は次のようになっています(IDは隠しています)。
containerd-shim /usr/bin/containerd-shim-runc-v2 -namespace k8s.io -id 0c1e…(64자) -address /run/containerd/containerd.sock
overlay on /run/containerd/io.containerd.runtime.v2.task/k8s.io/0c1e…/rootfs type overlay (rw,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/1/fs,upperdir=…/snapshots/3774/fs,workdir=…)
読み取った内容:
- shimの数 = Podの数。 両方のバージョンで完全に一致していました。4.3節の
sandbox-idのまとめが1.7にもすでに存在していたことを意味します。-idに記録されている値は コンテナではなくサンドボックスIDです。psのcommがcontainerd-shimに切り捨てられているのは、Linuxがプロセス名を15文字に切り捨てるためです。 - hostNetworkのPodにもpauseが存在します。 pause 22個のうち10個はhostNetwork Podのものであり、ネットワーク名前空間の数(12)は正確に 残りのPodの数と一致します。4.2節の「hostNetworkでなければnetnsを作成する」という分岐が数値として確認できます。
- タスクディレクトリ50 = サンドボックス22 + コンテナ28 です。pauseも1つのコンテナとしてカウントされます。ワーカーBは 31 + 42 = 73 で1つ余りますが、どのコンテナのものかは一覧権限がないため確認できませんでした(未確認)。
- 1層のoverlay 22個 = pause 22個。 pauseイメージはレイヤーが1つであるため、lowerdirも1つです。ワーカーBの33個は、pause 31個と単一レイヤーイメージの2つであると考えられます(推定)。
- ワーカーBのlowerdir
snapshots/1はこのノードで初めて展開されたスナップショットであり、upperの番号3774はその間に作成され削除されたスナップショットがそれだけ 多かったことを意味します。番号はstorage.CreateSnapshotがboltバケットのNextSequenceで採番するため(252行目)、削除された番号を再利用することはありません。 - 1.7ノードの設定を2.3.5デーモンにそのまま渡すと、バージョン2 → 4への移行を起動のたびに実行し、警告を残します(第3節)。実際にアップグレードは行いませんでした(未実測)。
kubelet側は両方のバージョンで containerRuntimeEndpoint: unix:///run/containerd/containerd.sock(2.xノードは /var/run/... と表記)、
cgroupDriver: systemd でした。ランタイムの SystemdCgroup = true と一致しています。
7. どこから読むべきか
api.protoのRuntimeService·ImageServiceのコメントのみをざっと読みます。契約が何を要求し、何をランタイムに委ねているのかが見えてきます。plugins/cri/cri.goとserver.goでプラグインがどのように連携するのかを確認します。sandbox_run.go→podsandbox/sandbox_run.goの順序でPodを1つ起動します。container_start.go→shim_manager.go→manager_linux.goでプロセス層まで降ります。unpacker.goとoverlay.goでディスク側を確認します。docs/snapshotters/·docs/content-flow.mdを添えると効果的です。
k3sやRKE2のようにcontainerdを内蔵して配布するディストリビューションがこの構造をどのようにラップしているのかは、 k3s・RKE2・k0sの構造比較で続けて確認できます。
8. 最初コントリビューションしやすい箇所
- CRI設定ドキュメントのバージョン番号が古くなっています。
docs/cri/config.mdの 「Config versions」セクションではバージョン3が最新であり、バージョン2は「バージョン3に自動変換される」と記載されており、「Full configuration」の例もversion = 3です。 同じタグのRELEASES.mdでは最新がバージョン4(v2.3.0以降)であると記載されており、コード内のConfigVersionも4です。1つのドキュメントPRで修正可能です。 - 2つのTODO。
plugins/cri/cri.goのinitCRIServiceの末尾に、「Closerはどこで呼ばれるのか」、「containerdをどのように停止するか」というTODOが残っています。実際に終了パスでCloseが呼ばれているかを追跡し、issueとして整理するだけでも役に立ちます。 - サンドボックスプラットフォーム判定の暫定処理。イシューの文脈を読み解く良い入り口です。
sandbox_run.go内の180行目付近に、「コントローラーがプラットフォームを早期に通知できないため、Linuxセクションの有無で推測している。これはハックである」というコメントがあります。コントローラー インターフェースに関する議論が必要なため初回のPRとしては大きめですが、 - cri-apiのREADMEのバージョンごとの変更履歴はv1.32で停止しています(v0.34.0タグ基準、masterは未確認)。送信先はkubernetes/kubernetesのstagingディレクトリです。
- ラベル:containerdは
exp/beginnerラベルを使用しています(2026-10-17時点でオープンなもの2件)。AIルールはCONTRIBUTINGの「Automated and AI-generated contributions」セクションにあります。PRは人間がオープンし、AIが作成したコード・本文・コメントは作成者がすべてレビューする必要があります。
9. 制限事項
- kubeletのソースコードは確認していません。kubeletがどのような順序でCRIを呼び出すか(例:
PullImageとCreateContainerの間のリトライ)はこの記事の範囲外です。 - NRI、CDI(デバイスインジェクション)、ユーザー名前空間、チェックポイント、ストリーミング(exec・attach・port-forward)サーバー、Windowsのパスについては扱っていません。
- transferサービスとローカルプルの違い、GCスケジューラーの周期・閾値は関数名までを確認したのみで、詳細は読み込んでいません。
- 実測は権限なしでの読み取りであるため、コンテンツストアのサイズ、bolt DBの内容、スナップショット数は未実測です。1.7から2.3へのバージョンアップを実際に実行した記録もありません(未実測)。
- 1.7との比較は、v1.7.27ソースコードのファイル構成といくつかの関数のみを対照したものです。
ティティの一言。 kubeletは注文書を出すだけで、テーブルごとに担当スタッフ(shim)がついています。だからシェフ(containerd)が少し休憩していても、お客さんの料理はそのままです!
参考
すべての資料は2026-10-17に閲覧しました。
- kubernetes/cri-api v0.34.0
pkg/apis/runtime/v1/api.proto, CONTRIBUTING.md - containerd v2.3.5:
plugins/cri/cri.go,cmd/containerd/server/server.go,internal/cri/server/sandbox_run.go,internal/cri/server/podsandbox/sandbox_run.go,core/runtime/v2/shim_manager.go,cmd/containerd-shim-runc-v2/manager/manager_linux.go,plugins/snapshots/overlay/overlay.go,core/unpack/unpacker.go,docs/cri/architecture.md,docs/containerd-2.0.md,RELEASES.md,CONTRIBUTING.md - containerd v1.7.27:
pkg/cri/cri.go,pkg/cri/server/sandbox_run.go - 引用コード:containerd v2.3.5, Apache License 2.0.