運用しているAWS CloudFormationのテンプレートをJSONからYAMLに移行する

現在運用しているAWS CloudFormationスタックがあるのですが、そのテンプレートはJSONで書かれています。それをYAMLに書き換えた上でシームレスにスタック更新が可能かが調べても分からなかったため試してみました。
2018.09.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。サービスグループの武田です。

現在運用しているAWS CloudFormationスタックがあるのですが、そのテンプレートはJSONで書かれています。それをYAMLに書き換えた上でシームレスにスタック更新が可能かが調べても分からなかったため試してみました。

環境

次の環境で検証しました。

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.13.6
BuildVersion:	17G65

$ aws --version
aws-cli/1.15.33 Python/3.6.5 Darwin/17.7.0 botocore/1.10.33

$ jq --version
jq-1.5

$ pip -V
pip 18.0 from /usr/local/lib/python3.6/site-packages/pip (python 3.6)

やってみた

まずはベースとなるJSONファイルを用意します。作成するリソースはなんでもよかったのですが、あたり障りのないセキュリティグループにしました。ファイル名はmig-test.template.jsonです。

mig-test.template.json

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": {
    "SecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupDescription": "CFn migration test",
        "SecurityGroupIngress": [
          {
            "IpProtocol": "TCP",
            "FromPort": 80,
            "ToPort": 80,
            "CidrIp": "0.0.0.0/0"
          }
        ]
      }
    }
  }
}

このテンプレートを使ってスタックを作成します。

$ aws cloudformation create-stack \
  --stack-name mig-test \
  --template-body file://mig-test.template.json

$ aws ec2 describe-security-groups \
  --group-names $(aws cloudformation describe-stack-resource \
    --stack-name mig-test \
    --logical-resource-id SecurityGroup \
    | jq -r '.StackResourceDetail.PhysicalResourceId')
{
    "SecurityGroups": [
        {
            "Description": "CFn migration test",
            "GroupName": "mig-test-SecurityGroup-1WPEQP3XYW2PP",
            "IpPermissions": [
                {
                    "FromPort": 80,
                    "IpProtocol": "tcp",
                    "IpRanges": [
                        {
                            "CidrIp": "0.0.0.0/0"
                        }
                    ],
                    "Ipv6Ranges": [],
                    "PrefixListIds": [],
                    "ToPort": 80,
                    "UserIdGroupPairs": []
                }
            ],
            "OwnerId": "123456789012",
            "GroupId": "sg-0cb2dbebe96971562",
            "IpPermissionsEgress": [
                {
                    "IpProtocol": "-1",
                    "IpRanges": [
                        {
                            "CidrIp": "0.0.0.0/0"
                        }
                    ],
                    "Ipv6Ranges": [],
                    "PrefixListIds": [],
                    "UserIdGroupPairs": []
                }
            ],
            "Tags": [
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "mig-test"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/mig-test/7beeff40-affc-11e8-8b76-50a68669982a"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "SecurityGroup"
                }
            ],
            "VpcId": "vpc-1c3e1278"
        }
    ]
}

ちゃんと作成されていますね。続いて先ほど作成したJSONファイルをcfn_flipでYAMLファイルに変換します。cfn_flipについては中山がエントリを書いていますので参考にしてください。

AWSがGitHubで公開しているCloudFormationの変換ツールを使ってみた

ファイル名はmig-test.template.ymlとしました。

$ pip install cfn_flip
$ cfn-flip mig-test.template.json mig-test.template.yml

YAMLファイルが作成されたら、セキュリティグループにタグを追加してみます。

mig-test.template.yml

AWSTemplateFormatVersion: '2010-09-09'
Resources:
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: CFn migration test
      SecurityGroupIngress:
      - IpProtocol: TCP
        FromPort: 80
        ToPort: 80
        CidrIp: '0.0.0.0/0'
      Tags:
        - Key: Name
          Value: MigTest

それではこのファイルを使ってスタックを更新してみます。

$ aws cloudformation deploy \
  --stack-name mig-test \
  --template-file mig-test.template.yml

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - mig-test

$ aws ec2 describe-security-groups \
  --group-names $(aws cloudformation describe-stack-resource \
    --stack-name mig-test \
    --logical-resource-id SecurityGroup \
    | jq -r '.StackResourceDetail.PhysicalResourceId')
{
    "SecurityGroups": [
        {
            "Description": "CFn migration test",
            "GroupName": "mig-test-SecurityGroup-1WPEQP3XYW2PP",
            "IpPermissions": [
                {
                    "FromPort": 80,
                    "IpProtocol": "tcp",
                    "IpRanges": [
                        {
                            "CidrIp": "0.0.0.0/0"
                        }
                    ],
                    "Ipv6Ranges": [],
                    "PrefixListIds": [],
                    "ToPort": 80,
                    "UserIdGroupPairs": []
                }
            ],
            "OwnerId": "123456789012",
            "GroupId": "sg-0cb2dbebe96971562",
            "IpPermissionsEgress": [
                {
                    "IpProtocol": "-1",
                    "IpRanges": [
                        {
                            "CidrIp": "0.0.0.0/0"
                        }
                    ],
                    "Ipv6Ranges": [],
                    "PrefixListIds": [],
                    "UserIdGroupPairs": []
                }
            ],
            "Tags": [
                {
                    "Key": "aws:cloudformation:stack-name",
                    "Value": "mig-test"
                },
                {
                    "Key": "Name",
                    "Value": "MigTest"
                },
                {
                    "Key": "aws:cloudformation:stack-id",
                    "Value": "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/mig-test/7beeff40-affc-11e8-8b76-50a68669982a"
                },
                {
                    "Key": "aws:cloudformation:logical-id",
                    "Value": "SecurityGroup"
                }
            ],
            "VpcId": "vpc-1c3e1278"
        }
    ]
}

追加したタグが付与されていることが確認できました。

まとめ

CloudFormationがYAMLをサポートしてもうすぐ2年ですね。すでに運用中のスタックであってもJSONからYAMLへの移行はシームレスにできることがわかりました。JSONで管理しているテンプレートは積極的に移行を計画していきたいですね。