Terraform CDK + Java + コミュニティプロバイダー(さくらのクラウド)という組み合わせを試してみます。
概要
Terraform CDKとは
Terraform CDKとは汎用のプログラミング言語を用い、Terraform(+エコシステム)を通じてクラウドなどの各種プラットフォームを操作するためのツールです。
サポートされているプログラミング言語としては以下のようなものがあります。
Terraform CDKの位置付け/立ち位置
AWS CDKが汎用のプログラミング言語での定義からCloudFormationのコンフィグレーションを生成するのと同じく、 Terraform CDKは汎用のプログラミング言語での定義からTerraformのコンフィグレーションを生成します。
こちらの図にある通り、Terraformへの入力の一つという位置付けです。
(出典: https://www.hashicorp.com/blog/cdk-for-terraform-enabling-python-and-typescript-support)
Terraformへの入力という位置付けなため、定義(dev)->プラン(plan)->適用(apply)というTerraformを用いたワークフローはそのまま利用する形です。
先ほどの記事にもThe goal of Terraform is to provide a consistent workflow for provisioning infrastructure
(著者訳: Terraformのゴールはインフラのプロビジョニングに対し一貫したワークフローを提供することです)と章のはじめに書かれており、The Tao of HashiCorpにも書かれているワークフローへのこだわり(テクノロジーじゃない、ワークフローだ)を感じさせられます。
利用者は次に紹介するCLI cdktf
を介してTerraformの各種コマンドを利用したり、Terraform向けのコードを(cdktf CLIで)生成して手動でTerraform CLIを実行するということも可能です。
Terraform CDKのツール
主に2つのパッケージが提供されています。
いずれもTypeScriptで実装されています。
CLIのヘルプはこんな感じです。
$ cdktf --help cdktf [command] Commands: cdktf deploy [OPTIONS] Deploy the given stack cdktf destroy [OPTIONS] Destroy the given stack cdktf diff [OPTIONS] Perform a diff (terraform plan) for the given stack cdktf get [OPTIONS] Generate CDK Constructs for Terraform providers and modules. cdktf init [OPTIONS] Create a new cdktf project from a template. cdktf login Retrieves an API token to connect to Terraform Cloud. cdktf synth [OPTIONS] Synthesizes Terraform code for the given app in a directory. [aliases: synthesize] Options: --version Show version number [boolean] --disable-logging Dont write log files. Supported using the env CDKTF_DISABLE_LOGGING. [boolean] [default: true] --disable-plugin-cache-env Dont set TF_PLUGIN_CACHE_DIR automatically. This is useful when the plugin cache is configured differently. Supported using the env CDKTF_DISABLE_PLUGIN_CACHE_ENV. [boolean] [default: false] --log-level Which log level should be written. Only supported via setting the env CDKTF_LOG_LEVEL [string] -h, --help Show help [boolean] Options can be specified via environment variables with the "CDKTF_" prefix (e.g. "CDKTF_OUTPUT")
CLIを用いた開発〜デプロイ(リソース作成)の基本的な流れは以下のようになります。
cdktf init
で言語別のテンプレートからTerraform CDKプロジェクトを生成- 構成ファイル
cdktf.json
に必要なTerraformプロバイダー/モジュールなどを定義 cdktf get
でプロバイダー/モジュールの取得〜TypeScriptのコード生成(jsii向け)
(Note: Terraform CDKは多言語サポートのためにjsiiを利用しているため、一旦TypeScriptのコードが生成される)- 生成されたコードとライブラリの方の
cdktf
を用いてインフラのリソース定義 cdktf deploy
して適用(またはcdktf synth
でJSONを出力してterraform apply
)
主要プロバイダー向けにはあらかじめコード生成済みのPrebuilt Providersも提供されています。
https://github.com/hashicorp/terraform-cdk/blob/main/docs/working-with-cdk-for-terraform/using-providers-and-modules.md#prebuilt-providers
例えばTypeScriptでリソース定義を行う場合以下のようなコードになります。
import { Construct } from "constructs"; import { App, TerraformStack } from "cdktf"; import { AwsProvider, Instance } from "./.gen/providers/aws"; class MyStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); new AwsProvider(this, "aws", { region: "us-east-1", }); new Instance(this, "Hello", { ami: "ami-2757f631", instanceType: "t2.micro", }); } } const app = new App(); new MyStack(app, "hello-terraform"); app.synth();
細かな解説は省きますが、ポイントは以下のとおりです。
- aws/constructsを利用している
- ライブラリの方の
cdktf
を利用している - 生成されたコードは
./.gen
配下に格納される
利用するプロバイダーの定義とリソースの定義だけのシンプルな例となっています。
コードを追加すればステートの保存先としてリモート(Terraform CloudやS3など)を利用することも可能です。
Terraform Cloud利用時の注意点
現時点ではTerraform Cloud上でterraform
コマンドを実行するExecution Mode=Remote
は利用できず、ステートだけをTerraform Cloudに保存するExecution Mode=Local
のみ利
用可能です。
参考: terraform-cdk/remote-backend.md at 342b4cc71568cc73be93954901265f753e8709b4 · hashicorp/terraform-cdk · GitHub
利用例: Terraform CDK + さくらのクラウド + Java
ここでは例としてJavaを用いてさくらのクラウド上にリソースを作成してみます。
余談ですが類似プロダクトのPulumiではJavaはまだサポートされていません
事前準備(Javaのみ、今だけの暫定処置)
現時点ではTerraform CDK周りのライブラリがMavenセントラルに登録されておらずGitHub Packages(https://maven.pkg.github.com/hashicorp/terraform-cdk)での提供となります。
このため、事前にMavenからGitHub Packagesを利用できるようにするための設定が必要になります。
(この問題は将来的に解消予定とのこと)
UPDATE: 2021/10/20 久しぶりに確認したらすでにMaven Centralで公開されていました。
https://search.maven.org/artifact/com.hashicorp/cdktf
なので以下の~/.m2/settings.xml
の編集は不要になっています。
=== UPDATE ここまで
事前にGitHubのPersonal Access Tokenを取得した上で~/.m2/settings.xml
ファイルを以下のようにしておいてください。(ファイルがなければ作成する)
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <activeProfiles> <activeProfile>github</activeProfile> </activeProfiles> <profiles> <profile> <id>github</id> <repositories> <repository> <id>central</id> <url>https://repo1.maven.org/maven2</url> </repository> <repository> <id>cdktf</id> <url>https://<GitHubユーザー名>:<アクセストークン>@maven.pkg.github.com/hashicorp/terraform-cdk</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> </repositories> </profile> </profiles> </settings>
参考: Working with the Apache Maven registry - GitHub Docs
CLIのインストール
まずTerraform CDKのCLIをインストールしておきます。
通常はstable版をインストールするのですが、今回はこの記事執筆段階でTerraform CDK側の問題を見つけたため、その問題が解消されたv0.2.3以降が必要です。
本日(2021/4/16)時点ではv0.2.3は未リリースですのでstable版ではなく開発版をインストールします。
$ npm install --global cdktf-cli@next
開発用のディレクトリの作成 & 初期コードの生成
次にcdktfでプロジェクトの雛形を生成します。
適当なディレクトリを作成しcdktf init
を実行してください。
# ステートの管理はローカル + 開発言語にはJavaを利用する $ cdktf init --local --template java
うまくいくと以下のようなファイル構成になっているはずです。
$ tree . . ├── cdktf.json ├── help ├── pom.xml ├── src │ └── main │ └── java │ └── com │ └── mycompany │ └── app │ └── Main.java └── target ├── cdk-work-java2-0.1.jar ├── classes │ └── com │ └── mycompany │ └── app │ └── Main.class ├── generated-sources │ └── annotations ├── maven-archiver │ └── pom.properties └── maven-status └── maven-compiler-plugin └── compile └── default-compile ├── createdFiles.lst └── inputFiles.lst
cdktf.jsonに依存プロバイダーを記載
次にカレントディレクトリに生成されているcdktf.json
を編集します。
今回はさくらのクラウド向けプロバイダーを利用するのでterraformProviders
にsacloud/sakuracloud@~> 2.8
と追記してください。
{ "language": "java", "app": "mvn -e -q compile exec:java", "terraformProviders": [ "sacloud/sakuracloud@~> 2.8" ], "terraformModules": [], "context": { "excludeStackIdFromLogicalIds": "true", "allowSepCharsInLogicalIds": "true" } }
cdktf get
の実行
次にプロバイダーの取得~コード生成を行うためにcdktf get
を実行します。
$ cdktf get
Generated java constructs in the output directory: .gen
通常は生成されたコードが.gen
ディレクトリ配下にあるのですが、Javaの場合はsrc/main/java/imports.sakuracloud
配下などに配置されています。
Javaでリソース定義
次にsrc/main/java/com/mycompany/app/Main.java
にコードを書いていきます。
今回はシンプルにスイッチを作るだけの例です。
package com.mycompany.app; import imports.sakuracloud.SakuracloudProvider; import imports.sakuracloud.Switch; import software.constructs.Construct; import com.hashicorp.cdktf.App; import com.hashicorp.cdktf.TerraformStack; public class Main extends TerraformStack { public Main(final Construct scope, final String id) { super(scope, id); // プロバイダーの定義 SakuracloudProvider.Builder.create(this, "default").build(); // リソースの定義 Switch.Builder.create(this, "testSwitch") .name("from-terraform-cdk-with-java") .description("this resource is created by terraform-cdk with java") .build(); } public static void main(String[] args) { final App app = new App(); new Main(app, "cdk-work-java"); app.synth(); } }
Terraformのコンフィギュレーションの生成(省略可能)
次に先ほど書いたコードからTerraformのコンフィギュレーションを生成してみます。
$ cdktf synth
Generated Terraform code in the output directory: cdktf.out
うまくいくとcdktf.out
というディレクトリにcdk.tf.json
というJSONファイルが生成されます。
$ tree cdktf.out/ cdktf.out/ └── cdk.tf.json 0 directories, 1 file
このファイルはTerraform CLIに直接渡せるものとなっています。
なお次のcdktf deploy
を実行するとsynth
も実行されますのでこの工程は省略可能です。
cdktf deploy
でデプロイ
いよいよデプロイです。cdktf deploy
を実行します。
途中で実行して良いか聞かれますのでyes
を入力します。
$ cdktf deploy Stack: cdk-work-java Resources + SAKURACLOUD_SWITCH testSwitch sakuracloud_switch.testSwitch Diff: 1 to create, 0 to update, 0 to delete. Do you want to perform these actions? CDK for Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: # yesと入力する # しばらく待つ Resources ✔ SAKURACLOUD_SWITCH testSwitch sakuracloud_switch.testSwitch Summary: 1 created, 0 updated, 0 destroyed.
デプロイできましたね!
今回はステートをローカルに保存するようにしましたので、カレントディレクトリにterraform.tfstate
ファイルが作成されているはずです。
後片付け: cdktf destroy
最後に忘れずに作成したリソースの削除を行っておきます。
こちらも途中で実行して良いか聞かれますのでyes
と入力します。
$ cdktf destroy
これで削除されるはずです。
終わりに
今回はTerraform CDKの紹介とTerraform CDK+さくらのクラウドプロバイダーを利用する方法について紹介しました。
またまだ開発段階ということでちらほら気になる挙動があったりしますが、Pulumiと比べると既存のTerraformプロバイダーが利用しやすいと感じました。
(Pulumiの場合はブリッジを書く必要がある)
Terraformへの入力が変わるだけで既存のワークフロー(CI/CDなど)はそのまま利用できるのも嬉しいですね。
今後もう少し使い込んでみようかと思います。以上です。