Skip to content
Published on

Kubernetesをローカルマシンに:Podmanがもたらす5つの革新

Authors
  • Name
    Twitter

1. はじめに:Dockerの光と影、そしてPodmanへの転換

1.1 Dockerが変えた世界

2013年、dotCloudのSolomon HykesがPyConで行った5分間のデモは、ソフトウェア業界の地図を完全に塗り替えました。 開発者の永遠の言い訳「自分のマシンでは動くのに」を歴史のゴミ箱に送りました。 DockerはLinuxコンテナ(LXC)を誰もが使えるものにし、イメージレイヤリング、Dockerfile、Docker Hubの三位一体で、 コンテナエコシステムのデファクトスタンダードとなりました。

しかし、すべての独占的な標準には構造的な脆弱性が伴います。

1.2 Docker Desktopライセンス変更の転機

2021年8月、Docker Inc.はDocker Desktopのライセンスポリシーを変更しました。 従業員250名以上または年間売上1,000万ドル超の企業は有料サブスクリプション(Pro、Team、Business)が必要になりました。 この変更は単なる価格政策を超えた意味を持ちます:

  • サプライチェーン依存性:重要な開発ツールが単一ベンダーのライセンスポリシーに依存する事態に
  • コンプライアンスリスク:無断使用は法的リスクを生む
  • 代替手段の模索が加速:Red Hat、SUSE、Googleなどが代替エコシステムへの投資を強化

1.3 ソフトウェアサプライチェーンセキュリティの必須化

2020年のSolarWindsハッキング、2021年のLog4Shell、2024年のXZ Utilsバックドアに至るまで、 ソフトウェアサプライチェーンセキュリティは選択ではなく必須となりました。 コンテナランタイムはこのサプライチェーンの最下層に位置し、そのセキュリティモデルがスタック全体の信頼基盤を決定します。

root権限で動作するDockerデーモンは、この文脈において根本的な再評価の対象となりました。

1.4 Podmanへの転換

この3つのトレンド、すなわちライセンスリスクサプライチェーンセキュリティアーキテクチャ上の限界の交差点に、 Red Hatが主導しオープンソースコミュニティと共に構築したPodmanが台頭しています。

Podmanは単なる「Dockerの代替」ではありません。コンテナ技術の根本的な前提を再設計するプロジェクトです。 2026年現在、Podman 5.xシリーズはTLS/mTLSベースのリモート接続暗号化、OCI Artifact管理の安定化、 macOS Hypervisor Frameworkのネイティブ統合、podman farm buildによるマルチプラットフォームビルドをサポートし、 エンタープライズ級のコンテナプラットフォームとして成熟しています。

本記事ではアーキテクトの視点から、Podmanがもたらす5つの根本的な革新を徹底分析します:

革新主要テーマ解決する課題
革新1デーモンレスアーキテクチャ単一障害点(SPOF)の排除
革新2ルートレスセキュリティコンテナエスケープリスクの根絶
革新3play kube開発/運用の言語二重性の解消
革新4Podネイティブ管理Kubernetesネイティブワークフロー
革新5PastaネットワーキングNATオーバーヘッドの除去、性能向上

2. [革新1] デーモンレスアーキテクチャ:単一障害点の終焉

2.1 Dockerデーモンの構造的問題

Dockerのアーキテクチャを理解するには、中心に位置するdockerd(Dockerデーモン)を理解する必要があります。 すべてのDocker CLIコマンドはREST APIを通じてdockerdに渡され、dockerdcontainerdを呼び出し、 containerdruncを通じて実際のコンテナを作成します。

+-------------------------------------------------------------+
|                    Docker Architecture (Client-Server)       |
|                                                              |
|  +----------+     REST API      +------------------------+  |
|  | docker   | ----------------->|       dockerd          |  |
|  | CLI      |     /var/run/     |   (Docker Daemon)      |  |
|  +----------+    docker.sock    |   +------------------+  |  |
|                                 |   |   containerd     |  |  |
|  +----------+     REST API      |   |  +------------+  |  |  |
|  | docker   | ----------------->|   |  |   runc     |  |  |  |
|  | CLI      |     /var/run/     |   |  +------------+  |  |  |
|  +----------+    docker.sock    |   +------------------+  |  |
|                                 |                        |  |
|  +----------+     REST API      |   +-----+ +-----+     |  |
|  | docker   | ----------------->|   | C1  | | C2  | ... |  |
|  | CLI      |                   |   +-----+ +-----+     |  |
|  +----------+                   +------------------------+  |
|                                          ^                  |
|                                          |                  |
|                              * Single Point of Failure *    |
|                              dockerdが停止すると            |
|                              全コンテナ管理が不能に        |
+-------------------------------------------------------------+

この構造の3つの核心的問題:

第一に、単一障害点(SPOF)dockerdが異常終了すると、実行中の全コンテナの管理が不可能になります。 コンテナ自体は動き続けますが、ログ収集、ヘルスチェック、リソース制限変更などのすべての管理機能が完全に失われます。

第二に、root権限の必要性dockerdはデフォルトでroot権限で動作します。 /var/run/docker.sockにアクセスできるユーザーは事実上root相当の権限を持ちます。 これは典型的な権限昇格攻撃ベクトルです。

第三に、リソースオーバーヘッド:コンテナが一つも動いていない状態でも、 dockerdcontainerdがスタンバイ状態でメモリを占有します。

2.2 PodmanのFork-Execモデル

Podmanはデーモンを完全に排除することで、これらすべての問題を解決しました。Podmanという名前自体がPod Managerの略であり、 根本的に異なる哲学に基づいたアーキテクチャで構築されています。

