CDKTF使ってみたので感想ですの
CDKTFを使ってみました.
n番煎じですが,やったこと,感想を書きます.
CDKTFとは
すでにZennに投稿されてる記事の方がわかりやすいと思いますし,自分の理解が誤っている気もするのですが,HCLを直接記述せずに(この記事を書いている時点だと)TypeScript,Python,Java,C#,Goで記述してTerraform経由で各種プロバイダでの構築ができるものです.
メリット
Terraformを使えるインフラエンジニアやSREなどの専門の人が,プロジェクトや社内にいれば良いですが,いない場合でもソフトウェアエンジニアが馴染みのある言語でインフラ構築もできることだそうです.ChatGPTが言ってます.ガンダムは言ってないです.
やったこと
以前Terraformを使った内容をCDKTFでも書いてみました.
若干tagなどを変えていたりしますがほぼ同じです.ゆえに試験的な構成なのでセキュリティ面とかで疎かになっている箇所もあります.インストール
TypeScriptを使いました.理由は投資信託のダッシュボードをAWS環境にデプロイしようとした一環でCDKTFを使ってみたのが発端で,SNMP検証用の内容に移植しやすかったからです.FlaskやFastAPIを使っていればPythonでも良かったのですが,Pythonを使わなかったので…
Terraformは既にインストール済みです.
一応バージョンを確認したところ
- Terraform : 1.5.6 (うわEOLじゃんってことに記事を書いていて気づきました)
- TypeScript : 5.8.3
- Node : 18.17.1 (うわEOLじゃんってことに記事を書いていて気づきました)
- cdktf:0.20.12
この辺は上げておきます.公式サイトをざっと読んだ限り,Nodeが16以上,Terraformが1.2以上なら良さげです.
インストール手順は公式サイトを参照しました.英語ですが一番下の参考にリンク貼ってます.
npm install --global cdktf-cli@latest
作業リポジトリ
└ infra
├ main.ts
├ server
│ └ server.ts
└ network
└ network.ts
インフラというディレクトリを作って開始します.
cdktf init --template=typescript --providers=aws --local
--templateでおそらくPython,C#,Goとか選べると思います.providerで他のクラウドベンダーを選べると思います.--localは確かTerraformのクラウドを利用しないフラグだったと思います.公式ドキュメントにも--local flag to prevent CDKTF from using HCP Terraform.と書いてあったので.
この後も対話的に色々yesやnoと答えていくことになると思います.ただ,あらかじめオプションで指定できるはずかと.init --helpでオプションが見れるはずです.
プロジェクト開始
main.tsがデフォルトで作成されると思います.
そこに色々AWSリソースを定義していくのもアリといえばアリなのですが,自分が試したSNMPの検証環境ですら,そこそこのリソースを使うことになったので,別ファイルに分けた方がいい気がします.
Terraformで書いてみたときは1個のtfファイルで対応しましたが,今回は上のディレクトリ構成のようにserver,networkという切り口でリソースを定義していきました.
networkディレクトリ内のnetwork.tsは,今回の場合でもそこそこ嵩張っているというか,読みづらくなりました.ACLとかも特に設定していない単純構成なんですけど.
import { Construct } from "constructs";
import { App, TerraformStack } from "cdktf";
import { AwsProvider } from "@cdktf/provider-aws/lib/provider";
import NetworkStack from "./network/network";
import ServerStack from "./server/server";
import { awsconfig } from "./config";
class MyStack extends TerraformStack {
constructor(scope: Construct, id: string) {
super(scope, id);
// define resources here
new AwsProvider(this, awsconfig.provider, {
region: awsconfig.region,
accessKey: awsconfig.accessKey,
secretKey: awsconfig.secretKey,
});
const networkStack = new NetworkStack(this, "network");
new ServerStack(
this,
"server",
networkStack.publicENI.id,
networkStack.privateENI.id
);
}
}
const app = new App();
new MyStack(app, "infra");
app.synth();
ベストプラクティスではないと思いますが,NetworkStack
としてawsネットワーク構成を書き,ServerStack
にサーバ構成を書きました.
シークレット情報について,configから呼び出してしまってますが,ベストプラクティス的にはTerraformVariableを使うことだそうです.環境変数呼び出しはせずにとのことです.追ってGitHub側含めて直して検証してみます.
ServerStack
にはNetworkStack
側のENIのidを渡してます.ENIはNICにあたる理解のため,EC2インスタンスに紐づける必要があったからです.
cdktf deploy
を実行します.
エラーなくできれば
cdktf destroy
で終わりです.
app.synth()はTerraformで読み込めるリソースをoutputディレクトリに生成する処理らしいです.
ハマったポイント一部
extendsの継承元
ServerStack
やNetworkStack
を0から作ろうとした際に,書き方がわからず,mainの内容をベースにしました.
するとextendsでTerraformStack
にしていたためか,エラーが出てました.
そもStackとはですが,CDKTFが構築するインフラの塊らしく,アプリ内の複数環境,開発や検証環境,本番環境などの状態管理を分別できるようにするものだそうです(英語自信ない)
このエラーは,Constructから継承したら解消しました.
次にConstructについてですが,CDKTFのプログラムはconstructから構成される木と考えられるようなので,要するにConstructは一番の親クラスにあたるもののようです.
TerraformStackクラスも継承されていました.
TerraformStackクラスは,Terraformデプロイ用の最小構成な気がします.先人たちの話を見た限り.ChatGPTもそんなようなことを言ってましたが,公式ドキュメントでは見つけられず.
公式ドキュメント記載のCross-Stack Referencesというものでも,今回の構成を実現できそうですが,自分は我流で進めてしまいました.
どういう書き方が適切なのかは,本番環境と検証環境でリソースをどうするか,今後のインフラの構成変更や使いまわせるコードにするという点で考慮していくポイントで,難しいなと感じました.
エラー解消方法としては,Constructから継承させれば良かったのですが,英語力の無さと日本語の文献の少なさ,Terraformの知識の無さ,アナロジーのように考えることもできないことから,モヤモヤは完全解消できず.
この件についてはホームワークにさせてください.転がる夢なんだよ追いかけていたいのは.
EC2インスタンスのuserDataについて
Terraformだとヒアドキュメントの<<EOFから始まりEOFで結んでいたのですが,どうやらTerraformの仕様であって,Linuxのシェルのものとも違うらしく,CDKTFというかTypeScript?の場合は不要なようです.これで起動してもSNMP周りのパッケージがインストールされておらず2時間近く溶かしました.
tagsの中身のNameについて
Terraform同様にオブジェクトのキーになってますがNameです.TypeScriptだからといってnameじゃないようです.
感想
結論から言うと,便利かどうかよくわからないです.学習コストが低いという感想を見かけましたが,自分には難しかったです.
いったん普通にHCL書いてTerraformを利用する場合,以下知識が必要だと思います.
- プロバイダー(AWS,Google Cloude, Azure, VMware...)の知識.AWSだったらEC2インスタンスとは何か?など
- Terraformの知識.ここでいう知識は書き方,リソース作成時にどんなオプションが使えるか(スペック,ami)など
- 瑣末ですが,基礎的なネットワークの知識も必要そうですかね.ルーティング(OSPFとかプロトコルではなくルーティングとはのレベル),どういう経路でどういう通信が発生し,ここの通信を許していいのか?など
CDKTFの場合,これプラスでCDKTFそのものについて調べること,当たり前かもですがTypeScriptやPythonを難なく書ける(オブジェクト指向的な書き方がなんとなくでもいいからわかる)必要があると思いました,
慣れ親しんでる言語でTerraformを使えるんじゃないのか?というと,そうではあるんですが,個人的に何が辛いかって結局2のEC2インスタンスのオプションとかを調べる必要があることだと思っています.
ソフトウェアエンジニアで活躍されてる方なら,HCLの記述自体はそんなに大変じゃないと思いますし,素直にHCL書くでも良い気もしています.
もちろんHCLは宣言型であったり,for文やif文もできるけど,柔軟性はCDKTFの方があるかもしれません.
他にもTypeScriptであれば,型による恩恵を受けられるかもしれないです.
その領域までまだ辿り着けてないです…
面白いとは思いました.自分が珍しいもの好きな性格もありますが,ニッチであるが故に調べがいがあると思います.ChatGPTもいい感じのコードを書いてくれたりアドバイスをくれますが,ソースはどこ?と聞くと嘘を返してきたので(たとえば上のTerraformStackのエラー解消方法は教えてくれたけど,TerraformStackとはなんぞ?についてのソースは持っていなかった.逆にどこで学習したんだ?って感じではあるんですが.怖)
Discussion