CloudFormationでAWSリソースを自動構築

CloudFormationは、AWSを利用する上で活用しておきたいサービスですが、ドキュメント量が膨大で理解に苦労します。そこで、CloudFormationの全体像を把握しやすくなるように押さえておきたいポイントを解説します。

CloudFormationとは

概要

テンプレートからAWSリソース( EC2 RDS S3 VPC Subnet など)を自動構築するためのサービスです。

インフラ構成をテンプレートで管理することで以下のメリットがあります。

  • 同じインフラ構成をすぐに再現できる。
  • インフラ構成をバージョン管理できる。
  • インフラ構成が可視化される。

テンプレートとスタック

CloudFormationを説明する中で、 テンプレートスタック という用語が出てきます。

489-aws-cloudformation_image.png

テンプレート とは、どのAWSリソースをどのような設定で起動するかコードで記述したものになります。

スタック とは、テンプレートから生成されるAWSリソースの集合です。スタック を消すと、紐づくリソースも全て消えます。

テンプレートの書き方|フォーマット

テンプレートファイルのフォーマットとして JSONYAML を利用できます。

YAMLがおすすめ
YAMLだとコメントを記述できるのでおすすめです。YAMLの書き方については こちら で取り上げています。注意点が1つあり、CloudFormationのYAMLは アンカー・エイリアス機能 を利用できません。

テンプレートの書き方|構成

全体構成

構成は以下のようになります(YAML形式)。

AWSTemplateFormatVersion: "version date"

Description:
  String

Metadata:
  template metadata

Parameters:
  set of parameters

Mappings:
  set of mappings

Conditions:
  set of conditions

Transform:
  set of transforms

Resources:
  set of resources

Outputs:
  set of outputs
セクション 必須 説明 AWSドキュメント
Format Version × テンプレートのバーションを指定します。 リンク
Description × テンプレートの説明を記述します。 リンク
Metadata × テンプレートの追加情報を記述します。 リンク
Parameters × テンプレートを実行するときに、ユーザーに入力させるパラメータを定義できます。Ref 組み込み関数 でパラメータの値を取得できます。

■ 利用例
DBのパスワード環境タイプ(dev, prodなど) を実行時に決定。
リンク
Mappings × 連想配列を定義できます。Fn::FindInMap 組み込み関数 でマップの値を取得できます。

■ 利用例
リージョンが us-east-1 のときは xxx を取得。
リージョンが ap-northeast-1 のときは yyy を取得。
リンク
Conditions × 条件を定義できます。 ResourcesConditionキー で作成した条件をもとにリソース制御できます。

■ 利用例
あるパラメーターが prod と等しい場合に true にするという 条件 を作成。
作成した 条件 を利用して、リソースを作成するか判定。
リンク
Transform × サーバーレスアプリケーションを利用するときなどに使います。 リンク
Resources AWSリソースを指定します(後述)。 リンク
Output × スタック構築後に出力させたい情報を記述します。Fn::ImportValue 組み込み関数 を利用して異なるスタックからOutputの値を参照できます。 リンク

Resourcesセクションの構成

Resources:
  Logical ID:
    Type: Resource type
    Properties:
      Set of properties

Logical ID は他のリソースから Ref 組み込み関数 で参照する際に利用されます。

Resource type ごとの詳しい設定方法は こちら から確認できます。

作成手順

各セクションですが以下の流れで利用すると良いかと思います。

  • Format VersionDescription を書く。
  • Resources を書く。
  • 再利用しやすくなるようにリファクタリングする。
    • ハードコーディングされている箇所を探す。
    • Parameters Mappings Conditions 組み込み関数 などを利用して書き直す。

テンプレートの書き方|擬似パラメータ

概要

AWSで事前定義されたパラメータです。

以下、主なパラメータです。

擬似パラメータ 概要
AWS::AccountId AWSアカウントIDを取得
AWS::Region AWSリージョン名を取得
AWS::StackName スタックの名前を取得

