🏃

Amazon ECS on EC2のTaskをFargateに移行する

2022/02/07に公開

こんにちは、スターフェスティバル エンジニアのsoriです。

今回は、AWS ECS上で構築してある、定時batch処理を行うClusterのScheduled Task(日本語ではタスクのスケジューリングと書いてありますね)の処理を、EC2起動タイプからFargate起動タイプへ移行したことについて、対応した内容とトラブル解決についてお話します。

前提

そもそも、なぜEC2からFargateに移行したかったかという話ですが、既存のEC2環境で動かしていたところ、バランシング先のうち一台のEC2環境がスタックして動かなったことがあったり、Container agentのアップデートが発生するなど、EC2インスタンス自体の環境管理の負荷が目立つことがあり、そのあたりの負荷を軽減したいと思ったことがあります。

Fargate起動タイプに切り替えた場合、サーバレスアーキテクチャとなるため自前でのその辺の管理が不要になります。

ただし、デメリットとして一般的にEC2での運用と比較してコストが高めになること、また、コンテナイメージのビルド時のキャッシュがEC2環境に比較して活用しづらいため、起動が遅くなる可能性が考えられます。

実際に採用する際には、そのあたりを考慮した上で実施するとよいかもしれません。

タスク定義に起動タイプを追加する

まず、実施対象のタスクをFargateに対応させるために、タスク定義の変更が必要になります。

今回移行した環境では、対象のコードリポジトリ内にある、container definitionのjsonにて定義を行い、GitHub Actionsのaws-actions/amazon-ecs-render-task-definitionにてデプロイ時にRenderを行う形になっていました。
(実行対象のタスクのリビジョン更新もGithub Actionsにて行っています。)

  • requiresCompatibilities項に現状はEC2が定義されているかと思いますが、ここにFARGATEを追加します。
  • containerDefinitions以下レベルに cpu, memory項がなければ定義します(実際の必要スペックと調整してください)

terraformやAWS Consoleで直接定義されている方は設定項目が若干異なるかもしれませんが、変更項目は同じかと思います。

これは、互換性を追加するのがメインですので、実作業の先にやっておいても大丈夫かと思います。

例:

{
  "containerDefinitions": [
    {
      "name": "container-batch",
      …(省略)
      "requiresCompatibilities": [
        "EC2",
        "FARGATE"
      ],
      "cpu": "512",
      "memory": "1024"
    }
  ]
}

VPCエンドポイントを定義

Private subnet内でFargate環境を利用するために、VPCエンドポイントの定義が必要になります。

FargateでECSを利用するためには下記の定義が有効になっている必要があります。(ゾーンは環境により異なるかもしれません)

  • com.amazonaws.ap-northeast-1.s3 (Gateway)
  • com.amazonaws.ap-northeast-1.ecr.dkr (Interface)
  • com.amazonaws.ap-northeast-1.ecr.api (Interface)

なかでも、ecr.apiエンドポイントについてはFargate1.4から必須となっており、この定義がないとタスクの起動に失敗します。(ここでつまづきました)

また、session manager利用環境ではssmのエンドポイントも定義が必要になるでしょう。

security group設定のトラブル

それぞれのエンドポイントでは、適切にバッチが使用されるAvailability Zone(AZ)のsecurity groupが定義されている必要がありますが、
環境移行実施時には、なぜか設定されているAZの片方が選択できず、それに気づかず別のAZを選択していたため、反対側のAZから起動された場合起動に失敗するという状況が発生していました。

タスク起動時に表示されたエラーはこのようなものです。

ResourceInitializationError: unable to pull secrets or registry auth: execution resource retrieval failed: unable to retrieve secrets from ssm: service call has been retried 5 time(s): RequestCanceled: request context canceled caused by: context deadli...

この問題については、該当ECS Clusterの、EC2向けに定義されていたキャパシティプロバイダを削除することにより、選択が可能になりました。
キャパシティプロバイダ設定がAZをブロックしていたのでしょうか。
(なお、キャパシティプロバイダ設定を削除した場合、EC2環境が稼働中の場合影響があると思いますので、設定を調整するかメンテナンス時に行うようにしましょう)

タスク定義の起動タイプ変更

さて、ここが本番です。

Scheduled Taskに設定してある定義の起動タイプをEC2からFARGATEに変更します。

キャパシティプロバイダを設定してある場合、デフォルトのキャパシティプロバイダ戦略項目が表示されているかもしれませんが、その場合は落ち着いて起動タイプを使用するを選択すると選択肢が出てきます。

設定してあるScheduled Taskを全部変更し終えたら、CloudWatch Logsや、タスクの起動状況から動作確認します。

Scheduled Taskではなく、事前にタスクを新規実行して確認してもいいかもしれないですね。

後始末

無事動作していることを確認し終えたら、EC2インスタンスの停止やEC2関連設定の削除などを行っておきましょう。お金は大事です。

さいごに

普段はアプリケーション実装をメインでやっているため、インフラ周りの移行作業は慣れておらず苦心しました。

インフラチームの皆様にも忙しい中助けていただきました、ありがとうございます。
(アプリケーションエンジニアだけでなく、インフラエンジニアも絶賛募集中です!)

また、不慣れなため間違いや漏れがあるかもしれません。何かありましたらやさしくツッコミお願いします。

参考にさせていただいたurl

スタフェステックブログ

Discussion