はじめに
アーキテクチャ選択の技術的背景
コンテナランタイムとしてPodmanを選択する技術的根拠は、そのアーキテクチャが解決する具体的な問題にあります。
Dockerアーキテクチャの構造的制約
Dockerはdockerd
デーモンがroot権限で常駐し、全コンテナのライフサイクルを管理する集中型アーキテクチャを採用しています。この設計は以下の制約を生みます:
# Dockerデーモンのプロセス構造
systemd
└─ dockerd (root)
├─ containerd
│ └─ containerd-shim
│ └─ runc
│ └─ container process
└─ docker-proxy (各公開ポートに対して)
測定された影響:
- デーモン再起動時の全コンテナ停止時間: 平均15-30秒
- メモリオーバーヘッド: デーモンプロセスで常時300-500MB
- CVE-2019-5736などの権限昇格脆弱性の影響範囲: システム全体
Podmanのforkベース実行モデル
Podmanは各コンテナ操作を独立したプロセスとして実行します:
// libpod/runtime_ctr.goから抜粋(簡略化)
func (r *Runtime) NewContainer(ctx context.Context, rSpec *spec.Spec) (*Container, error) {
// OCI runtimeを直接fork/exec
cmd := exec.Command(r.ociRuntime.Path(), "create", "--bundle", bundlePath, ctr.ID())
// 親プロセスのユーザー権限で実行
cmd.SysProcAttr = &syscall.SysProcAttr{
Setpgid: true,
Pgid: 0,
}
return ctr, cmd.Run()
}
この実装により:
- プロセス分離による障害の局所化
- 既存のLinuxセキュリティメカニズム(SELinux, AppArmor)の自然な適用
- systemdによる直接的なcgroup管理
性能特性とリソース効率
実測ベンチマーク結果
1000コンテナ同時起動時の比較(t3.2xlarge, 8vCPU, 32GB RAM):
# 測定スクリプト
time for i in {1..1000}; do
podman run -d --rm alpine sleep 3600 &
done
wait
# Podman結果
real 0m42.317s
user 0m28.441s
sys 0m18.662s
メモリ使用量: 2.8GB(コンテナのみ)
# Docker結果(参考)
real 1m23.846s
user 0m15.233s
sys 0m8.419s
メモリ使用量: 4.2GB(デーモン含む)
ユーザー名前空間のUID/GIDマッピング実装
// kernel/user_namespace.c の仕組み
struct uid_gid_extent {
u32 first; // 名前空間内の開始ID
u32 lower_first; // ホストの開始ID
u32 count; // マッピング数
};
// /etc/subuidの設定が以下のようにマッピングされる
// user:100000:65536
// → コンテナ内UID 0 = ホストUID 100000
// → コンテナ内UID 1000 = ホストUID 101000
技術仕様
動作環境要件
カーネル要件:
- Linux 4.18以上(cgroup v2フルサポート)
- 有効化必須のカーネル機能:
CONFIG_USER_NS=y
CONFIG_SECCOMP=y
CONFIG_CGROUPS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_DEVICE=y
ファイルシステム要件:
- overlay2: 推奨、copy-on-writeによる高速化
- fuse-overlayfs: rootless環境でのフォールバック
- VFS: 互換性重視だが性能劣化
実装アーキテクチャ
┌─────────────┐
│ podman CLI │
└──────┬──────┘
│ gRPC/varlink
┌──────▼──────┐
│ libpod │ (Container/Pod管理)
├─────────────┤
│ c/storage │ (イメージ/レイヤー管理)
├─────────────┤
│ c/image │ (イメージ操作)
└──────┬──────┘
│
┌──────────────┼──────────────┐
│ │ │
┌──────▼──────┐┌──────▼──────┐┌─────▼──────┐
│ conmon ││ CNI ││ crun │
│ (監視/ログ) ││(ネットワーク)││ (OCI実装) │
└─────────────┘└─────────────┘└────────────┘
│
┌──────▼──────┐
│Linux Kernel │
└─────────────┘
各コンポーネントの責務:
- libpod: Podmanコア、コンテナライフサイクル管理
- conmon: コンテナモニター、stdio/ログ処理、終了コード取得
- crun: OCI仕様準拠の軽量ランタイム(C実装、runcより50%高速)
- CNI: プラグイン形式のネットワーク管理
本書では、これらの実装詳細と、プロダクション環境での最適な構成方法を解説します。