参考

テンプレートの書き方|組み込み関数

Ref

パラメーターの値 擬似パラメーターの値 リソースの値 を取得できます。

Fn::FindInMap

Mappingsセクション で定義した値を取得できます。

Fn::GetAtt

テンプレートの Resources で指定したリソースから 属性値 を取得できます。

Resources:
  MyELB:
    Type: AWS::ElasticLoadBalancing::LoadBalancer
    Properties:
      (省略)
  MyELBIngressGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ELB ingress group
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: '80'
          ToPort: '80'
          SourceSecurityGroupOwnerId: !GetAtt MyELB.SourceSecurityGroup.OwnerAlias
          SourceSecurityGroupName: !GetAtt MyELB.SourceSecurityGroup.GroupName

!GetAtt logicalNameOfResource.attributeName で取得しています。

Fn::ImportValue

異なるスタックの Outputセクション で出力された値を取得できます。

Fn::Select

# bbb を取得します。
!Select [ "1", [ "aaa", "bbb", "ccc", "ddd" ] ]

Fn::Split

# ["aaa", "", "ccc", ""] を取得します。
!Split [ "," , "aaa,,ccc," ]

Fn::Join

# "a:b:c" を取得します。
!Join [ ":", [ a, b, c ] ]

Fn::Sub

JavaScriptの テンプレート文字列 のような機能を持ちます。

# RootDomainNameが「wakuwakubank.com」だった場合、「www.wakuwakubank.com」を取得します。
Name: !Sub
  - www.${Domain}
  - { Domain: !Ref RootDomainName }

短縮記法

YAMLであれば 短縮記法 が使えます。

Fn系 であれば以下のようになります。

Fn::FindInMap: [ MapName, TopLevelKey, SecondLevelKey ]
!FindInMap [ MapName, TopLevelKey, SecondLevelKey ]

Ref であれば以下のようになります。

Ref: logicalName
!Ref logicalName

参考

CloudFormation実行時の注意点

スタック作成

  • 作成したテンプレートを指定して実行します。
  • 作成するリソースのIAM権限が必要です。
    • 例えば、RDSのインスタンスを作成する場合、RDSの作成権限がないと失敗します。
  • 途中で失敗した場合、途中まで作成したものも全て削除されます。

参考

スタック更新

  • 修正したテンプレートを指定して実行します。
  • 修正したリソースのみが更新されます。
  • 修正内容により更新動作が異なります。
    • インスタンスタイプを変更した場合、 インスタンスが再起動されます。
    • AMIを変更した場合、 新しくインスタンスが作られます。作成後、古いインスタンスは削除されます。

参考

スタック削除

  • スタックを削除すると、紐づくAWSリソースはすべて削除されます。
  • DeletionPolicy属性 を使用して、リソースを削除しないようにすることもできます。

参考

テンプレート作成の効率化

公開テンプレートの利用

インターネット上で公開されているテンプレートに、既に似たような目的のテンプレートが存在するかもしれません。公開テンプレートを活用すると作業が早くなるかと思います。

Design TemplateとCloudFormer

テンプレート作成を支援するためのツールが提供されています。

テンプレートの分割

1つのテンプレートにリソースを含めすぎると、管理しづらく、再利用しづらいテンプレートになります。
そういったときには、以下のようにテンプレートの分割を検討します。

  • ネットワーク構築用のテンプレート
  • DB構築用のテンプレート

参考

IntelliJ IDEA用のプラグイン

IntelliJ IDEAを利用されているかたであれば、 AWS CloudFormationプラグイン の利用をおすすめします。入力候補の表示や、タイプミスの表示など役立ちます。

489-aws-cloudformation_plugin.png

参考

AWS CloudFormation ドキュメント

https://docs.aws.amazon.com/cloudformation/index.html#lang/ja_jp

BlackBelt

わくわくBank.
技術系の記事を中心に、役に立つと思ったこと、整理したい情報などを掲載しています。