概要
CloudFormation を使用する際に、よく使用する表記やコマンド、操作などの
情報共有および備忘録用としてメモしておきます。
よく使用するパラメータ、表記など
!Sub + !FindInMap の組み合わせ
!Sub
と !FindInMap
を組み合わせることで使い回ししやすCFnを作成することができる。
リージョン毎に値を変更したい場合に、よく使用する。
Mappings:
Prefix:
ap-northeast-1:
value: Tokyo
ap-northeast-3:
value: Osaka
# ========== <省略> ================
BackupPlanName: !Sub
- ${Key}-backup-plan
- Key: !FindInMap [Prefix, !Ref "AWS::Region", value]
# 東京リージョンの場合 Tokyo-backup-plan
# 大阪リージョンの場合 Osaka-backup-plan
アカウントID
AWS::AccountId
を使用することで、アカウントIDの値を返すことができる。
ユニークな値を生成する際などに使用する。
Outputs:
MyAccountIdk:
Value: !Ref "AWS::AccountId"
Value: !Sub "${AWS::AccountId}"
リージョンの表記
AWS::Region
を使用することで、デプロイ先のリージョンを表現することができる。
Outputs:
MyStacksRegion:
Value: !Ref "AWS::Region"
Value: !Sub "${AWS::Region}"
AZ (アベイラリティゾーン)
!GetAZs
を使用することで、AZの一覧を表示することができる。この関数に !Select
を組み合わせることで、 簡単にAZを表現することができる。以下は例
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""] # ap-northeast-1a
デフォルト サブネットがあるアベイラビリティーゾーンがない場合を除き、Fn::GetAZs
関数はデフォルト サブネットがあるアベイラビリティーゾーンのみを返します。その場合、すべてのアベイラビリティーゾーンが返されます。
条件
Conditions
や Condition
を使用することで、パラメータの条件によってリソースを作成したりすることができる。
また AWS::NoValue
を使用することで属性を削除することができる。
Parameters:
EnvType:
Description: Environment type.
Default: test
Type: String
AllowedValues:
- prod
- test
Conditions:
CreateProdResources: !Equals # EnvTypeがprodの場合、true
- !Ref EnvType
- prod
Resources:
InstanceProfile:
Condition: CreateProdResources # CreateProdResourcesがtrueのみ作成される
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref EC2Role
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref ImageId
InstanceType: t3.micro
IamInstanceProfile: !If
- CreateProdResources
- !Ref InstanceProfile
- !Ref AWS::NoValue # CreateProdResourcesがfalseの場合、この属性を削除する
SubnetId: !Ref PrivateSubnetId
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-EC2
循環依存
1つのリソースがそれ自体に依存していること、あるいは2つのリソースが互いに依存していることによって、リソースの作成に失敗する場合がある。
セキュリティグループを作成する際に、よく発生する。
※セキュリティグループAはセキュリティグループAの通信のみ許可する場合など、
以下に循環依存のNGな例と、OKの例を記載する。
# NGな例
InstanceSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow SSH from EIC
VpcId: !Ref Vpc
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref InstanceSG
# OKな例 SGの箱を作成し、Igressを別途設定することで循環依存を解消できる
InstanceSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Allow SSH from EIC
VpcId: !Ref Vpc
InstancSgIngress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref InstanceSG
IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref InstanceSG
最新のAMI取得
パラメータストアの「パブリックパラメータ」に最新のAMIのIDが記載されている。
そこから値を取得することによって、最新のAMI IDを取得することができる。
# AL2023の場合
Parameters:
Al2023EC2ImageId:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
# /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64
Resources:
MyEC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref EC2ImageId
InstanceType: t3.micro
最新の AMI ID を指定できる反⾯、AMI ID が更新された場合は EC2 の再作成が⾏われます
スタック更新の際には、変更セットで意図しない EC2 の再作成が⾏われないことをご確認ください。
セキュリティやポリシー、インポート関連
スタックポリシー
CFnはデフォルトで全てのリソースが更新されるようになっている。
だが、EC2、RDSなど更新したくないリソースがでてくるケースがある。
スタックポリシーを使用することで、意図しない更新を防ぐことができる。
スタックポリシーはJSON形式で作成する。以下は、EC2とRDSの更新を防ぐスタックポリシーである。
{
"Statement" : [
{
"Effect" : "Deny",
"Principal" : "*",
"Action" : "Update:*",
"Resource" : "*",
"Condition" : {
"StringEquals" : {
"ResourceType" : ["AWS::EC2::Instance", "AWS::RDS::DBInstance"]
}
}
},
{
"Effect" : "Allow",
"Principal" : "*",
"Action" : "Update:*",
"Resource" : "*"
}
]
}
既存のリソースに設定する場合のコマンド例
aws cloudformation set-stack-policy \
--stack-name sample-stack \
--stack-policy-body=file://stack-policy.json
既存リソースのインポート (ざっくり手順)
- インポートしたいリソースをCFnに記載し、
DeletionPolicy: Retain
を追記する。 - CFnのマネジメントコンソールより、インポートを実行する。この際、リソース識別子を入力する必要がある。
- ドリフト検出を実行し、テンプレートとリソースが一致していることを確認する。
EC2、RDSの依存リリースが多いものは、インポートが難しいので注意すること。
CloudFormation Guard
Ruleを記述した .guard
ファイルを作成し、CFnのテンプレートに対してルールの検証をすることができる。
この機能を利用することで、テンプレートが要件に沿ったものかを判断することができる。
CI/CDに活用できる。
例 EBS暗号化が有効になっていることを確認する guard
ルール
# EC2のEBSが暗号化されているかの確認
let aws_ec2_instance_resources = Resources.*[ Type == 'AWS::EC2::Instance' ]
rule aws_ec2_ebs when %aws_ec2_instance_resources !empty {
%aws_ec2_instance_resources.Properties.BlockDeviceMappings[*].Ebs.Encrypted == true
}
# EBSが暗号化されているかの確認
let aws_ec2_volume_resources = Resources.*[ Type == 'AWS::EC2::Volume' ]
rule aws_ebs when %aws_ec2_volume_resources !empty {
%aws_ec2_volume_resources.Properties.Encrypted == true
}
テンプレートの検証方法
ルールに沿っていれば何も結果が出力されず、ルールに違反している場合はメッセージが出力される。
cfn-guard validate --data <テンプレート名>.yaml --rules <guardファイル>.guard
コマンド集
デプロイ
aws cloudformation deploy \
--template-file sample.yaml \
--stack-name sample-stack \
--profile sample
検証コマンド
以下のコマンドを実行することで、テンプレートを検証することができる。
問題がなければ、パラメータの構文情報が返却され、
問題があれば、エラーメッセージが返却される。
aws cloudformation validate-template \
--template-body file:./sampletemplate.json \
--profile sample
削除コマンド
aws cloudformation delete-stack \
--stack-name myteststack \
--profile sample
変更セットの作成
新しいパラメータ値、修正済みのテンプレート、または両方を指定できる。たとえば、次のコマンドで Sample
という名前の変更セットが作成される
aws cloudformation create-change-set \
--stack-name sample-stack \
--change-set-name Sample \
--template-body=file://<CFnファイル名>.yaml
変更セットの確認
aws cloudformation describe-change-set --change-set-name <変更セットのID>
変更セットの実行
aws cloudformation execute-change-set --change-set-name <変更セットのID>
その他
Amazon CodeWhisperer
CodeWhisperer を利⽤すると、コメント⾏に記載した構成を実現するためのコードサジェストやコードの補完をしてくれます。
こちらを使用すると、記述スピードが20割近く速くなるので、可能であれば導入することをおすすめします。
https://docs.aws.amazon.com/ja_jp/codewhisperer/latest/userguide/what-is-cwspr.html