0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SAM・CloudFormation・CDKについてDVA対策としてまとめてみる

0
Posted at

サービスの違い

AWSでは、インフラ構成をコードで管理する仕組みを IaC(Infrastructure as Code) と呼ぶ。

サービス 主な役割 DVAでの重要ポイント
CloudFormation AWSリソースをテンプレートで定義・管理 Stack、Change Set、Rollback
AWS SAM サーバーレスアプリを簡潔に定義・開発 sam build、sam local、sam deploy
AWS CDK プログラミング言語でインフラを定義 Construct、cdk synth、cdk deploy

3つは完全に独立した仕組みではない。

CloudFormation
  ↑
  ├── SAM
  │    └── サーバーレス向けの簡潔な記法
  │
  └── CDK
       └── プログラミング言語から
           CloudFormationテンプレートを生成

CloudFormationの基本構造

CloudFormationは、YAMLまたはJSONのテンプレートでAWSリソースを定義する。

AWSTemplateFormatVersion: '2010-09-09'

Description: Sample Lambda Stack

Parameters:
  Environment:
    Type: String
    Default: dev

Resources:
  SampleFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub 'sample-${Environment}'
      Runtime: python3.12
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        S3Bucket: my-deployment-bucket
        S3Key: lambda.zip

Outputs:
  FunctionArn:
    Value: !GetAtt SampleFunction.Arn

※上記はテンプレートの構造を説明するための抜粋。LambdaExecutionRole は別途定義が必要。

主なセクション

セクション 用途
Parameters デプロイ時に渡す値
Resources 作成するAWSリソース
Outputs 作成したリソースの情報を出力
Conditions 条件によって作成内容を変更
Mappings 固定的な対応表を定義
Transform SAMなどの変換処理を指定

ResourcesがCloudFormationテンプレートの中心。

CloudFormationの組み込み関数

関数 役割
Ref パラメータやリソースの値を参照
Fn::GetAtt リソースの属性を取得
Fn::Sub 文字列に変数を埋め込む
Fn::Join 文字列を結合
Fn::ImportValue 別スタックのExport値を参照
Fn::If 条件によって値を切り替える

RefとGetAttの違い

Resources:
  MyBucket:
    Type: AWS::S3::Bucket

Outputs:
  BucketName:
    Value: !Ref MyBucket

  BucketArn:
    Value: !GetAtt MyBucket.Arn

この例では:

  • !Ref MyBucket → バケット名
  • !GetAtt MyBucket.Arn → バケットARN

ただし、Ref が返す値はリソース種別によって異なる。

「リソースのARNが必要」→ GetAttを確認。

Fn::Sub

BucketArn:
  Value: !Sub 'arn:aws:s3:::${MyBucket}'

文字列へ変数を埋め込む場合に利用する。

CloudFormationのスタック更新

CloudFormationでは、関連するAWSリソースをスタック(Stack) として管理する。

CloudFormation Template
          |
          v
        Stack
          |
          +-- Lambda
          +-- API Gateway
          +-- DynamoDB
          +-- IAM Role

テンプレートを変更し、スタックを更新することでリソース構成を変更できる。

ただし、更新方法はリソースやプロパティによって異なる。

更新方法 内容
中断なしの更新 リソースを置き換えずに更新
一時的な中断を伴う更新 更新中に影響が出る可能性がある
Replacement リソースを置き換える

テンプレートの変更が、必ず既存リソースのインプレース更新になるとは限らない。

Change Set

Change Setは、スタック更新前に変更内容を確認する仕組み。

テンプレート変更
       |
       v
Change Set作成
       |
       v
変更内容を確認
       |
       +-- Modify
       +-- Add
       +-- Remove
       |
       v
Change Set実行
       |
       v
スタック更新

例えば、更新によってRDSインスタンスが置き換えられる可能性がある場合、実行前に確認するために利用できる。

ただし、Change Setは実行結果を完全に保証するものではない。

Drift Detectionとの違い

機能 目的
Change Set これから適用する変更を確認
Drift Detection テンプレートと実際のリソース状態の差異を検出

「更新前の影響確認」→ Change Set。

「手動変更による構成差分を検出」→ Drift Detection。

CloudFormationのロールバック

スタックの作成・更新に失敗した場合、CloudFormationはロールバックを行う。

更新失敗時の例

UPDATE_IN_PROGRESS
        |
        v
