こんにちは!クラウドソリューション開発部の西谷です。 先日とある業務で気になっていたAWS CDKを使ってみて、結構いいじゃんCDK!となったので、その内容を記事にします。
背景
まず、CDKを導入することにした背景を説明します。私が携わっているサービスは、複数のサーバーから構成されています。
これらのサーバーのOS・ミドルウェア・ソフトウェアのログを1年間保存しておくといった要件があり、その手段としてCloudWatchのロググループにログを転送して保存しておくことにしました。
色々調査を進めて、ロググループを整理していくと、作成が必要なロググループの数が80を超えることがわかりました。これだけの数のロググループを手動で作っていくのは骨が折れます。
そこでCDKを使えば簡単に一撃でロググループが作れるのでは?と思い導入することにしました。
CDKとは
そもそもCDKとは何だろうという方のためにご説明しますと、CDKはAWSのIaCの1つです。IaCとはInfrastructure as Code の略で、コードを使ってインフラを管理することを指します。
またCDK自体もCloud Development Kitの略で、AWSリソースを構築するためのクラスやメソッド等がパッケージ化されたものです。
開発者はCDKをTypeScriptやPythonと言語を通して利用することにより、AWS環境を構築することができます。AWSに関わるIaCといわれて真っ先に思いつくのはCloudFormation(以降CFn)だと思いますが、他にもCFnをサーバレスに特化させたAWS SAMだったり、HashiCorpから出ているTerraform等、様々なIaCが存在します。
ちなみに、CDKをデプロイする際にはCFnテンプレートに変換されます。実際にデプロイしてからAWSマネジメントコンソールからCloudFormationを確認すると、スタックが作成されていることがわかります。
IaCのモデル
色々あるけど、それらとCDKはどう違うの?といった疑問に答えるために、ここではIaCのモデルについて説明します。まずCloudFormation、SAM、Terraformは宣言型と呼ばれるモデルに属します。
特徴としては、「何を作成するか」ということを定義することが挙げられます。
例えばCloudFormationでテンプレートを作成する場合は、yamlファイルやjsonファイルなどに自分が構築したいリソースや、入れたい設定を1つ1つ書いていく(宣言していく)必要があります。
一方でCDKは命令型と呼ばれるモデルです。
宣言型とは異なり、「何を作成するか」に加えて「どのように作成するか」を制御することができます。
「どのように」を制御するためにCDKではTypeScriptやPythonといったプログラミング言語を利用して、構築したいリソースや設定を定義していきます。
CDK以外にも命令型のIaCは世の中にたくさんあります。気になる方は調べてみてください!
CloudFormationだと
CDKについて軽く説明しましたので、ここからはCFnと比較したときのメリットを紹介します。下記は後に出てくるCDKのソースからcdk synthコマンドで作成されたCFnテンプレートの一部です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "Resources": { "BlogLogGroup31F11FE86": { "Type": "AWS::Logs::LogGroup", "Properties": { "LogGroupName": "/blog/os/cron", "RetentionInDays": 365 }, "UpdateReplacePolicy": "Retain", "DeletionPolicy": "Retain", "Metadata": { "aws:cdk:path": "BlogLogsTemplateStack/BlogLogGroup3/Resource" } } ... } } |
「/blog/os/cronというロググループ名で、ログの保持期間365日、スタックが更新や削除が行われても、ログは保持する」
といった設定が書かれています。 注目していただきたいのは、「CFnでロググループを1つ作成する場合にこれだけのコードが必要になる。」ということです。
上記では「…」で省略していますが、実際は後80個以上ロググループ名だけが異なる同じコード出てきます。
つまり。CFnを使う場合、これを何らかの形で書いていく必要があります。(今ならChatGPT等を使ってうまく効率化できそうですが、テンプレートとして定義しなければいけないということは変わりません。)
CDKなら
さて、これをCDKで実装するならどうでしょうか。上記の説明で勘の鋭い方ならお気づきかと思いますが、CDKであれば単純なループで実現が可能です。
サンプルを下記に示します。 ※下記の例はTypescriptです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as logs from 'aws-cdk-lib/aws-logs'; import { LOG_GROUP_LIST } from '../consts/log_group'; export class BlogLogsTemplateStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); LOG_GROUP_LIST.forEach((item, index) => { new logs.LogGroup(this, `BlogLogGroup${index}`, { logGroupName: item, retention: logs.RetentionDays.ONE_YEAR, }); }); } } |
ちなみにLOG_GROUP_LISTの例も下記のようなロググループ名だけのシンプルな配列です。
1 2 3 4 5 6 7 8 9 10 |
export const LOG_GROUP_LIST = [ '/blog/os/cron', '/blog/os/dmesg', '/blog/os/dracut.log', '/blog/os/lastlog', '/blog/os/maillog', '/blog/os/messages', '/blog/os/secure', ... ] |
ここでは説明は省略しますが、気になる方はCDK テストで調べてみてください。
いまいちポイント
いいことばっかり書きましたが、ちょっと引っかかるポイントもあります。実際にcdk synthコマンドを実行してCFnテンプレートを確認すると、自分が定義していないものをCDKが自動で定義してくれていることがわかります。
言い換えると自分で定義していないものが勝手に作成されてしまうのです。
このような、よくわからない設定が勝手にされていることに対してアレルギー反応を起こしてしまう人は一定数いるのではないでしょうか。
一方でCFnなどの宣言型の場合には、意図していない設定等が勝手に入り込むことはありません。
どちらが良いというわけではなく、ソフトウェア開発により多くの時間を使いたい場合はCDK、テンプレートに宣言した通りのインフラを定義するならCFnといったように、場合や状況に応じて適切に選択する必要があるという結論に落ち着くと思います。
上記で説明した、単純にロググループを大量に作るケースであれば圧倒的にCDKが優れていると思いますし。
まとめ
最後にいまいちなポイントについて紹介しましたが、私個人としてはCDKはかなり便利だと思いました。これからも業務で使っていきたいです。 次はAWS公式も推していたCDK+TDDなんかもやってみたいと思いました。エコモットでは一緒にモノづくりをしていく仲間を募集中です。弊社に少しでも興味がある方、AWSを使った開発に興味がある方はぜひ下記の採用ページをご覧ください!