Pulumi使ってみた

2024/06/20に公開されました。
2024/06/20に更新されました。

Pulumiを使ってみつつ、Terraformとの簡単な比較をしました


author: kuribo-,koba

はじめに

インフラエンジニアのkuribo-&kobaです。

だいぶ前からあるPulumiですが、デファクトスタンダードであるTerraformに負け続けてる感があり悲しいので試しに使ってみました。
使いつつ簡単な比較もしています。

Pulumiとは

PulumiとはPulumi社によるオープンソースのソフトウェアです。
PulumiではIaCを色々な言語を使って記述できます。

  • Typescript
  • Javascript
  • Go
  • C#
  • Java
  • Yaml(言語ではないけどYamlでも定義できる)

また、Terraformのコードを変換することで、上記言語のコードを生成できます。
(完璧にそのまま変換できないので、参考程度にしかなりませんが)

各種言語を利用することで、各種言語にあるLinterやFormatter、コンパイラによる構文チェックなども利用できます。
また、IDEのインテリジェンスも効くのでコードを書くのがだいぶ楽にできます。
(言語毎の嫌なところも出てきてしまいますが)

Terraformとの違い

TerraformはHachi Corp社が開発をしており、オープンソースではありません。
また、HCLという独自の言語を用いる必要があります。
個人的に感じる一番大きな違いは、TerraformはIaCのデファクトスタンダードであるというところです。
検索をしてもPulumiの情報はあまり出てきません。
ですので、Pulumiを使っていこうとすると自分で調査・検証をしていく必要があるので大変です。

大まかにそれぞれのメリット・デメリット。

メリットデメリット
Pulumi・ 各種言語で記述するときのLinterやFormatterなどのツールが利用できる。
・ 色々な言語が利用できるので、アプリケーションエンジニアでもIaCに参入しやすい。
・ それぞれ言語仕様の単体テストが書ける。
・ PulumiAIというLLMが利用でき、比較的簡単にコードの作成ができる。
・ Terraformで難しい繰り返しが言語の仕様で書けるのでとても楽。
・ デファクトスタンダードじゃないため、情報が少ない。
・ 利用者が少ないので相談しにくい。
・ 利用者が少ないのでプロジェクトで導入しにくい。
Terraform・ デファクトスタンダードなので知ってる人が多く、情報が多いので調べればわかることが多い。
・ 知ってる人が多いのでプロジェクトで採用しやすい。
・ Linter, Formatterが弱い。
・ HCLの学習コストがそこそこある。
・ 単体テスト書くのが独自仕様なのでめんどくさい。
・ HCLという言語自体が弱く、機能が少ない。

PulumiとTerraformの利用料

Pulumi Cloudはステート管理をPulumi Cloudで行い、かつ複数人で利用する場合には料金が発生します。
有料版(Team)では、10人までのメンバーで使用できます。

プロジェクト・スタック・ステートの管理をGCSのバケットで行うような運用にすれば、
Pulumi Cloudを使用することなく、Pulumiを利用できるため利用料はかからないようです。
Terraformと同様の形態のようですね。

詳しくは以下を参照ください。
https://www.pulumi.com/pricing/

Terraformは以下をご確認ください。
https://www.hashicorp.com/products/terraform/pricing

Pulumi AIの利用

PulumiAIを利用することでサンプルコードの作成ができます。
尚、PulumiAIでは対応している言語はもちろん、Terraformの生成も可能です。
PulumiAIで出力されたコードを元に組み合わせながら必要なリソースを作成するコードを作成していくことができます。

例:
Prompt: I want VPC and Subnet on Google Cloud

package main

import (
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
	"github.com/pulumi/pulumi-gcp/sdk/v6/go/gcp/compute"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Create a new VPC network
		network, err := compute.NewNetwork(ctx, "my-vpc", &compute.NetworkArgs{
			AutoCreateSubnetworks: pulumi.Bool(false),
		})
		if err != nil {
			return err
		}

		// Create a new Subnet in the VPC
		_, err = compute.NewSubnetwork(ctx, "my-subnet", &compute.SubnetworkArgs{
			IpCidrRange: pulumi.String("10.2.0.0/16"),
			Network:     network.ID(),
			Region:      pulumi.String("us-west1"),
		})
		if err != nil {
			return err
		}

		return nil
	})
}

