AWS IaC ツール、どれを選べばいい?🤔 AWSエキスパートが各ツールについて比較と採用のポイントを解説

AWS IaC ツール、どれを選べばいい?🤔 AWSエキスパートが各ツールについて比較と採用のポイントを解説

こんにちは! 今回は、AWSのインフラストラクチャ構築を自動化できるIaCツールについて解説します。
IaCって便利そうだけど、種類が多くてどれを選べばいいか迷っちゃいますよね。
本記事では、AWS IaCツールの中から、よく使われる4つのツールをピックアップして、それぞれのメリット・デメリットやコード例などを紹介します。

IaC(Infrastructure as Code)とは

IaCとは、インフラストラクチャの構成をコードで定義し、自動的に構築・管理する手法です。従来の手作業による構築と比べて、以下のメリットがあります。

  • 効率性向上: コードでインフラストラクチャを定義することで、手作業によるミスを減らし、構築時間を短縮できます。
  • 再現性向上: 同じコードを実行すれば、常に同じインフラストラクチャ環境を構築できます。環境の再現が容易になるため、開発、テスト、本番環境など、さまざまな環境を効率的に構築できます。
  • バージョン管理: コードをバージョン管理システムで管理することで、変更履歴を追跡し、必要に応じて以前の状態に戻すことができます。
  • 構成の一貫性: 複数の環境に同じインフラストラクチャを構築する場合、コードを共有することで構成の一貫性を保てます。

AWS IaC ツールの比較

AWSではさまざまなIaCツールが提供されていますが、今回は以下の4つを比較します。

  • AWS CloudFormation
  • AWS SAM (Serverless Application Model)
  • AWS CDK (Cloud Development Kit)
  • Terraform

各ツールの詳細

AWS CloudFormation

AWS CloudFormationは、AWSのネイティブサービスであり、AWSリソースの構築を自動化するための IaC サービスです。JSON または YAML 形式でテンプレートを作成し、AWSリソースを定義します。CloudFormation は AWS のさまざまなサービスをサポートしており、インフラストラクチャをコードとして管理するための強力なツールです。

AWS CloudFormationのメリット

  • ネイティブサービス: AWS によって完全にサポートされているため、AWS の最新機能やアップデートに迅速に対応できます。
  • 包括的な機能: AWS のほぼすべてのサービスとリソースをサポートしており、幅広いインフラストラクチャを定義できます。
  • 詳細な制御: インフラストラクチャの構成を細かく制御できます。
  • ロールバックサポート: デプロイメントに失敗した場合、自動的に以前の状態にロールバックできます。
  • ドリフト検出: 定義されたテンプレートと実際のインフラストラクチャの構成の差異を検出できます。

AWS CloudFormationのデメリット

  • 学習コストが高い: JSON または YAML 形式のテンプレートは、初心者にとって理解しにくく、学習コストが高いです。
  • 複雑な構文: 複雑なインフラストラクチャを定義する場合、テンプレートが複雑になりがちです。
  • 再利用性: モジュール化の機能が限定的であり、コードの再利用が難しい場合があります。
  • AWS限定: AWS 環境のみに限定され、他のクラウドプロバイダーでは使用できません。

CloudFormationのコード例 (YAML)

Resources:
  MyDynamoDbTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
  MyLambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: index.handler
      Role: !GetAtt MyLambdaRole.Arn
      Runtime: nodejs14.x
      Code:
        ZipFile: |
          exports.handler = async (event) => {
            // Your Lambda function code here
          };
  MyLambdaRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: 'sts:AssumeRole'
      Policies:
        - PolicyName: LambdaPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: 'dynamodb:PutItem'
                Resource: !GetAtt MyDynamoDbTable.Arn
  MyApi:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: MyApi
  MyApiResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !GetAtt MyApi.RootResourceId
      ParentId: !GetAtt MyApi.RootResourceId
      PathPart: items
  MyApiMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      HttpMethod: POST
      ResourceId: !Ref MyApiResource
      RestApiId: !Ref MyApi
      AuthorizationType: NONE
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${MyLambdaFunction.Arn}/invocations'
      MethodResponses:
        - StatusCode: 200
  LambdaApiGatewayPermission:
    Type: 'AWS::Lambda::Permission'
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !Ref MyLambdaFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${MyApi}/*/*/*'
    

AWS SAM (Serverless Application Model)

