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

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

【ハンズオン】既存リソースのPulumi管理化

ハンズオンの流れ

今回は、AWS環境に既に作成されているS3 Bucketを、Pulumiで管理させるケースを想定して検証を実施します。Pulumi ProgramはPythonで作成します。作業は主にMacOSのターミナルを利用します。

前提

  • ハンズオンを実施する上で必要なAWSのアクセス権限を有する(S3 Bucket作成など)
  • PCにPythonを導入済み(version 3.7以上)

事前準備

Pulumiを利用したAWSリソースデプロイのハンズオンを実施するには、事前に以下の作業が実施済みである必要があります。前回で事前準備の手順を紹介していますので、まだ実施されていない方はそちらをご確認ください。

  • Pulumi CLIのインストール
  • Pulumiアカウント新規作成
  • AWSアカウントへのPulumiアクセス設定

今回は、以下の事前準備の手順を紹介します。

  • 既存リソース(S3 Bucket)の用意
  • Pulumi Project & Stack 新規作成

・既存リソース(S3 Bucket)の用意
Pulumi管理化のリソース(S3 Bucket)をあらかじめ手動で作成します。今回のハンズオンではAWSリージョン「ap-northeast-1」の「my-bucket-pulumi」という名前でS3 Bucketを作成しました。

・Pulumi Project & Stack 新規作成
既存リソースをPulumiで管理するためのPulumi ProjectとStackを作成します。

  1. 作業用ディレクトリ「pulumi-import」を新規で作成して、ディレクトリを移動します。
    $ mkdir pulumi-import && cd pulumi-import
  2. 「pulumi new」コマンドを実行して、Program(Project)の雛形を作成します。「project name」「project description」「stack name」はデフォルト値で設定し、「aws:region:」については「ap-northeast-1」を設定しました。
    $ pulumi new aws-python
    
    This command will walk you through creating a new Pulumi project.
    
    Enter a value or leave blank to accept the (default), and press <ENTER>.
    Press ^C at any time to quit.
    
    project name: (operator-test)
    project description: (A minimal AWS Python Pulumi program)
    Created project 'operator-test'
    
    Please enter your desired stack name.
    To create a stack in an organization, use the format / (e.g. `acmecorp/dev`).
    stack name: (dev)
    Created stack 'dev'
    
    aws:region: The AWS region to deploy into: (us-east-1) ap-northeast-1
    Saved config
    
    Installing dependencies…
    ~~~
    Your new project is ready to go! ✨
    
    To perform an initial deployment, run `pulumi up`
  3. Stack作成直後はPulumiでリソースのデプロイは実施していないので、リソースに関する情報は記載されていないことを確認します。
    $ pulumi stack export
    
    {
        "version": 1,
        "deployment": {
            "manifest": {
                "time": "0001-01-01T00:00:00Z",
                "magic": "",
                "version": ""
            }
        }
    }

Programにimport option(リソースID)を
付与しない場合のPulumi up

