pulumi を試してみた
pulumi
terraform と似たような IaC ツールの一種。terraform と異なる最大の特徴は javascript, python など一般的なプログラミング言語で記述できる点。 これによって IDE サポート、言語の拡張性、モジュール化、変数定義 などの恩恵を最大限に受けている。
https://github.com/pulumi/pulumi
パット見て他の記事も参照した感じだと、state 管理と、サポートしているプロバイダーの種類を克服すれば十分 terraform を刺せそう。
install
$ curl -fsSL https://get.pulumi.com/ | sh === Installing Pulumi v3.9.1 === + Downloading https://get.pulumi.com/releases/sdk/pulumi-v3.9.1-darwin-x64.tar.gz... % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 61.6M 100 61.6M 0 0 14.8M 0 0:00:04 0:00:04 --:--:-- 14.8M + Extracting to /Users/k-jun/.pulumi/bin + Adding $HOME/.pulumi/bin to $PATH in /Users/k-jun/.zshrc === Pulumi is now installed! 🍹 === + Please restart your shell or add /Users/k-jun/.pulumi/bin to your $PATH + Get started with Pulumi: https://www.pulumi.com/docs/quickstart ~/ghq/github.com/k-jun/playground-aws master 6s $ which pulumi /Users/k-jun/.pulumi/bin/pulumi
setup
pulumi new コマンドを実行すると諸々の設定がインタラクティブに走る。pulumi にログインさせられた際には、思わず嫌悪感が走ったがまだ大丈夫...。
$ pulumi new ... ... Please choose a template: aws-typescript A minimal AWS TypeScript Pulumi program 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: (pulumi-demo) project description: (A minimal AWS TypeScript Pulumi program) Created project 'pulumi-demo' Please enter your desired stack name. To create a stack in an organization, use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`). stack name: (dev) Created stack 'dev' aws:region: The AWS region to deploy into: (us-east-1) Saved config Installing dependencies... added 122 packages, and audited 123 packages in 19s 28 packages are looking for funding run `npm fund` for details found 0 vulnerabilities npm notice npm notice New minor version of npm available! 7.19.1 -> 7.20.5 npm notice Changelog: https://github.com/npm/cli/releases/tag/v7.20.5 npm notice Run npm install -g npm@7.20.5 to update! npm notice Finished installing dependencies Your new project is ready to go! ✨ To perform an initial deployment, run 'pulumi up'
こういうファイルが生成されている。これを変更することでリソースを操作する。
import * as pulumi from "@pulumi/pulumi"; import * as aws from "@pulumi/aws"; import * as awsx from "@pulumi/awsx"; // Create an AWS resource (S3 Bucket) const bucket = new aws.s3.Bucket("my-bucket"); // Export the name of the bucket export const bucketName = bucket.id;
差分の詳細と確認がインタラクティブに行われ、変更を適用する。terraform の差分が全部かってに出力されて、これでいい...? と比べると雲泥の差。 こっちのほうがずっといい。そもそも terraform の差分は分かりづらい。
$ pulumi up ... Do you want to perform this update? details + pulumi:pulumi:Stack: (create) [urn=urn:pulumi:dev::pulumi-demo::pulumi:pulumi:Stack::pulumi-demo-dev] + aws:s3/bucket:Bucket: (create) [urn=urn:pulumi:dev::pulumi-demo::aws:s3/bucket:Bucket::my-bucket] [provider=urn:pulumi:dev::pulumi-demo::pulumi:providers:aws::default_4_14_0::04da6b54-80e4-46f7-96ec-b56ff0331ba9] acl : "private" bucket : "my-bucket-a7424d4" forceDestroy: false Do you want to perform this update? yes ...
run
ひとまず以下の箇所が気になったので、これを見ていく。
- ec2 の作成
- state 管理 & 競合防止
- github との連携
- changeIgnoreの設定
ec2 instance を作成するところまで。いずれ Terraform を超える気がする...。 以下の点が Terraform と比べて圧倒的に勝っている。
- Type Script で記述できるのがめちゃくちゃ良い。型がそのまま ドキュメントになるので全てコードで完結する。
- 言語としての柔軟性の高さ。モジュール化、変数化、繰り返しなど煩雑な問題が全て "プログラミング言語" で記述するという一撃で解決している。。圧倒的。
- state を意識せずとも使える勝手の良さ。console に全てかってに格納してくれる。何なら管理しているリソースの視覚化も勝手にやってくれる。
- Github との相性の良さ。pulumi を実行した際に、勝手に github の head を読み取ってリンクしてくれる。
が、差分検知は少し怪しいかもしれない。作成した インスタンスの Tag 差分は流石に pulumi で検知してくれなかった..。
import * as pulumi from "@pulumi/pulumi"; import * as aws from "@pulumi/aws"; import * as awsx from "@pulumi/awsx"; const pulumi_vpc = new aws.ec2.Vpc("pulumi_vpc", { cidrBlock: "10.1.0.0/16", enableDnsSupport: true, enableDnsHostnames: true, tags: { "Name": "pulumi-vpc" } }) const pulumi_subnet_private = new aws.ec2.Subnet("pulumi_subnet_private", { vpcId: pulumi_vpc.id, cidrBlock: "10.1.1.0/24", mapPublicIpOnLaunch: false, tags: { "Name": "pulumi-subnet-private" } }) const pulumi_subnet_public = new aws.ec2.Subnet("pulumi_subnet_public", { vpcId: pulumi_vpc.id, cidrBlock: "10.1.101.0/24", mapPublicIpOnLaunch: true, tags: { "Name": "pulumi-subnet-public" } }) const pulumi_internet_gateway = new aws.ec2.InternetGateway("pulumi_internet_gateway", { vpcId: pulumi_vpc.id, tags: { "Name": "pulumi-internet-gateway" } }) const pulumi_route_table = new aws.ec2.RouteTable("pulumi_route_table", { vpcId: pulumi_vpc.id, routes: [ { cidrBlock: "0.0.0.0/0", gatewayId: pulumi_internet_gateway.id, }, ], tags: { "Name": "pulumi-route-table" } }) const pulumi_security_group = new aws.ec2.SecurityGroup("pulumi_security_group", { vpcId: pulumi_vpc.id, ingress: [ { fromPort: 22, toPort: 22, protocol: "tcp", cidrBlocks: ["0.0.0.0/0"], }, { fromPort: 80, toPort: 80, protocol: "tcp", cidrBlocks: ["0.0.0.0/0"], self: true, }, { fromPort: 443, toPort: 443, protocol: "tcp", cidrBlocks: ["0.0.0.0/0"], self: true, }, ], }) const ubuntu1804 = "ami-0cfa3caed4b487e77" const pulumi_ec2 = new aws.ec2.Instance("pulumi_ec2", { subnetId: pulumi_subnet_private.id, ami: ubuntu1804, instanceType: aws.ec2.InstanceType.C5_Large, keyName: "k-jun", vpcSecurityGroupIds: [pulumi_security_group.id], tags: { "Name": "pulumi-ec2" } })
差分の無視も大丈夫そう。きちんと差分として表示されなくなった。
const pulumi_security_group = new aws.ec2.SecurityGroup("pulumi_security_group", { vpcId: pulumi_vpc.id, ingress: [ { fromPort: 22, toPort: 22, protocol: "tcp", cidrBlocks: ["0.0.0.0/0"], }, { fromPort: 80, toPort: 80, protocol: "tcp", cidrBlocks: ["0.0.0.0/0"], self: true, }, { fromPort: 443, toPort: 443, protocol: "tcp", cidrBlocks: ["0.0.0.0/0"], self: true, }, ], }, { ignoreChanges: ["ingress[0]"] })