- 0. 参考記事
- 1. 解説動画
- 2. 概要
- CFnとTerraform
- なぜコード化するのか?
- JSONとYAML
- 公式URL
- 3. CFnテンプレート解説
- テンプレート全体の構造
- Parametersの定義例・YAMLの読み方
- Resourcesの定義例・公式ドキュメントの読み方
- テンプレートで使えるCFn組み込み関数 ①Ref
- テンプレートで使えるCFn組み込み関数 ②GetAtt
- テンプレートで使えるCFn組み込み関数 ③Sub
- テンプレートで使えるCFn組み込み関数 ④Equals と Conditionsの定義例
- テンプレートで使えるCFn組み込み関数 ⑤If
- テンプレートで使えるCFn組み込み関数 ⑥FindInMap と Mappingsの定義例
- テンプレートで使えるCFn組み込み関数 ⑦ImportValue と Outputsの定義例
- 4. CFnスタックの操作
- スタック作成 (Create Stack)
- スタック更新 (Update Stack)
- スタック削除 (Delete Stack)
- 5. 最後にお願い
- 6. FAQ(随時追加)
CloudFormation(以下 CFn)について解説いたします!
0. 参考記事
私の解説より分かりやすい投稿がありましたので、まず
をご覧ください。組み込み関数については
- 【AWS初学者向け・図解】CloudFormationの組み込み関数を現役エンジニアがわかりやすく解説①
- 【AWS初学者向け・図解】CloudFormationの組み込み関数を現役エンジニアがわかりやすく解説②
にも詳しくまとめられていましたので、あわせてご覧ください。
1. 解説動画
※動画の画質が悪い場合は、歯車から1080pの画質を選択ください
2. 概要
CFnとTerraform
CFnはJSON形式かYAML形式で記述した定義通りにリソースを作れる、AWS公式のサービスです。最近流行りの「インフラのコード化(Infrastructure as Code=IaC)」の一種です。同じくIaCのサービスにTerraformがあります。こちらはオープンソース(OSS)で、AWSに限らず複数のクラウドに対応しています。
CFnはAWS公式なのでサポートが期待でき、コードがずっと変わっていない安定感があります。裏を返せば、AWSにベンダーロックイン(https://e-words.jp/w/ロックイン.html)されるのが欠点です。以前は手で作ったリソースをコード管理できませんでしたが、インポート可能になる(https://dev.classmethod.jp/articles/cloudformation-import-existing-resources/)など、進化も続けています。
一方でTerraformはネットの情報も多く、GitHubのコミュニティ活動は活発です。HCL(HashiCorp Configuration Language)と呼ばれる独自の宣言型言語で記述し、バージョンによって書き方が変わってしまうのが欠点です。
結果、AWSしか使わないならCFn、複数のクラウドを使ったりオープンソースを好む場合はTerraformを選択するのが良いでしょう。ここではAWSをより深く理解するためにCFnで学習していきます。
またCFnはYAML形式を採用しているので誰が書いても変わらない(=認知負担がかからない)というメリットもあります。一方でTerraformは書き方が人によって異なったり、CDKはオブジェクト指向を理解していないと謎のクラスが登場したりして、さらに認知負担がかかるのが欠点です。
さらに詳しく知りたい方は、IaCのCloudFormation/AWS CDK/Terraform/Pulumiを比較した技術書 比べてわかる!IaCの選びかた 〜クラウドネイティブIaCストーリー〜 - アライとウマカツの本屋さん - BOOTH が良かったのでご参考まで。
なぜコード化するのか?
コード化のメリットを挙げておきます。
- インフラ構築・変更時のオペミス(操作ミス)が減らせる=設定ミス、設定漏れ、コピペミスなどがなくなる
- コードをGitで管理することで、インフラ構築・変更内容を複数人でのレビューし合える。その差分(変更点)をバージョン管理できるので、いつでも過去の変更を振り返ることができる
- 設定値の管理表が不要になる
- 本番(prod)・検証(stg)・開発(dev)環境のテンプレートを共通化することで、複数環境をすぐに作れる
- 新規サービスで同様のインフラ構築が必要になっても、テンプレのコピペと微調整ですぐ作れる
- 組織内でインフラ構築のノウハウを共有・継承できる。
同時にコード化のデメリットも挙げておきます。
- コードに習熟するための学習コストがかかる
- ゼロからテンプレートを作る際に時間がかかる
- 変更も全てコードで行わないと整合性が取れなくなるので注意が必要
- 最初のテンプレ設計を慎重に・熟慮して行わないと、後で設計を変更するコストが高くなる
JSONとYAML
JSON(JavaScript Object Notation)も、YAML(YAML Ain't Markup Language)も、データを記述するための言語・形式で、相互に変換可能です。
https://www.json.org/json-ja.html と https://yaml.org/ が公式サイトです。
Linuxでは jq
コマンドや yq
コマンドを使うと整形や変換ができます。
以下、同じ内容をJSONとYAMLと書いた場合のサンプルです。⑤EC2・IAM Roleで出てくる AmazonSSMGetParametersPolicy
より。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters"
],
"Resource": "*"
}
]
}
{"Version":"2012-10-17", "Statement":[{"Effect":"Allow", "Action":["ssm:GetParameter", "ssm:GetParameters"], "Resource":"*"}]}
## Comment OK
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- ssm:GetParameter
- ssm:GetParameters
Resource: '*'
AWS内ではJSONで書かれることが多く、上記のように改行や空白はあってもなくても同じです。一方でYAMLの方はインデント(段下げ)や改行に意味がありますので、見やすくて書きやすいです。JSONと違ってコメントも書けます。そのためCFnのテンプレはYAMLで書いています。
YAMLについて勉強したい場合は https://magazine.rubyist.net/articles/0009/0009-YAML.html が分かりやすいので、ご参考まで。
公式URL
CloudFormation
- Docs: AWS CloudFormation とは - AWS CloudFormation
- CFn: AWS リソースおよびプロパティタイプのリファレンス - AWS CloudFormation
- CLI: cloudformation — AWS CLI v2 Command Reference
3. CFnテンプレート解説
④VPCのCFnテンプレートなどから抜粋して、YAMLとCFnを解説します。以下##
のコメントが解説文です。
テンプレート全体の構造
## "#" はコメント
## "---" はYAMLの区切り線
---
## マッピング設定。使い方は後述
Mappings:
## CFnスタックを作成する際に値を指定するためのParameters
## CFn管理画面でもParametersのタブがありますのでご確認ください
Parameters:
## Parameterの順番を定義するもので、それほど重要ではない
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
## テンプレートの中で使うConditions(条件)
## 条件によってリソースを作る/作らないの切替、値の切替などができる
Conditions:
## 一番重要なResources
## このテンプレで作るリソースを定義していきます
## CFn管理画面でもResourcesのタブがありますのでご確認ください
Resources:
## 作ったリソースの情報をOutputs(出力)できる
## CFn管理画面でもOutputsのタブがありますのでご確認ください
## 別テンプレートでImportValueして参照することができます
## 使い方は後述
Outputs:
Parametersの定義例・YAMLの読み方
## Parametesとして、SystemNameとEnvironmentとCreateSubnetProtectedが定義されている
Parameters:
## SystemNameとして、DescriptionとTypeとDefaultが定義されている
SystemName:
## Descriptionの値は "System Name"
Description: System Name
## Typeの値は "String"(文字列)
Type: String
## Defaultの値は "awsmaster"
Default: awsmaster
Environment:
Description: Environment
Type: String
Default: prod
## AllowedValues(指定可能な値)は複数ある
## "-" で縦に並べた項目はlist(配列)。同じ種類の値が並んでいる
AllowedValues:
- prod
- stg
- dev
CreateSubnetProtected:
Description: Create Protected Subnet
Type: String
Default: true
AllowedValues:
- true
- false
CidrBits:
Description: Subnet bits for the CIDR. For example, specifying a value "8" for this parameter will create a CIDR with a mask of "/24".
Type: Number
Default: 8
MinValue: 4
MaxValue: 16
Resourcesの定義例・公式ドキュメントの読み方
## EC2::VPC でググる。docs.aws.amazon.com が公式ドキュメント。たいてい一番上 *1
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.0.0.0/19
EnableDnsHostnames: true
EnableDnsSupport: true
InstanceTenancy: default
Tags:
- Key: Name
Value: awsmaster-prod-vpc
*1 EC2::VPC https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html
↓抜粋
①構文(Syntax) → 全体の構成
②プロパティ(Properties) → 必須のプロパティは書く。任意のは書かないとAWSが決めたデフォルト値に
> CidrBlock
> VPCのIPv4ネットワーク範囲をCIDR表記で指定します。
> (The IPv4 network range for the VPC, in CIDR notation.)
> 必須: 条件付き (Required: Conditional)
> タイプ: 文字列 (Type: String)
> Update requires: Replacement
↑このように説明が書いてある
「必須: 条件付き」はテンプレートに必須かどうか、条件を確認する必要がある
「タイプ」は取り得る値の種類
「Update requires: Replacement」は更新(Update)する場合は
作り直し(Replacement)になるという意味
> Tags
> VPC のタグ (The tags for the VPC.)
> 必須: いいえ (Required: No)
> タイプ: Tag の配列 (Type: Array of Tag)
> Update requires: No interruption
↑このように「タイプ: ○○の配列」という場合は "-" で複数並べる
今回はTagがリンク *2 になっているのでクリックすると
KeyとValueを定義しないといけないことが分かる
③戻り値(Return values) → Ref関数(参照番号)やGetAtt関数で返される値の説明
!Ref VPC は VPC ID が返されることが分かる
④例(Examples) → 書き方のサンプル。必ずあるわけではない
テンプレートで使えるCFn組み込み関数 ①Ref
## ①Ref関数。Parameterの値やResourceの戻り値を返す *1
Ref: SystemName
!Ref SystemName
## ↑どちらも同じ意味(以後同様)テンプレでは下の短縮形を多用している
## SystemNameは前述のParametersで定義済みなので、
## どちらも "awsmaster" という文字列に置換される
Ref: VPC
!Ref VPC
## ↑今度はResourcesで作ったVPCを参照している
## VPCの戻り値はVPC IDなので、どちらも "vpc-*************"
## というVPC IDに置換される(戻り値の詳細は後述)*2
Ref: AWS::AccountId
!Ref AWS::AccountId
## ↑疑似パラメータ参照 *3
## CFnで事前に定義されたパラメータを参照できる
## 例えば上記はどちらもAWSアカウントIDに置換される
*2 EC2::VPCの戻り値 https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html#aws-resource-ec2-vpc-return-values
*3 疑似パラメータ参照 https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/pseudo-parameter-reference.html
テンプレートで使えるCFn組み込み関数 ②GetAtt
## ②GetAtt関数。リソースの属性値を返す。リソースごとに変わるので注意 *1
Resources:
VPC:
Type: AWS::EC2::VPC
## ↑VPCという名前でVPCのリソースを作ったとすると、Ref関数とGetAtt関数の違いは次の通り
!Ref VPC
!GetAtt VPC.DefaultSecurityGroup
## ↑EC2::VPC でググって、戻り値(Return values)に説明がある *2
## !Ref VPC は(VPC ID)の値を返す
## !GetAtt VPC.DefaultSecurityGroup は(VPCのデフォルトのセキュリティグループID)の値を返す
## !GetAtt の代わりに Fn::GetAtt という書き方もある
*2 EC2::VPCの戻り値 https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html#aws-resource-ec2-vpc-return-values
テンプレートで使えるCFn組み込み関数 ③Sub
## ③Sub関数。Ref関数と同じくParameterやResourceの戻り値に置換される *1
## Refと違って複数まとめて置換できる
Fn::Sub: ${SystemName}-${Environment}-vpc
!Sub ${SystemName}-${Environment}-vpc
## ↑SystemNameとEnvironmentは前述のParametersで定義済みなので
## どちらも "awsmaster-prod-vpc" という文字列になる
## !Sub の代わりに Fn::Sub という書き方もある
ServiceName: Fn::Sub: com.amazonaws.${AWS::Region}.dynamodb
ServiceName: !Sub com.amazonaws.${AWS::Region}.dynamodb
## ↑疑似パラメータ参照も同様。Regionをap-northeast-1とすると
## ServiceName: com.amazonaws.ap-northeast-1.dynamodb となる
Resource: !Sub ${S3BucketStaticContents.Arn}/*
## ↑GetAtt関数の代わりにSub関数も使えます。
## Resource: arn:aws:s3:::awsmaster-prod-cloudfront-staticcontents/* となる(一例)
テンプレートで使えるCFn組み込み関数 ④Equals と Conditionsの定義例
## ④Equals関数。2つの値が等しいか比較できる。Conditions(条件)で使う *1
## Excelの関数で言えば =AND(A1=B1) と同じ感覚
Conditions:
ShouldCreateSubnetProtected: !Equals [ !Ref CreateSubnetProtected, true ]
## ↑(右)CreateSubnetProtectedの値が true なら
## (左)ShouldCreateSubnetProtectedの値も true
## !Equals の代わりに Fn::Equals: という書き方もある
Resources:
SubnetProtectedA:
Condition: ShouldCreateSubnetProtected
Type: AWS::EC2::Subnet
## 以下割愛
## ↑ShouldCreateSubnetProtectedの値が true の場合、SubnetProtectedAを作る
## ↑ShouldCreateSubnetProtectedの値が false の場合、SubnetProtectedAを作らない
テンプレートで使えるCFn組み込み関数 ⑤If
## ⑤If関数。指定された条件がtrueなら2つ目の値、falseなら3つ目の値を返す *1
## Excelの関数で言えば =IF(A1=B1, C1, D1) と同じ感覚
RouteTableIds:
- !Ref RouteTablePublic
- !If [ ShouldCreateSubnetProtected, !Ref RouteTableProtectedA, !Ref AWS::NoValue ]
- !If [ ShouldCreateSubnetProtected, !Ref RouteTableProtectedC, !Ref AWS::NoValue ]
- !If [ ShouldCreateSubnetProtected, !Ref RouteTableProtectedD, !Ref AWS::NoValue ]
## ShouldCreateSubnetProtectedの値が true の場合、下記の通りになる
RouteTableIds:
- !Ref RouteTablePublic
- !Ref RouteTableProtectedA
- !Ref RouteTableProtectedC
- !Ref RouteTableProtectedD
## ShouldCreateSubnetProtectedの値が false の場合、下記の通りになる
## "AWS::NoValue" は疑似パラメータ参照で「存在しない」という意味
## なので実質的に1つだけ残る
RouteTableIds:
- !Ref RouteTablePublic
- !Ref AWS::NoValue ## 実際は存在しない
- !Ref AWS::NoValue ## 実際は存在しない
- !Ref AWS::NoValue ## 実際は存在しない
## If関数は下記どちらの書き方でも同じ意味
!If [ ShouldCreateSubnetProtected, !Ref RouteTableProtectedA, !Ref AWS::NoValue ]
!If
- ShouldCreateSubnetProtected
- !Ref RouteTableProtectedA
- !Ref AWS::NoValue
## !If の代わりに Fn::If: という書き方もある
テンプレートで使えるCFn組み込み関数 ⑥FindInMap と Mappingsの定義例
## ⑥FindInMap関数。Mappingsで宣言したマッピングのキーに対応する値を返す *1
Mappings:
EnvironmentMap:
prod:
VPCCidrBlock: 10.0.0.0/19
stg:
VPCCidrBlock: 10.0.32.0/19
Parameters:
Environment:
Description: Environment
Type: String
Default: prod
CidrBlock: !FindInMap [ EnvironmentMap, !Ref Environment, VPCCidrBlock ]
## ↑!Ref Environmentは "prod" なので
## CidrBlock: !FindInMap [ EnvironmentMap, prod, VPCCidrBlock ] と同じ
## EnvironmentMapのprodのVPCCidrBlockは "10.0.0.0/19" なので
## CidrBlock: 10.0.0.0/19 と書いてあるのと同じ
## !FindInMap の代わりに Fn::FindInMap: という書き方もある
*1 FindInMap関数 https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-findinmap.html
テンプレートで使えるCFn組み込み関数 ⑦ImportValue と Outputsの定義例
## ⑦ImportValue関数 *1
## 別のスタックでエクスポートされたOutputs(出力)の値を返す
## ただし同一AWSアカウント内・同一リージョン内のみ
## 「クロススタック参照」という機能で使う *2
## ④VPCのテンプレートより
## CFn Stackの「Outputs」タブで出力される「Key」「Value」「Export name」を定義
Outputs:
VPC:
Value: !Ref VPC
Export:
## ${AWS::StackName} = awsmaster-prod-vpc なので
## Name: awsmaster-prod-vpc-VPC と同じ
Name: !Sub ${AWS::StackName}-VPC
## ⑤EC2のテンプレートより
VpcId:
Fn::ImportValue: !Sub ${SystemName}-${Environment}-vpc-VPC
## Fn::ImportValue: awsmaster-prod-vpc-VPC となり、
## VPCのOutputsにこのExport Nameがあるので、そのValue
## つまり !Ref VPC = (VPC ID) の値が返される
## 結果として VPCId: (VPC ID) となる
## Fn::ImportValue: の代わりに !Importvalue という書き方もある
*1 ImportValue関数 https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html
*2 AWS CloudFormation の更新 – YAML、クロススタック参照、簡略化された置換 | Amazon Web Services ブログ https://aws.amazon.com/jp/blogs/news/aws-cloudformation-update-yaml-cross-stack-references-simplified-substitution/
4. CFnスタックの操作
CFnテンプレートから「スタック (Stack)」を作ることでリソース一式を自動で作ることができます。
スタック作成 (Create Stack)
作成手順
- CFnテンプレートをS3バケット(AWSのストレージサービス=ファイル置き場。ファイルのことをオブジェクト(Object)と言う)にアップロードする ※画面操作でも、AWS CLI(awsコマンド)操作でも可能
- S3バケット: Objectの画面でObject URLをコピーしておく
- CFn: Create Stackの画面でS3 Object URLを貼り付ける
- Stack Nameを入力し、Parameterを入力・選択する
- 確認画面でStack Name・テンプレートのURL(S3 Object URL)・Parameterに間違いないことを確認し、作成する
- すぐ作成できるリソースと時間がかかるリソースがあるのでEventsタブやResourcesタブで、「Create Complete(緑色)」になるまで待つ
- 途中で「Create Failed(赤色)」など赤字で書かれたら何かのエラーが発生。原因が右側に英語で書かれるので確認する。分からない場合はSlackでスクショかコピペしてご質問ください!
スタック更新 (Update Stack)
- 既存のテンプレートのままでParameterだけ変更して更新するか、
- 新しいCFnテンプレートを読み込んで更新するか、
を選べます。流れは作成と同様です。
スタック削除 (Delete Stack)
既存のスタックを削除するとテンプレートから作られたリソース一式が削除されます。ただし注意点として、下記のようなケースは削除できませんので、事前に対処が必要です。
- (例えば)EC2やELBでVPCを使っているのに、VPCを先に消そうとする場合。依存関係がある場合は、作った順と逆順で消す
- S3バケットが空(から)ではなく、ファイルがある。事前に中身を削除するか、ログが定期的に出力されるような場合は手でバケットを削除しておくと早い
- ECRも空(から)ではなく、Dockerイメージがある。事前に中身を削除しておく
- EC2, ELB, RDSなどで「削除保護 (Deletion Protection)」が有効になっている。事前に編集ボタンから無効にしておく
- RDSが停止状態になっている。事前に起動しておく
削除時にエラーになり、その解決が面倒な場合は「手でリソースを削除」した後、改めてスタックごと削除して頂いてもかまいません。
5. 最後にお願い
- ③Certificate Managerの例外を除き、CFnやリソースは全て東京リージョン(ap-northeast-1) で作成してください
- システム名
[SystemName]
はお好きな名前に変えて頂いてもかまいませんが、英小文字a~z
のみ(どうしてもという場合には先頭以外に追加で数字0~9
とハイフン-
のみ)を使ってください。他の記号を使うと誤動作する可能性があります。AWSの中ではAthenaやParameter Storeなどの例外を除き、ハイフン区切りの英小文字(ケバブケースと呼びます)を名前に使うことが多いです - システム名
[SystemName]
は今後全てのCFnスタック名でも、テンプレート内でも、毎回同じでお願いします! 途中で1文字でも変わってしまうとエラーで動きません。またハイフン区切りのケバブケースでは大文字も使わず、CFnスタック名も毎回記載の通りでお願いします(例:[SystemName]-prod-vpc
) - 毎回CFn作ったリソースはそのまま残してください。ブロックを積み上げるように、リソースをどんどん積み上げていきますので。 ただしAWSの課金をなるべく避けるために、EC2やRDSなどを「停止」することは推奨します。NAT GatewayやELBは「停止」できませんが...
- 一方で勉強のために手で作ったリソースは、作ったり消したり自由に操作ください。課金が発生するものは宿題で計算して頂いていますので、参考にして頂ければと思います
6. FAQ(随時追加)
CFnテンプレートを提供していないリソースの場合はゼロから書くことになります。ググる以外に以下の3つ方法があるかと思いますが、私は2.で作ることが多いです。
公式ドキュメント↓で定義を見ながら作る ※王道だが、そのサービスや設定値を良く理解していないと大変https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html①正しく動作するリソースを手で作る ②次にAWS CLI(awsコマンド)のdescribe-○○
コマンド(例えばaws ec2 describe-instances
)やget-○○
コマンド(例えばaws route53 get-hosted-zone --id (Hosted Zone ID)
)を使ってリソースの設定値をYAMLで出力する ③それをCFnの公式ドキュメントと照らし合わせながらテンプレートを作成する ※コマンドとCFnで微妙に言い回しが違ったりするので修正が必要だが、全くのゼロから作るよりは早い公式サンプル(JSON)をyq
コマンドでYAMLに変換して修正する ※公式なので信頼でき、手っ取り早いhttps://aws.amazon.com/jp/cloudformation/resources/templates/
(↓ 2024年2月にマネジメントコンソールでも操作できるようになったので後述します!)
2023年2月に新たな方法が爆誕しました。AWS CLIで既存のリソースを元にCFnテンプレートが一発で作れる機能です。詳しくは
[アップデート] AWS CloudFormation の API を使って、既存リソースからテンプレートを生成出来るようになったようなので使ってみた | DevelopersIO
をご覧ください。ただ手順の中で、リソースを特定するID (ResourceIdentifier)が分からなくて悩みましたので、誰でもできる手順を調べました。
※ちなみに記事ではAWS CLI v1となっていますが、数日後にv2でも使えるようになりました
aws cloudformation start-resource-scan
でリソースのスキャンを開始aws cloudformation list-resource-scans
でスキャン進捗を確認 →Status: COMPLETE
になるまで待つaws cloudformation list-resource-scan-resources --output json --resource-scan-id <2.で表示されたResourceScanIdをarnから全部コピペ>
でスキャンしたリソースの一覧を表示- その中からテンプレ出力したいリソースを探す。例えば
- 末尾の
"ManagedByStack": false
を"LogicalResourceId": "WebACL"
のように書き換える。例えば - これで上記Classmethodさんの記事で書かれていたJSONファイルが簡単に作れます! せっかくなので続きも書いておくと、5.のJSON(末尾のカンマは削除)に前2行・後3行を追加して、次のようなJSONファイルを作る
aws cloudformation create-generated-template --cli-input-json file://<6.のJSONファイル名>
でテンプレートの生成開始aws cloudformation describe-generated-template --generated-template-name <6.で指定したGeneratedTemplateName>
でテンプレート生成に成功したこと (ResourcesSucceeded) を確認aws cloudformation get-generated-template --output json --generated-template-name <6.で指定したGeneratedTemplateName> | jq -r '.TemplateBody' | jq
でJSON形式のテンプレートが得られる
{
"ResourceType": "AWS::WAFv2::WebACL",
"ResourceIdentifier": {
"Scope": "REGIONAL",
"Id": "43bf1b1d-f357-4c7f-872c-b2c7d0828ce7",
"Name": "rubiconlink"
},
"ManagedByStack": false
},
{
"ResourceType": "AWS::WAFv2::WebACL",
"ResourceIdentifier": {
"Scope": "REGIONAL",
"Id": "43bf1b1d-f357-4c7f-872c-b2c7d0828ce7",
"Name": "rubiconlink"
},
"LogicalResourceId": "WebACL"
},
$ cat wafv2.json
{
"Resources": [
{
"ResourceType": "AWS::WAFv2::WebACL",
"ResourceIdentifier": {
"Scope": "REGIONAL",
"Id": "43bf1b1d-f357-4c7f-872c-b2c7d0828ce7",
"Name": "rubiconlink"
},
"LogicalResourceId": "WebACL"
}
],
"GeneratedTemplateName": "webacl-template"
}
→ Resources
は英語の複数形なので、複数のリソースを指定できます。JSONは「続きがある場合には末尾にカンマあり」「続きがない場合には末尾にカンマなし」になるのでご注意ください
2024年2月に上記のIaCジェネレーターがマネジメントコンソールでも使えるようになりました。詳しくは下記サイトを参照ください。
[アップデート] AWS CloudFormation の IaC ジェネレーターがマネジメントコンソールでも使えるようになってました | DevelopersIO
IaC ジェネレーターを使用して既存のリソースからテンプレートを生成する - AWS CloudFormation
AWS CloudFormation IaCジェネレータの使用感と注意点 #AWS - Qiita
VSCodeの場合はCloudFormationのプラグインを使うと「補完」されるので便利です。 → VSCodeのプラグインでAWSのCloudFormationの構文を簡単に記述する方法|sasshi
そのプラグインも含めた役立つツールのまとめ記事がありましたので、こちらも参考まで。 → AWS CloudFormation を開発・テストする際に役立つツール纏め - Qiita
AWS::EC2::VPC
や AWS::EC2::Subnet
ってどういうこと?TypeにはAWSリソースの種類を書きます。公式ドキュメント(AWS resource and property types reference - AWS CloudFormation)には service-provider::service-name::data-type-name
を書くと定義されています。
Type: AWS::IAM::User
や AWS::IAM::Group
は抵抗ないでしょう。IAMでUserやGroupを作るということですね。確かにIAMの管理画面でもUserやGroupのメニューがあります。
一方でAWSを少しでもかじったことがあると、Type: AWS::EC2::VPC
や AWS::EC2::Subnet
は抵抗ありますね。というのもAWSの管理画面からすると、VPCというサービスの中にVPCやSubnetのメニューがあるので AWS::VPC::VPC
や AWS::VPC::Subnet
の方が自然に思えるからです。
実はAWSの裏側としてはCFnの方が正解で、VPCやSubnetなど「VPC」の画面にまとめられているリソースは全て「EC2」のリソースなのです。なので Type: AWS::EC2::VPC
や AWS::EC2::Subnet
となります。
AWSでEC2がリリースされた2006年当初、VPCは存在しませんでした。その後、EC2をネットワーキングするための機能として2009年にVPCがリリースされた経緯があるのでしょう。
実はその名残がAWSの画面でも残っており、Security Groupというリソースは全く同じものを「EC2」の画面でも「VPC」の画面でも見ることができます。さらにRDSでは「VPC Security Group」という表記があります。普段「EC2」の画面でSecurity Groupを触っていると違和感がありますが、EC2とVPCの関係を知っていると謎が解けます。
蛇足ですが、VPCが存在しない時代のEC2は「EC2-Classic」と呼ばれていました。下記のサイトも参考まで。
- EC2-Classic - Amazon Elastic Compute Cloud
- EC2-Classic からの脱却! VPC 完全移行 ~ Backlog 編 | 株式会社ヌーラボ(Nulab inc.)
この後、講義動画を進めていく途中で、私がS3バケット内の格納場所を変えてしまったために混乱させてしまい、申し訳ありません。
結論から言えば、CFnテンプレート(YAMLファイル)はS3のどこに置いてもかまいません。例えばawsmaster-prod-vpc
スタック用のテンプレートであれば、S3バケット直下にawsmaster-vpc.yml
でもいいですし、ディレクトリを切ってawsmaster/vpc.yml
でもいいでしすし、自由です。
CFnでスタックを作成する時・更新する時には(テンプレートがどこにあるかという)S3のURLを入力します。その時だけS3からYAMLファイルを読み取りますので、それ以外のタイミングではどこに置いても、後から移動しても、むしろ削除してしまっても問題ありません。
後でテンプレートを変更したくなった場合に備えて、バックアップという意味合いで、私はS3に残してあるだけですね。
それでも問題ないですが、④VPC → ⑥RDS → ⑦ELB → ⑩CloudFront → ⑪ECS のように先に作ったものを参照しながら積み上げていきますので、削除する場合は逆順で削除する必要があります。作り直しもまた上の順番で作り直す必要があり、手間がかかってしまいます。削除保護のためにすぐ削除できなかったり、RDSだと中身のデータが消えたり、削除も戻すのも結構な手間なのでご注意ください。
課金をなるべく避けるために、リソースごとに料金体系や課金を減らす工夫(停止など)も宿題や補足で確認していきますので、参考にしてください。
CFnで「インポート」を行うと、手で作ったリソースも後からCFnスタックで作ったかのようにCFnの管理に含めることができます。
詳しくは公式ドキュメント
または、古い記事になりますが、Classmethodさんの記事
を参照ください。ちなみに
インポートするリソースは、テンプレート上でDeletionPolicy
をRetain
にする必要があります。
と記載されていますが、Retain
でなくてもどんな値でもOKです!
ただしインポートできないリソースもあります。インポートが可能かどうかは下記の公式ドキュメントをご覧ください。
またインポートできるリソースでも、インポートできないProperty値(設定値)もあります。その場合はそのProperty値を一旦無視してインポートし、インポート後にProperty値を上書きする形で設定すれば問題ありません。
ちなみに実務では、命名が良くないものの後から名前を変更できない場合、インポートするよりも、命名規則に従ったリソースをCFnで作成し、既存リソースからCFnで作ったリソースに移行するということも多いです。ケースバイケースで適切な方法を検討しましょう。
以上、お疲れさまでした!