+-------------------------------------------------------------+
|                  Podman Architecture (Daemonless Fork-Exec)  |
|                                                              |
|  +----------+   fork/exec    +-------+    +--------------+  |
|  | podman   | -------------->| conmon |--->| Container 1  |  |
|  | CLI      |                +-------+    +--------------+  |
|  +----------+                                                |
|       |                                                      |
|       |          fork/exec    +-------+    +--------------+  |
|       +--------------------->| conmon |--->| Container 2  |  |
|       |                      +-------+    +--------------+  |
|       |                                                      |
|       |          fork/exec    +-------+    +--------------+  |
|       +--------------------->| conmon |--->| Container 3  |  |
|                              +-------+    +--------------+  |
|                                                              |
|  * デーモンなし:各コンテナは独立したプロセス               |
|  * Podman CLIの終了はコンテナに影響しない                   |
|  * conmon:軽量コンテナモニター(ログ、終了コード)         |
|  * OCI ランタイム(crun/runc)の直接呼び出し               |
+-------------------------------------------------------------+

Podmanがコンテナを実行する際のプロセスフロー:

  1. ユーザーがpodman runを実行
  2. Podman CLIがOCIランタイム(デフォルト:crun、またはrunc)を直接fork/exec
  3. conmon(Container Monitor)が作成され、コンテナプロセスのstdout/stderr終了コードを管理
  4. Podman CLIプロセスは役割を終えて終了
  5. コンテナは独立したプロセスとして動作を継続

"最良のデーモンとは、デーモンが存在しないことだ。Podmanはコンテナ管理に 特権を持つ常駐サービスは不要であり、やるべき仕事をして退場するツールが 必要であることを証明した。" — Dan Walsh, Red Hat コンテナセキュリティアーキテクト

2.3 systemd統合:コンテナをOSの第一級市民に

Podmanのデーモンレスアーキテクチャが持つ最も強力な利点の一つは、systemdとの自然な統合です。 Dockerではdockerdという別のサービスマネージャーがコンテナのライフサイクルを管理していましたが、 PodmanではLinuxのPID 1であるsystemdが直接コンテナを管理します。

これはコンテナがOSの第一級市民に昇格したことを意味します:

  • 自動起動:システムブート時にコンテナが自動的に起動
  • 依存関係管理:systemdの依存関係グラフを活用しAfter=network-online.targetなどで制御
  • ログ統合journalctlでコンテナログを統合表示
  • リソース管理:systemd cgroupスライスによるリソース割り当て
  • ヘルスチェックWatchdogSec=に基づく精密なヘルス監視
# /etc/containers/systemd/webapp.container (Quadlet形式)
[Unit]
Description=Production Web Application
After=network-online.target
Wants=network-online.target

[Container]
Image=registry.example.com/webapp:v2.1.0
PublishPort=8080:8080
Environment=NODE_ENV=production
Environment=DB_HOST=db.internal
Volume=/data/webapp:/app/data:Z
Network=webapp.network
AutoUpdate=registry
HealthCmd=/bin/curl -f http://localhost:8080/health || exit 1
HealthInterval=30s
HealthRetries=3
HealthStartPeriod=10s

[Service]
Restart=always
RestartSec=5
TimeoutStartSec=120
WatchdogSec=60

[Install]
WantedBy=multi-user.target default.target

2.4 Quadlet:systemdネイティブコンテナ管理の決定版

Podman 4.4で導入されたQuadletは、コンテナをsystemdユニットファイルの拡張として定義する革新的なアプローチです。 レガシーのpodman generate systemdが生成する長いコマンドラインの代わりに、 .container.volume.network.pod.kube.build拡張子の宣言的ユニットファイルでコンテナを管理します。

Quadletの主な利点:

