概要
- CloudFormation で ECS Capacity Provider が限定的に操作できるようになった
- Fargate Spot がちょっと使いやすくなったかもしれない
- もうちょっと待ったらフルサポートされると思う(されてほしい)
- もうもうちょっと待ったら AWS CDK で良い感じに扱えるようになると思う(されてほしい)
- 特に Fargate Spot はきっと良い感じになる(なってほしい)
- EC2 Managed Scaling はもうちょっと様子見が必要かも(未確認)
本文
タイトルの通り、気付いたらやってきた。
Capacity Provider とはみたいな話は去年ブログに書きました:
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 では使える、くらいに思っておく方がよいのかもしれない。
用法・用例
とりあえず今回は Fargate Spot 周りのありがちなパターンを眺めた。 yaml や json は今回の話題に関係ないフィールドを省略して済ませているので、完成された 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 の利用率を定義
- Amazon ECS capacity providers - Amazon Elastic Container Service にあるように、ECS Service においては base は考慮されないことには注意
- 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 を使う
上記の派生パターンみたいな感じ。これは難しくて、
- AWS::ECS::Cluster の CapacityProvider 系の Property はふつうに追加したらよい
- CapacityProviders も DefaultCapacityProviderStrategy も更新時の挙動は "No Interruption" なので in place で更新できるはず
- AWS::ECS::Service の LaunchType の更新時には Resource が再作成されるので、サービスは再作成になる覚悟をする
- Capacity Provider と直接関係ないけど、たとえば ServiceName を指定していたりすると replace 不可能なので、削除してから再作成とかをする必要がある……
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 に切り換えることで、運用コストを削減できるといいなと思っている。