PulumiでAWSリソースをデプロイしよう

2023年3月15日(水)
大関 研丞 (Kenneth Ozeki)
第2回となる今回は、Pulumiのアカウント作成からAWSリソースの作成まで、ハンズオンを通して一通り実践していきます。

Pulumi Program更新

ここからは、Programを編集してインフラを更新していきます。Programを編集する際は各クラウドプロバイダのAPIドキュメント(AWSはこちら)を参照してください。

Bucket Object作成

無事にS3 Bucketが作成されたので、次はBucketのObjectとしてHTMLファイルを作成します。

  1. Pulumi Projectディレクトリ内で以下コマンドを実行し、HTMLファイルを作成します。
    $ pwd
    /********/pulumi-test
    
    $ cat <<EOT > index.html
    <html>
        <body>
            <h1>Hello, Pulumi!</h1>
        </body>
    </html>
    EOT
    
    $ ls
    Pulumi.dev.yaml  __main__.py  index.html  …
  2. Pulumi ProgramにBucket Objectを追加します。プロパティにはObject名「index.html」、Object格納先のBucket「bucket=bucket.id」、格納するObjectの元となるデータ「source=pulumi.FileAsset('index.html')」(先ほど作成したHTMLファイル)を設定します。
    〜〜(略)〜〜
    # Create an AWS resource (S3 Bucket)
    bucket = s3.Bucket('my-bucket')
    
    # Create a BucketObject
    bucketObject = s3.BucketObject(
        'index.html',
        bucket=bucket.id,
        source=pulumi.FileAsset('index.html')
    )
    
    # Export the name of the bucket
    〜〜(略)〜〜
  3. 更新したProgramを元に、再度「pulumi up」コマンドを実行します。念のため「details」を選択して更新箇所の詳細を確認します。
    $ pulumi up
    Previewing update (dev)
    
    View Live: https://app.pulumi.com/*****/pulumi-test/dev/previews/*****
    
         Type                    Name             Plan       
         pulumi:pulumi:Stack     pulumi-test-dev             
     +   └─ aws:s3:BucketObject  index.html       create     
    
    
    Resources:
        + 1 to create
        2 unchanged
    
    Do you want to perform this update? details
      pulumi:pulumi:Stack: (same)
        [urn=urn:pulumi:dev::pulumi-test::pulumi:pulumi:Stack::pulumi-test-dev]
        + aws:s3/bucketObject:BucketObject: (create)
            [urn=urn:pulumi:dev::pulumi-test::aws:s3/bucketObject:BucketObject::index.html]
            [provider=urn:pulumi:dev::pulumi-test::pulumi:providers:aws::default_5_29_1::0cc32f18-91d5-445b-a810-72a4244d789d]
            acl         : "private"
            bucket      : "my-bucket-c4e1d9c"
            forceDestroy: false
            key         : "index.html"
            source      : asset(file:cf43a91) { index.html }
    
    Do you want to perform this update?  [Use arrows to move, type to filter]
    > yes
      no
      details
  4. 更新箇所に問題がなければ「yes」を選択してStackデプロイします。
    Do you want to perform this update? yes
    Updating (dev)
    
    View Live: https://app.pulumi.com/*****/pulumi-test/dev/updates/**
    
         Type                    Name             Status              
         pulumi:pulumi:Stack     pulumi-test-dev                      
     +   └─ aws:s3:BucketObject  index.html       created (0.46s)     
    
    
    Outputs:
        bucket_name: "my-bucket-c4e1d9c"
    
    Resources:
        + 1 created
        2 unchanged
    
    Duration: 2s
    デプロイが完了すると、Programに追加したBucket ObjectがAWSマネジメントコンソールで確認できます。

    pulumi upにより作成されたBucket Object

    【参考】Pulumi CLI による Stack Output 確認
    Stackデプロイ時にexportしたOutputは、Pulumi CLIから確認できます。
    $ pulumi stack output       
    Current stack outputs (1):
        OUTPUT       VALUE
        bucket_name  my-bucket-c4e1d9c
    AWS CLIを利用されていれば、Outputのkey名(bucket_name)を引数に用いて、CLIからBucket Objectを確認することも可能です。
    $ aws s3 ls $(pulumi stack output bucket_name)
    2023-02-10 17:40:34         70 index.html

Bucket 静的Webサーバ設定

