Pulumi Kubernetes Operatorを活用したGitOps実践:IaCとK8sコントローラーの融合による次世代インフラ管理
こんにちは。大規模クラウドインフラの自動化とSREを統括しているテックリードだ。
今日君たちに共有するのは、「Pulumi Kubernetes Operator」を用いた、IaC(Infrastructure as Code)とKubernetesコントローラーの完全融合に関する極限の知見だ。
「え、KubernetesのデプロイならArgo CDやFluxがあるだろ? なぜ今さらPulumiなのか?」
そう思った者は、クラウドインフラの複雑性と日夜格闘していない証拠だ。
現代のインフラストラクチャにおいて、AWS/GCPのマネージドサービス(RDS, IAM, S3など)と、Kubernetes上のワークロードは不可分に結びついている。これらをYAMLのテンプレートエンジン(Helm/Kustomize)で無理やり管理し、外部のCI/CDパイプラインから回すアプローチは、状態管理の不整合(ドリフト)やシークレット管理の地獄を生み出す。
Kubernetesのカスタムリソース(CRD)としてPulumiプログラムを直接常駐させ、クラスタ自身が自身のインフラとワークロードの状態を調停(Reconcile)する――このパラダイムシフトを、現場の即戦力となる実用的な設定と共に入魂しよう。
—
1. なぜ「Pulumi Kubernetes Operator」なのか?(Argo CDとの比較・使い分け)
まず、既存のGitOps王者であるArgo CDとの違いを明確にしておこう。
| 比較項目 | Argo CD (Helm/Kustomize) | Pulumi Kubernetes Operator |
| :— | :— | :— |
| 定義言語 | YAML, Jinja, Helm templates | TypeScript, Python, Go, C# |
| クラウドプロビジョニング | 限界がある (Config Connector等が必要) | 得意分野 (AWS/GCP/Azureリソースを直接制御) |
| 状態管理 (State) | Kubernetesマニフェストが正 | Pulumi Backend (S3 + DynamoDB等) |
| 条件分岐・ループ | 貧弱(YAMLの限界) | 完全なプログラミング言語の表現力 |
使い分けの黄金律
- Argo CDを使うべきケース: 純粋なKubernetesマニフェストやHelmチャートのデプロイが9割を占め、クラウドインフラの変更頻度が低い場合。
- Pulumi Operatorを使うべきケース: 「Kubernetesクラスタの構築」と「その上で動くアプリ・関連クラウドインフラ(RDSやSQSなど)」を単一のライフサイクルで結合し、プログラムの表現力(動的な設定、型安全性、テスト)をフルに活用したい場合。
—
2. 導入の要諦:クラスタ内コントローラーのデプロイと権限設計
Pulumi Operatorは、Kubernetesのカスタムリソース(`Stack`リソース)を監視し、バックグラウンドで `pulumi up` を実行し続けるコントローラーだ。
まずは、Operator自身がAWSなどのクラウドを触るための権限移譲(IRSA: IAM Roles for Service Accountsなど)を正しく行い、クラスタにデプロイする。
現場で即座に使えるマニフェスト構成例
以下の設定は、EKS等の環境でプロダクション稼働させるためのベストプラクティスを網羅した配置だ。
apiVersion: v1
kind: Namespace
metadata:
name: pulumi-operator-system
—
apiVersion: apps/v1
kind: Deployment
metadata:
name: pulumi-kubernetes-operator
namespace: pulumi-operator-system
labels:
app.kubernetes.io/name: pulumi-kubernetes-operator
spec:
replicas: 1 # ステートフルな調停を行うため基本は1(Leader Electionで多重化可能)
selector:
matchLabels:
app.kubernetes.io/name: pulumi-kubernetes-operator
template:
metadata:
labels:
app.kubernetes.io/name: pulumi-kubernetes-operator
spec:
serviceAccountName: pulumi-operator-sa
containers:
- name: operator
image: pulumi/pulumi-kubernetes-operator:v1.8.0
env:
- name: PULUMI_ACCESS_TOKEN
valueFrom:
secretKeyRef:
name: pulumi-api-secret
key: accessToken
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 1000
—
3. 実践:Pulumi StackカスタムリソースによるGitOps駆動
Operatorの準備ができたら、次はいよいよ本丸である `Stack` リソースの定義だ。
これにより、Gitリポジトリ上のPulumiコードがKubernetesクラスタに直結する。
実用的な `Stack` リソースのベストプラクティス
apiVersion: pulumi.com/v1
kind: Stack
metadata:
name: production-core-infrastructure
namespace: production
spec:
# 連携するPulumiプログラムが存在するGitリポジトリ
projectRepo: https://github.com/your-org/infra-pulumi-stacks.git
branch: refs/heads/main
# リポジトリ内のどのディレクトリを指すか
stack: production
# 秘密情報のバックエンド(AWS Secrets ManagerやVault等と連携)
secretStore:
secretRef:
name: aws-secrets-manager-backend
# 自動同期的リフレッシュ・デプロイの設定
# 冪等性を担保するため、定期的なドリフト検知を有効化
refreshSettings:
period: “1h” # 1時間ごとにクラウド実態とStateの乖離をチェック
# デプロイメントの挙動制御
destroyOnDelete: false # 本番環境での誤削除を防止する絶対の防壁
# 環境変数や設定値の注入
config:
aws:region: ap-northeast-1
clusterName: prod-k8s-01
このリソースをArgo CDやFluxで管理する、あるいは直接Kubernetesに適用することで、「Kubernetesが自分自身のインフラをPulumi経由で維持し続ける」という究極のセルフホストGitOpsが完成する。
—
4. チーム開発を加速させるプロの知見:設定の共有化と神プラグイン
ここからは、日々の開発スピードを劇的に高めるための「現場の隠し味」を伝授しよう。
① 絶対に入れるべきVS Code神プラグイン
- Pulumi Snippets: リソース定義のボイラープレートを排除し、型安全な補完を爆速で引き出す。
- YAML / Kubernetes (Red Hat): カスタムリソース(`Stack`)を書く際のスキーマ検証に必須。
② 開発効率を爆上げするキーボードショートカット(VS Code / Mac基準)
- `Cmd + Shift + P` -> `Pulumi: Preview` : コードの変更がクラウドに与える影響を即座にプレビュー(脳内シミュレーション時間をゼロにする)。
- `Option + Shift + F` : 常にコードフォーマットを統一し、LinterエラーによるCIの落ち込みを防ぐ。
③ チーム開発における設定共有化ルール
Pulumiプロジェクトを複数人で回す際、ローカルの `Pulumi.
チーム全員が同じルールで安全に開発できるよう、以下の規約を徹底せよ。
1. Configの抽象化: 設定値は必ず `pulumi.Config` クラス経由で型安全に取得する。
2. スタック設定の分離: 共通設定は `Pulumi.yaml` に、環境差分は `Pulumi.dev.yaml`, `Pulumi.prod.yaml` に分離し、全てGit管理する(秘匿情報は `pulumi config set –secret` で暗号化)。
// TypeScriptでの型安全なConfig取得の例
import as pulumi from “@pulumi/pulumi”;
const config = new pulumi.Config();
const instanceType = config.require(“instanceType”); // 型安全・未定義時は即座にエラー
const replicaCount = config.getNumber(“replicaCount”) || 3;
—
5. トラブルシューティング:現場でハマる罠と回避策
最後に、実戦投入時に必ず遭遇する「沼」と、その脱出方法を記しておく。
- 罠1: OperatorがStateロックを掴んだままフリーズする
- 原因: 前回の `pulumi up` が何らかの原因で異常終了し、S3バックエンドにロック(`.lock`)が残った。
- 解決策: Operatorのログを確認し、該当スタックのロックを Pulumi CLI (`pulumi cancel
`) で強制解除する。 - 罠2: クラウドAPIのレートリミット(Throttling)によるデプロイ失敗
- 原因: 大規模なインフラを一度にプロビジョニングしようとしてAWS側から弾かれる。
- 解決策: Pulumiプログラム側でリソース間に `dependsOn` を明示的に張り、並列度(Parallelism)を抑制する。
—
結びにかえて
Pulumi Kubernetes Operatorを用いたGitOpsは、単なる「ツールの流行り」ではない。
インフラの定義(IaC)と、その状態の継続的調停(Kubernetes Controller)を高次元で融合させ、開発チームの認知負荷を劇的に下げるための現在到達しうる一つの最適解だ。
今日紹介した設定と知見をベースに、君たちのチームのインフラ管理を次の次元へ引き上げてほしい。健闘を祈る。