YAML を使用して Google Cloud で Pulumi を使用する

1. 概要

このラボでは、Infrastructure as Code ツールの Pulumi を使用して、Google Cloud リソースのプロビジョニングと管理を行う方法を学びます。

学習内容

このラボでは、次の方法について学びます。

  • Pulumi をインストールして構成する
  • Google Cloud でインフラストラクチャをモデル化する YAML プログラムを作成する
  • Pulumi を使用してクラウド リソースをプロビジョニングして管理する
  • pulumi 変換を使用して、YAML プログラムを Python プログラムに変換します。

2. 設定と要件

セルフペース型の環境設定

  1. Google Cloud Console にログインして、プロジェクトを新規作成するか、既存のプロジェクトを再利用します。Gmail アカウントも Google Workspace アカウントもまだお持ちでない場合は、アカウントを作成してください。

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • プロジェクト名は、このプロジェクトの参加者に表示される名称です。Google API では使用されない文字列です。この値はいつでも更新できます。
  • プロジェクト ID は、すべての Google Cloud プロジェクトにおいて一意でなければならず、不変です(設定後は変更できません)。Cloud コンソールでは一意の文字列が自動生成されます。通常、それが何であるかは関係ありません。ほとんどの Codelab では、プロジェクト ID を参照する必要があります(通常は PROJECT_ID として識別されます)。生成された ID が気に入らない場合は、別のランダムな ID を生成できます。または、ご自身でお試しになることもできます。このステップを終えた後は変更できず、プロジェクト期間中は維持されます。
  • なお、3 つ目の値は、一部の API で使用される [プロジェクト番号] です。これら 3 つの値について詳しくは、こちらのドキュメントをご覧ください。
  1. 次に、Cloud のリソースや API を使用するために、Cloud コンソールで課金を有効にする必要があります。この Codelab の操作をすべて行って、費用が生じたとしても、少額です。このチュートリアルの終了後に課金されないようにリソースをシャットダウンするには、作成したリソースを削除するか、プロジェクト全体を削除します。Google Cloud の新規ユーザーは、300 米ドル分の無料トライアル プログラムをご利用いただけます。

3. インフラストラクチャの設定

Pulumi のインストールと構成

Cloud Shell で、次のコマンドを実行して Pulumi をインストールします。

curl -fsSL https://get.pulumi.com | sh

Pulumi をパスに追加し、Pulumi からのヘルプ メッセージを表示する

export PATH=${PATH}:~/.pulumi/bin
# view the help message to verify pulumi runs
pulumi -h

次のコマンドを実行してプロジェクト ID を設定し、アクセスを承認します。コマンドが示す手順に沿って操作してください。

export PROJECT_ID=$(gcloud config get-value project)
gcloud auth application-default login

Cloud Shell で GCS バケットを作成し、バックエンドとして使用する

gsutil mb gs://pulumi-${PROJECT_ID}
pulumi login gs://pulumi-${PROJECT_ID}

新しいプロジェクトを作成

Cloud Shell で、プロジェクトのルート ディレクトリを作成する

mkdir pulumi-lab && cd pulumi-lab

プロジェクト ファイルの定義(Pulumi へのエントリ ポイント)

cat <<EOT > Pulumi.yaml
name: pulumi-lab
description: Try Pulumi

runtime: yaml
main: yaml-repo/
EOT

YAML リソースを定義する

クラウド リソース定義を保持するディレクトリを yaml 形式で作成する

mkdir yaml-repo

次のリソース定義を含むファイル yaml-repo/Pulumi.yaml を作成します。

  1. バケット
  2. IAM バインディング
  3. 文字列「Hello World!」を含むテキスト オブジェクト。
  4. 一部の出力
resources:
  # Create a GCP resource (Storage Bucket)
  my-bucket:
    type: gcp:storage:Bucket
    properties:
      location: US
      website:
        mainPageSuffix: index.html
      uniformBucketLevelAccess: true

  my-bucket-binding:
    type: gcp:storage:BucketIAMBinding
    properties:
      bucket: ${my-bucket.name}
      role: "roles/storage.objectViewer"
      members: ["allUsers"]

  index-object:
    type: gcp:storage:BucketObject
    properties:
      bucket: ${my-bucket}
      source:
        fn::stringAsset: Hello World!

outputs:
  bucketName: ${my-bucket.url}

リソースをデプロイする

スタックの初期化と構成

export PULUMI_CONFIG_PASSPHRASE=pulumi-lab
pulumi stack init dev
pulumi config set gcp:project $PROJECT_ID

スタック構成を確認すると、プロジェクト ID を値として持つ gcp:project キーが表示されるはずです。

pulumi config

