ECS(EC2)のScheduleTaskをCloudFormationで管理

タイトルどおりの備忘録です。

ECSのタスク定義を流用してオーバーライドしてcronみたいにバッチ実装しているのをCloudFormationで管理したいという話でやってみたらオーバーライドがなんかできそうもない？
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-events-rule-target.html
とおもいきや、CloudwatchEventのあたりの既存のルールをみたところ、Overrideの定義してる風の項目名にInputとかあるのでよく見るとCloudFormationで定義できそうだなあ～と思って気軽な気持ちでStateはDISABLEでテストしてみたところなんか登録できました。よかったです。


```yaml:scheduletask-test.yml
---
AWSTemplateFormatVersion: '2010-09-09'
Description: 'ecs scheduled task for test'
Parameters:
  BatchName:
    Type: String
    Description: A name of scheduletask
    Default: 'cftest'
  TaskDifinitionArn:
    Type: String
    Description: A name of task difinitionARN
    Default: "arn:aws:ecs:<region>:<awsaccount-number>:task-definition/<task-name>:<task-num>"
  ScheduleExpression:
    Type: String
    Description: Cron settings
    Default: 'cron(0 19 * * ? *)'
  TaskState:
    Type: String
    Description: state of scheduletask
    Default: DISABLED
  TasktargetInput:
    Type: String
    Description: command override input json
    Default: '{"containerOverrides":[{"name":"<container-name>","command":["php","artisan","command:xxx"]}]}'
Resources:
  TaskScheduleEvents:
    Type: AWS::Events::Rule
    Properties:
      Name: !Ref BatchName
      ScheduleExpression: !Ref ScheduleExpression
      State: !Ref TaskState
      Targets:
        - Id: !Ref BatchName
          RoleArn: "arn:aws:iam::<awsaccount-number>:role/ecsInstanceTaskRole"
          EcsParameters:
            TaskDefinitionArn: !Ref TaskDifinitionArn
            TaskCount: 1
          Arn: "arn:aws:ecs:<region>:<awsaccount-number>:cluster/<cluster-name>"
          Input: !Ref TasktargetInput

```
ECSクラスタとかタスク定義とかは既にある既存のARNを指定するかんじなので、なかったら別途つくらないとです。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/quickref-ecs.html
https://qiita.com/f-naoto832/items/d6523786daa128ddfe60

一応ググって出てきたやつを載せておきます

APIでスケジュールタスクの登録やってる人の記事
https://qiita.com/nagais/items/916fde2035a07beb80b7
APIでECSタスクをオーバーライド
https://codeday.me/jp/qa/20190401/519741.html
APIのマニュアル
https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerOverride.html

ECSまわりのARNも命名規則がありcliで調べなくていいんだなと思いました。
https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-arns-and-namespaces.html

```
arn:aws:ecs:region:account-id:cluster/cluster-name
arn:aws:ecs:region:account-id:container-instance/cluster-name/container-instance-id
arn:aws:ecs:region:account-id:task-definition/task-definition-family-name:task-definition-revision-number
arn:aws:ecs:region:account-id:service/cluster-name/service-name
arn:aws:ecs:region:account-id:task/cluster-name/task-id
arn:aws:ecs:region:account-id:container/container-id
```

stepfunctionのマニュアル(わりと関係ないがOverrideがのってた）
https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/connect-ecs.html

同じタスク定義つかってるのでCloudFormationだとまとめて色々書けそうかもですが、まとめて書いたものが運用引継ぎしやすいかどうかは多少考えたほうがいいのかな。

```yaml:マッピングの部分抜粋
Mappings:
  taskschedules:
    Cron1:
      Name: shori1 
      ScheduleExpression: 'cron(0 19 * * ? *)'
      State: ENABLED 
      TaskDifinitionArn: 'arn:aws:ecs:<region>:<account-num>:task-definition/task1:13'
      Input: '{"containerOverrides":[{"name":"contanier-name1","command":["php","artisan","command:shori1"]}]}'
    Cron2:
　　...
Resources:
  TaskScheduleEvents1:
    Type: AWS::Events::Rule
    Properties:
      Name: !FindInMap [taskschedules, "Cron1", "Name"]
      ScheduleExpression: !FindInMap [taskschedules, "Cron1", "ScheduleExpression"]
      State: !FindInMap [taskschedules, "Cron1", "State"]
      Targets:
        - Id: !FindInMap [taskschedules, "Cron1", "Name"]
          RoleArn: !Ref RoleArn
          EcsParameters:
            TaskDefinitionArn: !FindInMap [taskschedules, "Cron1", "TaskDifinitionArn"]
            TaskCount: 1
          Arn: !Ref EcsClusterArn
          Input: !FindInMap [taskschedules, "Cron1", "Input"]
  TaskScheduleEvents2:
     ...
```

たぶんカンマ区切りセレクトとかでなんとかするのがパラメータ節約（上限が50)とかにもなるし楽かもしれないと思ったんですが、InputのJSONに入ったカンマを違うのに変えるとかできなくてMappingにするしかなかったですね。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html#parameters-section-structure-properties

マッピングは環境ちがうとき用っぽいかも？と思ったけど辞書型の変数として便利だなと思いました。
https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/mappings-section-structure.html

別のラッパーツール使うなかでも以下は単純そうかなとは思いました。
https://qiita.com/yoshizow/items/bdf668a69e187eae1aba

マイスターシリーズ
https://www.slideshare.net/AmazonWebServicesJapan/aws-aws-cloudformation

実際にスタック作る時、同じ名前のリソースがすでにある感じだったので、既存リソースキャプチャとって確認して消してからスタック作る感じでした。

以上