CloudFormation の参照周りで意識すべきポイント・Tips

2020.06.18

AWS CloudFormation の参照周り(主に RefImportValue ) で意識すべきポイントやTipsを主観で並べてみました。

目次

  1. Ref を使う場面を把握する
  2. ImportValue を使う場面を把握する
  3. RefImportValue の使う場面の違いを把握する
  4. Ref で何の値を返すか調査する
  5. GetAtt で何の値を返せるか調査する
  6. Outputsセクション で何の値を渡すのかを意識する
  7. 擬似パラメータの活用を検討する
  8. Mappingsセクション を使った参照を検討する
  9. Parameter Store/Secrets Manager を使った参照を検討する
  10. おわりに

Ref を使う場面を把握する

組み込み関数 Ref は以下の用途で使用します。

以下は SampleVpc リソースのプロパティで VpcCidr パラメータを参照、 SampleSunet リソースのプロパティで SampleVpc リソースを参照する例です。 (※ !Ref は短縮形の記法)

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  VpcCidr:
    Type: String
Resources:
  SampleVpc:
    Type: AWS::EC2::VPC
    Properties:
      # パラメータの VpcCidr を参照
      CidrBlock: !Ref VpcCidr
  SampleSubnet:
    Type: AWS::EC2::Subnet
    Properties: 
      # リソースの SampleVpc を参照
      VpcId: !Ref SampleVpc
      ︙

ImportValue を使う場面を把握する

組み込み関数 Fn::ImportValue は別のスタックで エクスポートされた値 を参照するときに使います。 下図はスタックAでエクスポートされた値 (VPC ID) をスタックBで参照する例です (※ !ImportValue は短縮形の記法)

img

RefImportValue の使う場面の違いを把握する

以下意識することが大事です。

  • 同じスタックのリソース(もしくはパラメータ)を参照したい場合は Ref を使う
  • 別のスタックのリソース(もしくは何かしらの値)を参照したい場合は エクスポートされている名前、値を確認した上で ImportValue を使う

「別スタックのリソースを "Ref" で参照している」「同一スタック内のリソースを "ImportValue" で参照している」 は 関連するエラーでよくあると思います。

Ref で何の値を返すか調査する

リソースの参照で Ref を使うときは公式ドキュメントを見て、何の値が返されているか確認しましょう。

例えば AWS::EC2::VPC の場合は "VPC ID"、 AWS::IAM::Role の場合は "ロール名" が返されます。 これらの値は公式ドキュメントの「戻り値」セクションで確認できます。 リソースによって IDが返されたり、名前が返されたりと、異なります。

img

同じように、あるリソースのパラメータで Ref を使用しているときは 公式ドキュメントにある、そのパラメータの説明を確認しましょう。

前述の Ref の例で サブネットの VpcID パラメータに !Ref SampleVpc を指定しましたが、このときに「 VpcID パラメータで必要な値」と「 !Ref SampleVpc で返される値」 が合致しているかどうか、頭の片隅に置くことが大事です。

img

GetAtt で何の値を返せるか調査する

組み込み関数 Fn::GetAtt でリソースの属性を返すことができます。 返せる属性は リソースごとに異なる ので公式ドキュメントを参照しましょう。

例えば AWS::IAM::RoleFn::GetAtt によって、「ロールのARN」およびの「ロールを識別する文字列」を返すことができます。

img

以下は 以前書いた Chatbotブログ で使用したテンプレートで GetAtt を利用している場面です。 ( !GetAtt は短縮形の記法)

img

はじめにこのテンプレートを書き始めたとき、ドキュメントをしっかり読まずに IamRoleArn: !Ref ChatbotIamRole (これはロール名を返すので間違い) としていたため エラーが発生していました。リソースのパラメータに必要な値が Ref による 戻り値で書けるかどうか 、書けない場合は GetAtt による 属性で書けるかどうか 、調査が必要です。

Outputsセクション で何の値を渡すのかを意識する

Outputs セクションは以下用途があります。

  • 別スタックで値を参照( ImportValue )する
  • CloudFormation コンソールに値を出力する

ImportValue を使ったクロススタック参照では特に意識が必要です。

img

「参照先スタックで必要なパラメータの種類」がちゃんと 「参照元スタックのOutputs」でエクスポートできているか、確認しましょう。 場合によって、「 GetAtt によって属性をエクスポートしないといけないケース」、 「文字列操作をしてエクスポートしないと行けないケース」など出てくることもあります。

▼ 文字列操作には 組み込み関数 Fn::Sub などが利用できます

擬似パラメータの活用を検討する

擬似パラメーターは AWS CloudFormationで事前定義されたパラメータです。 以下のようなパラメータを Ref を使って参照できます。

パラメータ名 内容
AWS::AccountId スタックが作成されるアカウントのAWSアカウントID
AWS::Region スタックが作成されるAWSリージョン
AWS::StackName スタックの名前

「アカウント、リージョンごとに異なる値を指定」する場合や 「スタック名に基づいた命名規則」がある場合などに、活用できると思います。

Mappingsセクション を使った参照を検討する

プログラミングでいう Mapや Hash, Dictionary(的なもの)を Mappings セクションで作成し、 参照できます。参照は 組み込み関数 Fn::FindInMap で行います。

Mappings セクションに以下のような記述があったとします。

Mappings: 
  Mapping01: 
    Key01: 
      Name: Value01
    Key02: 
      Name: Value02
    Key03: 
      Name: Value03

このとき、 Mapping01 > Key01 > Name の値 Value01 を表現したい場合、 Fn::FindInMap によって次のように表せます。

  • Fn::FindInMap: [ Mapping01, Key01, Name ]
  • または !FindInMap [ Mapping01, Key01, Name ] (短縮形の場合)

「環境(ステージ)ごとに異なるパラメータを利用したい」、 「リージョンやアカウントごとに異なるパラメータを利用したい」 などのケースに Mappings は便利なので一度検討すると良いと思います。

▼アカウントごとに異なるパラメータを指定する例

Parameter Store/Secrets Manager を使った参照を検討する

AWS Systems Manager(SSM) パラメータストアや AWS Secret Manager に保存した値を 動的に参照することができます。

  • リソースのパラメータを SSMパラメータストア に外出しして管理する。スタック作成時にも利用する
  • パスワードなど秘匿情報を SSMパラメータストア Secure Strings または Secret Mamager に保存して テンプレートからスタックを作成するときに参照する

などの利用シーンがあります。

秘匿情報は SSMパラメータストア Secure Strings または Secret Mamagerに保存しましょう。 テンプレートにパスワードを書いてしまうと、CloudFormationのコンソールから見れる状態になってしまいます。 また、大規模な環境で多くのスタックで共通して使われるパラメータがある場合は、 SSMパラメータストアに保存して利用してもらうと、管理が楽になることが多いです。

おわりに

CloudFormation の参照周りつまずきやすいポイント・Tipsをまとめてみました。 少しでもどなたかのお役に立てば幸いです。

以下今回載せた公式ドキュメントのリンク集です。