Masayan tech blog.

  1. ブログ記事一覧>
  2. 【AWS CloudFormation】インフラリソースのコード化:応用編

【AWS CloudFormation】インフラリソースのコード化:応用編

公開日

環境

  • windows10

発展的な知識

CloudFormationを使ったスタックの作成手順は以上の通りですが、ここからパラメータや組み込み関数を使用した発展的なテンプレートの書き方等について紹介します。

パラメータ

  • 要はハードコーディングを避けるために、値をパラメータとして外に出すことができる
  • テンプレートのParametersセクションに列挙する
  • デフォルト値や、複数選択候補(AllowedValues)を設定することが可能
  • ここに指定した項目はAWSコンソールでスタック作成の際に値を入力することが可能
    • SystemName
      各リソースにprefixとして付与する名称(プロジェクト名等)
    • EnvType
      リソースに付与する環境タイプ(本番、ステージング...)
    • CidrBlock
      こちらはVPCを作るときに指定する必要があるIPアドレスの割り当て
Parameters:
  SystemName:
    Description: Please type SystemName
    Type: String
    Default: ProjectName
  EnvType:
    Description: Select Environment Type.
    Type: String
    Default: prd
    AllowedValues:
      - dev
      - stg
      - prd
  CidrBlock:
    Description: Please type VPC CidrBlock.
    Type: String
    Default: 192.168.0.0/16

パラメータの順序の制御等

  • 現時点(2022/1/10)で使用できるメタデータは3種類

    https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html

  • 特に、AWS::CloudFormation::Interface:を使用すると、パラメータの順番をソートして表示できるので便利(デフォルトでは、AWS CloudFormation コンソールではパラメーターが論理 ID によりアルファベット順にソートされるので、意図しない順番で表示されるのを防止できる)
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Parameters:
          - SystemName
          - EnvType
          - CidrBlock

組み込み関数

組み込み関数リファレンス

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html

Sub

  • !Sub(CloudFormation の組み込み関数 Fn::Sub の短縮形) と${}を使用で可能
  • 以下の例では、コンソールの入力値として受け取ったCidrBlockのパラメータを展開し、VPCリソースのCidrBlockのプロパティとして指定している
Resources:
  SampleVPC:
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: !Sub ${CidrBlock}

Ref

  • 指定したパラメータやリソースを取得できる
  • パラメータでは設定された値が、リソースではリソース宣言の戻り値を返す (大抵はリソースの物理ID)
  • 例えば、EC2はインスタンスをID返す
  • インターネットゲートウェイをVPCにアタッチする場合、該当のVPCとインターネットゲートウェイと指定する必要がありますが、以下の例では、!Refでリソース名を指定することで、それぞれのリソースを指定することが可能になっている
Resources:
  SampleVPC:
  ..
  InternetGateway:
  ..

  InternetGatewayAttachment:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref SampleVPC

Select

  • 何らかのリストから値を取得できる
  • 例えば、VPCのCIDRをサブネット数で分割して、各サブネットに均等に割り当てるということが可能になる
  • !Select [ 分割したVPCのCidrのうち何個目か, !Cidr [ 参照するVPCのCidr, 何個目のsubnetか, CIDRのビット数 ]]
PublicSubnet01:
  Type: "AWS::EC2::Subnet"
  Properties:
  VpcId: !Ref SampleVPC
  AvailabilityZone: ap-northeast-1a
  CidrBlock: !Select [0, !Cidr [!GetAtt SampleVPC.CidrBlock, 1, 4]]
PrivateSubnet01:
  Type: "AWS::EC2::Subnet"
  Properties:
    VpcId: !Ref SampleVPC
    AvailabilityZone: ap-northeast-1a
    CidrBlock: !Select [1, !Cidr [!GetAtt SampleVPC.CidrBlock, 2, 4]]
..

GetAtt

  • リソースの戻り値を取得することが可能
  • Refと似ているが、GetAttはリソースのみを対象とする(パラメータやほかの変数を参照することは不可)
  • GetAttはリソースに対してのみ有効だが、Refよりも各リソースのより詳細な属性情報を取得することが可能(Refの戻り値はたいていの場合、物理IDしか取得できない)
  • RefやGetAttを使用した際の戻り値は、各リソースのドキュメントページに記載されているのでそちらを参照。(以下はVPCの例。戻り値はretrun valueの箇所に記述されている)
    https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-vpc.html
  • 例えば、以下の例では作成したVPCのCIDR値を取得できる(RefではVPCのIDしか取得できない)
!GetAtt SampleVPC.CidrBlock

テンプレートの分割

  • AWS公式によると、レイヤーごとにテンプレート(スタック)を分けて疎結合にすることを推奨している

    レイヤー

    リソース例

    Application

    EC2, RDS, ELBなど

    Security

    Security Group, IAMなど

    Network

    VPC, Subnet, Internet Gatewayなど

  • テンプレートを分けると管理がしやすくなるが、Refはテンプレート内の変数しか参照できないので、Outputsと、組み込み関数のImportValueを使用する必要がある
  • 以下は、VPCの出力の例
  • 参照される側のテンプレートでは、Outputsに値を記述
Outputs:
  SampleVPC:
    Value: !Ref SampleVPC
    Export:
      Name: !Sub "${AWS::StackName}-SampleVPC"
  • 以下は、上記で出力したVPCをセキュリティグループのリソース作成の際にインポートとして、使用している例
  • 参照する側は、組み込み関数のImportValueを使用して他テンプレートのVPCを使用することが可能
  • Outputsで出力されている値は、Export.Nameの名称で参照可能
  • !Joinは、リストの値をデリミタ(区切り文字)で連結して1つの文字列にする
  • NetworkStackNameは、VPCのリソースを記述したテンプレートで、セキュリティグループのスタック作成の際に、インプットパラメータとしてコンソールからの入力を受ける想定
Resources:
  WebSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId:
        {
          "Fn::ImportValue":
            !Join ["-", ["Ref": "NetworkStackName", "SampleVPC"]],
        }

スタックの更新

スタックを更新してリソースをアップデートすることが可能。
※更新する項目によっては、スタックの更新ではなく、新規作成なるものもあるので、事前に準文な検証を行ってください。

あらかじめ変更したい内容を更新したテンプレートファイルを用意。

対象のスタックを選択し、スタックアクションより、「既存スタックの変更セットを作成」を選択

あとは、新規でスタックを作成する場合の手順とほぼ同内容で進めると変更したテンプレートファイルの内容でスタックが更新される

ドリフト検出

作成時のリソースと現在のリソースにおける差分(ソースコードと実体の差分)

対象のスタックを選択した状態でドリフトの検出を選択する

つづいて、ドリフト結果を表示を選択する

今回は何も変更していないため、IN_SYNCとなっていますが、編集した内容がある場合、結果画面でMODIFIEDと表示されます。

以上です。

まとめ

いかがでしたでしょうか。本記事では、AWSのCloudFormationでインフラリソースのコード化を行う際に役立つTipsや応用的な使い方や情報について紹介しています