NRIネットコム社員が様々な視点で、日々の気づきやナレッジを発信するメディアです

注目のタグ

    TerraformとCDKのコードの書き方を比較してみる

    本記事は  【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以外のパブリッククラウドを扱う可能性がある場合

    執筆者: 後藤 涼太
    AWSをメインとするクラウドエンジニア
    2024 Japan AWS All Certifications Engineers
    2025 Japan AWS All Certifications Engineers
    執筆記事:https://tech.nri-net.com/archive/author/r-goto