「Pulumi Stack」とは ー Pulumiによるマルチステージ環境の構築方法

2023年4月20日(木)
大関 研丞 (Kenneth Ozeki)
第3回となる今回は、Pulumi Stackの概要について解説し、複数Stackのデプロイについてハンズオンを実施していきます。

Pulumi Stackの新規作成/設定

現時点でdev用のStackが作成されており、かつdev用のStack設定ファイルが用意されている状態になります。ここではさらにPulumi CLIからprod用のStackを作成し、devおよびprodのStack設定ファイルにProgramで読み込むために必要なStackごとの設定(サブネットのCIDRブロック、availability zone)を実施します。

  1. Pulumi CLIで新たにprod用のStackを作成します。コマンドを実行すると自動的にprod用のStackが選択されます。
    $ pulumi stack init prod
    Created stack 'prod'
    
    $ pulumi stack ls
    NAME   LAST UPDATE  RESOURCE COUNT  URL
    dev    n/a          n/a             https://app.pulumi.com/***/pulumi-stack/dev
    prod*  n/a          n/a             https://app.pulumi.com/***/pulumi-stack/prod
    この時点ではまだprod用のStack設定ファイルは作成されません。次の手順のStack設定コマンドを実行するか、手動でStack設定ファイルを作成する必要があります。
  2. prod用のStackが選択された状態で、Programで読み込むために必要なStackの設定を実施します。今回はprod用のCIDRブロックとavailability zoneの値を設定します。また「Pulumi Project/Stackの新規作成」手順でdev用Stackに設定した、デフォルトのAWSリージョン「ap-northeast-1」も設定します。
    $ pulumi config set subnet_cidr_block "10.0.2.0/24"
    $ pulumi config set availability_zone "ap-northeast-1c"
    $ pulumi config set aws:region ap-northeast-1
    コマンドを実行すると、自動的にprod用のStack設定ファイル「Pulumi.prod.yaml」が作成されます。ファイルの中身を確認すると、先ほど設定したCIDRブロックとavailability zoneがkey-valueの形で保存されています。
    $ ls | grep prod
    Pulumi.prod.yaml
    
    $ cat Pulumi.prod.yaml                       
    config:
      aws:region: ap-northeast-1
      pulumi-stack:availability_zone: ap-northeast-1c
      pulumi-stack:subnet_cidr_block: 10.0.2.0/24
  3. 同様にdev用のStackにもCIDRブロックとavailability zoneの値を設定します。dev用Stackを選択して、Stackにdev用のCIDRブロックとavailability zoneの値を設定します。
    $ pulumi stack select dev
    
    $ pulumi stack ls
    NAME  LAST UPDATE  RESOURCE COUNT  URL
    dev*  n/a          n/a             https://app.pulumi.com/***/pulumi-stack/dev
    prod  n/a          n/a             https://app.pulumi.com/***/pulumi-stack/prod
    
    $ pulumi config set subnet_cidr_block "10.0.1.0/24"
    $ pulumi config set availability_zone "ap-northeast-1a"
    同様にdev用Stack設定ファイルの中身を確認すると、先ほど設定したCIDRブロックとavailability zoneがkey-valueの形で保存されています。
    $ cat Pulumi.dev.yaml                        
    config:
      aws:region: ap-northeast-1
      pulumi-stack:availability_zone: ap-northeast-1a
      pulumi-stack:subnet_cidr_block: 10.0.1.0/24

Pulumi Programの更新

