【AWS】起動テンプレートとBatch Compute環境を同時に書くと、起動テンプレートが3つ生成される

# 概要
以前作成したAWS BatchのAutoscalingGroup設定を確認すると「起動設定」になっていました。
今回、これを起動テンプレートにしたところなぜか3つも自動作成されました...色々試したので、記事にします。

# 前提・Cfnテンプレート

まず、AWS BatchをCloudformationで作成すると、EC2を起動するためにAutoscalingGroupが作成されることを確認しました。なので、そのAutoscalingの設定を起動テンプレートにしてあげればよいのでは？と思い、以下のようにしました。

`BatchComputeEnvironment`に`LaunchTemplate`を加えています。
（セキュリティグループやサブネットなどは省いています）

```yaml
  BatchServiceRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
              - batch.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSBatchServiceRole
      Path: "/"
      RoleName: BatchServiceRole

  BatchComputeEnvironment:
    Type: 'AWS::Batch::ComputeEnvironment'
    Properties:
      Type: MANAGED
      ServiceRole: !GetAtt BatchServiceRole.Arn
      ComputeEnvironmentName: sample-batch-ec2-compute-environment
      ComputeResources:
        Type: EC2
        LaunchTemplate:
            LaunchTemplateName: sample-launch-template
            Version: $Latest
        MinvCpus: !Ref MinvCpus
        DesiredvCpus: !Ref DesiredvCpus
        MaxvCpus: !Ref MaxvCpus
        InstanceTypes:
          - optimal
        InstanceRole: !GetAtt BatchInstanceProfile.Arn
        Subnets:
          - !ImportValue PrivateSubnet
        SecurityGroupIds:
          - !Ref BatchSecurityGroup
        Tags: {"Name": "sample-batch"}
      State: ENABLED

  BatchJobQueue:
    Type: 'AWS::Batch::JobQueue'
    Properties:
      ComputeEnvironmentOrder:
        - ComputeEnvironment: !Ref BatchComputeEnvironment
          Order: 1
      Priority: 1
      State: ENABLED
      JobQueueName: sample-batch-job-queue


  BatchLaunchTemplate:
    Type: 'AWS::EC2::LaunchTemplate'
    Properties:
      LaunchTemplateName: sample-launch-template
      LaunchTemplateData:
        InstanceType: "t3.micro"
        IamInstanceProfile:
          Arn: !GetAtt BatchInstanceProfile.Arn
        KeyName: !Ref KeyPair
        SecurityGroupIds:
          - !Ref BatchSecurityGroup
        TagSpecifications:
          - ResourceType: instance
            Tags:
              - Key: Name
                Value: "sample-batch"

  BatchInstanceProfile:
    Type: "AWS::IAM::InstanceProfile"
    Properties:
      Roles:
        - !Ref EcsInstanceRole
```

上記で実行すると、なぜか起動テンプレートが3つも自動で生成されます。
上記の`LaunchTemplate`の部分を消すと、生成されるのは2つになりました。

また、試しに管理コンソールから`Compute Environment`のJSONで指定された起動テンプレートのIDを確認。このIDの起動テンプレートを削除しても、バッチは正常に動作。これで起動テンプレートは1つになりました。
Autoscaling Groupで指定された起動テンプレートのみが残っている状態です。

結論、`Compute Environment`を作り替えたら勝手に起動テンプレートになった、というお話...。
なぜかはわかりません。
この現象について調べてみましたが、特に似ている現象の方はいませんでした。

以下アナウンスのようにAWSは以前から、起動テンプレートへの移行を推奨する、と言っているので、これと関係があるかもしれません。私がAWS Batchを作成したのは一年前くらいなので、その時と何か仕様が異なるのかも。

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/migrate-to-launch-templates.html

## わかったことまとめ
改めてまとめ。

まずは`Compute Environment`を作成すれば、自動でAutoscalingGroupと`LaunchTemplate`が作成されることはわかりました。なので、
```
  BatchLaunchTemplate:
    Type: 'AWS::EC2::LaunchTemplate'
    ...
```
というように書いていましたが、これは不要っぽい。
同時に、`Compute Environment`で以下のように指定していたのも不要でした。


```
        LaunchTemplate:
            LaunchTemplateName: sample-launch-template
            Version: $Latest
```


次に、それでも二つの起動テンプレートが生成されるので、生成後にAutoScalingGroupに紐づいていないほうの起動テンプレートだけ消してあげます。そうすると、テンプレートは一つになりスッキリします。

## 原因
このようにする必要があるのは、そもそもAWS Batchは「起動設定」をメインに設計されているからなのでしょうか。
AWS Batchは、CPUやメモリに最適化されたコンピューティング環境を用意し、バッチジョブを処理するサービス。つまり、そもそも起動テンプレートを作ってあげる、というようなユーザが任意のEC2を作成するような思想ではないのかも。

とはいえ、ドキュメントには指定できるような書き方がある...よくわからん。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-batch-computeenvironment-launchtemplatespecification.html

また、なぜか二つ生成される理由の推測ですが、よく見ると一つはインスタンスタイプが入っていて、一つはインスタンスタイプが入っていませんでした。つまり`optimal`にすることで、インスタンスタイプを選択していない自由なテンプレートと、指定したcpu/メモリと合致するインスタンスタイプを用意するテンプレートと二つを作成し、より最適なテンプレートを選んでいくという仕組みなのかもしれません。

ということで、以上推測ではあります。何か他にご存知の方がいればぜひ教えてください。

## 備忘録

ちなみに、`Compute Environment`と`LaunchTemplate`を同時に作成していたとき、EC2テンプレートの`NetworkInterfaces`以下にSecurityGroupを参照している一方、`Compute Environment`でもSecurityGroupを参照していると以下のエラーになりました。

> Resource handler returned message: "Error executing request, Exception : Either compute environment Security Groups or Network Interfaces in Launch template are exclusively allowed,

`NetworkInterfaces`ではなくて、`ComputeResources`直下の`SecurityGroupIds`で指定してあげればエラーは無くなります。