【入門編】Pulumiを使ったゼロトラストインフラの実現:Ephemeral Environments(エフェメラル環境)の動的構築と自動破棄 – インフラ構成管理(IaC)活用バイブル

こんにちは!クラウドインフラ・SREの世界へようこそ。
今日は、開発現場の誰もが一度は頭を悩ませる「環境管理」の苦しみを根本から解決する、最高にエキサイティングな技術のお話をします。

「PR(プルリクエスト)ごとに本番そっくりの検証環境を自動で立ち上げ、用事が済んだら跡形もなく綺麗に消し去る」——そんな夢のようなエフェメラル環境(Ephemeral Environments)を、次世代IaCツール「Pulumi」とGitHub Actionsを使って実現する方法を、優しく、そして徹底的に深掘りしていきましょう。

これをマスターすれば、もう「ステージング環境の奪い合い」や「消し忘れたリソースによるAWS高額請求の恐怖」に怯える必要はなくなります。毎日の開発作業が劇的に楽になりますよ。それでは、一緒に旅を始めましょう!

—

1. なぜ「エフェメラル環境」なのか?(ツールの役割と設計思想)

従来のインフラ運用では、「dev環境」「stg環境」「prod環境」といった固定的な環境を数個用意するのが一般的でした。しかし、これには大きな問題があります。

  • 複数の開発者が同じstg環境を使ってしまい、デプロイがコンフリクトする。
  • 「俺のローカルでは動いたのに!」という環境差異の悪夢。
  • 使っていない夜間や週末も稼働し続け、財布を直撃するクラウド代。

ここで登場するのが、「ゼロトラストなエフェメラル環境」という思想です。
「コード変更(PR)が発生したら、その瞬間だけの隔離されたインフラを動的に生成し、レビューが終わってマージされたら、容赦なく完全破棄(ゼロ化)する」。

これを支えるのが、プログラミング言語のパワーをそのままIaCに持ち込めるPulumiです。Terraformのような独自DSL(HCL)の縛りから解放され、TypeScriptやPythonなどの慣れ親しんだ言語で、if文やループを駆使した堅牢なインフラを構築できます。

—

2. 基礎セットアップ:Pulumiの世界へ飛び込もう

まずは、手元のマシンにPulumiを迎え入れましょう。今回は、最もエコシステムが安定している TypeScript を使用します。

インストール(macOSの場合)

brew install pulumi

※Windows(winget)やLinux環境でも、公式サイトから一発でインストール可能です。

プロジェクトの初期化

適当なディレクトリを作成し、プロジェクトをセットアップします。

mkdir pulumi-ephemeral-env
cd pulumi-ephemeral-env
pulumi new aws-typescript

対話形式でプロジェクト名やパスワード(暗号化用)を聞かれますが、基本はEnterキー連打でOKです。これだけで、TypeScriptのプロジェクト構造と必要な設定ファイルが生成されます。

—

3. 「Hello World」:動的プレビュー環境のコード設計

ここからが腕の見せ所です。PRごとに環境を作るということは、リソース名が衝突しないように一意のサフィックス(接尾辞)を動的に付与する必要があります。

以下のコードを見てください。これがエフェメラル環境構築の心臓部です。

`index.ts` を開き、次のように書き換えてみてください。

import as pulumi from “@pulumi/pulumi”;
import as aws from “@pulumi/aws”;

// 1. 現在のPulumiスタック名(例: pr-123)を取得する
// これにより、PRごとに完全に分離された名前空間を動的に作ります
const stackName = pulumi.getStack();

// 2. リソース名がグローバルで重複しないよう、一意のプレフィックスを生成
const namePrefix = `ephemeral-${stackName}`;

// 3. ネットワーキング層:この環境専用のVPCを爆誕させる
const vpc = new aws.ec2.Vpc(`${namePrefix}-vpc`, {
cidrBlock: “10.100.0.0/16”,
enableDnsHostnames: true,
enableDnsSupport: true,
tags: {
Name: `${namePrefix}-vpc`,
Environment: “Ephemeral”,
ManagedBy: “Pulumi”,
},
});

// 4. パブリックサブネットの作成
const subnet = new aws.ec2.Subnet(`${namePrefix}-subnet`, {
vpcId: vpc.id,
cidrBlock: “10.100.1.0/24”,
mapPublicIpOnLaunch: true,
tags: { Name: `${namePrefix}-subnet` },
});