「Pulumi Project/Stackの新規作成」手順で自動生成されたPulumi Program「__main__.py」について、以下のコードに書き換えます。コードのポイントは下記のとおりです。

  • 「Pulumi Stackの設定」手順で設定したStackの設定値(availability_zone、subnet_cidr_block)は「config = pulumi.Config()」でProgramに読み込み1つの「サブネットの作成」コードブロックで利用することで、Stackごと(dev/prod)にコードを用意する必要がなくなります
  • サブネットやEC2インスタンスはStackごとに作成するので「stack_name = pulumi.get_stack()」でStack名を取得し、リソース名のプレフィックスにStack名を付け加えます
  • サブネット/EC2インスタンスはStackごとに作成しますが、VPCはStack間で共有となるため、少々力技ですが「StackがdevであればVPC新規作成、dev以外なら既存VPCを利用」の判定処理を入れます。既存VPCの情報は「stack_ref = pulumi.StackReference("***/pulumi-stack/dev")」でdev用Stackの情報からvpc-idのoutputを取得します。取得するStackのフォーマットは「<organization>/<project>/<stack>」となるため、<organization>の部分は適宜変更してください($ pulumi whoamiコマンドで自身の組織名を調べられます)

AWSリソースそれぞれのAPIリファレンスは、こちらを参考にしてください。また「pulumi.get_stack()」や「pulumi.Config()」など、Pulumi Configurationの取得に関してはこちらが参考になります。今回のハンズオンではStackの切り替えをPulumi CLIで実施してからリソースをデプロイしますが、前述の「Pulumi Automation API」を利用することでStackの作成や切り替えをProgram内で完結することも可能です。

import pulumi
import pulumi_aws as aws

# スタックの名前を取得
stack_name = pulumi.get_stack()

# スタックの設定を読み込む
config = pulumi.Config()

# VPCの作成または取得
if stack_name == "dev":
    vpc = aws.ec2.Vpc("my-vpc",
        cidr_block="10.0.0.0/16",
        tags={
            "Name": "my-vpc",
        })
    # VPC IDのoutput export
    pulumi.export("vpc_id", vpc.id)
else:
    stack_ref = pulumi.StackReference("***/pulumi-stack/dev")
    vpc_id = stack_ref.get_output("vpc_id")
    vpc = aws.ec2.Vpc.get("my-vpc", id=vpc_id)

# サブネットの作成
subnet = aws.ec2.Subnet(f"{stack_name}-my-subnet",
    vpc_id=vpc.id,
    cidr_block=config.require("subnet_cidr_block"),
    availability_zone=config.require("availability_zone"),
    tags={
        "Name": f"{stack_name}-my-subnet",
    })

# EC2インスタンスの作成
ami = aws.ec2.get_ami(
    filters=[{
        "name": "name",
        "values": ["amzn2-ami-hvm-*-x86_64-gp2"],
    }],
    most_recent=True,
)

instance = aws.ec2.Instance(f"{stack_name}-my-instance",
    instance_type="t2.micro",
    subnet_id=subnet.id,
    ami=ami.id,
    tags={
        "Name": f"{stack_name}-my-instance",
    })
【Pulumi Program (__main__.py)】
著者
大関 研丞 (Kenneth Ozeki)
クリエーションライン株式会社 Data Platform Team
前職では保険や金融エンタープライズのミッションクリティカルシステム(オンプレミス、仮想サーバー、CDN等のインフラ系業務)の設計/構築を経験。クリエーションラインに転職後はクラウドエンジニアとしてGCP関連の案件でインフラの設計/構築、IaCやCI/CDを用いたDevOpsの導入、コンテナ(Kubernetes)基盤の構築、運用自動化ツールの作成などを担当。
クリエーションラインの技術ブログをチェック

連載バックナンバー

システム運用技術解説
第10回

Pulumiの最新機能「Pulumi ESC」を使ってみよう

2023/12/26
最終回となる今回は、2023年12月時点でリリースされている新機能の紹介と、その新機能の中から「Pulumi ESC」を用いたハンズオンを実践していきます。
システム運用技術解説
第9回

TerraformからPulumiへの移行

2023/11/28
第9回となる今回は、既にTerraformでAWS環境に作成されているリソースをPulumiへ移行するケースを想定して、CoexistenceとConversionのハンズオンを実践していきます
システム運用技術解説
第8回

既に存在するリソースをPulumiで管理してみよう

2023/10/19
第8回となる今回は、既にクラウド環境にデプロイされているリソースをPulumiで管理(import)する方法について、ハンズオンで実践していきます。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています