👀

CloudFormation 変更セットを使用した更新

2023/12/29に公開

スタックの作成

テンプレートファイルを作成します。

vpc.yml
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  CidrBlock:
    Type: String
    Default: "10.0.0.0/16"
  SystemName :
    Type: String
    Default: "zenn_test"
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref CidrBlock
      Tags:
      - Key: Name
        Value: !Sub "${SystemName}_vpc"
      - Key: SystemName
        Value: !Ref SystemName
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
      - Key: Name
        Value: !Sub "${SystemName}_igw"
      - Key: SystemName
        Value: !Ref SystemName
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId:
        Ref: VPC
      InternetGatewayId:
        Ref: InternetGateway
Outputs:
  VpcId:
    Value: !Ref VPC
  IgwId:
    Value: !Ref InternetGateway

テンプレートの有効性を確認します。

$ aws cloudformation validate-template --template-body file://vpc.yml | tee parameter.tmp
{
    "Parameters": [
        {
            "DefaultValue": "10.0.0.0/16",
            "NoEcho": false,
            "ParameterKey": "CidrBlock"
        },
        {
            "DefaultValue": "zenn_test",
            "NoEcho": false,
            "ParameterKey": "SystemName"
        }
    ]
}

パラメータファイルを作成します。

$ jq '.Parameters' parameter.tmp > parameter.json
$ vi parameter.json

$ jq . parameter.json
[
  {
    "ParameterValue": "10.0.0.0/16",
    "ParameterKey": "CidrBlock"
  },
  {
    "ParameterValue": "zenn_test",
    "ParameterKey": "SystemName"
  }
]

テンプレートファイル、パラメータファイルを利用して、スタックを作成します。

$ aws cloudformation create-stack --template-body file://vpc.yml --parameters file://parameter.json --stack-name <stack_name>
{
    "StackId": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5"
}

スタックの状態を確認します。

$ aws cloudformation describe-stacks --stack-name <stack_name>
{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5",
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            },
            "Parameters": [
                {
                    "ParameterValue": "10.0.0.0/16",
                    "ParameterKey": "CidrBlock"
                },
                {
                    "ParameterValue": "zenn_test",
                    "ParameterKey": "SystemName"
                }
            ],
            "Tags": [],
            "Outputs": [
                {
                    "OutputKey": "IgwId",
                    "OutputValue": "igw-09a8a7cd70d9c64f3"
                },
                {
                    "OutputKey": "VpcId",
                    "OutputValue": "vpc-088d128811eb40c93"
                }
            ],
            "EnableTerminationProtection": false,
            "CreationTime": "2023-12-28T21:33:14.249Z",
            "StackName": "<stack_name>",
            "NotificationARNs": [],
            "StackStatus": "CREATE_COMPLETE",
            "DisableRollback": false,
            "RollbackConfiguration": {}
        }
    ]
}

作成されたリソースを確認します。

$ aws cloudformation list-stack-resources --stack-name <stack_name>
{
    "StackResourceSummaries": [
        {
            "ResourceStatus": "CREATE_COMPLETE",
            "DriftInformation": {
                "StackResourceDriftStatus": "NOT_CHECKED"
            },
            "ResourceType": "AWS::EC2::VPCGatewayAttachment",
            "LastUpdatedTimestamp": "2023-12-28T21:33:37.647Z",
            "PhysicalResourceId": "IGW|vpc-088d128811eb40c93",
            "LogicalResourceId": "AttachGateway"
        },
        {
            "ResourceStatus": "CREATE_COMPLETE",
            "DriftInformation": {
                "StackResourceDriftStatus": "NOT_CHECKED"
            },
            "ResourceType": "AWS::EC2::InternetGateway",
            "LastUpdatedTimestamp": "2023-12-28T21:33:34.226Z",
            "PhysicalResourceId": "igw-09a8a7cd70d9c64f3",
            "LogicalResourceId": "InternetGateway"
        },
        {
            "ResourceStatus": "CREATE_COMPLETE",
            "DriftInformation": {
                "StackResourceDriftStatus": "NOT_CHECKED"
            },
            "ResourceType": "AWS::EC2::VPC",
            "LastUpdatedTimestamp": "2023-12-28T21:33:30.050Z",
            "PhysicalResourceId": "vpc-088d128811eb40c93",
            "LogicalResourceId": "VPC"
        }
    ]
}

change set

差分を発生させます。
ここではパラメータファイルを編集して、タグの値を変更してみます。

$ cp -pi parameter.json{,.000}
$ vi parameter.json

$ diff -u parameter.json{,.000}
--- parameter.json      2023-12-28 21:39:59.201608396 +0000
+++ parameter.json.000  2023-12-28 21:00:35.438369344 +0000
@@ -4,7 +4,7 @@
     "ParameterKey": "CidrBlock"
   },
   {
-    "ParameterValue": "zenn-test",
+    "ParameterValue": "zenn_test",
     "ParameterKey": "SystemName"
   }
 ]

変更セットを作成します。

$ aws cloudformation create-change-set --stack-name <stack_name> --template-body file://vpc.yml --parameters file://parameter.json --change-set-name <change_set_name> --description 'change SystemName'
{
    "StackId": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5",
    "Id": "arn:aws:cloudformation:<region>:<aws_account_id>:changeSet/<change_set_name>/5503be9c-f6e0-48e4-b097-3f1da2eaa3b3"
}

$ aws cloudformation list-change-sets --stack-name <stack_name>
{
    "Summaries": [
        {
            "StackId": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5",
            "Status": "CREATE_COMPLETE",
            "ChangeSetName": "<change_set_name>",
            "Description": "change SystemName",
            "CreationTime": "2023-12-28T21:41:01.200Z",
            "StackName": "<stack_name>",
            "ExecutionStatus": "AVAILABLE",
            "ChangeSetId": "arn:aws:cloudformation:<region>:<aws_account_id>:changeSet/<change_set_name>/5503be9c-f6e0-48e4-b097-3f1da2eaa3b3"
        }
    ]
}

想定される構成変更を確認します。
RequiresRecreation の値が Never となっているものは、リソースの再作成は行われず、属性値の変更だけが行われます。

$ aws cloudformation describe-change-set --stack-name <stack_name> --change-set-name <change_set_name>
{
    "StackId": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5",
    "Status": "CREATE_COMPLETE",
    "ChangeSetName": "<change_set_name>",
    "Description": "change SystemName",
    "Parameters": [
        {
            "ParameterValue": "10.0.0.0/16",
            "ParameterKey": "CidrBlock"
        },
        {
            "ParameterValue": "zenn-test",
            "ParameterKey": "SystemName"
        }
    ],
    "Tags": null,
    "ChangeSetId": "arn:aws:cloudformation:<region>:<aws_account_id>:changeSet/<change_set_name>/5503be9c-f6e0-48e4-b097-3f1da2eaa3b3",
    "CreationTime": "2023-12-28T21:41:01.200Z",
    "StatusReason": null,
    "StackName": "<stack_name>",
    "NotificationARNs": [],
    "Capabilities": [],
    "ExecutionStatus": "AVAILABLE",
    "Changes": [
        {
            "ResourceChange": {
                "ResourceType": "AWS::EC2::InternetGateway",
                "PhysicalResourceId": "igw-09a8a7cd70d9c64f3",
                "Details": [
                    {
                        "CausingEntity": "SystemName",
                        "ChangeSource": "ParameterReference",
                        "Evaluation": "Static",
                        "Target": {
                            "Attribute": "Properties",
                            "Name": "Tags",
                            "RequiresRecreation": "Never"
                        }
                    },
                    {
                        "ChangeSource": "DirectModification",
                        "Evaluation": "Dynamic",
                        "Target": {
                            "Attribute": "Properties",
                            "Name": "Tags",
                            "RequiresRecreation": "Never"
                        }
                    }
                ],
                "Action": "Modify",
                "Scope": [
                    "Properties"
                ],
                "LogicalResourceId": "InternetGateway",
                "Replacement": "False"
            },
            "Type": "Resource"
        },
        {
            "ResourceChange": {
                "ResourceType": "AWS::EC2::VPC",
                "PhysicalResourceId": "vpc-088d128811eb40c93",
                "Details": [
                    {
                        "CausingEntity": "SystemName",
                        "ChangeSource": "ParameterReference",
                        "Evaluation": "Static",
                        "Target": {
                            "Attribute": "Properties",
                            "Name": "Tags",
                            "RequiresRecreation": "Never"
                        }
                    },
                    {
                        "ChangeSource": "DirectModification",
                        "Evaluation": "Dynamic",
                        "Target": {
                            "Attribute": "Properties",
                            "Name": "Tags",
                            "RequiresRecreation": "Never"
                        }
                    }
                ],
                "Action": "Modify",
                "Scope": [
                    "Properties"
                ],
                "LogicalResourceId": "VPC",
                "Replacement": "False"
            },
            "Type": "Resource"
        }
    ],
    "RollbackConfiguration": {}
}

あとから比較するため、変更が想定されるリソースの現在の情報を取得しておきます。

$ aws ec2 describe-vpcs --vpc-ids vpc-088d128811eb40c93 > vpc.before
$ aws ec2 describe-internet-gateways --internet-gateway-ids igw-09a8a7cd70d9c64f3 > igw.before

変更セットを適用します。

$ aws cloudformation execute-change-set --stack-name <stack_name> --change-set-name <change_set_name>

$ aws cloudformation list-change-sets --stack-name <stack_name>
{
    "Summaries": []
}

スタックの状態を確認します。

$ aws cloudformation describe-stacks --stack-name <stack_name>
{
    "Stacks": [
        {
            "StackId": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5",
            "DriftInformation": {
                "StackDriftStatus": "NOT_CHECKED"
            },
            "LastUpdatedTime": "2023-12-28T21:50:16.556Z",
            "Parameters": [
                {
                    "ParameterValue": "10.0.0.0/16",
                    "ParameterKey": "CidrBlock"
                },
                {
                    "ParameterValue": "zenn-test",
                    "ParameterKey": "SystemName"
                }
            ],
            "Tags": [],
            "Outputs": [
                {
                    "OutputKey": "IgwId",
                    "OutputValue": "igw-09a8a7cd70d9c64f3"
                },
                {
                    "OutputKey": "VpcId",
                    "OutputValue": "vpc-088d128811eb40c93"
                }
            ],
            "EnableTerminationProtection": false,
            "CreationTime": "2023-12-28T21:33:14.249Z",
            "StackName": "<stack_name>",
            "NotificationARNs": [],
            "StackStatus": "UPDATE_COMPLETE",
            "DisableRollback": false,
            "ChangeSetId": "arn:aws:cloudformation:<region>:<aws_account_id>:changeSet/<change_set_name>/5503be9c-f6e0-48e4-b097-3f1da2eaa3b3",
            "RollbackConfiguration": {}
        }
    ]
}

事前に取得していた情報との差分を確認します。