AWS SAMは、サーバーレスアプリケーションの構築・デプロイを簡素化するためのフレームワークです。CloudFormation をベースに構築されており、サーバーレスリソースをより簡単に定義できます。SAMは、AWS Lambda、Amazon API Gateway、Amazon DynamoDB などのサーバーレスサービスに特化しており、これらのサービスを組み合わせたアプリケーションの構築を容易にします。

AWS SAMのメリット

  • 簡潔な構文: サーバーレスリソースを簡潔に定義するための独自の構文を提供します。
  • 開発者向け: 開発者に使いやすいように設計されており、アプリケーションコードとインフラストラクチャコードを同じ言語で記述できます。
  • ローカルテスト: ローカル環境でサーバーレスアプリケーションのテストとデバッグを容易にするツールが付属しています。
  • CloudFormationとの互換性: SAM テンプレートは CloudFormation と互換性があり、既存の CloudFormation テンプレートに統合できます。

AWS SAMのデメリット

  • サーバーレスアプリケーションに特化: サーバーレスアプリケーションに最適化されており、従来のインフラストラクチャの定義には不向きです。
  • AWS限定: AWS 環境のみに限定され、他のクラウドプロバイダーでは使用できません。

SAMのコード例 (YAML)

Resources:
  MyDynamoDbTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: id
        Type: String
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5
  MyLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs14.x
      CodeUri: ./src
      Policies:
        - DynamoDBWritePolicy:
            TableName: !Ref MyDynamoDbTable
      Events:
        MyApi:
          Type: Api
          Properties:
            Path: /items
            Method: POST
Outputs:
  ApiUrl:
    Description: API Gateway endpoint URL for Prod stage for Hello World function
    Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/items'
    

AWS CDK (Cloud Development Kit)

AWS CDKは、使い慣れたプログラミング言語を使用してインフラストラクチャを定義できるフレームワークです。 TypeScript、JavaScript、Python、Java、.NET、Go などの言語をサポートしており、オブジェクト指向の概念を使用してインフラストラクチャをモデル化できます。CDK は、インフラストラクチャコードの再利用性と保守性を向上させるための構成要素を提供します。

AWS CDKのメリット

  • 使い慣れたプログラミング言語: 開発者は使い慣れたプログラミング言語を使用してインフラストラクチャを定義できるため、学習コストが低いです。
  • オブジェクト指向: オブジェクト指向の概念を使用してインフラストラクチャをモデル化できるため、コードの再利用性と保守性が向上します。
  • 強力な抽象化: 高レベルの構成要素を提供し、複雑なインフラストラクチャを簡潔に定義できます。
  • AWS Construct Library: AWS リソースを簡単に利用するための豊富なライブラリを提供します。
  • AWS限定: AWS 環境のみに限定され、他のクラウドプロバイダーでは使用できません。

AWS CDKのデメリット

  • 実行環境: CDK を使用するには、Node.js の実行環境が必要です。
  • CloudFormationへの依存: CDK は最終的に CloudFormation テンプレートを生成するため、CloudFormation の制限事項が適用される場合があります。

CDKのコード例 (JavaScript)

const cdk = require('@aws-cdk/core');
const lambda = require('@aws-cdk/aws-lambda');
const dynamodb = require('@aws-cdk/aws-dynamodb');
const apigateway = require('@aws-cdk/aws-apigateway');

class CdkStack extends cdk.Stack {
  constructor(scope, id, props) {
    super(scope, id, props);

    // DynamoDB table
    const table = new dynamodb.Table(this, 'MyDynamoDbTable', {
      partitionKey: { name: 'id', type: dynamodb.AttributeType.STRING },
      readCapacity: 5,
      writeCapacity: 5,
    });

    // Lambda function
    const myLambda = new lambda.Function(this, 'MyLambdaFunction', {
      runtime: lambda.Runtime.NODEJS_14_X,
      handler: 'index.handler',
      code: lambda.Code.fromAsset('./src'),
    });

    // Grant Lambda permission to write to DynamoDB
    table.grantWriteData(myLambda);

    // API Gateway
    const api = new apigateway.RestApi(this, 'MyApi', {
      restApiName: 'My API',
    });

    const items = api.root.addResource('items');
    items.addMethod('POST', new apigateway.LambdaIntegration(myLambda));
  }
}

module.exports = { CdkStack };

Terraform

Terraformは、HashiCorp によって開発されたオープンソースの IaC ツールです。
宣言型の構成ファイルを使用して、AWS を含むさまざまなクラウドプロバイダーのインフラストラクチャを定義できます。
Terraform は、モジュール化と状態管理の機能を備えており、大規模で複雑なインフラストラクチャを効率的に管理できます。