既にAWS環境に作成されているリソースについて、stateに情報が記載されていない状態でpulumi upを実施するとどうなるか確認します。

  1. 既存リソースの設定値(名前、ロケーションなど)に合わせて、Program(__main__.py)を編集します。
    $ pwd 
    /***/pulumi-import
    
    $ vi __main__.py
    以下コードに編集(__main__.py)
    import pulumi
    from pulumi_aws import s3
    
    bucket = s3.Bucket('my-bucket-pulumi')
    
    pulumi.export('bucket_name', bucket.id)
    【Pulumi Program (__main__.py)】
  2. pulumi upを実行します。
    $ pulumi up
    Previewing update (***/dev)
    
    View in Browser (Ctrl+O): https://app.pulumi.com/***/pulumi-import/dev/previews/***
    
         Type                 Name               Plan       
     +   pulumi:pulumi:Stack  pulumi-import-dev  create     
     +   └─ aws:s3:Bucket     my-bucket-pulumi   create     
    
    
    Outputs:
        bucket_name: output<string>
    
    Resources:
        + 2 to create
    
    Do you want to perform this update? yes
    Updating (***/dev)
    
    View in Browser (Ctrl+O): https://app.pulumi.com/***/pulumi-import/dev/updates/1
    
         Type                 Name               Status           
     +   pulumi:pulumi:Stack  pulumi-import-dev  created (4s)     
     +   └─ aws:s3:Bucket     my-bucket-pulumi   created (2s)     
    
    
    Outputs:
        bucket_name: "my-bucket-pulumi-fcd164b"
    
    Resources:
        + 2 created
    
    Duration: 8s
  3. 上記pulumi upの実行結果の通り、stateにリソースの情報がないため、pulumiでは新しくリソースが作成(create)されてしまいます。pulumi up後のstateは以下のようになります。
    $ pulumi stack export
    {
        "version": 3,
        "deployment": {
            "manifest": {
                "time": "2023-09-28T16:01:51.629695+09:00",
                "magic": "1fce246d436c6e46d168db13ed1014131c96be0ccf8401639052718fba57ac37",
                "version": "v3.72.2"
            },
            "secrets_providers": {
                "type": "service",
                "state": {
                    "url": "https://api.pulumi.com",
                    "owner": "***",
                    "project": "pulumi-import",
                    "stack": "dev"
                }
            },
            "resources": [
                {
                    "urn": "urn:pulumi:dev::pulumi-import::pulumi:pulumi:Stack::pulumi-import-dev",
                    "custom": false,
                    "type": "pulumi:pulumi:Stack",
                    "outputs": {
                        "bucket_name": "my-bucket-pulumi-fcd164b"
                    },
                    "created": "2023-09-28T07:01:47.453547Z",
                    "modified": "2023-09-28T07:01:47.453547Z"
                },
                {
                    "urn": "urn:pulumi:dev::pulumi-import::pulumi:providers:aws::default_6_2_1",
                    "custom": true,
                    "id": "69044939-2182-498b-9919-b3a529f1ce10",
                    "type": "pulumi:providers:aws",
                    "inputs": {
                        "region": "ap-northeast-1",
                        "skipCredentialsValidation": "false",
                        "skipMetadataApiCheck": "true",
                        "skipRegionValidation": "true",
                        "version": "6.2.1"
                    },
                    "outputs": {
                        "region": "ap-northeast-1",
                        "skipCredentialsValidation": "false",
                        "skipMetadataApiCheck": "true",
                        "skipRegionValidation": "true",
                        "version": "6.2.1"
                    },
                    "created": "2023-09-28T07:01:49.057079Z",
                    "modified": "2023-09-28T07:01:49.057079Z"
                },
                {
                    "urn": "urn:pulumi:dev::pulumi-import::aws:s3/bucket:Bucket::my-bucket-pulumi",
                    "custom": true,
                    "id": "my-bucket-pulumi-fcd164b",
                    "type": "aws:s3/bucket:Bucket",
                    "inputs": {
                        "__defaults": [
                            "acl",
                            "bucket",
                            "forceDestroy"
                        ],
                        "acl": "private",
                        "bucket": "my-bucket-pulumi-fcd164b",
                        "forceDestroy": false
                    },
                    "outputs": {
                        "accelerationStatus": "",
                        "acl": "private",
                        "arn": "arn:aws:s3:::my-bucket-pulumi-fcd164b",
                        "bucket": "my-bucket-pulumi-fcd164b",
                        "bucketDomainName": "my-bucket-pulumi-fcd164b.s3.amazonaws.com",
                        "bucketRegionalDomainName": "my-bucket-pulumi-fcd164b.s3.ap-northeast-1.amazonaws.com",
                        "corsRules": [],
                        "forceDestroy": false,
                        "grants": [],
                        "hostedZoneId": "Z2M4EHUR26P7ZW",
                        "id": "my-bucket-pulumi-fcd164b",
                        "lifecycleRules": [],
                        "loggings": [],
                        "objectLockConfiguration": null,
                        "region": "ap-northeast-1",
                        "replicationConfiguration": null,
                        "requestPayer": "BucketOwner",
                        "serverSideEncryptionConfiguration": {
                            "rule": {
                                "applyServerSideEncryptionByDefault": {
                                    "kmsMasterKeyId": "",
                                    "sseAlgorithm": "AES256"
                                },
                                "bucketKeyEnabled": false
                            }
                        },
                        "versioning": {
                            "enabled": false,
                            "mfaDelete": false
                        },
                        "website": null
                    },
                    "parent": "urn:pulumi:dev::pulumi-import::pulumi:pulumi:Stack::pulumi-import-dev",
                    "provider": "urn:pulumi:dev::pulumi-import::pulumi:providers:aws::default_6_2_1::69044939-2182-498b-9919-b3a529f1ce10",
                    "additionalSecretOutputs": [
                        "tagsAll"
                    ],
                    "created": "2023-09-28T07:01:51.619949Z",
                    "modified": "2023-09-28T07:01:51.619949Z"
                }
            ]
        }
    }
  4. ここで一度作成されたbucketを削除して、元に状態に戻します。
    $ pulumi destroy
            
    Previewing destroy (***/dev)
    
    View in Browser (Ctrl+O): https://app.pulumi.com/***/pulumi-import/dev/previews/***
    
         Type                 Name               Plan       
     -   pulumi:pulumi:Stack  pulumi-import-dev  delete     
     -   └─ aws:s3:Bucket     my-bucket-pulumi   delete     
    
    
    Outputs:
      - bucket_name: "my-bucket-pulumi-fcd164b"
    
    Resources:
        - 2 to delete
    
    Do you want to perform this destroy? yes
    Destroying (***/dev)
    
    View in Browser (Ctrl+O): https://app.pulumi.com/***/pulumi-import/dev/updates/3
    
         Type                 Name               Status              
     -   pulumi:pulumi:Stack  pulumi-import-dev  deleted             
     -   └─ aws:s3:Bucket     my-bucket-pulumi   deleted (0.64s)     
    
    
    Outputs:
      - bucket_name: "my-bucket-pulumi-fcd164b"
    
    Resources:
        - 2 deleted
    
    Duration: 3s
  5. リソースを削除すると、再度stateの中身からリソースの情報が削除されます。
    $ pulumi stack export
       
    {
        "version": 3,
        "deployment": {
            "manifest": {
                "time": "2023-09-28T16:51:21.248956+09:00",
                "magic": "1fce246d436c6e46d168db13ed1014131c96be0ccf8401639052718fba57ac37",
                "version": "v3.72.2"
            },
            "secrets_providers": {
                "type": "service",
                "state": {
                    "url": "https://api.pulumi.com",
                    "owner": "***",
                    "project": "pulumi-import",
                    "stack": "dev"
                }
            }
        }
    }
著者
大関 研丞 (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メルマガ会員のサービス内容を見る

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