CloudFormationで起動テンプレートを使用する際に注意すること

記事タイトルとURLをコピーする

こんにちは、SWX3人目の熊谷(悠)です。
以下のような事象が発生しましたので、回避策を残しておきます。

事象

CloudFormation(以下CFn)を用いて、起動テンプレートからEC2 インスタンス(以下EC2)を作成する際に、起動テンプレートの設定で上書きされませんでした。
なお、CFnを用いず、マネジメントコンソール(以下マネコン)にてテンプレートからEC2を起動する場合は、問題無く設定内容が反映されます。

以下画像のような設定で起動テンプレートを作成します。
※起動テンプレート自体はCFnで作成してもマネコンから作成しても変わりません。 2020-08-30_18h05_40.png

CFnでこの起動テンプレートを指定して作成したEC2の設定は以下画像のようになります。
実際にできたEC2と起動テンプレートで設定内容が異なっています。

使用したCFnテンプレート
起動テンプレートとEC2を同時に作成する場合
AWSTemplateFormatVersion: "2010-09-09"
Description: "Template Settings Overwrite Test"
Parameters:
  ImageId:
    Default: "ami-0cc75a8978fbbc969"
    MinLength: 1
    Type: "String"
  KeyPairName:
    MinLength: 1
    Type: "AWS::EC2::KeyPair::KeyName"
  SubnetIdForEth0:
    MinLength: 1
    Type: "AWS::EC2::Subnet::Id"
  SecurityGroupIdsForEth0:
    MinLength: 1
    Type: "List<AWS::EC2::SecurityGroup::Id>"
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      -
        Label:
          default: "Basic Configuration"
        Parameters:
          - "InstanceType"
          - "ImageId"
          - "KeyPairName"
      -
        Label:
          default: "NetworkInterface Configuration For Eth0"
        Parameters:
          - "SubnetIdForEth0"
          - "SecurityGroupIdsForEth0"
Resources:
  EC2LaunchTemplate:
    Type: "AWS::EC2::LaunchTemplate"
    DeletionPolicy: "Delete"
    Properties:
      LaunchTemplateName: "test_EC2LaunchTemplate"
      LaunchTemplateData:
        BlockDeviceMappings:
          - DeviceName: "/dev/xvda"
            Ebs:
              DeleteOnTermination: true
              Encrypted: false
              VolumeSize: 8
              VolumeType: "gp2"
        CreditSpecification:
          CpuCredits: "unlimited"
        DisableApiTermination: true
        EbsOptimized: true
        ImageId:
          Ref: "ImageId"
        InstanceInitiatedShutdownBehavior: "terminate"
        InstanceType: "t3.nano"
        KeyName:
          Ref: "KeyPairName"
        Monitoring:
          Enabled: true
        NetworkInterfaces:
          - AssociatePublicIpAddress: true
            DeleteOnTermination: true 
            DeviceIndex: 0
            Groups:
              Ref: "SecurityGroupIdsForEth0"
            SubnetId:
              Ref: "SubnetIdForEth0"
        TagSpecifications:
          - ResourceType: "instance"
            Tags:
              - Key: "Name"
                Value: "test"
          - ResourceType: "volume"
            Tags:
              - Key: "Name"
                Value: "test-root"
  EC2Instance:
    Type: "AWS::EC2::Instance"
    Properties:
      LaunchTemplate:
        LaunchTemplateId: !Ref 'EC2LaunchTemplate'
        Version: !GetAtt 'EC2LaunchTemplate.LatestVersionNumber'
Outputs:
  EC2LaunchTemplate:
    Value: !Ref 'EC2LaunchTemplate'
    Export:
      Name: !Sub '${AWS::StackName}-LaunchTemplateID'

上のCFnテンプレートで作成した起動テンプレートを別スタックで指定してEC2を作成する場合

AWSTemplateFormatVersion: "2010-09-09"
Description: "Overwriting test of template settings to be imported"
Parameters:
  EC2LaunchTemplateStackName:
    MinLength: 1
    Type: "String"
Resources:
  EC2Instance:
    Type: "AWS::EC2::Instance"
    Properties:
      LaunchTemplate:
        LaunchTemplateId:
          Fn::ImportValue:
            !Sub '${EC2LaunchTemplateStackName}-LaunchTemplateID'
        Version: "1"

マネコンで作成した起動テンプレートを指定してEC2を作成する場合

AWSTemplateFormatVersion: "2010-09-09"
Description: "Overwriting test of template settings to be imported"
Resources:
  EC2Instance:
    Type: "AWS::EC2::Instance"
    Properties:
      LaunchTemplate:
        LaunchTemplateId: "lt-xxxxxxxxxxxxxxxxx"
        Version: "1"

2020-08-30_18h22_58.png2020-08-30_18h23_53.png

AWS::EC2::Instance ドキュメントLaunchTemplate項目には以下記載があります。

インスタンスの起動に使用する起動テンプレート。AWS CloudFormation テンプレートで指定したパラメータはすべて、起動テンプレート内の同じパラメータを上書きします。

記載通りならEC2を作成するCFnで起動テンプレートを指定した場合は、設定内容が上書きされる筈なので、完全に謎です。
ただし、全ての項目が上書きされないわけではなく、以下の項目が上書きされないようです。

  • DisableApiTermination(終了保護)
  • EbsOptimized(EBS 最適化インスタンス)※
  • InstanceInitiatedShutdownBehavior(シャットダウン動作)
  • Monitoring(CloudWatch モニタリングの詳細)

※EBS 最適化インスタンス項目については、デフォルトでEBS最適化がサポートされるインスタンスタイプの場合、false指定であってもEBS最適化が適用されます。false にすると マネコン上の表示やawscliで参照した結果は false になるもののEBS最適化は適用状態となります。

結論

AWSサポートに問い合わせたところ、不具合との事でした。

ご連絡いただきました事象が再現することを確認いたしました。
CloudFormation によるパラメータの暗黙的な上書きが発生していることが分かりました。
なお、この動作につきましてはドキュメント化されていない動作となり、将来的に変更される可能性も考えられます。
AWSサポート回答より※2020/08/27時点

回避策

現状では、EC2を作成するCFnテンプレートのAWS::EC2::Instanceリソース側で、明示的にプロパティを指定すれば起動テンプレートを指定していても任意の設定が可能です。

例えば、以下のようにCFnテンプレートを作成すれば、終了保護がTrueになります。

AWSTemplateFormatVersion: "2010-09-09"
Description: "Overwriting test of template settings to be imported"
Resources:
  EC2Instance:
    Type: "AWS::EC2::Instance"
    Properties:
      LaunchTemplate:
        LaunchTemplateId: "lt-xxxxxxxxxxxxxxxxx"
        Version: "1"
      DisableApiTermination: true # 終了保護設定項目を追加

熊谷 悠司 (記事一覧)