Pulumi を Google Cloud で使ってみた
- Google Cloud
- Pulumi
- Terraform
はじめまして。株式会社トップゲート、開発部所属の大澤です。
クラウドインフラストラクチャを管理する Infrastructure as Code (IaC) ツールといえば真っ先に挙がるのが Terraform だと思いますが、 同じくマルチクラウド対応の IaC ツールで JavaScript や Python など既存のプログラミング言語を利用できる Pulumi を使ってみました。
本記事では公式の Get started with Pulumi & Google Cloud に従って Cloud Storage バケットの構築と、Terraform で同様のリソース構築するコードを比較してみます。
目次
対象読者
- Terraform の使用経験はあるが Pulumi は触ったことがない方
- Pulumi に興味のある方
Pulumi とは
(公式より引用)
プログラミング言語 (TypeScript、Go、.NET、Python、Java) とマークアップ言語 (YAML、CUE) を使用して、チームがクラウドの複雑さを制御できるコード プラットフォームとしてのオープンソース インフラストラクチャです。
Terraform との主な違いは、Terraform が固有言語である HashiCorp構成言語 (HCL) の使用が必須なのに対し、Pulumi は上述した汎用言語を使用できる点です。インフラストラクチャの構築と管理に慣れ親しんだプログラミング言語を使用できるのはキャッチフレーズである「Built by engineers for engineers. Open source.」を表していると言えます。
検証環境
- macOS 13.5.2
- Homebrew 4.1.12
- Go 1.20.7
- Google Cloud SDK 417.0.1
使ってみる
インストール
こちらの手順を参考に Pulumi をインストールします。
$ brew install pulumi/tap/pulumi
インストールが完了したらバージョンを確認します。
$ pulumi version
v3.84.0
Google Cloud 認証
ローカルから開発できるようユーザアカウントで Google Cloud プロジェクトへアクセス認証します。
対象の Google Cloud プロジェクトは事前に作成済、使用するアカウントにはプロジェクトのオーナーロールを付与しています。
# Google Cloud CLI を認証
$ gcloud auth login
# 接続するアカウントとプロジェクトを設定
$ gcloud config set account <YOUR_GCP_ACCOUNT>
$ gcloud config set project <YOUR_GCP_PROJECT_ID>
# プログラミング言語のクライアントライブラリを認証
$ gcloud auth application-default login
Pulumi プロジェクト作成
こちらの手順を参考に Pulumi プロジェクトを作成します。
プログラミング言語は Go を選択します。
$ mkdir quickstart && cd quickstart
$ pulumi new gcp-go
上記コマンドを実行すると Pulumi へのログインを求められました。
そのままEnterキーを押下するとログイン画面がブラウザ表示されます。
Create an account リンクを押下してユーザ登録を行います。
今回は自身の GitHub アカウントでシングルサインオン (SSO) しました。
用途を個人使用で回答した後、「Connect the CLI to Pulumi Cloud」ボタンを押下します。
ダッシュボードが表示されたら再度プロジェクト作成コマンドを実行します。
$ pulumi new gcp-go
プロジェクトの名前と説明の入力を求められます。
そのままEnterキーを押下するとデフォルト (カレントディレクトリ名) でプロジェクトが作成されます。
続けてスタック名の入力を求められます。
そのままEnterキーを押下するとデフォルト (dev) でスタックが作成されます。
スタックは 1 つのプロジェクトに複数作成することができ、デフォルトに dev が設定されているように開発環境毎 (dev、staging、prod) に分けるなど、独立して構成可能なインスタンスです。
最後に Google Cloud プロジェクトIDの入力を求められるので入力してEnterキーを押下します。
gcp:project: The Google Cloud project to deploy into: <YOUR_GCP_PROJECT_ID>
インストールが完了しプロジェクトとスタックの準備が整いました。
ブラウザのダッシュボード上からも作成したプロジェクトとスタックが確認できます。
構成情報がデフォルトでクラウド (Pulumi.com) に保存されるのも Pulumi の特徴です。
Pulumi プロジェクトのファイル確認
生成されたファイルの中身を確認します。
Pulumi.yaml
Pulumi プロジェクトの名前、ランタイム、説明が記載されてます。
name: quickstart
runtime: go
description: A minimal Google Cloud Go Pulumi program
Pulumi.dev.yaml
スタックの情報として Google Cloud プロジェクトIDが記載されてます。
config:
gcp:project: <YOUR_GCP_PROJECT_ID>
main.go
リソースを定義するプログラムが記載されてます。
「my-bucket」という名前の Cloud Storage バケットを US マルチリージョンに構築する内容となっています。
package main
import (
"github.com/pulumi/pulumi-gcp/sdk/v6/go/gcp/storage"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Create a GCP resource (Storage Bucket)
bucket, err := storage.NewBucket(ctx, "my-bucket", &storage.BucketArgs{
Location: pulumi.String("US"),
})
if err != nil {
return err
}
// Export the DNS name of the bucket
ctx.Export("bucketName", bucket.Url)
return nil
})
}
実行計画の確認
デプロイする前に pulumi preview
コマンドで Dry Run を実行してみます。
Terraform の terraform plan コマンドに相当します。
$ pulumi preview
スタックのデプロイ
pulumi up
コマンドでデプロイを実施します。
「-y, --yes」オプションをつけることで実行の確認を省略します。
Terraform の terraform apply -auto-approve コマンドに相当します。
$ pulumi up -y
Outputs を見ると my-bucket-c7c8e05 という名前で Cloud Storage バケットが作成されています。
pulumi stack output bucketName コマンドでもバケット名が確認できます。
$ pulumi stack output bucketName
gs://my-bucket-c7c8e05
gsutil ls コマンドで Google Cloud プロジェクト上に上記バケットが存在することを確認できました。
$ gsutil ls -L -b gs://my-bucket-c7c8e05
gs://my-bucket-c7c8e05/ :
Storage class: STANDARD
Location type: multi-region
Location constraint: US
...
バケット名の接尾辞に -c7c8e05 というランダムな英数字が設定されているのは Pulumi の Auto-Naming 機能によるもので、リソース名の競合回避と置き換えが必要なリソースに対してダウンタイム無しで更新可能にするのが主な目的のようです。
リソース名を指定したい場合は Name プロパティで定義します。
bucket, err := storage.NewBucket(ctx, "my-bucket", &storage.BucketArgs{
Name: pulumi.String("my-bucket-tg-123456"),
Location: pulumi.String("US"),
})
再度 pulumi up
コマンドを実行し変更を反映してみます。
Outputs を見るとバケット名が my-bucket-c7c8e05 から Name プロパティで指定した my-bucket-tg-123456 にリプレースされているのが分かります。
pulumi stack output bucketName コマンド、および変更前・変更後のバケット名で gsutil ls コマンドを実行してみます。
$ pulumi stack output bucketName
gs://my-bucket-tg-123456
$ gsutil ls -L -b gs://my-bucket-c7c8e05
BucketNotFoundException: 404 gs://my-bucket-c7c8e05 bucket does not exist.
$ gsutil ls -L -b gs://my-bucket-tg-123456
gs://my-bucket-tg-123456/ :
Storage class: STANDARD
Location type: multi-region
Location constraint: US
...
my-bucket-c7c8e05 が存在しないこと、my-bucket-tg-123456 が存在することを確認できました。
Terraformの場合
Terraform で同様の Cloud Storage バケットを構築する場合、以下のコードになります。
resource "google_storage_bucket" "my_bucket" {
project = <YOUR_GCP_PROJECT_ID>
name = "my-bucket-tg-123456"
location = "US"
}
output "bucket_name" {
value = google_storage_bucket.my_bucket.name
}
今回のように Cloud Storage バケットを1つ作成するシンプルなケースでは Terraform の HCL の方がコード量は少なくなります。ただし、細かく処理を条件分岐したりネストされた繰り返し処理などを HCL で実現するのは難しく、汎用プログラミング言語のような柔軟な制御構造は持ち合わせていません。
まとめ
既存の Terraform コードを Pulumi に移行するコンバーターも公式で用意されており、Atlassian や GreenPark Sports などの企業が導入するなど、Pulumi の需要が高まってきていると感じます。
Pulumi は Terraform よりも新しいツールのため、現時点では安定性やドキュメントの充実度は劣りますが、初めて IaC ツールを使用する際に Terraform の HCL のような固有言語の学習コストをかけずに使い慣れたプログラミング言語と IDE などの開発ツールを使用してインフラストラクチャを構築および管理できるのは Pulumi の強みと言えます。
最後まで読んでいただきありがとうございました。