無事にBucket Objectが作成されたので、次はBucketでHTMLファイルを公開できるようにProgramを更新します。

  1. Programにて、Bucketにプロパティ「website」を追加します。「index_document」の値は先ほど生成したBucket Object「index.html」を指定します。
    〜〜(略)〜〜
    # Create an AWS resource (S3 Bucket)
    bucket = s3.Bucket('my-bucket',
        website=s3.BucketWebsiteArgs(
            index_document="index.html",
        ))
    
    # Create a BucketObject
    〜〜(略)〜〜
  2. 次に、ProgramのBucket Objectにプロパティ「acl='public-read'」と「content_type='text/html'」を追加します。現時点のObjectはprivate(非公開)の設定となるため、明示的にaclプロパティを追加してインターネット経由でのアクセスを可能にし、content_typeプロパティでObjectがHTMLファイルとしてサーブできるようにします。
    〜〜(略)〜〜
    # Create a BucketObject
    bucketObject = s3.BucketObject(
        'index.html',
        acl='public-read',
        content_type='text/html',
        bucket=bucket.id,
        source=pulumi.FileAsset('index.html')
    )
    〜〜(略)〜〜
  3. 最後に、Programの最終行にアクセス先となるBucketのendpoint URLをStack Outputとしてexportします。
    〜〜(略)〜〜
    # Export the name of the bucket
    pulumi.export('bucket_name', bucket.id)
    pulumi.export('bucket_endpoint', pulumi.Output.concat('http://', bucket.website_endpoint))
  4. 更新後のProgramを再度「pulumi up」でデプロイします。更新内容に問題がなければプロンプトで「yes」を選択します。
    $ pulumi up
    Previewing update (dev)
    
    View Live: https://app.pulumi.com/*****/pulumi-test/dev/previews/*****
    
         Type                    Name             Plan       Info
         pulumi:pulumi:Stack     pulumi-test-dev             
     ~   ├─ aws:s3:Bucket        my-bucket        update     [diff: +website]
     ~   └─ aws:s3:BucketObject  index.html       update     [diff: ~acl,contentType]
    
    
    Outputs:
      + bucket_endpoint: output
    
    Resources:
        ~ 2 to update
        1 unchanged
    
    Do you want to perform this update? yes
    Updating (dev)
    
    View Live: https://app.pulumi.com/*****/pulumi-test/dev/updates/**
    
         Type                    Name             Status              Info
         pulumi:pulumi:Stack     pulumi-test-dev                      
     ~   ├─ aws:s3:Bucket        my-bucket        updated (1s)        [diff: +website]
     ~   └─ aws:s3:BucketObject  index.html       updated (0.36s)     [diff: ~acl,contentType]
    
    
    Outputs:
      + bucket_endpoint: "http://my-bucket-c4e1d9c.s3-website-ap-northeast-1.amazonaws.com"
        bucket_name    : "my-bucket-c4e1d9c"
    
    Resources:
        ~ 2 updated
        1 unchanged
    
    Duration: 3s
  5. BucketおよびBucket Objectの更新が完了したら、endpoint URLにアクセスします。ブラウザで確認することも可能ですが、Pulumi CLIのOutput出力コマンドを利用して、curlで確認することもできます。以下のようにリクエストを投げて、作成した通りのコンテンツが返ってきたら、無事設定完了となります。
    $ curl $(pulumi stack output bucket_endpoint)
    <html>
        <body>
            <h1>Hello, Pulumi!</h1>
        </body>
    </html>

Pulumi Stack resourceの削除

