はじめに
こんにちは!株式会社クロスパワー クラウドシステム開発部の N です。
近頃、クラウドシステム開発部では AWS 開発環境におけるクラウドリソース管理の重要性の増加とともに、クラウド上のインフラ構築をコードとして管理する Infrastructure as Code (以降 IaC) の需要が高まっています。
特に CI/CD を回している環境なら IaC の利用は必須と言ってもよいでしょう。
AWS で利用可能な IaC ツールとして AWS Cloud Development Kit (以降 CDK) と Terraform の2つが有名です。
これら2つの IaC ツールの仕組みと使い方を横断的に解説する書籍
『[詳解]AWS Infrastructure as Code ――使って比べるTerraform&AWS CDK』
が、今年の2月に技術評論社から発行されました。
筆者は、これまで実際の開発において CDK を触ってきましたが Terraform にはノータッチだったのですが、この書籍を読んだことで Terraform の使い方や CDK との違いについて知見を得ることができました。
本記事では、書籍の内容と筆者が調べた情報を元に、Terraform と CDK の相違点を整理し、2つのツールの使い分け方について考察していきます。
- はじめに
- Terraform とは
- CDK とは
- Terraform と CDK の相違点
- Terraform と CDK の使い分け方の考察
- おわりに
- 余談1: CDK for Terraform について
- 余談2: Terraform Cloud について
- 余談3: Terraform と CDK の同時運用の可能性について
Terraform とは
Terraform は米国 HashiCorp 社によって開発されている IaC ツールです。
Hashicorp Configuration Language (以降 HCL) という独自の言語でインフラを記述・管理します*1。
AWS 以外のクラウド (例: Google Cloud Platform や Azure 等) にも対応しています。
CDK とは
CDK は AWS 公式の IaC ツールです。
TypeScript や Python 等のプログラミング言語を用いて AWS クラウド上のリソースを定義し、プロビジョニングすることができます*2。
Terraform と CDK の相違点
マルチクラウドへの対応
前述のとおり Terraform はマルチクラウドに対応しています。
HCL を用いて AWS 以外の IaaS のリソースを記述することが可能です。
一方 CDK は AWS 以外の IaaS には対応していません。
マルチクラウドに対応した CDK for Terraform というツールもありますが、これは CDK とは別物です(余談1)。
差分抽出の仕組み
IaC ツールにおいて差分抽出は重要な機能です。
それは IaC におけるデプロイ処理とは、コード上に記述された定義と実リソースの差分を抽出し、その情報を元に実リソースを更新するプロセスだからです。
Terraform と CDK ではこの差分抽出の仕組みが大きく異なります。
Terraform では、コードを元に作成する tfstate
というファイルを用いてリソースの情報を管理します。
tfstate
ファイル内には、コードで定義したリソースのあらゆる属性が保存されています。
Terraform で差分抽出するには terrafrom plan
コマンドを実行します。
このコマンドを実行すると、tfstate
ファイルの情報を元に実際のリソースの最新の状態を取得し、手元のコードと比較して差分を抽出します。
このため、Terraform では、実リソースに加えられたすべての変更を必ず抽出することが可能です。
一方 CDK では、コードを元に作成する CloudFormation のテンプレートを用いてリソースの情報を管理します。
CloudFormation テンプレートはリソースの属性をすべて網羅しているとは限りません。
CDK で差分抽出するコマンドは cdk diff
です。
このコマンドを実行すると、1つ前のデプロイ時の CloudFormation テンプレートを取得し、手元の CloudFormation テンプレートと比較して差分を抽出します。
このため、CDK では、実リソースに加えられた変更を抽出できないケースが存在します。
言い換えると、同一のコードなのに環境ごとに異なるリソースが作成されてしまう可能性があります。
CDK でリソースを管理する際は、リソースを手動で変更しないように徹底する必要があるでしょう*3。
言語
Terraform では、リソースを定義するコードを HCL という言語を用いて記述します。
次に示すのは SQS キューを HCL で記述したコードの一部です。
resource "aws_sqs_queue" "my_queue" { name = "test-queue-tf" max_message_size = 4096 tags = { "name" = "test-queue-tf" } }
HCL の構文はシンプルなので、学習コストはそこまでかからないと思います。
言語に関連して、ディレクトリ構成にも触れておきます。
Terraform は1つのディレクトリをモジュールという構成単位で取り扱います。
モジュール内及びモジュール間においてファイル名やディレクトリの構成に大きな制約はありません。
実際の開発においては、事前にチーム内で命名規則やディレクトリ構成のルールを決めておいたほうがよいでしょう。
CDK では、リソースを定義するコードを TypeScript を用いて記述します。
次に示すのは SQS キューを TypeScript で記述したコードの一部です。
import * as cdk from 'aws-cdk-lib'; import { Construct } from 'constructs'; import * as sqs from 'aws-cdk-lib/aws-sqs'; export class SqsStack extends cdk.Stack { constructor(scope: Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const queue = new sqs.Queue(this, 'MyQueue', { queueName: 'test-queue-cdk', maxMessageSizeBytes: 4096, }); cdk.Tags.of(queue).add('Name', 'test-queue-cdk'); } }
cdk init
コマンドで生成される CDK のディレクトリ構成は、言うなれば一般的な Node.js アプリと同じです。
Node.js + TypeScript の開発環境に慣れ親しんだ人であれば、CDK の開発環境にもすぐ順応できると思います。
抽象度
Terraform では、基本的に作成するリソースをすべてコード内で記述する必要があります。
前述したモジュールの仕組みを利用することで、複数のリソースを単一のモジュールとしてカプセル化できます。
モジュールを活用すれば、複雑なリソースを少ない記述で管理することが可能となります。
また、Terraform Registry*4 ではモジュールを共有する仕組みが提供されています。
ここでは、有志によって作成された、複数の AWS リソースをまとめて扱えるモジュールが公開されていたりします*5。
CDK においても、基本的に作成するリソースをすべてコード内で記述する必要があるのは Terraform と同様です。
CDK ではリソースをコンストラクトという構成要素で表現します。
コンストラクトにはその抽象度に応じて3つのレベルが存在します。
- L1 コンストラクト : 最も抽象度の低いコンストラクト。CloudFormaion リソースと対応している。
- L2 コンストラクト : L1 より抽象化されたコンストラクト。より簡潔にリソースを記述可能。
- L3 コンストラクト : 特定のユースケースに対応したアーキテクチャ全体を作成するためのコンストラクト。
CDK 公式のライブラリ*6では、ほぼすべての AWS リソースに対応する L2 コンストラクトが提供されています。
Terraform と比較して、CDK の方が抽象度の高い扱いやすいライブラリが充実していると言えます。
作業履歴の管理方法
前述したように Terraform では tfstate
というファイルを用いてリソースの情報を管理します。
tfstate
ファイルにはコードで定義されたリソースと実際のリソースを結びつけるのに必要な情報が格納されています。外部に漏れてはいけないような機密情報が含まれることもあります。
デフォルトの設定では tfstate
ファイルはローカルに保存されます。
AWS を対象とするチーム開発においては、tfstate
ファイルは S3 バケット上で管理するのが一般的なようです。
Terraform 自体には tfstate
ファイルへのアクセス権限を管理したり、過去のデプロイ時のバックアップをとったりする機能ないので、S3 バケット側で設定する必要があります。
また、Terrafrom には、デプロイを実行したときのログを保存する機能がありません。
作業履歴を残したい場合、他の方法――例えば CI/CD ツール等を用いてログを保存する必要があるでしょう。
あるいは、Terraform の SaaS である Terraform Cloud (余談2) を利用すれば、これらを一元的に管理することができます。
一方、CDK では CloudFormation テンプレートを用いてリソースの情報を管理します。
このテンプレートは CDK Toolkit
という CloudFormation スタック(( CDK Toolkit
CloudFormation スタックは cdk bootstrap
コマンド実行時に自動的に作成されます。 ))が管理する S3 バケット上に保存されます。
AWS CLI や AWS CloudFormation コンソールから過去のテンプレートやデプロイ時の情報の履歴にアクセスすることが可能です。
アクセス権限の設定には IAM ロールをはじめとする AWS の仕組みが利用できます。
Terraform と CDK の使い分け方の考察
これまでに挙げた相違点を元に Terraform と CDK の使い分け方について考えていきましょう。
まず、マルチクラウドへの対応非対応の違いです。
プロジェクトの要件として AWS 以外の IaaS の利用が不可欠な場合は Terraform の採用が絶対となります。
どうしても CDK を使いたいという場合には CDKTF の利用を検討してもよいかもしれません。
次に、差分抽出の仕組みの違いです。
Terraform では実リソースのあらゆる差分を検知できるのに対し、CDK では検知できない可能性があります。
リソース操作の安全性を重視する場合は Terraform を採用すべきでしょう。
さらに、使用する言語の違いがあります。
Terraform では独自言語の HCL を、CDK では TypeScript (+ Node.js) を使用しています。
また、CDK の方がより抽象度の高いライブラリを利用できるということでした。
換言すれば、CDK はリソースに関する知識が浅い場合でも、最小限の記述で多様なリソースを作成できるということです。
チームメンバーのスキルセットや確保できる工数によっては、CDK の方がより効率的に作業を進められるケースもあるでしょう。
最後に、作業履歴の管理方法の違いです。
Terraform と CDK でリソースの情報を管理する方法が異なることを説明しました。
これに関しては優劣ではなく、CI/CD ツールや開発環境の運用方法との相性次第と言えるでしょう。
IaC ツールは飽くまで開発環境を潤滑に運用するための手段です。
どのような CI/CD ツールを利用するか、ひいてはどのように開発環境を運用していくかを明確にしたうえで IaC ツールを選択すべきと考えます。
おわりに
Terraform と CDK の相違点と使い分け方について自分なりの考えも合わせて説明しました。
AWS 開発環境の立ち上げ時の IaC ツール選定のお役に立てれば嬉しいです。
この記事の執筆にあたり、『[詳解]AWS Infrastructure as Code
――使って比べるTerraform&AWS CDK』を大いに参考にさせていただきました。
この書籍には
- Terraform と CDK の基本的な使い方や仕組みの解説
- Terraform と CDK の注意すべき相違点
- 実践的なサンプルコード
などなど、本記事では書き切れなかった詳細な情報がとても分かりやすく書かれています。
AWS 開発環境の IaC ツールに少しでも興味があれば、読んでみることを強くおすすめします。
余談1: CDK for Terraform について
CDK for Terraform (以降 CDKTF) とは、一言で説明すると CloudFormation の代わりに Terraform でリソース管理を行うようになった CDK です。
CDKTF を用いることで、CDK の開発体験はそのままに、安全なリソース管理やマルチクラウド対応といった Terraform の強力な機能を利用することが可能となるようです。
実際の活用例はまだあまり耳にしたことはないですが、今後の発展に期待したいところです。
なお、CDKTF は既存の CDK の拡張機能ではなく、CDK とは別の独立したツールです。
そのため、既存の CDK で書かれたコードを Terraform で扱える形式に変換することはできません*7。
これができるようになると Terraform と CDK の相互運用性が高まって嬉しいのですが……今後の発展に期待です。
余談2: Terraform Cloud について
Terraform Cloud は Terraform を開発する HashiCorp 社が提供している SaaS です。
tfstate
ファイルの管理- アクセス権限・ログの管理
- GitHub 等の外部サービスとの連携
といった Terraform をチーム開発で利用する際に便利な機能が揃っているようです。 組織として Terraform を活用していくのであれば Terraform Cloud の採用を検討してもよいかもしれません。
余談3: Terraform と CDK の同時運用の可能性について
ここまで読んで、
「1つのプロジェクト内で Terraform と CDK を同時運用することはできないか?」
と思った方もいるかもしれません。
結論から言うと、それは不可能だと筆者は考えます。
Terraform と CDK のそれぞれに既存の AWS リソースを IaC の管理下にインポートする機能があります。
また、任意のリソースを管理下から除外する機能についても、それぞれの IaC ツールに備わっています。
しかしながら、Terraform と CDK の間でリソースをやり取りすることは、ワンボタンで実行できるような簡単な作業ではありません。
各種 AWS リソース、動作させるシステム、そして IaC ツール自体についての専門知識が問われる高難度な作業です。
したがって、複数の IaC ツールを同時に運用しようとは思わず、プロジェクト立ち上げ時にどの IaC ツールを使うか十分に検討して決定することが重要だと筆者は考えています。
*1: JSON を利用することも可能ですが、本記事では説明の簡単のため HCL のみ取り扱います。
*2: 本記事では説明の簡単のため TypeScript を用いた場合のみを想定して解説します。
*3:リソースの変更を検知するドリフト検出という機能が CloudFormation コンソールにはありますが、残念ながら一部のリソースには未対応です。
*4: プロバイダ (デプロイ先のプラットフォーム) やモジュールなどの Terraform に関連するリソースを検索するためのプラットフォーム。https://registry.terraform.io/browse/modules
*5: https://registry.terraform.io/namespaces/terraform-aws-modules
*6: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-construct-library.html
*7: AWS Adapter という機能を使えば、既存の CDK コンストラクトを CDKTF から利用することは可能なようです。https://developer.hashicorp.com/terraform/cdktf/create-and-deploy/aws-adapter