1. はじめに
AWSでインフラ構築をしていると、以下のような課題が出てきます。
- コンソールでポチポチ作っていたら、本番と検証環境の設定が微妙に違っていた
- 手作業だと、各種設定のルール漏れ・ミスが怖い
こうした課題を解決してくれるのが、CloudFormationです。
本記事では、
- CloudFormationとは何か
- テンプレートの構造(各セクションの役割と具体例)
- よく使う組み込み関数
- 実際にどうやってデプロイするのか
を、YAML例を交えながら解説します。
2. CloudFormation とは
CloudFormation は、テンプレート(設定ファイル)をもとに AWS リソースを自動で構築するサービス です。
イメージとしては、次のような流れになります。
テンプレート(YAML/JSON で書かれた設計書)
↓
CloudFormation(設計書を読み込むサービス)
↓
Stack(スタック)
↓
VPC / Subnet / S3 / RDS などの AWS リソースが自動作成
- テンプレート:インフラの設計書
- CloudFormation:設計書を読み取り実際に構築を行う「施工担当」
- スタック:その設計書から作られたリソース一式のまとまり
一度テンプレートを作成しておけば、同じ構成を何度でも再現できる点が大きな利点だと感じています。
3. CloudFormationを使うメリット
✅ IaC(Infrastructure as Code)の実現
手作業でコンソールからリソースを作成していると、次のような問題が発生しがちです。
- 本番と検証環境の設定が微妙に異なる
- 設定手順が属人化し、引き継ぎが困難になる
- セキュリティグループや IAM の設定ミスが発生する
CloudFormation でテンプレート化しておくと、次のようなメリットがあります。
- Git などでバージョン管理できる
- 差分(どこを変更したか)が履歴として残る
- dev / stg / prd など複数環境を同じ構成で構築できる
✅ 環境の統制・管理がしやすい
- 「本番だけこのリソースを作る」などを
Conditionsで制御できる - どのリソースがそのスタックで管理されているかが一覧で分かる
✅ CDK・SAMの基礎になる
-
AWS CDKやAWS SAMは、最終的には CloudFormationテンプレートを生成してデプロイしている - CloudFormationの構造を知っておくと、「CDKが裏側で何をやっているか」が理解しやすい
4. CloudFormation による構築作業の流れ
CloudFormation を用いた構築の流れは次のとおりです。
① テンプレートを作成する(YAML/JSON)
② CloudFormation でスタックを作成する
③ 変更があればテンプレートを修正し、スタックを更新する
④ 不要になった場合はスタックを削除する(関連リソースもまとめて削除)
以降の章では、このうち特に重要な「① テンプレート」の内容について詳しく見ていきます。
5. YAMLの基礎
CloudFormation のテンプレートはYAMLまたはJSONで記述できますが、実務では可読性の高いYAMLが利用されることが多いです。
YAML のイメージを掴むために、簡単な例を示します。
# キャラクター情報
character:
name: Jotaro
level: 20
skills:
- oraora
- star_platinum
isHero: true
この例から分かるポイントは次のとおりです。
- key: value の形式で記述する
- インデントにより階層構造を表現する
-
-から始まる行は配列を表す -
#コメントを記述できる
CloudFormation のテンプレートも、この YAML の表現の上に成り立っています。
6. テンプレート全体像の例
テンプレート全体のイメージを掴むために、少しだけ実務寄りの例を示します。
ここでは、ログ用 S3 バケットと、本番環境のときだけ SNS トピックを作成するテンプレートとします。
なお、この例に登場する各セクションについて、次章で順に解説します。
AWSTemplateFormatVersion: 2010-09-09
Description: "ログ用 S3 バケットと、本番専用のアラート用 SNS トピックを作成するテンプレート"
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "環境設定"
Parameters:
- EnvName
- LogBucketName
ParameterLabels:
EnvName:
default: "dev / stg / prd"
LogBucketName:
default: "ログ S3 バケット名"
Parameters:
EnvName:
Type: String
Default: dev
AllowedValues:
- dev
- stg
- prd
LogBucketName:
Type: String
Default: myapp-logs
Mappings:
RegionMap:
ap-northeast-1:
Suffix: tokyo
us-east-1:
Suffix: virginia
Conditions:
IsProd: !Equals [ !Ref EnvName, "prd" ]
Resources:
LogsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${LogBucketName}-${EnvName}-${AWS::Region}"
VersioningConfiguration:
Status: Enabled
ProdAlertTopic:
Type: AWS::SNS::Topic
Condition: IsProd
Properties:
TopicName: !Sub "myapp-${EnvName}-alerts"
Outputs:
LogsBucketName:
Description: "作成されたログバケット名"
Value: !Ref LogsBucket
ProdAlertTopicArn:
Condition: IsProd
Description: "本番用アラート用 SNS トピックの ARN"
Value: !Ref ProdAlertTopic
7. テンプレートの主要セクション解説
CloudFormation テンプレートに登場する主なセクションは次のとおりです。
-
AWSTemplateFormatVersion(任意) -
Description(任意) -
Metadata(任意) -
Parameters(任意) -
Mappings(任意) -
Conditions(任意) -
Resources(必須) -
Outputs(任意)
必須なのはResourcesのみですが、実務では他のセクションも併用されることがほとんどです。
7-1. AWSTemplateFormatVersion(任意)
テンプレートのフォーマットバージョンを示す項目です。
現時点では "2010-09-09" のみが利用されており、省略しても動作には影響しません。
AWSTemplateFormatVersion: "2010-09-09"
※ 将来の互換性を考慮すると記載するのが推奨とされている
7-2. Description(任意)
スタック全体の説明文です。
CloudFormation コンソールの「スタックの詳細」画面などで表示されます。
Description: "ログ用 S3 バケットと SNS トピックを作成するテンプレート"
7-3. Metadata(任意)
Metadata には、CloudFormation 自体やツール向けのメタ情報を記述します。
代表的な利用例がAWS::CloudFormation::Interfaceです。
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: "環境設定"
Parameters:
- EnvName
- LogBucketName
ParameterLabels:
EnvName:
default: "環境名(dev / stg / prd)"
LogBucketName:
default: "ログ S3 バケット名"
-
ParameterGroups:
パラメータをグループ化し、「環境設定」「ネットワーク設定」といったまとまりで表示するために使用 -
ParameterLabels:
個々のパラメータに対して、ユーザーに表示するラベル名を定義
パラメータ数が多いテンプレートでは、このようにグルーピングしておくと、運用者が入力内容を理解しやすくなります。
7-4. Parameters(任意)
Parametersは、外部からテンプレートに値を渡すための入口です。
Parameters:
EnvName:
Type: String
Default: dev
AllowedValues:
- dev
- stg
- prd
LogBucketName:
Type: String
Default: myapp-logs
-
Type:
String、Number、List<String>のほか、AWS::EC2::VPC::IdのようなAWS固有の型も指定可能 -
Default:
パラメータが未入力の場合に使用されるデフォルト値 -
AllowedValues:
許容される値を列挙でき、環境名や種別が限定されている場合に有効 -
AllowedPattern:
正規表現により入力値のパターンを制限できる
7-5. Mappings(任意)
Mappingsは、条件に応じて値を切り替えるための「表」のような役割を持ちます。
Mappings:
RegionMap:
ap-northeast-1:
Suffix: tokyo
us-east-1:
Suffix: virginia
!FindInMap関数と組み合わせて利用します。
リージョンごとに異なる設定値(サフィックスなど)をマッピングする用途で利用されることが多いです。
BucketSuffix: !FindInMap [RegionMap, !Ref "AWS::Region", Suffix]
7-6. Conditions(任意)
Conditionsでは、真偽値(true / false)を返す条件式を定義します。
Conditions:
IsProd: !Equals [ !Ref EnvName, "prd" ]
定義した条件は、リソースやOutputsに対してConditionプロパティとして関連付けます。
Resources:
ProdAlertTopic:
Type: AWS::SNS::Topic
Condition: IsProd
Properties:
TopicName: !Sub "myapp-${EnvName}-alerts"
この例では、EnvNameがprdのときのみSNSトピックが作成されます。
1 つのテンプレートを dev / stg / prd 共通で利用しつつ、「本番環境のみ存在するリソース」を制御したい場合などに有効です。
7-7.Resources(必須)
Resourcesは、CloudFormation テンプレートにおける中核であり、唯一の必須セクションです。ここに実際に作成したい AWSリソースを定義します。
Resources:
LogsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "${LogBucketName}-${EnvName}-${AWS::Region}"
VersioningConfiguration:
Status: Enabled
-
LogsBucket:
論理IDであり、このテンプレート内で一意である必要がある -
Type:
リソースの種類(例:AWS::S3::Bucket、AWS::EC2::Instanceなど)を表す -
Properties:
リソース固有の設定を記述する(バケット名、バージョニング設定等)
7-8. Outputs(任意)
Outputsには、スタック作成後に参照したい値を定義します。
Outputs:
LogsBucketName:
Description: "作成されたログバケット名"
Value: !Ref LogsBucket
ProdAlertTopicArn:
Condition: IsProd
Description: "本番用アラート用 SNS トピックの ARN"
Value: !Ref ProdAlertTopic
利用用途としては次のようなものがあります。
- コンソール上で確認したい情報(ALBのDNS名、S3バケット名など)を見やすくする
- Exportと組み合わせて、別スタックから
!ImportValueで参照する
スタック間でVPC IDやSubnet IDを共有するような構成では、Outputs / Export / ImportValue の組み合わせがよく利用されます。
8. 組み込み関数の基礎
CloudFormation には多くの組み込み関数があります。本章では頻出の組み込み関数のみ、短縮形で紹介します。
8-1. !Ref
パラメータやリソースを参照するための関数です。
Value: !Ref LogsBucket
- パラメータの場合:入力された値を返す
- リソースの場合:そのリソースの「代表値」(S3 であればバケット名、SNS であれば ARN など)を返す
- どの値が返るかはリソースタイプごとに異なるため、必要に応じて公式ドキュメントを確認する必要があります。
8-2. !Sub
文字列中で${}を用いて埋め込み展開を行うための関数です。
BucketName: !Sub "${LogBucketName}-${EnvName}-${AWS::Region}"
-
!Refと異なり、「文字列の一部として値を埋め込みたい」場合に利用します。 - 複数の値を連結して識別子を生成したいケースで頻繁に利用されます。
8-3. !GetAtt
リソースの属性(Attribute)を取得する関数です。
RoleArn: !GetAtt MyRole.Arn
- どの属性が取得可能かはリソースタイプごとに異なるため、必要に応じて公式ドキュメントを確認する必要があります。
- 例:
IAM RoleであればArn,VPCであればCidrBlockなど。
8-4. !FindInMap
Mappingsセクションで定義した値を取得するための関数です。
!FindInMap [RegionMap, !Ref "AWS::Region", Suffix]
- リージョンごとに異なる
AMI IDやサフィックス、接頭辞などを切り替えたい場面で利用されます。
8-5. !ImportValue
他のスタックのOutputsでExportされた値を参照するための関数です。
SubnetId: !ImportValue "my-vpc-public-subnet-1a"
8-6. !Equals(Conditionsセクションで利用)
Conditions セクションの中などで、値の等価比較を行う関数です。
IsProd: !Equals [ !Ref EnvName, "prd" ]
8-7. DependsOnによる依存関係の明示
CloudFormation は、!Refや!GetAttによる参照をもとに依存関係を自動的に解決してくれますが、参照を用いない依存関係が存在する場合にはDependsOnを使用して明示します。
Resources:
AttachGateway:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref Vpc
InternetGatewayId: !Ref Igw
PublicRoute:
Type: AWS::EC2::Route
DependsOn: AttachGateway
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref Igw
この例では、IGWのアタッチが完了してからルートを作成してほしいため、PublicRouteにDependsOn: AttachGatewayを指定しています。
9. 効率的なテンプレート作成のコツ
9-1. 既存テンプレートの活用
- 過去に自分またはチームで作成したテンプレート
- AWS 公式サンプル
- GitHub 上の公開リポジトリ
これらを参考にしながら、自身の要件に合わせて少しずつカスタマイズしていく方法が効率的です。
9-2. 生成AIの活用
- ChatGPT
- Amazon Q Developer
これら用いて、「VPC+パブリックサブネット+ ALB のテンプレートを生成する」といった使い方をすると、たたき台を短時間で用意できます。
その上で、最終的な内容については公式ドキュメントを見ながら調整する必要があります。
9-3. VS Code / Linter の利用
-
cfn-lint(CloudFormation Linter)- プロパティ名の誤り
- 必須パラメータの不足
- サポートされていない組み合わせ
などを検出できます。
テンプレートの規模が大きくなるほど、Linterによる事前チェックの効果は大きくなります。
10. AWS コンソールからのデプロイ手順
最後に、作成したテンプレートを AWS コンソールからデプロイする手順を整理します。
- AWS コンソールで「CloudFormation」を開く
- 「スタックの作成」→「新しいリソースを使用」を選択
- 「テンプレートの指定」で「テンプレートファイルのアップロード」を選択し、ローカルの
template.yamlをアップロード - スタック名(例:
myapp-logs-stack)を入力する - Parameters が定義されている場合、
EnvNameなど必要な値を入力する - 必要に応じてタグやロールなどを設定し、「次へ」を押下
- 最終確認画面で内容を確認し、「送信」を押下
- スタックのステータスが
CREATE_COMPLETEになれば作成完了
その後、CloudFormationのスタック詳細画面や、各サービス(S3、SNS 等)のコンソールから、実際にリソースが作成されていることを確認できます。
おわりに
本記事では、CloudFormation の基礎として、以下の内容を整理しました。
- CloudFormation が担う役割
- テンプレートの主要セクション(
AWSTemplateFormatVersion/Description/Metadata/Parameters/Mappings/Conditions/Resources/Outputs) - よく利用される組み込み関数(
!Ref/!Sub/!GetAtt/!FindInMap/!ImportValue/!Equals/DependsOn) - コンソールからのデプロイ手順
CloudFormation は、最初は記述量や概念が多く、取っつきにくく感じられる部分もありますが、一度テンプレートベースで環境を構築できるようになると、環境の再構築や変更管理が格段に行いやすくなると思っています。
本記事の内容が、これから CloudFormation を学習される方や、すでに触れているもののテンプレート構造を改めて整理したい方の一助となれば幸いです。