リソース更新失敗
        |
        v
UPDATE_ROLLBACK_IN_PROGRESS
        |
        v
UPDATE_ROLLBACK_COMPLETE

重要なステータス

ステータス 意味
CREATE_COMPLETE 作成成功
UPDATE_COMPLETE 更新成功
ROLLBACK_COMPLETE 作成失敗後のロールバック完了
UPDATE_ROLLBACK_COMPLETE 更新失敗後のロールバック完了
UPDATE_ROLLBACK_FAILED 更新ロールバック自体が失敗

UPDATE_ROLLBACK_FAILED の場合は、原因を解消したうえで ContinueUpdateRollback を利用する場合がある。

作成失敗のROLLBACKと、更新失敗のUPDATE_ROLLBACKは区別する。

DeletionPolicyとUpdateReplacePolicy

CloudFormationでは、リソースを削除・置換する際の扱いを指定できる。

DeletionPolicy

Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    DeletionPolicy: Retain

Retain を指定すると、スタック削除時などにリソースを残せる。

UpdateReplacePolicy

Resources:
  MyDatabase:
    Type: AWS::RDS::DBInstance
    UpdateReplacePolicy: Snapshot

リソース置換時に、古いリソースをどう扱うか指定する。

属性 対象
DeletionPolicy スタック削除やテンプレートからの削除
UpdateReplacePolicy 更新によるリソース置換

代表的な指定値は Delete、Retain、対応リソースでの Snapshot。

「スタック削除後もデータを残したい」→ DeletionPolicy。

「置換される旧リソースを残したい」→ UpdateReplacePolicy。

CloudFormationのスタック間連携

複数のスタック間で値を共有する場合、Export と Fn::ImportValue を利用できる。

出力側

Outputs:
  SharedBucketName:
    Value: !Ref MyBucket
    Export:
      Name: SharedBucketName

参照側

Parameters:
  Dummy:
    Type: String
    Default: sample

Resources:
  ExampleParameter:
    Type: AWS::SSM::Parameter
    Properties:
      Type: String
      Name: /sample/bucket
      Value: !ImportValue SharedBucketName

ただし、クロススタック参照には制約がある。

  • 同じAWSアカウント・リージョン内で利用する
  • ImportされているExport値は自由に変更・削除できない

「別スタックの出力値を参照」→ Export / ImportValue。

CloudFormationのIAM権限

CloudFormationがIAMリソースを作成・変更する場合、デプロイ時に能力宣言が必要になることがある。

宣言 主な用途
CAPABILITY_IAM IAMリソースの作成・変更を承認
CAPABILITY_NAMED_IAM 明示的な名前を持つIAMリソースを含む場合
CAPABILITY_AUTO_EXPAND 特定のマクロ・変換を伴うテンプレートを直接実行する場合など

CloudFormationサービスロール

CloudFormationにサービスロールを指定すると、そのロールの権限でリソース操作を実行する。

デプロイ実行者
      |
      v
CloudFormation
      |
      | サービスロール
      v
Lambda / IAM / S3などを作成

デプロイ実行者の権限と、CloudFormationが実際に使用する権限は分けて考える。

AWS SAMとは

AWS SAM(Serverless Application Model)は、サーバーレスアプリケーションを簡潔に定義するためのフレームワーク。

Lambda、API Gateway、DynamoDBなどを組み合わせた構成を扱いやすい。

SAMテンプレートの書き方

SAMテンプレートでは、Transform が重要。

Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Runtime: python3.12
    Timeout: 10
    MemorySize: 256

Resources:
  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: app.lambda_handler
      Events:
        HelloApi:
          Type: Api
          Properties:
            Path: /hello
            Method: get

※AWS::Serverless-2016-10-31 は、AWSが定義したSAM Transformの固定識別子。任意の名前には変更できず、CloudFormationがSAM構文を変換するために使用する。

各項目の意味

項目 役割
Transform SAMテンプレートとして変換
Globals 複数リソースで共通する設定
CodeUri Lambdaコードの場所
Handler 実行する関数
Events Lambdaを起動するイベント

この例では、GET /hello に対応するLambda関数を定義している。

SAMのEventsとIAM Policies

SAMでは、Lambdaを起動するイベントをテンプレートで定義できる。

SQSイベントの例

