本記事は
【Advent Calendar 2024】
20日目②の記事です。
🌟🎄
20①日目
▶▶ 本記事 ▶▶
21日目
🎅🎁
こんにちは、後藤です。
今回はIaCツールの代表格であるAWS CDKとTerraformについてのお話です。
AWSリソースの管理にはCloudFormationを使われるシーンもありますが、近年の注目度や利用率を見るとAWS CDKかTerraformを採用しているケースが多いです。そのため当記事ではAWS CDKとTerraformに焦点を当てて比較し、その中でも選択の決め手に大きく関わるコードの書き方に着目したいと思います。
私自身、CDKとTerraformを使い込んできましたが、IAMリソースの作成において両者の違いが顕著に感じられましたので、IAMリソース作成の具体例を通して、これらの特徴の違いを比較していきたいと思います。
そもそもCDKとは
CDKとはAWSが提供するインフラコード化のためのフレームワークで、AWS環境に特化したインフラ管理に適しています。CDKの内部ではCloudFormationを使われており、TypeScriptやPythonどの一般的なプログラミング言語を使って定義できるため、より柔軟なプログラミングが可能です。抽象化という概念があり、すべてのパラメータを記載せずともベストプラクティスに沿ってツール側が自動で設定適用するようにすることも可能で、これが非常に魅力的です。
ちなみにCDK for Terraformという、CDKの内部で動作しているのがCloudFormationではなくTerraformになっているツールも存在しますが、採用率が比較的低いため本記事では割愛します。
そもそもTerraformとは
TerraformはHashiCorp社によって提供されているインフラ構築ツールで、HCL(HashiCorp Configuration Language)という専用言語を使って、クラウドインフラをコードで定義します。AWS以外のクラウドプロバイダー(Azure、Google Cloudなど)や、オンプレミスのインフラも管理できるため、マルチクラウド戦略に柔軟に対応します。
コード量の比較
それでは実際に比較していきましょう。まずはコード量の違いです。
CDKを使って、最低限の設定で以下リソースを作っていきます。
・EC2
・S3
・IAMロール (S3参照権限有)
・EC2にIAMロールをアタッチ
CDKを使ったリソース定義部分
#EC2作成 const instance = new ec2.Instance(this, 'Instance', { vpc: vpc, instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.MICRO), machineImage: new ec2.AmazonLinuxImage({ generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2023 }), }); #S3作成 const bucket = new s3.Bucket(this, 'my_Bucket', { bucketName: 'mybucket2024-example' }); #S3への参照権限を持ったIAMロールをEC2に付与 bucket.grantRead(instance);
続いてTerraformのコードです。同様の構成を作ると以下のようになります。
Terraformを使ったリソース定義部分
#EC2作成 resource "aws_instance" "ec2" { ami = "ami-xxxxxxxxxx" instance_type = "t2.micro" subnet_id = "subnet-xxxxxxxxx" iam_instance_profile = aws_iam_role.role.name } #S3作成 resource "aws_s3_bucket" "s3" { bucket = "mybucket2024-example" } #IAMロール作成 resource "aws_iam_role" "role" { name = "ec2-example" assume_role_policy = << -EOT { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOT } # インスタンスプロファイル設定 resource "aws_iam_instance_profile" "Instance-profile" { name = aws_iam_role.role.name role = aws_iam_role.role.name } #IAMポリシー作成 resource "aws_iam_policy" "policy" { name = "example-policy" policy = << -EOT { "Version": "2012-10-17", "Statement": [ { "Action": [ "s3:GetBucket*", "s3:GetObject*", "s3:List*" ], "Resource": [ "arn:aws:s3:::mybucket2024-example", "arn:aws:s3:::mybucket2024-example/*" ], "Effect": "Allow" } ] } EOT } #IAMポリシーをIAMロールにアタッチ resource "aws_iam_policy_attachment" "attach" { role = aws_iam_role.role.name policy_arn = aws_iam_policy.policy.arn }
一目瞭然でCDKの方がコード量が少ないですね。コード量が少ないと可読性が高く、記載ミスの可能性も減ります。特にIAMリソースの定義部分がほとんど不要で、grantRead
メソッドの1行で実装できました。
コードを読み書きする難易度の比較
続いて、難易度の比較です。
CDKは一般的なプログラミング言語で記述できるため、自由度の高いコードが書けます。しかし自由度が高いがゆえに、関数の使い方や構造設計が多様であり、第三者が書いたコードを読み解くのに時間がかかることがあります。さらに抽象化の概念を理解する必要があり、インフラエンジニアにとっては慣れないプログラミング言語も習得しなければならない場合があります。これらの要因からプログラミング言語や抽象化の理解が前提となり、とっかかりのハードルが高い印象があります。ただし苦戦するのはほんの始めの部分だけで、慣れてしまえばなんてことはないです。プログラミング言語をTypeScriptにすれば、VSCode等のIDEの型補完機能が効くので利用可能なプロパティやメソッドを簡単に確認でき、ドキュメント参照する手間が省けるので非常に便利だと感じられます。
一方、Terraformに関しては自作関数も作れなければif文も使えないので、ある程度限られた使い方になってきます。流派がわかれるとしたらどのようにモジュールを分けるか、どのようにディレクトリを分けるかといったぐらいでしょうか。シンプルなツールで学習コストが低い印象があります。とっかかりのハードルが低いことに加え、ネットに落ちている情報がとても多いので開発もスムーズに進みやすいです。
AWSに関する前提知識の比較
続いて、AWSの前提知識の比較です。
CDKでIAMリソースを作る場合は「IAMポリシーにはs3:GetBucketアクションが必要」や「IAMロールを紐づけるためにインスタンスプロファイルを指定する必要がある」といったことを知っている必要がありません。しかも最小権限になるように簡単に実装できます。このように、すべてのパラメータを記載せずともベストプラクティスに沿ってツール側が自動で設定し、「それらしく動く」ものが作れてしまいます。
一方、TerraformはAWSサービスへのより深い理解が求められます。上記コードのとおり、詳細設計書を埋めるようにコードを書いていくことになり、インフラエンジニアにとっては馴染みのある作業になるでしょう。
「Terraformコードの書き方がわからない」=「対象AWSサービスの理解が不足している」という状況であることが多い感覚です。
上記を表にすると
比較項目 | CDK | Terraform |
---|---|---|
コード量 | 少 | 多 |
開発に必要な前提知識量 | 少 | 多 |
開発のしやすさ | 高 | 高 |
まとめ
CDK採用が良いパターン、Terraform採用が良いパターンを考えてみました。
CDK採用が良いパターン:
・アプリ開発者もAWSインフラを扱う場合
・技術検証をササっと行いたい場合
Terraform採用が良いパターン:
・チーム内にアプリ開発経験者がいない場合、もしくは少ない場合
・プロダクション環境のような細かいパラメータ設定が必要で、暗黙の設定値を避ける場合
・プロジェクトが始まったばかりなど、今後AWS以外のパブリッククラウドを扱う可能性がある場合