🎣

初学者向けCloudFormationテンプレートの書き方の調べ方

2024/07/09に公開

「CloudFormationが何かは分かった、次は自分が作りたいものを自分で書いてみよう!」という人のための記事です。

公式ドキュメントで書き方を調べる

リソースの書き方を調べる

リソースタイプ(Type)でググると、公式のCloudFormationユーザーガイドがヒットします。

例えばサブネットの書き方が知りたい場合は、「AWS::EC2::Subnet」で検索するとAWS::EC2::Subnet - AWS CloudFormationが見つかります。

実際にテンプレートを書くときは、やはりこのユーザーガイドを見ながら書いていくことになると思います[1]

記載例を見る

ユーザーガイドの「Example」セクションを見ると、テンプレートの例を確認できます。ここで基本的な書き方をさっと知ることができます。

サブネットの場合、以下のような例が掲載されています。

  mySubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref myVPC
      CidrBlock: 10.0.0.0/24
      AvailabilityZone: "us-east-1a"
      Tags:
      - Key: stack
        Value: production

必須プロパティを知る

プロパティ(Properties)の中で最低限必要な項目を知るには、「Required: Yes」となっているプロパティを探します。

サブネットの場合はVpcIdの指定が必須のようです。

VpcId
The ID of the VPC the subnet is in.

If you update this property, you must also update the CidrBlock property.

Required: Yes

Type: String

Update requires: Replacement

また、「Required: Conditional」となっているプロパティも場合により必須となります。サブネットの場合、通常はCidrBlockも必要になると思います。

これらの必須プロパティは、必ずテンプレートに記載するようにします。

プロパティの値の書き方を知る

プロパティの値の形式は、各プロパティの説明の「Type」に記載されています。

例えばTagsは「Type: Array of Tag」と記載されています。

Tags
Any tags assigned to the subnet.

Required: No

Type: Array of Tag

Update requires: No interruption

「Tag」のリンクを開くと、以下の構文であることが分かります。

  Key: String
  Value: String

したがって、Tagsはその配列となるため、以下のようにテンプレートを書けばよいことが分かります。

  Tags:
    - Key: key1
      Value: value1
    - Key: key2
      Value: value2

このようにして、リソースの各プロパティを埋めていきます。

!Ref!GetAttで得られる値を知る

他のリソースで!Ref mySubnetのようにリソースを参照することがよくありますが、このとき返ってくる値は何でしょうか?

それは「Return values」セクションの「Ref」を見ると分かります。

サブネットの場合は「IDを返す」と説明されています。

Ref
When you pass the logical ID of this resource to the intrinsic Ref function, Ref returns the ID of the subnet.

サブネットの場合はIDを返すとすぐに分かるかもしれませんが、以下のように迷うリソースもあります。リソースタイプによって返す値はかなりバラバラであるため、参照を使用する際は都度確認が必要です。

また、同じセクションの「Fn::GetAtt」で、!GetAttで得られるアトリビュートも確認することができます。

例えば、サブネットでは!GetAtt mySubnet.CidrBlockのように書くと、サブネットのIPv4 CIDRブロックの値を得られることが分かります。

!RefなどのCloudFormation特有の表記を調べる

リソースのプロパティの書き方以外にも、CloudFormation特有の書き方のコツを知っておく必要があります。

すぐにすべてを覚える必要はありませんが、一度目を通しておくと、後で役に立つ場面があるはずです。

既存のリソースを参考にする

コンソールで作ったリソースを参考に、各プロパティの書き方を調べたい場合があると思います。

そんなときは、AWS CLIでget-*describe-*list-*などの読み取りコマンドを実行するとよく分かります。

# サブネットのプロパティを取得できそうなコマンドを確認します。もちろんググっても良いです。
$ aws ec2 help | grep subnet
       o associate-subnet-cidr-block
       o create-default-subnet
       o create-subnet
       o create-subnet-cidr-reservation
       o delete-subnet
       o delete-subnet-cidr-reservation
       o describe-subnets
       o disassociate-subnet-cidr-block
       o get-subnet-cidr-reservations
       o modify-subnet-attribute

# describe-subnetsで行けそうなので実行します。
$ aws ec2 describe-subnets
{
    "Subnets": [
        {
            "AvailabilityZone": "ap-northeast-1c",
            "AvailabilityZoneId": "apne1-az1",
            "AvailableIpAddressCount": 4091,
            "CidrBlock": "10.0.16.0/20",
            "DefaultForAz": false,
            "MapPublicIpOnLaunch": false,
            "MapCustomerOwnedIpOnLaunch": false,
            "State": "available",
            "SubnetId": "subnet-1234567890abcdefg",
            "VpcId": "vpc-1234567890abcdefg",
            "OwnerId": "123456789012",
            "AssignIpv6AddressOnCreation": false,
            "Ipv6CidrBlockAssociationSet": [],
            "Tags": [
                {
                    "Key": "Name",
                    "Value": "mysystem-subnet-public2-ap-northeast-1c"
                }
            ],
            "SubnetArn": "arn:aws:ec2:ap-northeast-1:123456789012:subnet/subnet-1234567890abcdefg",
            "EnableDns64": false,
            "Ipv6Native": false,
            "PrivateDnsNameOptionsOnLaunch": {
                "HostnameType": "ip-name",
                "EnableResourceNameDnsARecord": false,
                "EnableResourceNameDnsAAAARecord": false
            }
        },
        ...

これを見ると、describe-subnetsの出力はAWS::EC2::Subnetの構文とほとんど同じであることが分かります。

Type: AWS::EC2::Subnet
Properties:
  AssignIpv6AddressOnCreation: Boolean
  AvailabilityZone: String
  AvailabilityZoneId: String
  CidrBlock: String
  EnableDns64: Boolean
  EnableLniAtDeviceIndex: Integer
  Ipv4IpamPoolId: String
  Ipv4NetmaskLength: Integer
  Ipv6CidrBlock: String
  Ipv6CidrBlocks: 
    - String
  Ipv6IpamPoolId: String
  Ipv6Native: Boolean
  Ipv6NetmaskLength: Integer
  MapPublicIpOnLaunch: Boolean
  OutpostArn: String
  PrivateDnsNameOptionsOnLaunch: 
    PrivateDnsNameOptionsOnLaunch
  Tags: 
    - Tag
  VpcId: String

よって、AWS CLIの出力と同じようにテンプレートを書けば、同じようなリソースを作成することができます。

AIに書いてもらう

最近では、まずはAIに書いてもらうのも良い手段だと思います。

ChatGPTに「○○を含むCloudFormationテンプレートをYAML形式で書いて」などと聞いてみると、説明付きでテンプレートを例示してくれて便利です。

本格的にやるなら、Visual Studio CodeにAmazon Q拡張機能をインストールしてAWS Builder IDにサインアップしてCodeWhisperer(AIコード提案機能)を使用するといった方法もあります。

書き方が合っているか検査する

CloudFormation Linter(cfn-lint)をインストールして、テンプレートをデプロイする前に書き方の間違いに気づけるようにしましょう。

Pythonのpipを使用するため少し導入のハードルが高いですが、CloudFormationテンプレートを開発するならばほぼ必須のツールだと思います。

具体的なインストール方法や使い方はここでは省略します。

脚注
  1. ググってヒットしたQiitaやZennやDevelopersIOのテンプレートをコピーして弄るだけで満足するな! ↩︎

  2. 答え:VpcIdプロパティを指定したときはIDを、そうでないときはセキュリティグループ名を返します。 ↩︎

  3. 答え:関数名を返します。 ↩︎

  4. 答え:ARNを返します。 ↩︎

Discussion