この時点で、ディレクトリ構造は次のようになります。

├── Pulumi.dev.yaml
├── Pulumi.yaml
└── yaml-repo
    └── Pulumi.yaml

スタックをデプロイする

pulumi up

このコマンドは、プログラムを評価し、行うリソース更新を決定します。まず、プレビューが表示され、このコマンドを実行したときに行われる変更の概要が示されます。

(出力)

Previewing update (dev):
Downloading plugin gcp v6.44.0: 45.69 MiB / 45.69 MiB [=============] 100.00% 1s
     Type                             Name               Plan
 +   pulumi:pulumi:Stack              pulumi-lab-dev     create
 +   ├─ gcp:storage:Bucket            my-bucket          create
 +   ├─ gcp:storage:BucketObject      index-object       create
 +   └─ gcp:storage:BucketIAMBinding  my-bucket-binding  create


Outputs:
    bucketName: output<string>

Resources:
    + 4 to create

Do you want to perform this update?  [Use arrows to move, type to filter]
  yes
> no
  details

[yes] を選択すると、リソースがプロビジョニングされます。出力は次のようになります。

Do you want to perform this update? yes
Updating (dev):
     Type                             Name               Status
 +   pulumi:pulumi:Stack              pulumi-lab-dev     created (3s)
 +   ├─ gcp:storage:Bucket            my-bucket          created (1s)
 +   ├─ gcp:storage:BucketObject      index-object       created (0.78s)
 +   └─ gcp:storage:BucketIAMBinding  my-bucket-binding  created (5s)


Outputs:
    bucketName: "gs://my-bucket-874aa08"

Resources:
    + 4 created

Duration: 11s

次のコマンドを実行すると、定義された出力が出力されます。

pulumi stack output

次のコマンドを実行して、変更を確認します。

gsutil ls $(pulumi stack output bucketName)

出力は次のようになります。

(出力)

gs://my-bucket-11a9046/index-object-77a5d80

4. YAML を Python に変換する

上の例を Pulumi Python プログラムに変換します。

pulumi convert --language python --out ./py-repo

py-repo で生成されたコードを調べます。

cat py-repo/__main__.py

(出力)

import pulumi
import pulumi_gcp as gcp

my_bucket = gcp.storage.Bucket("my-bucket",
    location="US",
    website=gcp.storage.BucketWebsiteArgs(
        main_page_suffix="index.html",
    ),
    uniform_bucket_level_access=True)
my_bucket_binding = gcp.storage.BucketIAMBinding("my-bucket-binding",
    bucket=my_bucket.name,
    role="roles/storage.objectViewer",
    members=["allUsers"])
index_object = gcp.storage.BucketObject("index-object",
    bucket=my_bucket.id,
    source=pulumi.StringAsset("Hello World!"))
pulumi.export("bucketName", my_bucket.url)
.......

Python 仮想環境を有効にする

source py-repo/bin/activate

Python プログラムを指すように Pulumi.yaml プロジェクト ファイルを更新します。ランタイムとメインエントリが変更されていることに注目してください。

cat <<EOT > Pulumi.yaml
name: pulumi-lab
description: Try Pulumi

runtime: python
main: py-repo/
EOT

スタックの再デプロイを試行し、[yes] を選択します。

pulumi up

何も変更されず、出力は次のようになります。

(出力)

Previewing update (dev):
     Type                 Name            Plan
     pulumi:pulumi:Stack  pulumi-lab-dev


Resources:
    4 unchanged

Do you want to perform this update? yes
Updating (dev):
     Type                 Name            Status
     pulumi:pulumi:Stack  pulumi-lab-dev


Outputs:
    bucketName: "gs://my-bucket-c2b49ad"

Resources:
    4 unchanged

Duration: 6s

5. リソースを削除する

作成されたリソースを削除する

pulumi destroy

確認内容は次のようになります

Previewing update (dev):
     Type                 Name            Plan
     pulumi:pulumi:Stack  pulumi-lab-dev


Resources:
    4 unchanged

Do you want to perform this update?  [Use arrows to move, type to filter]
  yes
> no
  details


Do you want to perform this destroy? yes
Destroying (dev):
     Type                             Name               Status
 -   pulumi:pulumi:Stack              pulumi-lab-dev     deleted
 -   ├─ gcp:storage:BucketIAMBinding  my-bucket-binding  deleted (5s)
 -   ├─ gcp:storage:BucketObject      index-object       deleted (1s)
 -   └─ gcp:storage:Bucket            my-bucket          deleted (0.73s)


Outputs:
  - bucketName: "gs://my-bucket-874aa08"

Resources:
    - 4 deleted

Duration: 10s

6. 完了

これでラボは終了です。