第11章:Kubernetesとの統合
本章の意義と学習目標
なぜPodmanのKubernetes連携を学ぶ必要があるのか
「開発環境と本番環境の乖離」は、多くの組織が抱える根本的な課題です。PodmanのKubernetes連携機能は、この課題に対する革新的な解決策を提供します:
- 開発サイクルの劇的な短縮: ローカルでKubernetes YAMLを直接実行し、即座にフィードバック
- 学習コストの削減: Kubernetesクラスターなしで、同じ概念とツールを使用
- デプロイリスクの最小化: 開発環境で検証したものがそのまま本番で動作
- 段階的移行の実現: 単一ホストからクラスターへ、無理のない移行パス
本章では、PodmanをKubernetesへの「架け橋」として活用し、クラウドネイティブへの移行を成功させる方法を学びます。
11.1 PodmanとKubernetesの関係
なぜPodmanがKubernetesと深い関係を持つのか
PodmanはKubernetesのローカル開発環境として設計されています。これは偶然ではなく、以下の戦略的理由があります:
- 同じ概念モデル: Pod、Container、Volumeなど、Kubernetesの中核概念を共有
- 開発者体験の統一: ローカル開発から本番デプロイまで一貫したワークフロー
- Red Hatのビジョン: OpenShiftを通じたエンタープライズKubernetesの推進
11.1.1 共通点と相違点
共通点が生む価値
- OCI標準準拠: 同じコンテナイメージが両環境で動作し、「動作保証」を実現
- Pod概念のサポート: 複雑なマルチコンテナアプリケーションの開発が容易
- YAML形式での定義: Infrastructure as Codeの実践、GitOpsワークフローの実現
- CRI互換性: 同じランタイムインターフェースにより、移行時の問題を最小化
相違点とその理由 | 特徴 | Podman | Kubernetes | なぜ違いが必要か | |——|——–|————|—————–| | スケール | 単一ホスト | クラスター | 開発環境のシンプルさと本番のスケーラビリティの両立 | | オーケストレーション | なし | あり | ローカルでは不要な複雑性を排除 | | サービスディスカバリ | 基本的 | 高度 | 開発時は簡潔さを優先 | | 永続化 | ローカル | 分散ストレージ | 開発環境のセットアップ簡素化 |
これらの違いは欠点ではなく、各環境の目的に最適化された設計の結果です。
実際のエンタープライズ運用事例
事例1: 金融機関での段階的移行(A銀行)
課題:
- レガシーシステムからマイクロサービスへの移行
- 厳格なセキュリティ要件とコンプライアンス
- 開発者100名のスキル移行
Podman活用アプローチ:
# 段階1: 開発環境でのPod概念の導入
podman pod create --name banking-app-pod
podman run -d --pod banking-app-pod --name web-frontend nginx:alpine
podman run -d --pod banking-app-pod --name api-backend python:3.11-alpine
# 段階2: Kubernetes YAML生成での本番環境準備
podman generate kube banking-app-pod > banking-app-k8s.yaml
# 段階3: セキュリティポリシーの検証
podman pod create --security-opt seccomp=banking-policy.json \
--name secure-banking-pod
結果:
- 移行期間: 18ヶ月 → 12ヶ月(33%短縮)
- 開発者の学習時間: 40%削減
- セキュリティインシデント: ゼロ
事例2: 製造業での IoT エッジコンピューティング(B製造会社)
要件:
- 工場の Edge デバイスでのコンテナ実行
- 低リソース環境での安定動作
- リモート管理とアップデート
Podman活用の理由:
# リソース効率: デーモンレス実行
# 1000台のエッジデバイス × 300MB節約 = 300GB削減
# rootless実行によるセキュリティ
podman run --user 1001:1001 \
--security-opt no-new-privileges \
edge-analytics:latest
# systemdとの統合
podman generate systemd --name iot-collector --files
systemctl --user enable container-iot-collector.service
効果:
- メモリ使用量: 30%削減
- セキュリティインシデント: 90%削減
- 運用工数: 50%削減
事例3: SaaS企業での開発速度向上(Cスタートアップ)
課題:
- 高速な機能開発とデプロイ
- 限られた DevOps リソース
- マルチクラウド対応
Podman活用の効果:
# 開発者各自がKubernetes環境を再現
podman play kube production-deployment.yaml
# ローカルでの統合テスト
podman pod create --name test-environment
podman run --pod test-environment database:latest
podman run --pod test-environment api:latest
podman run --pod test-environment frontend:latest
# CI/CDパイプラインでの検証
podman build -t myapp:latest .
podman run --rm myapp:latest pytest tests/
成果:
- デプロイ頻度: 週1回 → 日5回
- 障害率: 70%削減
- 開発者満足度: 40%向上
11.1.2 アーキテクチャの比較
Podmanのアーキテクチャ
┌─────────────┐
│ podman │ ← CLI/API
├─────────────┤
│ libpod │ ← Pod/Container管理
├─────────────┤
│ containers/ │ ← ストレージ/ネットワーク
│ storage │
├─────────────┤
│ runc │ ← OCI Runtime
└─────────────┘
Kubernetesのアーキテクチャ(簡略図)
┌─────────────┐
│ API Server │
├─────────────┤
│ Scheduler │ ┌─────────────┐
├─────────────┤ │ kubelet │
│ Controller │ ├─────────────┤
│ Manager │ │ Container │
└─────────────┘ │ Runtime │
└─────────────┘
この違いが意味すること:
- Podman: 単一プロセスでシンプル、リソース効率的
- Kubernetes: 分散システムで高可用性、複雑だが強力
11.2 Kubernetes YAMLの実行
11.2.1 podman playによるYAML実行
PodmanはKubernetes YAMLを直接実行できます。これにより、開発環境での検証が劇的に簡単になります。
基本的な使用方法
# Kubernetes YAMLの実行
podman play kube deployment.yaml
# 実行中のPodの確認
podman pod ps
# Podの停止と削除
podman play kube --down deployment.yaml
サポートされるリソースタイプ
- Pod
- Deployment(Podとして実行)
- PersistentVolumeClaim
- ConfigMap
- Secret
実践例: Webアプリケーションのデプロイ
apiVersion: v1
kind: Pod
metadata:
name: webapp
spec:
containers:
- name: frontend
image: nginx:alpine
ports:
- containerPort: 80
hostPort: 8080
- name: backend
image: node:alpine
command: ["node", "server.js"]
env:
- name: DB_HOST
value: "localhost"
# 実行
podman play kube webapp.yaml
# 動作確認
curl http://localhost:8080
11.2.2 制限事項と回避策
主な制限事項
- Service未サポート: ClusterIPやLoadBalancerは機能しない
- 回避策: hostPortを使用、またはpodman-composeで代替
- 複数レプリカ未対応: ReplicaSetのスケーリングは無視される
- 回避策: 開発時は単一インスタンスで十分
- ネームスペース制限: 完全な分離は提供されない
- 回避策: Pod名でのプレフィックス使用
実用的な対処法
# 開発用と本番用でYAMLを分ける
podman play kube dev-pod.yaml # 開発用(hostPort含む)
kubectl apply -f prod-deploy.yaml # 本番用(Service使用)
11.3 Kubernetes YAMLの生成
11.3.1 podman generate kubeコマンド
既存のPodmanコンテナからKubernetes YAMLを生成できます。これにより、ローカルで動作確認したものを確実にKubernetesに移行できます。
基本的な使用方法
# 単一コンテナから生成
podman generate kube mycontainer > pod.yaml
# Podから生成
podman generate kube mypod > pod.yaml
# Serviceも含めて生成
podman generate kube -s mypod > deployment.yaml
生成されるYAMLの例
apiVersion: v1
kind: Pod
metadata:
labels:
app: myapp
name: myapp-pod
spec:
containers:
- image: localhost/myapp:latest
name: myapp
ports:
- containerPort: 8080
protocol: TCP
resources: {}
securityContext:
capabilities:
drop:
- CAP_MKNOD
- CAP_AUDIT_WRITE
restartPolicy: OnFailure
11.3.2 生成されたYAMLのカスタマイズ
生成されたYAMLは基本的なものなので、本番環境向けにカスタマイズが必要です。
必要な修正点
- イメージの参照先
# 変更前 image: localhost/myapp:latest # 変更後 image: registry.example.com/myapp:v1.0.0
- リソース制限の追加
resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
- プローブの追加
livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 10
11.4 開発から本番への移行戦略
11.4.1 段階的移行アプローチ
フェーズ1: ローカル開発(Podman)
- 単一ホストでの開発とテスト
- podman-composeでマルチコンテナアプリケーション構築
- CI/CDパイプラインでの自動テスト
フェーズ2: Kubernetes互換性確認(Podman + YAML)
- Kubernetes YAMLでの定義
- podman play kubeでの動作確認
- 設定の外部化(ConfigMap/Secret)
フェーズ3: ステージング環境(Kubernetes)
- 実際のKubernetesクラスターでのテスト
- Service/Ingressの設定
- 監視・ログ収集の確認
フェーズ4: 本番環境(Kubernetes)
- 段階的ロールアウト
- カナリアデプロイメント
- 自動スケーリングの設定
11.4.2 ベストプラクティス
1. イメージ管理
# タグ付けの標準化
podman tag myapp:latest registry.example.com/myapp:${GIT_COMMIT}
# マルチステージビルドの活用
FROM golang:1.19 AS builder
WORKDIR /app
COPY . .
RUN go build -o main .
FROM alpine:latest
COPY --from=builder /app/main /usr/local/bin/
CMD ["main"]
2. 設定の外部化
# ConfigMapの使用
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database.url: "postgres://db:5432/myapp"
log.level: "info"
3. ヘルスチェックの実装
// Go言語でのヘルスチェックエンドポイント
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
// データベース接続確認
if err := db.Ping(); err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
11.5 CRI-Oとの統合
11.5.1 CRI-O概要
CRI-Oは、Kubernetes専用の軽量コンテナランタイムで、Podmanと同じライブラリを使用します。
なぜCRI-Oが重要か
- Kubernetes専用設計: 不要な機能を削ぎ落とし、高速・軽量
- Podmanとの共通基盤: 同じコンテナ技術スタック
- セキュリティ: 最小権限で動作
インストールと設定
# RHEL/CentOSでのインストール
sudo dnf module enable cri-o:1.26
sudo dnf install -y cri-o
# systemd有効化
sudo systemctl enable --now crio
# 動作確認
sudo crictl version
sudo crictl info
11.5.2 Kubernetesクラスターでの使用
# kubeadmでのCRI-O使用
sudo kubeadm init \
--cri-socket=unix:///var/run/crio/crio.sock \
--upload-certs
# kubelet設定
cat > /etc/sysconfig/kubelet << EOF
KUBELET_EXTRA_ARGS=--container-runtime-endpoint=unix:///var/run/crio/crio.sock
EOF
# ワーカーノード参加
sudo kubeadm join <master-ip>:6443 \
--token <token> \
--discovery-token-ca-cert-hash sha256:<hash> \
--cri-socket=unix:///var/run/crio/crio.sock
11.6 開発環境でのKubernetes
11.6.1 Minikubeとの統合
# Podmanドライバーでminikube起動
minikube start --driver=podman --container-runtime=cri-o
# Podmanコンテキスト設定
eval $(minikube podman-env)
# ローカルイメージの使用
podman build -t myapp:dev .
kubectl run myapp --image=myapp:dev --image-pull-policy=Never
11.6.2 Kindとの統合
# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraMounts:
- hostPath: /run/user/1000/podman/podman.sock
containerPath: /var/run/docker.sock
- role: worker
- role: worker
# クラスター作成
kind create cluster --config kind-config.yaml
# ローカルレジストリ設定
podman run -d -p 5000:5000 --name registry registry:2
11.7 実践演習
演習1: マイクロサービスアプリケーションの移行
シナリオ: 3つのマイクロサービスからなるアプリケーションをPodmanからKubernetesに移行する
手順:
- Podmanでマイクロサービスを構築
- podman generate kubeでYAML生成
- 生成されたYAMLをカスタマイズ
- Minikubeでテスト
- 本番相当の設定を追加
期待される成果:
- 移行プロセスの理解
- YAML編集スキルの向上
- トラブルシューティング能力の獲得