はじめに
今回はスタック実行前に事前に変更箇所を確認できる変更セット
と、スタック実行後に手動操作などで変更されたリソースを確認できるドリフト検出
を試してみようと思います。
- 【前】CloudFormationをゼロから勉強する。(その6:Transformによるインクルード)
- 【次】CloudFormationをゼロから勉強する。(その8:スタックのネスト)
- 【番外編】CloudFormationをゼロから勉強する。(番外編:AWS Perspective)
変更セットについて
前述の通り、スタック実行前に変更箇所を確認することができる機能です。
スタック実行前に変更されるリソースやパラメータを確認できるので、スタック実行することによって意図せずリソースが削除されたりする事故が防げます。
テスト環境ならともかく、サービスが動作している本番環境でスタックを実行する際には必須の機能かと思います。
ドリフト検出について
これも前述の通り、スタック実行後に手動操作などで変更されたリソースを確認できる機能です。
本来は環境をCloudFormation
で管理しているのであればスタックで作成したリソースや設定に対して手動で操作することは極力避けるべきですが、何かしらの理由で手動操作した場合でも変更箇所を検出することができます。
例えば障害対応などで手動で変更した設定を、後日ドリフト検出で確認してCloudFormation
テンプレートに落とし込む場合に便利です。
今回のシナリオ
変更セット
とドリフト検出
を試すため、1つのVPC
と2つのサブネット
リソースのみのシンプルな構成とし、サブネットリソースだけタグ付けした構成をベースとして以下を実施します。
- サブネットのタグを修正して変更セットを作成する。
- 手動で1つのサブネットの削除、VPCのタグの追加とサブネットのタグを修正してドリフト検出する。
- テンプレートからサブネットの削除とタグの追加・修正を行い、再度変更セットを作成する。
また、コンソールやコマンドで実行する際のスタック名等は以下で行うため、適宜読み替えるようにして下さい。
項目 | 名前 |
---|---|
スタック名 | stack-test |
変更セット名 | change-set-test |
テンプレートファイルパス | /home/ec2-user/cf.yaml |
パラメータファイルパス | /home/ec2-user/param.yaml |
ベーステンプレートの作成
今回はVPC
とサブネット
のみのテンプレートとパラメータファイルを新たに作成します。
Metadata
や不要な設定は削除して極力シンプルにしました。
ベーステンプレートの作成(展開して下さい)
AWSTemplateFormatVersion: 2010-09-09
Resources:
EC2VPC1:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: !Ref VPCRange
EC2Subnet1:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref EC2VPC1
CidrBlock: !Ref SubnetRange1
Tags:
- Key: "Name"
Value: "CloudFormation"
EC2Subnet2:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref EC2VPC1
CidrBlock: !Ref SubnetRange2
Tags:
- Key: "Name"
Value: "CloudFormation"
Parameters:
VPCRange:
Type: String
Description: "VPC Subnet Range"
SubnetRange1:
Type: String
Description: "Subnet Range1"
SubnetRange2:
Type: String
Description: "Subnet Range2"
ベースパラメータファイルの作成(展開して下さい)
[
{ "ParameterKey" : "VPCRange", "ParameterValue" : "172.24.0.0/16" },
{ "ParameterKey" : "SubnetRange1", "ParameterValue" : "172.24.0.0/24" },
{ "ParameterKey" : "SubnetRange2", "ParameterValue" : "172.24.1.0/24" }
]
aws cloudformation create-stack --template-body file:///home/ec2-user/cf.yaml --stack-name stack-test --parameters file:///home/ec2-user/param.json
ベーステンプレートの修正
前準備として作成したベーステンプレートを以下の内容に修正します。
- サブネットリソースのタグを
cf_Subnet
という名前に修正する。
変更セットの作成
変更セット
は作成済みスタックのテンプレートと修正したテンプレートの差分をチェックして変更となる項目を確認することができます。
AWSマネジメントコンソール
から操作する場合は作成したスタックを選択し、変更セット
→変更セットの作成
から修正したテンプレートをアップロードするか、直接編集を行います。
AWS CLI
で実行する場合は以下コマンドを実行します。
aws cloudformation create-change-set --change-set-name change-set-test --template-body file:///home/ec2-user/cf.yaml --stack-name stack-test --parameters file:///home/ec2-user/param.json
変更セット
を作成すると以下画面のような比較結果が表示され、どのリソースが変更されるかが確認できます。
コマンドの場合は以下。
aws cloudformation describe-change-set --change-set-name change-set-test --stack-name stack-test
コマンド実行結果(展開して下さい)
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:335417439444:stack/stack-test/d5249730-01dc-11eb-8e2a-0af1581a9dde",
"Status": "CREATE_COMPLETE",
"ChangeSetName": "change-set-test",
"Parameters": [
{
"ParameterValue": "172.24.0.0/24",
"ParameterKey": "SubnetRange1"
},
{
"ParameterValue": "172.24.1.0/24",
"ParameterKey": "SubnetRange2"
},
{
"ParameterValue": "172.24.0.0/16",
"ParameterKey": "VPCRange"
}
],
"Changes": [
{
"ResourceChange": {
"ResourceType": "AWS::EC2::Subnet",
"PhysicalResourceId": "subnet-0c76cd08741e9b6af",
"Details": [
{
"ChangeSource": "DirectModification",
"Evaluation": "Static",
"Target": {
"Attribute": "Tags",
"RequiresRecreation": "Never"
}
}
],
"Action": "Modify",
"Scope": [
"Tags"
],
"LogicalResourceId": "EC2Subnet1",
"Replacement": "False"
},
"Type": "Resource"
},
{
"ResourceChange": {
"ResourceType": "AWS::EC2::Subnet",
"PhysicalResourceId": "subnet-04755c355840e4956",
"Details": [
{
"ChangeSource": "DirectModification",
"Evaluation": "Static",
"Target": {
"Attribute": "Tags",
"RequiresRecreation": "Never"
}
}
],
"Action": "Modify",
"Scope": [
"Tags"
],
"LogicalResourceId": "EC2Subnet2",
"Replacement": "False"
},
"Type": "Resource"
}
],
"CreationTime": "2020-09-28T22:50:52.425Z",
"Capabilities": [],
"StackName": "stack-test",
"NotificationARNs": [],
"ExecutionStatus": "AVAILABLE",
"ChangeSetId": "arn:aws:cloudformation:ap-northeast-1:335417439444:changeSet/change-set-test/845b6229-3800-448c-9f80-d54cdf81f17d",
"RollbackConfiguration": {}
}
変更セットの実行
変更セット
は作成しただけでは差分結果を表示するだけなので、差分結果に問題が無ければ実際に修正したテンプレートを反映させるため変更セット
を実行します。
修正したテンプレートを実行するためには、コンソールからなら実行
ボタン、コマンドからならexecute-change-set
を実行します。
aws cloudformation execute-change-set --change-set-name change-set-test --stack-name stack-test
変更セット実行後は以下の様にタグが追加、修正されているのが確認できます。
サブネットリソースの手動削除とタグ追加・修正
ドリフト検出
を試すため、SubnetRange2
で作成したサブネットを手動で削除してみます。
コマンドで実行する場合は事前にサブネットID
を調べておいて下さい。
aws ec2 delete-subnet --subnet-id [サブネットID]
aws ec2 create-tags --resources [VPC ID] --tags Key=Name,Value=cf_VPC1
aws ec2 create-tags --resources [サブネットID] --tags Key=Name,Value=cf_Subnet1
ドリフト検出の実行
スタック一覧画面でスタックを選択し、スタックアクション
からドリフトの検出
を選択することで最新のテンプレートと異なる設定をチェックできます。
コマンドの場合は以下。
aws cloudformation detect-stack-drift --stack-name stack-test
ドリフト結果の確認
スタック一覧画面でスタックを選択し、スタックアクション
からドリフト結果を表示
を選択することで先ほど実行したドリフト検出
の結果を確認できます。
今回はEC2Subnet1
のタグの修正とEC2Subnet2
リソースを手動で削除しているので、それぞれMODIFIED
、DELETED
と検出されていることが確認できます。
コマンドの場合は以下。
aws cloudformation describe-stack-resource-drifts --stack-name stack-test
コマンド実行結果(展開して下さい)
{
"StackResourceDrifts": [
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:335417439444:stack/stack-test/d5249730-01dc-11eb-8e2a-0af1581a9dde",
"ActualProperties": "{\"CidrBlock\":\"172.24.0.0/24\",\"Tags\":[{\"Key\":\"Name\",\"Value\":\"cf_Subnet1\"}],\"VpcId\":\"vpc-0d228fc345e494e45\"}",
"ResourceType": "AWS::EC2::Subnet",
"Timestamp": "2020-09-28T23:20:59.182Z",
"PhysicalResourceId": "subnet-0c76cd08741e9b6af",
"StackResourceDriftStatus": "MODIFIED",
"ExpectedProperties": "{\"CidrBlock\":\"172.24.0.0/24\",\"Tags\":[{\"Key\":\"Name\",\"Value\":\"cf_Subnet\"}],\"VpcId\":\"vpc-0d228fc345e494e45\"}",
"PropertyDifferences": [
{
"PropertyPath": "/Tags/0/Value",
"ActualValue": "cf_Subnet1",
"ExpectedValue": "cf_Subnet",
"DifferenceType": "NOT_EQUAL"
}
],
"LogicalResourceId": "EC2Subnet1"
},
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:335417439444:stack/stack-test/d5249730-01dc-11eb-8e2a-0af1581a9dde",
"ResourceType": "AWS::EC2::Subnet",
"Timestamp": "2020-09-28T23:20:59.746Z",
"PhysicalResourceId": "subnet-04755c355840e4956",
"StackResourceDriftStatus": "DELETED",
"LogicalResourceId": "EC2Subnet2"
},
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:335417439444:stack/stack-test/d5249730-01dc-11eb-8e2a-0af1581a9dde",
"ActualProperties": "{\"CidrBlock\":\"172.24.0.0/16\"}",
"ResourceType": "AWS::EC2::VPC",
"Timestamp": "2020-09-29T22:21:03.431Z",
"PhysicalResourceId": "vpc-0d228fc345e494e45",
"StackResourceDriftStatus": "IN_SYNC",
"ExpectedProperties": "{\"CidrBlock\":\"172.24.0.0/16\"}",
"PropertyDifferences": [],
"LogicalResourceId": "EC2VPC1"
}
]
}
また、上記ドリフトの画面からリソースを選択し、ドリフトの詳細の表示
をクリックするとJSON
形式ですがテンプレートとの差分を確認することができるので、実際にテンプレートを修正する場合に便利です。
ドリフト検出の注意点
今回、手動修正した個所はEC2Subnet1
のタグ修正、EC2Subnet2
のリソース削除、EC2VPC1
のタグ追加ですが、上記の画像を見るとEC2VPC1
のタグ追加が検出されておりません。
はっきり調べていませんが、ドリフト検出
はテンプレートにもともと記載されている設定に対する検出なので、記載されていた設定値の変更は検出できても、そもそも記載されていなかった設定を検出することはできないようです。
そのような設定変更を検出するためにはAWS Config
で検出する必要があるのかな?
変更セットの更新
テンプレートとパラメータファイルからもEC2VPC1
とEC2Subnet1
のタグ追加・修正とEC2Subnet2
リソースを削除して先ほどと同様変更セット
を実行します。
コマンドから実行する場合も、先ほどと同様のコマンドで実行できます。
aws cloudformation create-change-set --change-set-name change-set-test --template-body file:///home/ec2-user/cf.yaml --stack-name stack-test --parameters file:///home/ec2-user/param.json
aws cloudformation execute-change-set --change-set-name change-set-test --stack-name stack-test
おわりに
変更セット
、ドリフト検出
をこまめに行うことでシステムを運用していると常に付きまとう設計書と実機の差分を減らすことができるのは非常にありがたいですね。
※CloudFormation
で管理されていない設定については検出できませんが。
次回はスタックのネスト
を試してみようと思います。