ここからは、今回のハンズオンで構築した環境のクリーンアップ手順となります。

  1. Pulumiで作成したリソースを削除する際は「pulumi destroy」コマンドを実行します。「pulumi up」と同じく、「details」の選択で削除するリソースの詳細が確認できます。問題がなければ「yes」を選択します。
    $ pulumi destroy             
    Previewing destroy (dev)
    
    View Live: https://app.pulumi.com/*****/pulumi-test/dev/previews/*****
    
         Type                    Name             Plan       
     -   pulumi:pulumi:Stack     pulumi-test-dev  delete     
     -   ├─ aws:s3:BucketObject  index.html       delete     
     -   └─ aws:s3:Bucket        my-bucket        delete     
    
    
    Outputs:
      - bucket_endpoint: "http://my-bucket-c4e1d9c.s3-website-ap-northeast-1.amazonaws.com"
      - bucket_name    : "my-bucket-c4e1d9c"
    
    Resources:
        - 3 to delete
    
    Do you want to perform this destroy? details
    - aws:s3/bucketObject:BucketObject: (delete)
        [id=index.html]
        [urn=urn:pulumi:dev::pulumi-test::aws:s3/bucketObject:BucketObject::index.html]
        [provider=urn:pulumi:dev::pulumi-test::pulumi:providers:aws::default_5_29_1::0cc32f18-91d5-445b-a810-72a4244d789d]
    - aws:s3/bucket:Bucket: (delete)
        [id=my-bucket-c4e1d9c]
        [urn=urn:pulumi:dev::pulumi-test::aws:s3/bucket:Bucket::my-bucket]
        [provider=urn:pulumi:dev::pulumi-test::pulumi:providers:aws::default_5_29_1::0cc32f18-91d5-445b-a810-72a4244d789d]
    - pulumi:pulumi:Stack: (delete)
        [urn=urn:pulumi:dev::pulumi-test::pulumi:pulumi:Stack::pulumi-test-dev]
        --outputs:--
      - bucket_endpoint: "http://my-bucket-c4e1d9c.s3-website-ap-northeast-1.amazonaws.com"
      - bucket_name    : "my-bucket-c4e1d9c"
    
    Do you want to perform this destroy? yes
    Destroying (dev)
    
    View Live: https://app.pulumi.com/*****/pulumi-test/dev/updates/**
    
         Type                    Name             Status              
     -   pulumi:pulumi:Stack     pulumi-test-dev  deleted             
     -   ├─ aws:s3:BucketObject  index.html       deleted (0.41s)     
     -   └─ aws:s3:Bucket        my-bucket        deleted (0.55s)     
    
    
    Outputs:
      - bucket_endpoint: "http://my-bucket-c4e1d9c.s3-website-ap-northeast-1.amazonaws.com"
      - bucket_name    : "my-bucket-c4e1d9c"
    
    Resources:
        - 3 deleted
    
    Duration: 3s
    AWSマネジメントコンソールからは、該当のBucketが既に削除されていることが確認できます。

    ちなみに、Pulumi Serviceコンソール画面のStack詳細[Resources]タグからも、すべてのリソースが削除されていることが確認できます。

Pulumi Stackの削除

Pulumi Stack自体も削除できます。ただし、Stack自体を削除すると「pulumi config」などで設定したStack自体の設定や、Stackのリソース変更履歴なども削除されるので、削除する際は注意してください。

  1. 「pulumi stack rm」コマンドを実行してStackを削除します。コマンド実行後は、確認としてStack名の入力が求められます。Stack名の「dev」を入力すると、Stackが完全に削除されます。
    $ pulumi stack rm
    This will permanently remove the 'dev' stack!
    Please confirm that this is what you'd like to do by typing `dev`: dev
    Stack 'dev' has been removed!
    Stackを削除すると、Pulumi Serviceコンソール画面からも削除したStackが存在しないことが確認できます。Stackが存在しないため、先ほどまで確認できていたリソース変更履歴「Activity」やStackの設定「Settings」も確認できなくなります。

    ※ Stackのリソースが残った状態で「pulumi stack rm」を実行すると、以下のエラーが出力されます。Stack削除前にリソースを削除するか、強制的にStackを削除するオプション「--force」を追加してから、再度Stackを削除する必要があります。
    $ pulumi stack rm
    This will permanently remove the 'dev' stack!
    Please confirm that this is what you'd like to do by typing `dev`: dev
    
    error: 'dev' still has resources; removal rejected. Possible actions:
    - Make sure that 'dev' is the stack that you want to destroy
    - Run `pulumi destroy` to delete the resources, then run `pulumi stack rm`
    - Run `pulumi stack rm --force` to override this error

おわりに

今回は、Pulumiのアカウント作成からAWSリソースの作成まで、ハンズオンを通して一通り実践しました。普段からPythonなどの開発言語を利用されていれば、あまり違和感なくPulumi Programの編集に取り組めたのではないかと思います。

Pulumiには、この他にもインフラストラクチャのポリシー管理やCI/CDとのインテグレーションなど、さまざまな便利機能がありますので、次回以降もこれらの機能について少しずつ紹介していきます。

【参考】Pulumi公式ホームページ(英語)

著者
大関 研丞 (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メルマガ会員のサービス内容を見る

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