Terraformのメリット

  • マルチクラウドサポート: AWS、Azure、Google Cloud など、さまざまなクラウドプロバイダーをサポートしています。
  • 強力なコミュニティとエコシステム: 活発なコミュニティと豊富なエコシステムがあり、多くのモジュールやプラグインが利用可能です。
  • モジュール化: インフラストラクチャコードを再利用可能なモジュールに分割することで、コードの保守性と再利用性を向上させます。
  • 状態管理: Terraform はインフラストラクチャの状態を管理し、変更を効率的に追跡および適用します。

Terraformのデメリット

  • 学習コスト: Terraform 独自の構成言語 (HCL) を習得する必要があります。
  • 依存関係管理: 複数のモジュールを使用する場合、依存関係の管理が複雑になることがあります。

Terraformのコード例 (HCL)

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

resource "aws_dynamodb_table" "example" {
  name           = "example"
  read_capacity  = 5
  write_capacity = 5
  hash_key       = "id"

  attribute {
    name = "id"
    type = "S"
  }
}

resource "aws_lambda_function" "example" {
  function_name = "example"
  handler       = "index.handler"
  runtime       = "nodejs14.x"

  # The filebase64() function is available in Terraform 0.11.12 and later
  # For Terraform 0.11.11 and earlier, use the base64encode() function and the file() function:
  # code = "${base64encode(file("lambda_function_payload.zip"))}"
  code = filebase64("lambda_function_payload.zip")

  role = aws_iam_role.iam_for_lambda.arn

  environment {
    variables = {
      foo = "bar"
    }
  }
}

resource "aws_iam_role" "iam_for_lambda" {
  name = "iam_for_lambda"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "lambda_policy" {
 name = "lambda_policy"
  role = aws_iam_role.iam_for_lambda.id

  # Terraform's "jsonencode" function converts a
  # Terraform expression result to valid JSON syntax.
  policy = jsonencode({
    Version = "2012-10-17"
 Statement = [
      {
        Action = [
          "dynamodb:GetItem",
 "dynamodb:PutItem",
        ]
        Effect   = "Allow"
        Resource = aws_dynamodb_table.example.arn
      },
    ]
  })
}

resource "aws_api_gateway_rest_api" "example" {
  name        = "example"
}

resource "aws_api_gateway_resource" "example" {
  rest_api_id = aws_api_gateway_rest_api.example.id
  parent_id   = aws_api_gateway_rest_api.example.root_resource_id
  path_part   = "example"
}

resource "aws_api_gateway_method" "example" {
  rest_api_id   = aws_api_gateway_rest_api.example.id
 resource_id   = aws_api_gateway_resource.example.id
  http_method   = "ANY"
  authorization = "NONE"
}

resource "aws_api_gateway_integration" "example" {
  rest_api_id             = aws_api_gateway_rest_api.example.id
  resource_id             = aws_api_gateway_resource.example.id
  http_method             = aws_api_gateway_method.example.http_method
  integration_type        = "aws_proxy"
  integration_http_method = "POST"
  type                    = "aws"
  uri                     = aws_lambda_function.example.invoke_arn
} 

各ツールの使い分け

それぞれのツールのメリット・デメリットを理解した上で、プロジェクトの要件に合わせて適切なツールを選択することが重要です。

  • CloudFormation: AWS 環境に限定されますが、AWSのネイティブサービスであるため、AWSの最新機能をすぐに利用できることが大きなメリットです。インフラストラクチャの構成を細かく制御したい場合に最適です。
  • SAM: サーバーレスアプリケーションに特化したフレームワークです。ローカルでのテストやデバッグを容易にしたい場合に最適です。
  • CDK: 使い慣れたプログラミング言語でインフラストラクチャを定義できます。オブジェクト指向の概念を活用して、コードの再利用性と保守性を向上させたい場合に最適です。
  • Terraform: 複数のクラウドプロバイダーをサポートしており、マルチクラウド環境でインフラストラクチャを管理する場合に最適です。

まとめ

AWS の IaC ツールには、それぞれメリット・デメリットがあります。
プロジェクトの要件やチームのスキルなどを考慮して、適切なツールを選択することが重要です。

  • AWS CloudFormation: AWS 環境に特化しており、細かい設定をコード化したい場合に最適
  • AWS SAM: サーバーレスアプリケーションに特化しており、開発者中心に設計されている
  • AWS CDK: 開発者が使い慣れた言語でコード化できます。
  • Terraform: マルチクラウドに対応し、コードの再利用性が高い

AWSモダナイズ開発基幹業務システムのUI.UX刷新はお気軽にお問い合わせください。