$ aws ec2 describe-vpcs --vpc-ids vpc-088d128811eb40c93 | diff -u - vpc.before
--- -   2023-12-28 21:52:24.982994416 +0000
+++ vpc.before  2023-12-28 21:47:50.583599706 +0000
@@ -5,16 +5,16 @@
             "InstanceTenancy": "default",
             "Tags": [
                 {
-                    "Value": "zenn-test",
-                    "Key": "SystemName"
+                    "Value": "zenn_test_vpc",
+                    "Key": "Name"
                 },
                 {
                     "Value": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5",
                     "Key": "aws:cloudformation:stack-id"
                 },
                 {
-                    "Value": "zenn-test_vpc",
-                    "Key": "Name"
+                    "Value": "zenn_test",
+                    "Key": "SystemName"
                 },
                 {
                     "Value": "VPC",

$ aws ec2 describe-internet-gateways --internet-gateway-ids igw-09a8a7cd70d9c64f3 | diff -u - igw.before
--- -   2023-12-28 21:53:03.331128862 +0000
+++ igw.before  2023-12-28 21:48:52.078822486 +0000
@@ -4,7 +4,7 @@
             "OwnerId": "<aws_account_id>",
             "Tags": [
                 {
-                    "Value": "zenn-test_igw",
+                    "Value": "zenn_test_igw",
                     "Key": "Name"
                 },
                 {
@@ -16,7 +16,7 @@
                     "Key": "aws:cloudformation:stack-name"
                 },
                 {
-                    "Value": "zenn-test",
+                    "Value": "zenn_test",
                     "Key": "SystemName"
                 },
                 {

change set パターン2

差分を発生させます。
パラメータファイルを編集して、CidrBlock の値を変更してみます。

$ cp -pi parameter.json{,.001}
$ vi parameter.json

$ diff -u parameter.json{,.001}
--- parameter.json      2023-12-28 23:14:14.975254718 +0000
+++ parameter.json.001  2023-12-28 21:39:59.201608396 +0000
@@ -1,6 +1,6 @@
 [
   {
-    "ParameterValue": "10.1.0.0/16",
+    "ParameterValue": "10.0.0.0/16",
     "ParameterKey": "CidrBlock"
   },
   {

変更セットを作成します。

$ aws cloudformation create-change-set --stack-name <stack_name> --template-body file://vpc.yml --parameters file://parameter.json --change-set-name <change_set_name> --description 'change CidrBlock'
{
    "StackId": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5",
    "Id": "arn:aws:cloudformation:<region>:<aws_account_id>:changeSet/<change_set_name>/042ae1e2-db71-485a-9987-a43edb3eb94c"
}

$ aws cloudformation list-change-sets --stack-name <stack_name>
{
    "Summaries": [
        {
            "StackId": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5",
            "Status": "CREATE_COMPLETE",
            "ChangeSetName": "<change_set_name>",
            "Description": "change CidrBlock",
            "CreationTime": "2023-12-28T23:15:40.050Z",
            "StackName": "<stack_name>",
            "ExecutionStatus": "AVAILABLE",
            "ChangeSetId": "arn:aws:cloudformation:<region>:<aws_account_id>:changeSet/<change_set_name>/042ae1e2-db71-485a-9987-a43edb3eb94c"
        }
    ]
}

想定される構成変更を確認します。
RequiresRecreation の値が Always となっているものは、リソースの再作成が行われます。
リソースが再作成されると好ましくない結果になる可能性がある場合は、再考が求められます。

$ aws cloudformation describe-change-set --stack-name <stack_name> --change-set-name <change_set_name>
{
    "StackId": "arn:aws:cloudformation:<region>:<aws_account_id>:stack/<stack_name>/b4e20e60-a5c8-11ee-8c99-0676a70102b5",
    "Status": "CREATE_COMPLETE",
    "ChangeSetName": "<change_set_name>",
    "Description": "change CidrBlock",
    "Parameters": [
        {
            "ParameterValue": "10.1.0.0/16",
            "ParameterKey": "CidrBlock"
        },
        {
            "ParameterValue": "zenn-test",
            "ParameterKey": "SystemName"
        }
    ],
    "Tags": null,
    "ChangeSetId": "arn:aws:cloudformation:<region>:<aws_account_id>:changeSet/<change_set_name>/042ae1e2-db71-485a-9987-a43edb3eb94c",
    "CreationTime": "2023-12-28T23:15:40.050Z",
    "StatusReason": null,
    "StackName": "<stack_name>",
    "NotificationARNs": [],
    "Capabilities": [],
    "ExecutionStatus": "AVAILABLE",
    "Changes": [
        {
            "ResourceChange": {
                "ResourceType": "AWS::EC2::VPCGatewayAttachment",
                "PhysicalResourceId": "IGW|vpc-088d128811eb40c93",
                "Details": [
                    {
                        "CausingEntity": "VPC",
                        "ChangeSource": "ResourceReference",
                        "Evaluation": "Static",
                        "Target": {
                            "Attribute": "Properties",
                            "Name": "VpcId",
                            "RequiresRecreation": "Always"
                        }
                    }
                ],
                "Action": "Modify",
                "Scope": [
                    "Properties"
                ],
                "LogicalResourceId": "AttachGateway",
                "Replacement": "True"
            },
            "Type": "Resource"
        },
        {
            "ResourceChange": {
                "ResourceType": "AWS::EC2::VPC",
                "PhysicalResourceId": "vpc-088d128811eb40c93",
                "Details": [
                    {
                        "CausingEntity": "CidrBlock",
                        "ChangeSource": "ParameterReference",
                        "Evaluation": "Static",
                        "Target": {
                            "Attribute": "Properties",
                            "Name": "CidrBlock",
                            "RequiresRecreation": "Always"
                        }
                    },
                    {
                        "ChangeSource": "DirectModification",
                        "Evaluation": "Dynamic",
                        "Target": {
                            "Attribute": "Properties",
                            "Name": "CidrBlock",
                            "RequiresRecreation": "Always"
                        }
                    }
                ],
                "Action": "Modify",
                "Scope": [
                    "Properties"
                ],
                "LogicalResourceId": "VPC",
                "Replacement": "True"
            },
            "Type": "Resource"
        }
    ],
    "RollbackConfiguration": {}
}

今回は差分を適用しないで、作成した変更セットを削除しておきます。パラメータファイルも切り戻します。

$ aws cloudformation delete-change-set --stack-name <stack_name> --change-set-name <change_set_name>

$ aws cloudformation list-change-sets --stack-name <stack_name>
{
    "Summaries": []
}

$ mv parameter.json{.001,}
GitHubで編集を提案

Discussion