CloudFormationテンプレート入門 - 基礎から実践まで
実務でAWS CloudFormationを使用する機会があったため、CloudFormationとは何か?どのように使うか?を調べてみました。
メモ・知識を整理がてら記載します。
ターゲット
CloudFormationの基本的な知識があり、これから構築しようとする方向け目次
- CloudFormationとは何か?
- テンプレートの基本構造
- 主要セクションの詳細解説
- 実際に動かしてみる
- よくあるエラーと解決方法
- ベストプラクティス
- CloudFormation Designer
- IaC ジェネレーター
- 躓きやすいポイント
CloudFormationとは何か?
AWS CloudFormationは、インフラストラクチャをコードとして管理する(Infrastructure as Code: IaC)ためのサービスです。従来の手動によるリソース作成とは異なり、JSON形式またはYAML形式のテンプレートファイルを使用して、AWS上のリソースを宣言的に定義・管理できます。
記載方法には、CloudFormationとSAMの2種類あります。SAM方式の方が記述量が少なく、比較的簡単に記載出来ますが、今回は基本的なCloudFormation形式で解説します。
CloudFormationの主な利点
コンソールで作成すれば、簡単に作れるものを、コード化するのは正直面倒…ですが、コード化して資産を管理すると様々なメリットがあります。
利点 | 説明 |
---|---|
再現性 | 同じテンプレートから何度でも同じ環境を構築可能 |
バージョン管理 | テンプレートをGitで管理し、変更履歴を追跡 |
自動化 | CI/CDパイプラインに組み込んでデプロイメントを自動化 |
依存関係管理 | リソース間の依存関係を自動的に解決 |
ロールバック機能 | デプロイに失敗した場合の自動復旧 |
テンプレートの基本構造
CloudFormationテンプレートは以下の主要セクションから構成されます:
AWSTemplateFormatVersion: '2010-09-09'
Description: 'テンプレートの説明'
Parameters:
# 実行時に指定するパラメータ
Mappings:
# 静的な値のマッピング
Conditions:
# 条件式の定義
Resources:
# 作成するAWSリソース(必須)
Outputs:
# 出力値の定義
AWSTemplateFormatVersion
テンプレートの形式バージョンを指定します。現在は'2010-09-09'
が最新版です。
Description
テンプレートの目的や内容を簡潔に説明します。
Parameters
スタック作成時にユーザーが指定できる値を定義します。CICDパイプラインなどを構成する場合など、環境ごとに異なる値(インスタンスタイプ、キーペア名など)を柔軟に設定することで、同じ伝プレートから異なる値でデプロイすることが出来ます。
主要セクションの詳細解説
Resources(必須セクション)
実際に作成するAWSリソースを定義する最も重要なセクションです。Lambda、EC2、S3など、作成するリソースは全てこちらに記載します。
Resources:
SampleVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: MyVPC
Outputs
作成されたリソースの情報を外部に出力します。他のスタックから参照したり、管理画面で確認したりできます。
Outputs:
VPCId:
Description: 'VPCのID'
Value: !Ref SampleVPC
Export:
Name: !Sub '${AWS::StackName}-VPC-ID'
Mappings
静的な値のマッピングテーブルを定義します。リージョンごとのAMI IDなど、条件に応じて値を切り替える場合に使用します。
Mappings:
RegionMap:
us-east-1:
AMI: ami-0abcdef1234567890
ap-northeast-1:
AMI: ami-0987654321abcdef0
実際に動かしてみる
例として、簡単にS3を作成するテンプレートを記載しました。実際に作成するときは、一から書くのではなく、Qiitaの記事から近いリソースを作っているテンプレートを探したり、AWS公式サイトのサンプルから、カスタマイズしていくのが早いと思います。
AWSTemplateFormatVersion: '2010-09-09'
Description: 'S3バケット作成'
Parameters:
BucketName:
Type: String
Description: 'S3バケット名'
Default: 'cloudformation-bucket'
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub '${BucketName}-${AWS::AccountId}'
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Outputs:
BucketName:
Description: '作成されたS3バケット名'
Value: !Ref MyS3Bucket
BucketArn:
Description: 'S3バケットのARN'
Value: !GetAtt MyS3Bucket.Arn
デプロイの前に構文チェック!
テンプレートの記述によって作成されるものの、最初は正しく書けているのか不安だと思います。
デプロイのエラーで一番多いのがValidation Errorです。
デプロイ→失敗→エラーメッセージを元に修正→デプロイ→失敗の繰り返しを行わないためにも、事前に構文や記載のチェックを行うことを推奨します。
(私はこれを知らなかったため、デプロイしてみないと何が悪いかわからないという非常に非効率な状態でした)
- テンプレートの検証
- AWS CLIにてテンプレートの検証
-
aws cloudformation validate-template --template "自身のテンプレートファイルへのパス"
コマンド
-
- CloudFormation Linterツールで文法・記載のチェック
-
aws cloudformation validate-template --template "自身のテンプレートファイルへのパス" --lint
コマンド
-
- AWS CLIにてテンプレートの検証
- IDEのYAML拡張機能でリアルタイム検証
デプロイ手順
コンソールから実施する場合
- AWS CLIまたはマネジメントコンソールからスタックを作成
- テンプレートファイルをアップロード
- パラメータを入力
- スタック作成を実行
CLIで実施する場合
- AWS CLIまたはマネジメントコンソールからスタックを作成
- テンプレートファイルをアップロード
- パラメータを入力
- スタック作成を実行
初回実行時は、S3バケット名がグローバルでユニークである必要があるため、${AWS::AccountId}
を含めています。アカウントIDやリージョンなどは、${AWS::AccountId}
、${AWS::Region}
と記載することで取得することが出来ます。
よくあるエラーと解決方法
Rollback時の対処法
リソース作成に失敗すると、CloudFormationは自動的にロールバックを実行します。
対処手順:
- CloudFormationコンソールでエラー詳細を確認
- 失敗したリソースの設定を修正
- スタックを削除してから再作成、またはChangeSetを使用して更新
権限不足エラー
IAMロールや権限設定の不備で発生します。
解決方法:
- 必要な権限をIAMロール/ユーザーに付与
- CloudFormation実行用の専用ロールを作成
- 最小権限の原則に従って権限を設定
ベストプラクティス
命名規則
一貫した命名規則を採用することで、リソースの管理が容易になります。
# 推奨パターン
Resources:
WebServerInstance: # PascalCase
Type: AWS::EC2::Instance
Properties:
Tags:
- Key: Name
Value: !Sub '${Environment}-WebServer-${AWS::StackName}'
タグ付け
すべてのリソースに適切なタグを設定し、コスト管理や運用を効率化します。
Parameters:
Environment:
Type: String
AllowedValues: [prod, staging, dev]
Resources:
MyResource:
Type: AWS::EC2::Instance
Properties:
Tags:
- Key: Environment
Value: !Ref Environment
- Key: Project
Value: MyProject
- Key: Owner
Value: TeamA
テンプレート分割の考え方
大規模なインフラでは、テンプレートを論理的な単位に分割します。
基本的には、なるべくテンプレート間の依存関係が増えないよう関連のあるリソースは同じテンプレートでの記載が良いと思います。
レイヤー | 含まれるリソース |
---|---|
ネットワーク層 | VPC、サブネット、ルートテーブル |
セキュリティ層 | セキュリティグループ、IAMロール |
アプリケーション層 | EC2、RDS、ALB |
監視層 | CloudWatch、SNS |
Cross-Stack Reference
分割したテンプレート間でリソースを参照するには、Outputsで作成したリソースをエクスポートし、別のテンプレートにてImportします。
# ネットワークスタックのOutputs
Outputs:
VPCId:
Value: !Ref MyVPC
Export:
Name: !Sub '${AWS::StackName}-VPC-ID'
# アプリケーションスタックでの参照
Resources:
WebServer:
Type: AWS::EC2::Instance
Properties:
VpcId: !ImportValue NetworkStack-VPC-ID
Tips1:CloudFormation Designerの活用
CloudFormation Designerは、テンプレートを視覚的に編集できるWebベースのツールです。
効果的な使い方
用途 | 説明 |
---|---|
初期設計 | 新しいテンプレートの構造を視覚的に設計 |
依存関係の確認 | リソース間の関係を図で確認 |
複雑なテンプレートの理解 | 既存テンプレートの構造を把握 |
プレゼンテーション | アーキテクチャ図として活用 |
Designer使用時の注意点
- Designerで生成されるテンプレートは読みにくい場合があるため、手動で整理
- 複雑な条件分岐やマッピングはDesignerでは表現困難
- 最終的にはテキストエディタでの編集が必要
Tips2:IaC ジェネレーターの活用
IaC ジェネレーターは、既に手動で作成したリソースをテンプレート化してくれるサービスです。
コンソール上から作成・テストなどを行った後に、テンプレート化を行えば、作成の手間を大幅に削減することが出来ます。
また、指定したリソースに関連する別のリソースもテンプレートに含めるかどうか提案してくれるため、関連するIAMなどもまとめて作成できます。
Designer使用時の注意点
- IaCジェネレーターが使用できるリソースは限られている
- SAMでの記述は出来ず、CloudFormation方式での記述のみ
躓きやすいポイント
私がよく引っかかったエラーなどをまとめます。
YAMLのインデントエラー(スペース2つが基本)
YAMLはインデントに厳格です。必ずスペース2つでインデントし、タブ文字は使用しません。
このあたりの文法・記述方法はデプロイ前に必ずlintツールでチェックしましょう。
# 正しい例
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
# 間違った例(インデントが不正)
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
リソースの依存関係(DependsOnの適切な使用)
CloudFormationは自動的に依存関係を解決しますが、明示的な指定が必要な場合があります。
例えば、同じテンプレートでLambdaとRoleとPolicyを作っていた場合、記述の順序にもよりますが、明示的にPolicy→Role→Lambdaという依存関係を記載する必要がある場合があります。
Resources:
MyVPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/16
MyInternetGateway:
Type: AWS::EC2::InternetGateway
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref MyVPC
InternetGatewayId: !Ref MyInternetGateway
# インターネットゲートウェイの接続完了後にルートテーブルを作成
PublicRouteTable:
Type: AWS::EC2::RouteTable
DependsOn: AttachGateway # 明示的な依存関係
Properties:
VpcId: !Ref MyVPC
パラメータの大文字小文字区別
CloudFormationのパラメータ名や関数は大文字小文字を区別します。
デバッグ用Outputsを常に設定
テンプレート開発時は、デバッグ用のOutputsを設定することを強く推奨します。
Outputs:
# 基本情報
StackName:
Description: 'スタック名'
Value: !Ref AWS::StackName
StackId:
Description: 'スタックID'
Value: !Ref AWS::StackId
# 作成されたリソースの詳細
VPCId:
Description: 'VPC ID'
Value: !Ref MyVPC
VPCCidr:
Description: 'VPC CIDR Block'
Value: !GetAtt MyVPC.CidrBlock
# デバッグ用
AllParameters:
Condition: IsDebugMode
Description: 'デバッグ用 - 全パラメータ'
Value: !Sub |
Environment: ${Environment}
InstanceType: ${InstanceType}
KeyPairName: ${KeyPairName}
デバッグ条件の設定
Parameters:
DebugMode:
Type: String
Default: 'false'
AllowedValues: ['true', 'false']
Conditions:
IsDebugMode: !Equals [!Ref DebugMode, 'true']
本番環境には、デバッグ用のOutputs記述は削除または無効化するようにしてください
まとめ
CloudFormationの基本的な使い方・私が詰まってしまったポイントについて解説しました。
一気に書き進めるのではなく、小さいところから記載・確認をしていきながら作成していくのがおすすめです。
タグ
#AWS
#CloudFormation
#IaC
#YAML
#インフラ
#自動化
#DevOps
#初心者向け
** 参考リンク**