カテゴリレガシー(generate systemdQuadlet
ファイル形式自動生成された長いExecStart宣言的な.containerファイル
メンテナンスイメージ更新時に再生成が必要宣言的な編集 + daemon-reload
可読性すべてのオプションが1コマンドラインセクション別に構造化
ファイル配置(root)/etc/systemd/system//etc/containers/systemd/
ファイル配置(rootless)~/.config/systemd/user/~/.config/containers/systemd/

マルチコンテナスタックの例 -- データベースとアプリケーション:

# ~/.config/containers/systemd/app-network.network
[Network]
Subnet=10.89.1.0/24
Gateway=10.89.1.1

# ~/.config/containers/systemd/postgres.container
[Unit]
Description=PostgreSQL Database

[Container]
Image=docker.io/library/postgres:16-alpine
Volume=pgdata.volume:/var/lib/postgresql/data:Z
Network=app-network.network
Environment=POSTGRES_DB=appdb
Environment=POSTGRES_USER=appuser
Secret=pg-password,type=env,target=POSTGRES_PASSWORD
HealthCmd=pg_isready -U appuser
HealthInterval=10s

[Service]
Restart=always

[Install]
WantedBy=multi-user.target default.target

# ~/.config/containers/systemd/pgdata.volume
[Volume]
# Quadletの適用
systemctl --user daemon-reload

# サービス起動
systemctl --user start postgres.service

# ステータス確認
systemctl --user status postgres.service

# ログ表示
journalctl --user -u postgres.service -f

Quadletはコンテナ管理における**Infrastructure as Code(IaC)**の精神を完璧に体現しています。 AnsibleやTerraformなどのツールで.containerファイルをデプロイすれば、別途のコンテナオーケストレータなしに、 systemd自体がコンテナオーケストレータになります。


3. [革新2] ルートレスセキュリティ:権限のパラダイムシフト

3.1 コンテナエスケープ:rootが危険な理由

Dockerのデフォルト実行モデルでは、コンテナ内のroot(UID 0)がホストのroot(UID 0)と同じUIDを共有しています。 もちろんLinux Capabilities、seccomp、AppArmor/SELinuxなどのセキュリティレイヤーで制限されていますが、 カーネルの脆弱性が発見されるたびにこれらの制限をバイパスされる可能性があります。

注目すべきコンテナエスケープ事例:

CVE脆弱性影響
CVE-2019-5736runcの脆弱性コンテナからホストのruncバイナリを上書き
CVE-2020-15257containerd Shim APIホストネットワーク名前空間にアクセス
CVE-2022-0185カーネルヒープオーバーフロー非特権コンテナからホストrootを取得
CVE-2024-21626runcファイルディスクリプタリークコンテナからホストファイルシステムにアクセス

これらの脆弱性に共通するのは、コンテナプロセスがホスト上でroot権限で動作するという前提を悪用している点です。

3.2 User NamespaceとUIDマッピング:Podmanの解答

PodmanのルートレスモードはLinux User Namespaceを使用して、この前提を完全に無効化します。 核心的な原理はシンプルです:コンテナ内のUID 0(root)をホスト上の非特権UIDにマッピングします。

+-------------------------------------------------------------+
|               User Namespace UIDマッピング図                  |
|                                                              |
|  +---------------------+      +---------------------------+ |
|  |   コンテナ内部      |      |      ホストシステム       | |
|  |   (User Namespace)  |      |                           | |
|  |                     |      |                           | |
|  |   UID 0 (root) ----+------+--> UID 1000 (youruser)    | |
|  |   UID 1        ----+------+--> UID 100000             | |
|  |   UID 2        ----+------+--> UID 100001             | |
|  |   UID 3        ----+------+--> UID 100002             | |
|  |   ...               |      |    ...                    | |
|  |   UID 65535    ----+------+--> UID 165535             | |
|  |                     |      |                           | |
|  +---------------------+      +---------------------------+ |
|                                                              |
|  * コンテナのrootがエスケープしてもホスト上ではUID 1000      |
|  * 非特権ユーザー -> システムファイルへのアクセス不可         |
|  * カーネルエクスプロイトの影響範囲が大幅に縮小              |
+-------------------------------------------------------------+

このマッピングは/etc/subuid/etc/subgidファイルで設定されます:

# /etc/subuid - ユーザーごとの従属UID範囲
youruser:100000:65536

# /etc/subgid - ユーザーごとの従属GID範囲
youruser:100000:65536

# 意味:youruserはUID 100000から65536個のUIDを使用可能

実際のマッピングを確認する方法:

# ルートレスモードでコンテナを実行
podman run -d --name test-rootless alpine sleep 3600

# コンテナ内のUIDを確認
podman exec test-rootless id
# uid=0(root) gid=0(root)  <- コンテナ内ではrootに見える

# ホスト上の実際のUIDを確認
podman top test-rootless huser
# HUSER
# 1000     <- ホスト上では一般ユーザー(UID 1000)

3.3 User Namespaceモード:きめ細かなセキュリティ制御

Podmanは--usernsオプションを通じて多様なUser Namespaceモードをサポートしています:

モード説明用途
auto自動UID/GID範囲割り当て(デフォルト)一般的なルートレスコンテナ
keep-idホストユーザーのUIDをコンテナ内でそのまま維持バインドマウントのファイル権限維持
nomapホストユーザーのUIDをコンテナにマッピングしない最大限のセキュリティ分離
hostUser Namespaceを無効化レガシー互換性(非推奨)
# keep-idモード:ホストUIDをコンテナ内で維持
# -> バインドマウントしたファイルの所有権問題を解決
podman run --userns=keep-id -v $HOME/project:/workspace:Z \
  -it node:20-alpine sh

# nomapモード:ホストユーザーのUIDを一切マッピングしない
# -> コンテナはホストユーザー所有のファイルにアクセス不可(world権限を除く)
podman run --userns=nomap alpine cat /proc/self/uid_map

3.4 コンプライアンス:PCI-DSS、FedRAMP、NIST規制への準拠

ルートレスコンテナは技術的改善を超えて、コンプライアンス面で決定的な優位性を提供します:

PCI-DSS v4.0(Payment Card Industry Data Security Standard)

  • 要件7.2:「最小権限の原則に従いシステムコンポーネントへのアクセスを制限する」
  • ルートレスコンテナはroot権限なしで動作し、この要件を構造的に満たす

FedRAMP(Federal Risk and Authorization Management Program)

  • AC-6(最小権限):「システム機能に必要な最小限の権限のみを付与する」
  • Podmanのルートレスモードはこの管理策の技術的実装そのもの

NIST SP 800-190(Application Container Security Guide)

  • 「ホストOSへのリスクを低減するため、コンテナを非rootユーザーで実行する」
  • Podmanはこれをデフォルト動作として実装

Linux Capabilities比較 -- Docker vs Podman:

Podmanはデフォルトでコンテナに11個のカーネルCapabilitiesのみを付与し、Dockerの14個より少なくなっています。 これは最小権限の原則の具体的な実装です:

# PodmanのデフォルトCapabilitiesを確認
podman run --rm alpine grep Cap /proc/1/status
# CapBnd: 00000000a80425fb

# DockerのデフォルトCapabilitiesを確認
docker run --rm alpine grep Cap /proc/1/status
# CapBnd: 00000000a80435fb
# -> DockerはCapabilitiesが多い(NET_RAWなどを含む)

セキュリティアーキテクトの原則:「セキュリティとは追加することではなく、不要なものを取り除くことだ。」 Podmanのルートレスモデルはこの原則の教科書的な実装です。


4. [革新3] play kube:「開発と運用の言語を統一する」

4.1 Docker Compose vs Kubernetes YAML:二重性の苦痛

開発者がクラウドネイティブ環境で直面する最も一般的な摩擦の一つは、 ローカル開発と本番デプロイの言語が異なることです。

+-------------------------------------------------------------+
|              開発/運用の言語二重性問題                        |
|                                                              |
|  開発者のラップトップ                  本番クラスター         |
|  +-------------------+            +--------------------+    |
|  | docker-compose.yml|            |  deployment.yaml   |    |
|  |                   |  ------->  |  service.yaml      |    |
|  | version: "3.8"    |   変換    |  configmap.yaml    |    |
|  | services:         |   が必要   |  ingress.yaml      |    |
|  |   web:            |            |                    |    |
|  |     image: app    |            |  apiVersion: apps/v1|   |
|  |     ports:        |            |  kind: Deployment  |    |
|  |       - "8080:80" |            |  spec:             |    |
|  +-------------------+            |    replicas: 3     |    |
|                                   +--------------------+    |
|                                                              |
|  * 2つの構文、2つのツール、2倍の学習コスト                  |
|  * 微妙な変換差異によるデプロイ失敗                         |
|  * 「自分のラップトップでは動いたのに…」の新たな変種        |
+-------------------------------------------------------------+

KomposeやDocker Compose to Kubernetesコンバーターなどのツールが存在しますが、 それらは問題の上にさらにレイヤーを追加しているだけで、根本的な解決策ではありません。

4.2 play kube:Kubernetes YAMLをローカルで実行

Podmanのplay kube(旧podman play kube、現podman kube play)はこの二重性を根本から排除します。 Kubernetes YAMLファイルをローカルのPodman環境でそのまま実行します。

サポートされるKubernetesリソースタイプ:

  • Pod
  • Deployment
  • DaemonSet
  • ConfigMap
  • Secret
  • PersistentVolumeClaim

ステップバイステップ:play kubeでマイクロサービススタックを実行

ステップ1 -- Kubernetes YAMLを作成(microservices-stack.yaml):

# microservices-stack.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DATABASE_HOST: 'postgres'
  DATABASE_PORT: '5432'
  DATABASE_NAME: 'appdb'
  APP_LOG_LEVEL: 'info'
---
apiVersion: v1
kind: Pod
metadata:
  name: microservices
  labels:
    app: microservices-stack
    environment: development
spec:
  # Initコンテナ:データベースマイグレーション
  initContainers:
    - name: db-migration
      image: docker.io/library/flyway/flyway:10
      command: ['flyway', 'migrate']
      env:
        - name: FLYWAY_URL
          value: 'jdbc:postgresql://localhost:5432/appdb'
        - name: FLYWAY_USER
          value: 'appuser'
        - name: FLYWAY_PASSWORD
          value: 'secret123'
      volumeMounts:
        - name: migration-scripts
          mountPath: /flyway/sql
  containers:
    # データベース
    - name: postgres
      image: docker.io/library/postgres:16-alpine
      ports:
        - containerPort: 5432
      env:
        - name: POSTGRES_DB
          value: 'appdb'
        - name: POSTGRES_USER
          value: 'appuser'
        - name: POSTGRES_PASSWORD
          value: 'secret123'
      volumeMounts:
        - name: pgdata
          mountPath: /var/lib/postgresql/data
    # APIサーバー
    - name: api-server
      image: docker.io/library/node:20-alpine
      ports:
        - containerPort: 3000
          hostPort: 3000
      env:
        - name: DATABASE_HOST
          value: 'localhost'
        - name: DATABASE_PORT
          value: '5432'
      command: ['node', 'server.js']
      volumeMounts:
        - name: app-source
          mountPath: /app
    # Redisキャッシュ
    - name: redis
      image: docker.io/library/redis:7-alpine
      ports:
        - containerPort: 6379
      command: ['redis-server', '--maxmemory', '256mb']
  volumes:
    - name: pgdata
      persistentVolumeClaim:
        claimName: pgdata-pvc
    - name: migration-scripts
      hostPath:
        path: ./migrations
    - name: app-source
      hostPath:
        path: ./src

ステップ2 -- スタックを実行:

# YAMLファイルからスタック全体を作成
podman kube play microservices-stack.yaml

# 実行状態を確認
podman pod ps
# POD ID        NAME            STATUS   CREATED        INFRA ID      # OF CONTAINERS
# a1b2c3d4e5f6  microservices   Running  10 seconds ago 9f8e7d6c5b4a  4

# 個別コンテナを確認
podman ps --pod
# CONTAINER ID  IMAGE                            STATUS         POD ID        NAMES
# ...           docker.io/library/postgres:16    Up 10 seconds  a1b2c3d4e5f6  microservices-postgres
# ...           docker.io/library/node:20        Up 8 seconds   a1b2c3d4e5f6  microservices-api-server
# ...           docker.io/library/redis:7        Up 8 seconds   a1b2c3d4e5f6  microservices-redis

# APIサーバーのログを確認
podman logs microservices-api-server

ステップ3 -- スタックを破棄:

# --downフラグでスタック全体を破棄・クリーンアップ
podman kube play --down microservices-stack.yaml

# 確認
podman pod ps
# (空 - すべてのリソースがクリーンアップ済み)

4.3 コンベンションベースのイメージビルド

play kubeの隠れた強力な機能の一つはコンベンションベースの自動イメージビルドです。 YAML内で参照されるイメージと同名のディレクトリが現在のパスに存在し、 その中にContainerfileまたはDockerfileがある場合、自動的にビルドされます。

プロジェクトディレクトリ構造:
+-- my-stack.yaml          <- image: my-api を参照
+-- my-api/                <- 自動ビルド対象
|   +-- Containerfile
|   +-- src/
|       +-- server.js
+-- my-frontend/           <- image: my-frontend を参照
    +-- Containerfile
    +-- dist/
        +-- index.html
# --buildフラグでイメージ自動ビルド + 実行
podman kube play --build my-stack.yaml

# 既にビルド済みのイメージを置換(強制ビルド)
podman kube play --replace --build my-stack.yaml

この機能によりCI/CDパイプラインとローカル開発環境を同じYAMLで実行でき、 Podmanのビジョン「Develop locally, deploy globally」を実現します。

4.4 Initコンテナ:alwaysとonce

PodmanはKubernetesのInitコンテナ概念をローカルで忠実に実装しています。 Podman独自のalwaysonceタイプの区別は実務で特に有用です:

タイプ動作用途
once(デフォルト)Pod起動時に一度だけ実行され削除されるDBマイグレーション、シークレット初期化
alwaysPod起動のたびに毎回実行される(削除されない)ヘルスチェック待機、設定リフレッシュ
# Initコンテナタイプの指定(Podmanアノテーション)
metadata:
  annotations:
    io.podman.annotations.init.container.type/wait-for-db: 'always'
spec:
  initContainers:
    - name: wait-for-db
      image: docker.io/library/busybox:latest
      command:
        ['sh', '-c', 'until nc -z localhost 5432; do echo "Waiting for DB..."; sleep 2; done']

alwaysタイプのInitコンテナはpodman kube generateの出力にも含まれるため、 ローカルで検証した初期化ロジックをそのままKubernetesクラスターに持ち込めます。


5. [革新4] Podネイティブ管理:真のPod Manager

5.1 Podmanの本質:Podを管理するツール

Podmanの名前はPod Managerに由来します。 これは単なる巧みなネーミングではなく、KubernetesのPod概念をローカル環境で第一級市民として実装するという設計意図を表しています。

Dockerでは複数のコンテナを一緒に実行するにはDocker Composeという別のツールが必要でしたが、 PodmanではPodが組み込み機能です。

+-------------------------------------------------------------+
|                      Podman Podアーキテクチャ                 |
|                                                              |
|  +--- Pod ------------------------------------------------+ |
|  |                                                        | |
|  |  +----------+                                          | |
|  |  |  Infra   |  <- pauseコンテナ                        | |
|  |  |Container |  <- ネットワーク名前空間のオーナー       | |
|  |  | (pause)  |  <- Podライフサイクルのアンカー           | |
|  |  +----------+                                          | |
|  |       |                                                | |
|  |       |-- 共有: Network Namespace                      | |
|  |       |-- 共有: IPC Namespace                          | |
|  |       |-- 共有: UTS Namespace (hostname)               | |
|  |       |                                                | |
|  |  +----------+  +----------+  +----------+             | |
|  |  |   App    |  |  Sidecar |  |  Logging |             | |
|  |  |Container |  | (envoy)  |  | (fluentd)|             | |
|  |  |          |  |          |  |          |             | |
|  |  | :8080    |  | :15001   |  | :24224   |             | |
|  |  +----------+  +----------+  +----------+             | |
|  |                                                        | |
|  |  * 全コンテナがlocalhostで通信                         | |
|  |  * Kubernetes Podと同じネットワークモデル              | |
|  +--------------------------------------------------------+ |
|                                                              |
+-------------------------------------------------------------+

Podman Podの主な特徴:

  1. Infraコンテナ:KubernetesのPauseコンテナと同じ役割。ネットワーク名前空間を所有し、Pod内の全コンテナで共有
  2. localhost通信:Pod内のコンテナはlocalhost(127.0.0.1)で通信
  3. 名前空間の共有:Network、IPC、UTS名前空間がデフォルトで共有
  4. 一括管理podman pod start/stop/rmによるPodレベルのライフサイクル管理

5.2 サイドカーパターンの実装

クラウドネイティブアーキテクチャで最も広く使われるサイドカーパターンは、 Podman Podを使ってローカルで完璧に実装できます:

# 1. Podを作成(ポートマッピングはPodレベルで設定)
podman pod create --name my-app \
  --publish 8080:8080 \
  --publish 9090:9090

# 2. メインアプリケーションコンテナ
podman run -d --pod my-app \
  --name app-main \
  my-registry.io/my-app:v1.0

# 3. サイドカー:Envoyプロキシ
podman run -d --pod my-app \
  --name app-envoy \
  docker.io/envoyproxy/envoy:v1.31

# 4. サイドカー:ログコレクター
podman run -d --pod my-app \
  --name app-logger \
  docker.io/fluent/fluentd:v1.17

# 5. サイドカー:メトリクスコレクター
podman run -d --pod my-app \
  --name app-metrics \
  docker.io/prom/node-exporter:v1.8

# Podのステータスを確認
podman pod inspect my-app

このパターンにより、Kubernetes向けのサービスメッシュ構成(Envoy + アプリ + ロギング)を ローカル開発環境で同じネットワークトポロジーでテストできます。

5.3 generate kube:ローカルからクラスターへの橋渡し

Podmanのgenerate kube(現podman kube generate)は、 ローカルで実行中のコンテナやPodをKubernetes YAMLにエクスポートする逆方向のワークフローをサポートしています。

完全なワークフロー例:

# ステップ1:ローカルでPodを構成
podman pod create --name webapp --publish 8080:80

podman run -d --pod webapp \
  --name webapp-nginx \
  -v ./html:/usr/share/nginx/html:Z \
  docker.io/library/nginx:alpine

podman run -d --pod webapp \
  --name webapp-redis \
  docker.io/library/redis:7-alpine

# ステップ2:Kubernetes YAMLを生成
podman kube generate webapp -f webapp-k8s.yaml

# ステップ3:生成されたYAMLを確認
cat webapp-k8s.yaml

生成されたYAMLの例:

# webapp-k8s.yaml (podman kube generateにより自動生成)
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: '2026-03-01T09:00:00Z'
  labels:
    app: webapp
  name: webapp
spec:
  containers:
    - name: webapp-nginx
      image: docker.io/library/nginx:alpine
      ports:
        - containerPort: 80
          hostPort: 8080
          protocol: TCP
      volumeMounts:
        - mountPath: /usr/share/nginx/html
          name: html-host
    - name: webapp-redis
      image: docker.io/library/redis:7-alpine
  volumes:
    - name: html-host
      hostPath:
        path: /home/user/project/html
        type: Directory
# ステップ4:生成されたYAMLをKubernetesクラスターに適用
kubectl apply -f webapp-k8s.yaml

# または別のPodmanホストで同じYAMLを実行
podman kube play webapp-k8s.yaml

generate kubeの追加オプション:

# Serviceオブジェクトも一緒に生成
podman kube generate -s webapp -f webapp-with-service.yaml

# Deploymentタイプで生成(レプリカ数指定)
podman kube generate --type deployment --replicas 3 webapp

# DaemonSetやJobタイプでも生成可能
podman kube generate --type job webapp

この双方向ワークフロー(play kube <-> generate kube)は、 「Develop locally, deploy globally」を技術的に可能にするPodmanの核心的な革新です:

+-----------------------------------------------------------+
|            Podman <-> Kubernetes 双方向ワークフロー         |
|                                                           |
|   ローカル開発                     Kubernetesクラスター    |
|   +---------+                       +-------------+      |
|   | podman  |   podman kube generate| kubectl     |      |
|   | pod     | --------------------->| apply -f    |      |
|   | create  |                       |             |      |
|   | + run   |   podman kube play    | Deployment  |      |
|   |         | <---------------------| export      |      |
|   +---------+                       +-------------+      |
|                                                           |
|   * 同じYAML、同じセマンティクス                          |
|   * 環境間の変換が不要                                    |
+-----------------------------------------------------------+

6. [革新5] Pastaネットワーキング:NATフリーのルートレスネットワーキング

6.1 ルートレスネットワーキングのジレンマ

ルートレスコンテナの最大の技術的課題の一つはネットワーキングです。 一般ユーザーにはネットワークインターフェースの作成やiptablesルールの操作の権限がありません。 Podmanがこの問題を解決するために最初に採用した技術がslirp4netnsでした。

slirp4netnsの動作原理:

slirp4netnsはユーザー空間でTCP/IPスタックをエミュレートします。 コンテナからのすべてのネットワークトラフィックは次のパスを辿ります:

Container -> TAPデバイス -> slirp4netns (ユーザー空間NAT) -> ホストネットワーク

このアプローチは動作しますが、すべてのパケットがユーザー空間でNAT変換されるため、 大きなレイテンシとCPUオーバーヘッドが発生します。

6.2 Pasta:パラダイムシフト

Pasta(Pack A Subtle Tap Abstraction)passtプロジェクトの一部であり、 slirp4netnsのNATベースのアプローチをL2-L4ソケットマッピングに置き換えた次世代ルートレスネットワーキングソリューションです。

Podman 5.0からデフォルトのルートレスネットワークドライバーとして採用され、 RHEL 9.5でもデフォルトに設定されています。

+-------------------------------------------------------------+
|            slirp4netns vs Pasta アーキテクチャ比較            |
|                                                              |
|  +- slirp4netns (レガシー) ---------------------------------+|
|  |                                                          ||
|  |  コンテナ            ユーザー空間           ホスト       ||
|  |  +-------+    +------------------+    +----------+       ||
|  |  | eth0  |--->|  slirp4netns     |--->| Host     |       ||
|  |  | (TAP) |    |  +------------+  |    | Network  |       ||
|  |  +-------+    |  | ユーザー空間|  |    +----------+       ||
|  |               |  | TCP/IP     |  |                       ||
|  |               |  | + NAT      |  |  <- 全パケットNAT処理||
|  |               |  +------------+  |  <- CPUオーバーヘッド大||
|  |               +------------------+                       ||
|  +----------------------------------------------------------+|
|                                                              |
|  +- Pasta (Podman 5.0+デフォルト) --------------------------+|
|  |                                                          ||
|  |  コンテナ            カーネル空間           ホスト       ||
|  |  +-------+    +------------------+    +----------+       ||
|  |  | eth0  |--->| L2->L4ソケット   |--->| Host     |       ||
|  |  | (TAP) |    |  マッピング       |    | Network  |       ||
|  |  +-------+    |  +------------+  |    | cfg copy |       ||
|  |               |  | splice(2)  |  |    +----------+       ||
|  |               |  | sendmmsg() |  |                       ||
|  |               |  | recvmmsg() |  |                       ||
|  |               |  +------------+  |  <- NATなし           ||
|  |               +------------------+  <- 直接ソケット転送  ||
|  +----------------------------------------------------------+|
|                                                              |
+-------------------------------------------------------------+

Pastaの核心的技術革新:

  1. ホストネットワーク設定のコピー:ホストのネットワーク設定をコンテナ名前空間に直接コピーし、NAT自体を不要にする
  2. L2-L4ソケットマッピング:Layer-2 TAPインターフェースのパケットをLayer-4ソケット(TCP/UDP/ICMP)に直接マッピング
  3. splice(2)システムコール:カーネルのsplice(2)システムコールを使用しローカル接続でゼロコピーデータ転送
  4. recvmmsg/sendmmsg最適化:単一のシステムコールで複数パケットを処理し、syscallオーバーヘッドを削減
  5. Tap Bypassパス:ローカルアドレス宛のパケットはL2変換をスキップし、L4ソケット間で直接転送

6.3 性能比較:slirp4netns vs Pasta

メトリックslirp4netnsPasta改善率
コンテナ起動時間約1.2秒約0.8秒33%高速
メモリ使用量約100MB約85MB15%削減
TCPスループット(1接続)ベースライン+15-30%大幅改善
TCPレイテンシ(p50)ベースライン-20-40%大幅改善
UDPスループットベースライン+10-20%改善
並列接続(8以下)ベースライン優位Pastaが勝利
並列接続(8超)優位ベースラインslirp4netnsが勝利*
CPUオーバーヘッド(アイドル)高い低い大幅改善

*注:高並列シナリオ(並列数8超)では、slirp4netnsの方が良い性能を示す場合があります。 これはPastaのソケットマッピング方式が極度の高並列時に競合を起こす可能性があるためです。 ただし、一般的な開発環境やほとんどの本番ワークロードでは、Pastaが全般的に優位です。

6.4 Pastaネットワーキングの設定と使用

# PastaはPodman 5.0+でデフォルト
# 明示的に指定する場合:
podman run --network=pasta -d nginx

# slirp4netnsにフォールバックする場合:
podman run --network=slirp4netns -d nginx

# Pastaポートフォワーディング(特定ポートのみ公開)
podman run --network=pasta:-T,8080,-U,5353 -d my-app

# Pastaネットワーキングのステータス確認
podman inspect --format '{{.HostConfig.NetworkMode}}' <container>

6.5 ネットワークモード選択ガイド

シナリオ推奨ネットワークモード理由
一般的なルートレス開発pasta(デフォルト)性能/互換性の最適なバランス
レガシー互換性が必要slirp4netns古いカーネルでも安定
rootコンテナbridge(CNI/netavark)rootモードの伝統的なブリッジ
ホストネットワークへの直接アクセスhostネットワーク分離が不要な場合
Pod内のコンテナ間通信pod共有名前空間localhost通信

7. Podman Desktop:GUIによるPodmanのフルエクスペリエンス

7.1 Podman Desktopの概要

2025年はPodman Desktopにとって決定的な年でした。300万ダウンロードを突破し、 Docker Desktopの代替としての地位を確立しました。 2026年1月にはCNCF(Cloud Native Computing Foundation)プロジェクトとしても登録されました。

Podman Desktopの主な機能:

機能説明
コンテナ管理作成、起動、停止、削除、ログ表示、ターミナルアクセス
イメージ管理ビルド、プル、プッシュ、検索、プルーン(不要イメージ削除)
Pod管理Pod作成、Kubernetes YAMLデプロイ、Podログ検索
ボリューム/ネットワークボリューム作成/削除、ネットワーク可視化と管理
Kubernetes統合Kind、Minikube、OpenShiftクラスター統合
エクステンションBootC、Headlamp、AI Labエクステンション
ComposeサポートDocker Composeファイル互換実行
ダッシュボードカスタマイズウィジェット配置、テーブル列カスタマイズ

7.2 エンタープライズPodman Desktop

Red Hatはエンタープライズ環境向けに機能を強化したRed Hat build of Podman Desktopをリリースしています:

  • フリートワイド設定:レジストリミラー、HTTPプロキシなどの組織レベルの設定管理
  • OpenShift統合:OpenShiftクラスターへの直接デプロイサポート
  • BootCワークフロー:コンテナからブータブルOSイメージへの変換
  • セキュリティポリシー適用:企業セキュリティ基準に準拠したデフォルト設定のデプロイ

8. DockerからPodmanへ:実践的マイグレーションガイド

8.1 マイグレーションが簡単な理由

PodmanはDocker CLIとのコマンドレベルの互換性を維持するよう設計されています。 ほとんどのdockerコマンドはそのままpodmanに置き換え可能です。

8.2 コマンドマッピング表

DockerコマンドPodmanコマンド相違点
docker runpodman run同一
docker buildpodman build同一
docker pullpodman pull同一
docker pushpodman push同一
docker pspodman ps同一
docker execpodman exec同一
docker logspodman logs同一
docker imagespodman images同一
docker composepodman compose別途インストールまたはpodman-compose
docker swarmサポートなし代わりにKubernetesを使用
N/Apodman podPodman専用機能
N/Apodman kube playPodman専用機能
N/Apodman kube generatePodman専用機能

8.3 ステップバイステップマイグレーション

ステップ1 -- インストール:

# macOS
brew install podman
podman machine init --cpus 4 --memory 8192 --disk-size 60
podman machine start

# RHEL/CentOS/Fedora
sudo dnf install -y podman

# Ubuntu/Debian
sudo apt-get install -y podman

# Windows
winget install RedHat.Podman

ステップ2 -- Docker互換エイリアスの設定(任意):

# ~/.bashrc または ~/.zshrc
alias docker=podman

# Docker Socket互換性(Docker APIを使用するツール向け)
# macOS:
podman machine stop
podman machine set --rootful
podman machine start

# Linux (rootless):
systemctl --user enable --now podman.socket
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/podman/podman.sock

ステップ3 -- Docker Composeファイルのマイグレーション:

# 方法1: podman compose(Podman 5.x組み込みサポート)
podman compose up -d

# 方法2: podman-compose(Pythonベースのスタンドアロンツール)
pip install podman-compose
podman-compose up -d

# 方法3: Kubernetes YAMLに変換(推奨)
# docker-compose.ymlをKubernetes YAMLに変換後
podman kube play my-stack.yaml

ステップ4 -- CI/CDパイプラインの更新:

# GitHub Actionsの例
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Podman
        run: |
          sudo apt-get update
          sudo apt-get install -y podman

      - name: Build Image
        run: podman build -t my-app:${{ github.sha }} .

      - name: Push to Registry
        run: |
          podman login -u ${{ secrets.REGISTRY_USER }} \
                       -p ${{ secrets.REGISTRY_PASS }} \
                       registry.example.com
          podman push my-app:${{ github.sha }} \
                      registry.example.com/my-app:${{ github.sha }}

8.4 マイグレーション時の注意事項

領域DockerPodman対策
デーモン状態常時稼働デーモンなしsystemdによる自動起動の設定
Docker Socket/var/run/docker.sockPodman Socketの有効化が必要podman.socketサービスを有効化
Docker SwarmサポートサポートなしKubernetesに移行
イメージ保存先/var/lib/docker~/.local/share/containers(rootless)既存イメージの再プルが必要
ネットワークドライバーbridge(dockerd管理)Netavark + Pasta(rootless)互換性あり、設定の確認が必要
ビルドキャッシュDocker BuildKitPodman Buildah組み込み互換性あり

9. Podman vs Docker:総合比較

比較項目DockerPodman
アーキテクチャクライアント-サーバー(dockerdデーモン)デーモンレス(Fork-Exec)
デフォルト実行モードroot(rootlessは実験的)rootless(デフォルト)
Podサポートなし(Composeで代替)ネイティブPodサポート
Kubernetes YAML実行別途ツールが必要podman kube playが組み込み
systemd統合限定的Quadletによるネイティブ統合
コンテナ起動時間約1.2秒約0.8秒
アイドルメモリ約100MB(デーモン含む)約85MB
アイドルCPUデーモンが常時稼働0%(デーモンなし)
カーネルCapabilities14(デフォルト)11(デフォルト)
OCI準拠完全準拠完全準拠
イメージ互換性Docker HubがデフォルトDocker Hub + 全OCIレジストリ
ビルドツールBuildKitBuildah組み込み
ルートレスネットワーキングslirp4netnsPasta(デフォルト)
Docker Composeネイティブ互換(podman compose
Docker Swarmサポートサポートなし(Kubernetes推奨)
GUIツールDocker Desktop(有料*)Podman Desktop(無料/オープンソース)
ライセンスApache 2.0(Engine)/ 有料(Desktop)Apache 2.0(完全無料)
マルチプラットフォームビルドbuildxpodman farm build
シークレット管理Docker Secrets(Swarm)podman secret
TLS/mTLSリモートアクセスサポート5.xで強化
OCI Artifact管理限定的podman artifact(5.xで安定化)

*Docker Desktop:従業員250名以上または年間売上1,000万ドル超の企業は有料サブスクリプションが必要


10. まとめ:コンテナの未来は引き算にある

Podmanが提示する5つの革新を振り返ると、一貫した哲学が貫かれています:

10.1 デフォルトとしてのセキュリティ

Dockerではセキュリティは「追加する」ものでした。ルートレスモードを有効にし、seccompプロファイルを書き、AppArmorポリシーを設定する必要がありました。 Podmanではセキュリティは**「最初からオン」**です。ルートレスがデフォルト、デーモンなし、最小限のCapabilitiesがデフォルトで適用されます。

引き算によるセキュリティ:デーモンの除去(デーモンレス)、rootの除去(ルートレス)、不要な権限の除去(最小限のCapabilities)。 追加されたセキュリティは忘れられますが、デフォルトで提供されるセキュリティは常に機能します。

10.2 開発と運用の言語統一

Docker Composeで開発しKubernetes YAMLでデプロイするという二重性は、 開発組織に目に見えない税金、すなわち変換コストを課してきました。

Podmanのplay kubegenerate kubeはこの税金を排除します。 開発者が書くYAMLがそのまま本番環境のYAMLになるというSingle Language Principleを実現します。

10.3 リソース効率

デーモンレスアーキテクチャはアイドル時のCPU使用率ゼロ、Pastaネットワーキングはオーバーヘッドの排除、 systemd統合は別途のオーケストレータのリソースコスト削減を意味します。 これは単一の開発マシンでは気づきにくいかもしれませんが、 数百台のエッジノードリソースが制約されたIoT環境コスト最適化されたクラウドインフラでは有意義な差を生みます。

10.4 最終まとめ

+-------------------------------------------------------------+
|                   Podmanの5つの革新まとめ                     |
|                                                              |
|  +-------------+   デーモンの除去    -> 安定性              |
|  | 革新1       |   SPOFの排除        -> コンテナの自律性    |
|  | デーモンレス|   systemd統合       -> OSネイティブ管理    |
|  +-------------+                                            |
|                                                              |
|  +-------------+   rootの除去        -> 攻撃面の最小化     |
|  | 革新2       |   User Namespace    -> UID分離            |
|  | ルートレス  |   最小Capabilities  -> コンプライアンス   |
|  +-------------+                                            |
|                                                              |
|  +-------------+   変換の除去        -> 開発/運用言語統一  |
|  | 革新3       |   K8s YAML直接実行  -> 環境間一貫性       |
|  | play kube   |   コンベンションビルド -> ワークフロー簡素化|
|  +-------------+                                            |
|                                                              |
|  +-------------+   抽象化の除去      -> K8sと同じ単位      |
|  | 革新4       |   ネイティブPod     -> ローカルサイドカー |
|  | Pod管理     |   generate kube     -> 双方向ワークフロー |
|  +-------------+                                            |
|                                                              |
|  +-------------+   NATの除去         -> レイテンシ削減     |
|  | 革新5       |   L2-L4ソケットマッピング -> スループット向上|
|  | Pasta       |   splice(2)         -> ゼロコピー転送     |
|  +-------------+                                            |
|                                                              |
|  * 共通哲学:不要なものを取り除くことで                      |
|    本質的な価値を最大化する                                  |
+-------------------------------------------------------------+

PodmanはDockerを否定するものではありません。Dockerが始めたコンテナ革命の基盤の上に、 セキュリティ標準準拠リソース効率という現代の要件に合わせてコンテナ技術を再設計しています。

2026年のクラウドネイティブの世界において、コンテナツールを選ぶ基準は 「何ができるか」ではなく**「何をしないか」**であるべきです。 不要なデーモンを動かさない、不要な権限を付与しない、 不要な変換レイヤーを追加しない。それがPodmanが描くコンテナの未来です。


11. 参考文献

公式ドキュメント

Red Hatブログおよび技術ドキュメント

コミュニティおよび技術分析

セキュリティとコンプライアンス

クイズ

Q1: 「Kubernetesをローカルマシンに:Podmanがもたらす5つの革新」の主なトピックは何ですか?

Podmanのデーモンレスアーキテクチャ、ルートレスセキュリティモデル、play kubeによるK8s YAMLのローカル実行、Pod ネイティブ管理、Pastaネットワーキングまで、Dockerを超えてクラウドネイティブ開発環境の新たな標準となった5つの革新をアーキテクトの視点から徹底分析します。

Q2: [革新1] デーモンレスアーキテクチャ:単一障害点の終焉について説明してください。

2.1 Dockerデーモンの構造的問題 Dockerのアーキテクチャを理解するには、中心に位置するdockerd(Dockerデーモン)を理解する必要があります。 すべてのDocker CLIコマンドはREST APIを通じてdockerdに渡され、dockerdはcontainerdを呼び出し、 containerdがruncを通じて実際のコンテナを作成します。 この構造の3つの核心的問題: 第一に、単一障害点(SPOF):dockerdが異常終了すると、実行中の全コンテナの管理が不可能になります。

Q3: [革新2] ルートレスセキュリティ:権限のパラダイムシフトの核心的な概念を説明してください。

3.1 コンテナエスケープ:rootが危険な理由 Dockerのデフォルト実行モデルでは、コンテナ内のroot(UID 0)がホストのroot(UID 0)と同じUIDを共有しています。 もちろんLinux Capabilities、seccomp、AppArmor/SELinuxなどのセキュリティレイヤーで制限されていますが、 カーネルの脆弱性が発見されるたびにこれらの制限をバイパスされる可能性があります。

Q4: [革新3] play kube:開発と運用の言語を統一するの主な特徴は何ですか? 4.1 Docker Compose vs Kubernetes YAML:二重性の苦痛 開発者がクラウドネイティブ環境で直面する最も一般的な摩擦の一つは、 ローカル開発と本番デプロイの言語が異なることです。 KomposeやDocker Compose to Kubernetesコンバーターなどのツールが存在しますが、 それらは問題の上にさらにレイヤーを追加しているだけで、根本的な解決策ではありません。

Q5: [革新4] Podネイティブ管理:真のPod Managerはどのように機能しますか? 5.1 Podmanの本質:Podを管理するツール Podmanの名前はPod Managerに由来します。 これは単なる巧みなネーミングではなく、KubernetesのPod概念をローカル環境で第一級市民として実装するという設計意図を表しています。 Dockerでは複数のコンテナを一緒に実行するにはDocker Composeという別のツールが必要でしたが、 PodmanではPodが組み込み機能です。 Podman Podの主な特徴: Infraコンテナ:KubernetesのPauseコンテナと同じ役割。