平常運転

アニソンが好き

過去記事とかは記事一覧で見れます

AWS CloudFormation に AWS::ECS::CapacityProvider が来はじめた

概要

  • CloudFormation で ECS Capacity Provider が限定的に操作できるようになった
  • Fargate Spot がちょっと使いやすくなったかもしれない
  • もうちょっと待ったらフルサポートされると思う(されてほしい)
  • もうもうちょっと待ったら AWS CDK で良い感じに扱えるようになると思う(されてほしい)
    • 特に Fargate Spot はきっと良い感じになる(なってほしい)
  • EC2 Managed Scaling はもうちょっと様子見が必要かも(未確認)

本文

タイトルの通り、気付いたらやってきた。

docs.aws.amazon.com

Capacity Provider とはみたいな話は去年ブログに書きました:

blog.astj.space


2020/06/20 時点だと:

  • AWS::ECS::CapacityProvider を作ることができる
    • ここで作れるのは EC2 の Auto Scaling Group に対応する provider
    • FARGATE と FARGATE_SPOT は作らなくても最初から存在する
  • AWS::ECS::Cluster#CapacityProviders に AWS::ECS::CapacityProvider を登録することができる
  • AWS::ECS::Cluster#DefaultCapacityProviderStrategy に AWS::ECS::CapacityProviderStrategyItem の List を登録することができる
  • AWS::ECS::Service に CapacityProviderStrategy を設定することはできない

という感じ。

これにより、"ある ECS Cluster に対してデフォルトの CapacityProviderStrategy を設定し、その Cluster 内の新規 ECS Service ではその Strategy を使うようにする" というのが CloudFormation だけでできるようになった。ここでいう CapacityProviderStrategy には Fargate / Fargate Spot も含むので、たとえば費用節約のために常に Fargate Spot を使う Cluster を作ったりすることができる。

ただし、本来は ECS Service を定義する際に Service ごとに CapacityProviderStrategy を設定できるのだけど、上でもさらっと触れたように、 06/20 時点だと CloudFormation の AWS::ECS::Service には CapacityProviderStrategy を設定できないので、これはまだ CloudFormation では使えない。そのうちできるようになると信じてはいる。

EC2 Cluster Auto Scaling

disclaimer: 実際の挙動がどうなのか手元で確認していません

また、 GitHub 上でのやりとりをみていると、どうやら Auto Scaling 周りはまだ CloudFormation サポートが不十分そうに見える。当面は Fargate Spot では使える、くらいに思っておく方がよいのかもしれない。

github.com

用法・用例

とりあえず今回は Fargate Spot 周りのありがちなパターンを眺めた。 yamljson は今回の話題に関係ないフィールドを省略して済ませているので、完成された CloudFormation テンプレートや Service 定義だと思って使っても動かないのはあしからず。。

CloudFormation で完結する新規の ECS Cluster / ECS Service で Fargate Spot を使う

今回できるようになった。 CloudFormation template はこういう感じ。

Resources:
  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      CapacityProviders:
        - FARGATE
        - FARGATE_SPOT
      DefaultCapacityProviderStrategy:
        - 
          CapacityProvider: FARGATE
          Base:  1
          Weight: 1
        - 
          CapacityProvider: FARGATE_SPOT
          Base: 0
          Weight: 1

  ECSService:
    Type: AWS::ECS::Service
    Properties: 
      Cluster: !Ref ECSCluster
      DesiredCount: 1
      #LaunchType: "FARGATE" # LaunchType は指定しては *いけない*
      NetworkConfiguration:  ...
      PlatformVersion: "1.4.0"
      SchedulingStrategy: "REPLICA"
      TaskDefinition: ...

見るところはこういう感じ:

  • ECSCluster の CapacityProviders Property で FARGATE と FARGATE_SPOT を定義
    • Fargate Spot しか使わない鋼の意思があるなら FARGATE は不要
  • ECSCluster の DefaultCapacityProviderStrategy Property で FARGATE と FARGATE_SPOT の利用率を定義
  • ECSService の LaunchType を指定 **しない** ことで、 ECSCluster の DefaultCapacityProviderStrategy を参照させる
    • 間違って "Fargate" を指定すると、Capacity Provider の設定は参照されず、 (Capacity Provider 誕生以前と同様に) 通常 Fargate 100% で起動する
    • これが難しい
      • Service 定義のパラメータにあるように、 launchType と capacityProviderStrategy は排他指定で、どちらも省略すると defaultCapacityProviderStrategy が使われる
      • そして CloudFormation では capacityProviderStrategy を指定できないので、「launchType があればそれに従い、なければ defaultCapacityProviderStrategy に従う」という挙動が完成している

CloudFormation で完結する既存の ECS Cluster / ECS Service で Fargate Spot を使う

上記の派生パターンみたいな感じ。これは難しくて、

ECS Cluster まで CloudFormation で作って、 ECS Service は別途反映する場合に Fargate Spot を使う

Service (/ Task) の更新時には直接 API を叩いたり、 kayac/ecspresso のようなツールを使ってデプロイする場合はこっち。
この場合は、今までの CloudFormation で完結させるときの選択肢であった「ECS Cluster の DefaultCapacityProviderStrategy を定義して、配下の Service でそれを共用する」の他に、「ECS Service ごとに CapacityProviderStrategy を定義してそれを使う」ことが出来るようになる。めでたい。

CloudFormation による Cluster 更新部分は前述と共通。
あとは Service を定義するときに launchType は省略し、capacityProvierStrategy をよしなに定めるか、あるいは省略することになる。

Cluster の DefaultCapacityProviderStrategy を使いたいのなら、 capacityProviderStrategy と launchType を両方省略したサービス定義を作ることになるし、

{
  "deploymentConfiguration": { ... },
  "desiredCount": 1,
  "networkConfiguration": { ... },
  "platformVersion": "1.4.0",
  "schedulingStrategy": "REPLICA",
  "taskDefinition": "..."
}

以下のように capacityProviderStrategy を明記すれば、その Service における FARGATE と FARGATE_SPOT の利用比を指定することもできる。

{
  "capacityProviderStrategy": [
    {
      "capacityProvider": "FARGATE",
      "base": 0,
      "weight": 2
    },
    {
      "capacityProvider": "FARGATE_SPOT",
      "base": 1,
      "weight": 1
    }
  ],
  "deploymentConfiguration": { ... },
  "desiredCount": 1,
  "networkConfiguration": { ... },
  "platformVersion": "1.4.0",
  "schedulingStrategy": "REPLICA",
  "taskDefinition": "..."
}

いかがでしたか?

という感じ。きっと近いうちに CloudFormation で AWS::ECS::Service に直接 CapacityProviderStrategy を定義できるようになったり、 さらに CDK ではこの辺りをよしなに隠蔽した Construct がでてくるのだと信じているけれど、 6/20 時点ではこういう状態。

個人的には、特に開発環境で積極的に Fargate Spot に切り換えることで、運用コストを削減できるといいなと思っている。