// 5. 動作確認用の最小限のEC2インスタンス(またはECSなど)
// 今回はコストがかからないよう、最小構成のセキュリティグループと組み合わせます
const sg = new aws.ec2.SecurityGroup(`${namePrefix}-sg`, {
vpcId: vpc.id,
description: “Ephemeral environment security group”,
ingress: [
{ protocol: “tcp”, fromPort: 80, toPort: 80, cidrBlocks: [“0.0.0.0/0”] },
],
egress: [
{ protocol: “-1”, fromPort: 0, toPort: 0, cidrBlocks: [“0.0.0.0/0”] },
],
});

// 6. 外部に出力するエンドポイント(Outputs)
// CI/CDパイプラインやPRのコメント欄に自動通知するために使います
export const vpcId = vpc.id;
export const subnetId = subnet.id;

手元での動作確認(プレビュー)

Pulumiの最大の特徴は、実際にクラウドをいじる前に「何が起きるか」を完全に可視化できる点です。

スタック(環境の単位)をPR番号に見立てて作成・切り替え
pulumi stack init pr-42

プレビューの実行(ドライラン)
pulumi preview

ターミナルに、これから作成されるAWSリソースの計画が美しく描出されたはずです。「これをCI/CDに組み込めばいいのか!」と直感的に理解できたなら、もうエンジニアとしての視座が一つ上のステージに上がっています。

—

4. 究極の自動化:GitHub ActionsによるCI/CDワークフロー設計

さて、ここからが本番です。GitHubのPull RequestのライフサイクルとPulumiを完全に同期させます。

以下のワークフローファイルを作成してください。
`.github/workflows/ephemeral-env.yml`

name: Ephemeral Environment Pipeline

on:
pull_request:
types: [opened, synchronize, closed]

permissions:
id-token: write # AWS OIDC認証に必須
contents: read
pull-requests: write # PRにコメントを残す権限

jobs:
pulumi-ephemeral:
runs-on: ubuntu-latest
steps:

  • name: Checkout Repository

uses: actions/checkout@v4

  • name: Setup Node.js

uses: actions/setup-node@v4
with:
node-version: ’20’
cache: ‘npm’

  • name: Install Dependencies

run: npm ci

  • name: Configure AWS Credentials (OIDC)

uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsPulumiRole
aws-region: ap-northeast-1

  • name: Login to Pulumi

uses: pulumi/actions@v5
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}

# PRが閉じられた(マージまたはクローズ)場合の処理

  • name: Destroy Ephemeral Environment on PR Close

if: github.event.action == ‘closed’
run: |
pulumi stack select pr-${{ github.event.pull_request.number }} –non-interactive || exit 0
pulumi destroy –yes –non-interactive
pulumi stack rm pr-${{ github.event.pull_request.number }} –yes –non-interactive

# PRがオープン、または更新された場合の処理

  • name: Up Ephemeral Environment on PR Open/Sync

if: github.event.action != ‘closed’
run: |
STACK_NAME=”pr-${{ github.event.pull_request.number }}”

# スタックが存在しない場合は新規作成、存在する場合は選択
pulumi stack select ${STACK_NAME} –non-interactive || pulumi stack init ${STACK_NAME} –non-interactive

# インフラのデプロイ実行
pulumi up –yes –non-interactive

この設計の美しさと強靭さ(SRE的解説)

1. 完全なステート管理の分離:
`pr-${{ github.event.pull_request.number }}` という規則的なスタック名を使うことで、PRごとに独立したステート(状態ファイル)がPulumi Cloud(またはS3等のバックエンド)に保持されます。これにより、他のPRと干渉することが物理的に不可能です。
2. ゼロトラストなクリーンアップ:
`github.event.action == ‘closed’` を検知した瞬間に、`pulumi destroy` と `pulumi stack rm` が走ります。開発者がボタンを押し忘れても、PRを閉じさえすれば、AWSの請求書からその環境は綺麗さっぱり消え去ります。
3. OIDCによるセキュアな認証:
AWSの長寿命なアクセスキー(Access Key)をGitHubに保存する必要はありません。OIDC(OpenID Connect)を使うことで、GitHub Actionsから一時的なトークンを発行し、セキュアにAWSリソースを操作します。

—

おわりに

お疲れ様でした!
Pulumiを用いたエフェメラル環境の自動構築・自動破棄の全体像が見えてきたのではないでしょうか。

この仕組みを導入したチームでは、「ステージング環境の順番待ち」という無駄な時間が消え、レビューの質が劇的に跳ね上がります。コードを書いてPRを投げたら、数分後には自分専用の検証環境がURL付きで目の前に現れる——そんな未来を、ぜひあなたの現場でも形にしてみてください。

あなたのインフラライフが、よりモダンで、よりクリエイティブになることを心から応援しています!

タイトルとURLをコピーしました