Pulumiサンプルコード

PulumiAIを使って以下のサンプルコードも作成してみました。
TerraformのようにDocumentを探してサンプルを書くより圧倒的に楽です。

Cloud Storage

package main

import (
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
	"github.com/pulumi/pulumi-gcp/sdk/v6/go/gcp/storage"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Create a Google Cloud Storage bucket
		bucket, err := storage.NewBucket(ctx, "my-bucket", &storage.BucketArgs{
			Location: pulumi.String("US"),
		})
		if err != nil {
			return err
		}

		// Export the bucket URL
		ctx.Export("bucketUrl", bucket.Url)
		return nil
	})
}

Compute Engine & SA

package main

import (
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
	"github.com/pulumi/pulumi-gcp/sdk/v7/go/gcp/compute"
	"github.com/pulumi/pulumi-gcp/sdk/v7/go/gcp/serviceaccount"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		// Create a Service Account
		sa, err := serviceaccount.NewAccount(ctx, "my-service-account", &serviceaccount.AccountArgs{
			AccountId:   pulumi.String("my-service-account"),
			DisplayName: pulumi.String("My Service Account"),
		})
		if err != nil {
			return err
		}

		// Create a Compute Engine instance
		instance, err := compute.NewInstance(ctx, "my-instance", &compute.InstanceArgs{
			MachineType: pulumi.String("n1-standard-1"),
			BootDisk: &compute.InstanceBootDiskArgs{
				InitializeParams: &compute.InstanceBootDiskInitializeParamsArgs{
					Image: pulumi.String("debian-cloud/debian-10"),
				},
			},
			NetworkInterfaces: compute.InstanceNetworkInterfaceArray{
				&compute.InstanceNetworkInterfaceArgs{
					Network: pulumi.String("default"),
					AccessConfigs: compute.InstanceNetworkInterfaceAccessConfigArray{
						&compute.InstanceNetworkInterfaceAccessConfigArgs{
							NatIp: pulumi.String(""),
						},
					},
				},
			},
			ServiceAccount: &compute.InstanceServiceAccountArgs{
				Email:  sa.Email,
				Scopes: pulumi.StringArray{pulumi.String("https://www.googleapis.com/auth/cloud-platform")},
			},
		})
		if err != nil {
			return err
		}

		// Export the instance name and service account email
		ctx.Export("instanceName", instance.Name)
		ctx.Export("serviceAccountEmail", sa.Email)

		return nil
	})
}

まとめ

PulumiはTerraformと比べて様々なプログラミング言語で記述できるという点で、
アプリケーション開発者がインフラ領域に参入するハードルを下げることができるでしょう。
言語毎のLinterやFormatterなどのツールを活用でき、IDEのインテリジェンスも活かせるためコードの記述が容易になります。
さらに、PulumiAIを用いることで、サンプルコードの作成もスムーズに行うことができます。

一方で、デファクトスタンダードではないため情報が少なく、バグを踏んだ場合など解決に時間がかかることが課題です。
プロジェクトへの導入には、慎重な検討が必要となるでしょう。

Terraformとの使い分けを検討する際には、プロジェクトの規模、チームのスキル、情報収集のしやすさなどを考慮し、最適な選択をすることが重要です。

個人的には今後Pulumiも使っていきたいです。

※本記事は、ジーアイクラウド株式会社の見解を述べたものであり、必要な調査・検討は行っているものの必ずしもその正確性や真実性を保証するものではありません。

※リンクを利用する際には、必ず出典がGIC dryaki-blogであることを明記してください。
リンクの利用によりトラブルが発生した場合、リンクを設置した方ご自身の責任で対応してください。
ジーアイクラウド株式会社はユーザーによるリンクの利用につき、如何なる責任を負うものではありません。