Resources:
  WorkerFunction:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: python3.12
      Handler: app.lambda_handler
      CodeUri: worker/
      Events:
        QueueEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt WorkQueue.Arn
            BatchSize: 10

  WorkQueue:
    Type: AWS::SQS::Queue

SAMが必要なイベントソースマッピングなどのCloudFormationリソースを生成する。

ただし、イベントを定義しただけで、アプリケーションが必要とするすべてのIAM権限が自動付与されるわけではない。

Policies

SAMでは、Lambdaの実行ロールに対する権限を簡潔に指定できる。

Policies:
  - DynamoDBReadPolicy:
      TableName: !Ref OrdersTable

このようなポリシーテンプレートを利用すると、対象リソースに必要な権限を付与しやすい。

「SAMでLambdaのIAM権限を簡潔に定義」→ Policies / Policy Templates。

SAM CLIの基本コマンド

コマンド 用途
sam init SAMプロジェクト作成
sam build アプリケーションをビルド
sam validate SAMテンプレートを検証
sam local invoke Lambdaをローカルで実行
sam local start-api APIをローカルで起動
sam deploy AWSへデプロイ
sam sync 開発中の変更をAWSへ同期

基本的な開発フロー

sam init
   |
   v
コードを書く
   |
   v
sam build
   |
   v
sam local invoke
   |
   v
sam deploy
   |
   v
CloudFormation Stack

sam build

sam build

依存ライブラリなどを含めてビルドし、通常は .aws-sam/build に成果物を作成する。

sam local invoke

sam local invoke HelloFunction

Dockerを利用し、Lambdaに近い実行環境で関数をローカル実行する。

ただし、AWS上の実行環境を完全に再現するわけではない。

sam local start-api

sam local start-api

ローカルHTTPエンドポイントを起動し、API経由でLambdaをテストできる。

「Lambdaを単体でローカル実行」→ sam local invoke。

「API Gateway経由の処理をローカル確認」→ sam local start-api。

sam deployとsam sync

sam deploy

sam deploy --guided

初回デプロイでは --guided を利用すると、スタック名やリージョンなどを対話形式で設定できる。

設定は samconfig.toml に保存できる。

以降は次のように実行できる。

sam build
sam deploy

SAMは、必要な成果物をS3やECRへアップロードし、CloudFormationを通じてリソースをデプロイする。

sam sync

sam sync --watch

sam sync は、開発中の変更をAWS環境へ同期するためのコマンド。

--watch を指定すると、ファイル変更を監視して同期できる。

ローカルコードを変更
        |
        v
sam sync --watch
        |
        v
AWS開発環境へ反映

使い分け

要件 コマンド
正式なデプロイ sam deploy
ローカルでLambda実行 sam local invoke
ローカルAPIテスト sam local start-api
開発中の変更を迅速に反映 sam sync --watch

sam sync は開発環境での反復作業に適している。

本番デプロイでは、検証された成果物を使った管理されたデプロイを優先する。

SAMのデプロイ方式とCanary

SAMでは、Lambdaの段階的デプロイを定義できる。

AutoPublishAlias

Resources:
  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/
      Handler: app.lambda_handler
      Runtime: python3.12
      AutoPublishAlias: live
      DeploymentPreference:
        Type: Canary10Percent5Minutes

動作イメージ

Lambda Alias: live
        |
        +-- 旧Version 90%
        |
        +-- 新Version 10%
                 |
                 v
              5分後
                 |
                 v
           新Version 100%

SAMの DeploymentPreference は、Lambdaのバージョン・エイリアスとCodeDeployを利用した段階的デプロイを構成する。

主な方式

方式 特徴
Canary 一部のトラフィックを新バージョンへ流し、後で切り替える
Linear 一定間隔で段階的に増やす
AllAtOnce 一度に切り替える

「SAMでLambdaのCanaryデプロイ」→ AutoPublishAlias + DeploymentPreference。

CloudFormationのNested StackとStackSets

Nested Stack

Nested Stackは、CloudFormationスタックを別のスタックから呼び出す仕組み。

親Stack
   |
   +-- Network Stack
   |
   +-- Database Stack
   |
   +-- Application Stack

共通の構成を再利用したい場合に便利。

StackSets

StackSetsは、複数アカウント・複数リージョンへスタックを展開する仕組み。

StackSet
   |
   +-- Account A / 東京
   |
   +-- Account B / 東京
   |
   +-- Account C / 大阪
要件 選択
テンプレートを分割して再利用 Nested Stack
複数アカウント・リージョンへ展開 StackSets

