カミナシ エンジニアブログ

株式会社カミナシのエンジニアが色々書くブログです

Fargate Spot が Arm アーキテクチャに対応! シュッと移行してコスト削減を実現

こんにちは。ソフトウェアエンジニアの坂井 (@manabusakai) です。

円安を乗り越えるための Arm アーキテクチャへの移行が完了! そのプロセスを公開します」にも書いたとおり、カミナシではほぼすべてのコンピューティングに Arm アーキテクチャを採用しています。また、運用コストを下げるために AWS Fargate を最大限活用しています。

Fargate には Fargate Spot という選択肢があります。 EC2 のスポットインスタンスと同様のコンセプトで、次のような特徴があります。

  • AWS クラウドの空きキャパシティを活用してタスクを実行
  • キャパシティが逼迫すると 2 分前の通知とともに停止させられる
  • コストは Fargate と比べて 7 割引(東京リージョンの場合)

高い可用性を求められない環境では Fargate Spot を使ってコストを抑えたいところですが、これまで Fargate Spot は x86_64 アーキテクチャしかサポートしていませんでした。

ところが、先月 Graviton プロセッサをサポートしたことが発表され、ついに Arm アーキテクチャでも Fargate Spot が使えるようになりました!

aws.amazon.com

さっそく社内向けの環境を Fargate Spot にシュッと移行したので、手順と注意点をご紹介します。

Fargate Spot に移行する手順

やることは 2 つだけです。慣れてしまえば 10 分もかからずに変更できます。

  1. capacity provider に Fargate Spot を追加する
  2. ECS service に capacity provider strategy を追加する

以下では、IaC に Terraform を使って説明します。

まずは ECS cluster の capacity provider に Fargate Spot を追加します。

resource "aws_ecs_cluster_capacity_providers" "example" {
  cluster_name       = aws_ecs_cluster.example.name
  capacity_providers = ["FARGATE", "FARGATE_SPOT"]
}

次に ECS service に Fargate Spot を指定した capacity provider strategy を追加します。

次の例だと 1 つ目のタスクは Fargate Spot で起動します。それ以降は Fargate と Fargate Spot が 1:1 の割合で起動します。

resource "aws_ecs_service" "example" {
  name            = "example"
  cluster         = aws_ecs_cluster.example.id
  task_definition = aws_ecs_task_definition.example.arn
  desired_count   = 4

  (snip)

  # launch_type と capacity_provider_strategy はどちらかしか指定できない
  # launch_type = "FARGATE"

  capacity_provider_strategy {
    capacity_provider = "FARGATE"
    base              = 0
    weight            = 1
  }

  capacity_provider_strategy {
    capacity_provider = "FARGATE_SPOT"
    base              = 1
    weight            = 1
  }
}

なお、Terraform で capacity provider strategy を追加しようとすると再作成になってダウンタイムが発生してしまいます。ドキュメントにも以下の注意書きがあります。 (ref. Resource: aws_ecs_service)

These can be updated without destroying and recreating the service only if force_new_deployment = true and not changing from 0 capacity_provider_strategy blocks to greater than 0, or vice versa.

これを防ぐために、先に AWS CLI から更新して後から Terraform のコードを実体に合わせることで再作成を回避できます。できればこうしたワークアラウンドは避けたいところですが、頻繁に更新するわけではないので許容することにしました。

$ aws ecs update-service \
    --capacity-provider-strategy \
        capacityProvider=FARGATE,base=0,weight=1 \
        capacityProvider=FARGATE_SPOT,base=1,weight=1 \
    --cluster example \
    --service example \
    --force-new-deployment

ECS service の変更後に新しく立ち上がったタスクを確認すると、Fargate Spot で起動していることがわかります。

$ aws ecs describe-tasks \
    --cluster example \
    --tasks (snip) \
    --query "tasks[].capacityProviderName"
[
    "FARGATE_SPOT"
]

Fargate Spot の注意点

Fargate Spot タスクが起動できなくても Fargate タスクにはフォールバックしてくれないため 1、本番環境で使う場合は工夫が必要になります。

たとえば 10 タスクのうち半分が Fargate Spot で動いている場合、Fargate Spot タスクが起動できない場合は 5 タスクが足りないままになります。これを回避するアイデアとしては、Fargate と Fargate Spot のそれぞれで ECS service を作って Application Auto Scaling を設定すれば良さそうです。

Fargate Spot を積極的に活用していくには、キャパシティを上手にコントロールする必要があります。

おわりに

社内向けの環境を Fargate Spot に変更して数週間が経ちますが、今のところ実行中タスクの中断は観測されていません。

Arm アーキテクチャでも Fargate Spot が使えるようになったことで、ECS のコストをさらに削減できそうです。まずは社内向けの環境でシュッと移行してみてはどうでしょうか?

最後に宣伝です 📣 カミナシでは絶賛採用中です! 一緒に強いチームを作っていく仲間を募集しています!


  1. Containers Roadmap にも Issue (Fargate Spot failover to Fargate #852) が作られています。