CloudFormationのCustom Resource

CloudFormationの標準リソースでは対応できない処理を、Custom Resourceで実行できる。

例えば、スタック作成時に独自の初期化処理を行いたい場合。

CloudFormation Stack
        |
        v
Custom Resource
        |
        v
Lambdaなどで独自処理
        |
        v
CloudFormationへ結果を返す

重要なのは、Custom Resourceの処理結果をCloudFormationへ返す必要があること。

応答しないと、スタック操作がタイムアウトする原因になる。

また、作成・更新・削除それぞれのイベントに対応した実装が必要になる場合がある。

CloudFormationのDynamic Reference

CloudFormationでは、Secrets ManagerやParameter Storeの値を動的参照できる。

MasterUserPassword: '{{resolve:secretsmanager:my-db-secret:SecretString:password}}'

秘密情報をテンプレートに直接書かずに済む。

ただし、シークレットがローテーションされても、CloudFormationで作成したリソースの設定が自動更新されるわけではない。

さらに、スタック更新を実行しても、対象リソースが更新されなければ動的参照が再取得されない場合がある。

AWS CDKとは

AWS CDK(Cloud Development Kit)は、プログラミング言語でAWSインフラを定義するフレームワーク。

TypeScript、Python、Java、C#などの言語を利用できる。

CDKの構造

CDK App
   |
   +-- Stack
         |
         +-- Construct
         |
         +-- Construct
         |
         +-- Construct

Constructのレベル

レベル 特徴
L1 CloudFormationリソースに近い低レベル構成
L2 使いやすい抽象化と便利なデフォルト設定
L3 複数リソースを組み合わせた高レベルパターン

L1とL2の例

TypeScriptの例:

import * as s3 from 'aws-cdk-lib/aws-s3';

// L1 Construct
new s3.CfnBucket(this, 'RawBucket');

// L2 Construct
new s3.Bucket(this, 'AppBucket', {
  versioned: true
});

L1ではCloudFormationに近いプロパティを扱う。

L2では、CDKが提供する便利なAPIやデフォルト設定を利用できる。

「CloudFormationに近い細かな定義」→ L1。

「簡潔にリソースを定義」→ L2。

CDKの基本コマンド

コマンド 用途
cdk init CDKプロジェクト作成
cdk bootstrap CDKデプロイに必要な環境を準備
cdk synth CloudFormationテンプレート生成
cdk diff デプロイ前の変更差分を表示
cdk deploy スタックをデプロイ
cdk destroy スタックを削除

CDKのデプロイフロー

CDKコード
    |
    | cdk synth
    v
CloudFormationテンプレート
    |
    | cdk deploy
    v
CloudFormation Stack
    |
    v
AWSリソース

cdk bootstrap

cdk bootstrap

CDKのデプロイに必要なS3バケット、IAMロールなどの環境を準備する。

通常は対象のAWSアカウント・リージョンごとに実施する。

cdk synth

cdk synth

CDKコードからCloudFormationテンプレートを生成する。

AWSリソースをデプロイするコマンドではない。

cdk diff

cdk diff

現在デプロイされているスタックと、CDKコードから生成した構成との差分を確認する。

cdk deploy

cdk deploy

CloudFormationを利用してAWSリソースを作成・更新する。

CDKのTokenと環境依存値

CDKでは、デプロイ時まで確定しない値をTokenとして扱う。

例えば、作成予定のリソースのARNなど。

const bucket = new s3.Bucket(this, 'MyBucket');

console.log(bucket.bucketArn);

bucket.bucketArn は、CDKの実行時点では最終的な文字列として確定していない場合がある。

Tokenの注意点

  • CDKコード実行時に値が確定しているとは限らない
  • CloudFormationで解決される値がある
  • 通常の文字列と同じ感覚で加工すると問題になる場合がある

「CDKでARNがまだ確定していない」→ Token。

SAM・CloudFormation・CDKの使い分け

要件 選択
AWSリソースをYAMLで定義 CloudFormation
サーバーレスアプリを簡潔に定義 SAM
Lambdaをローカル実行 SAM CLI
APIをローカルテスト SAM CLI
プログラミング言語でインフラを定義 CDK
CloudFormationテンプレートを生成 cdk synth
更新前に変更を確認 Change Set / cdk diff
複数アカウントへ同じ構成を展開 StackSets
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?