EC2稼働マイクロサービスをECS on Fargateに移行した

はじめに

これは Kyash Advent Calendar 2021の12日目の記事です。

こんにちは。KyashでSREを担当する、福岡県在住の@hikarunです。
本日は、Kyashで稼働するマイクロサービスをAWS Fargateに移行した話を紹介させていただきます。

事前知識

AWS Fargateとは

AWSが提供しているAWS Fargate*1は、コンテナ向けのサーバレスコンピューティングの機能です。
サーバ不要のためインフラリソース管理を効率化できる、非常に魅力的な環境です。


EC2をFargate化するメリット・デメリットについては既に多くの皆様が記事に書かれておりますので、私の方で特に強く思う事を抜粋して記載させて頂きます。

EC2をFargate化するメリット

  1. インスタンス自体の設定や脆弱性を気にしなくてよい

    EC2インスタンスでコンテナを稼働させることはもちろん可能です。
    ですが、自前で入れるDockerやその他ミドルウェアインスタンス自体の設定やセキュリティアップデートが必要となり、運用管理にかける工数が非常に重くなってしまいます。

  2. アクセスの増減によるスケールアウト・スケールインが容易

    以下のように、突発的なアプリケーションへのアクセス負荷に備えて、増減させる台数を入力し適用するだけで必要数のコンテナがすぐ立ち上がります。*2 f:id:hikarun_sre:20211208155556p:plain

EC2をFargate化するデメリット

  1. Fargateで稼働するコンテナに固定グローバルIPアドレスを付与できない

    固定グローバルIPアドレスを使用する場合は、ロードバランサを使用するなど構成の工夫が必要となります。


  2. コンテナをホストしているサーバにssh等で入ることはできない

    ホストサーバにsshしてコマンドを実行することができません。
    ですが、コンテナ自体には直接入ることができるようになり、利便性が向上しました。*3

Fargate移行で立ちはだかる3つの壁

さて、本題に入ります。
Fargate移行を行う上で苦戦した3つの壁についてご紹介します。

f:id:hikarun_sre:20211208174635p:plain:w200

仕様の壁

まず立ちはだかったのは仕様の壁です。

構築された当時に作成された仕様を紐解くところからスタートしました。

移行対象のマイクロサービスに対して、以下のアクションを取りました。
- マイクロサービスの詳細を把握するためソースコードを読み解明する
- どのマイクロサービスとやりとりをするのかを解明する

言語の壁

次なる相手は言語の壁でした。

EC2で稼働するマイクロサービスがFargateで動けば良いので、
既にEC2内にあるバイナリをFargateに持っていけば動くのでは!
とSREのメンバー誰もがそう思いました。

私はマイクロサービスのコードを読み進めるうちに、あることに気づきました。

f:id:hikarun_sre:20211208183752p:plain:w200
おっと、EC2でしか使えない記述があるな…まずい…

ソースコードの中で、以下のようなEC2に関係するモジュールを使用している場合は、Fargateではエラーとなりタスクが起動しません。

"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/ec2metadata"

Go言語に限らずバックエンド周りの言語を解読する能力がSREにも必要だ!と感じました。
私自身そんなにGo言語が分かる方ではありませんでしたが、 気合いでGo言語を理解しソースコードを紐解きました。


後に登場する移行の壁であるEC2とFargateを並行稼働させて移行期間を設けるを実現するために、覚えたてのGo言語を駆使してECS Flagを実装しました。

ECS Flagについて

バイナリは共通なので、Fargateで起動する場合のみEC2特有の処理をスキップさせる必要があります。 それを実現するために、ソースコードの中にフラグ処理を追加しました。

if !config.GetEnvValue().EcsFlag.Flag {

複数のマイクロサービスのFargate移行を進めていく上で、このECS Flagが非常に活躍しました。*4

移行の壁

Fargateで起動し、問題なくマイクロサービスの動作確認が取れたところで最後の移行の壁が来ました。

Kyashでは、CircleCIを使ってAWSへのデプロイを自動化しています。
CircleCIが解読するデプロイ用ファイルをうまく改造して、EC2とFargate両方にビルド&デプロイする仕組みができました。

version: x.x
executors:
  builder:
    docker: ...
  deployer:
    docker: ...

jobs:
  ec2-build:
    environment:
      TYPE: ec2
    executor: builder
    working_directory: /your/source/path
    steps: ...

  ecs-build:
    environment:
      TYPE: ecs
    executor: builder
    working_directory: /your/source/path
    steps: ...

  ec2-deploy:
    executor: deployer
    steps: ...
  ecs-deploy:
    executor: deployer
    steps: ...

workflows:
  version: x.x
  build_and_deploy:
    jobs:
      - ec2-build
      - ecs-build
      - ec2-deploy:
          requires:
            - ec2-build
      - ecs-deploy:
          requires:
            - ecs-build

EC2用とFargate用に分けておくことで、移行が完了した後にEC2用のデプロイ処理を削除するのも容易になります。

まとめ

今年1年間で、7つのマイクロサービスをFargateへ移行しました。
EC2の台数を減らすことができ、SREの運用負荷を下げることができました。
まだ一部移行対象のマイクロサービスがありますが、引き続きFargate化に取り組んで行きたいと思います。

おわりに

最後まで読んでいただきありがとうございます。
EC2からECS on Fargateへの移行をご検討されているSREの皆様の参考になれば幸いです。

Kyash Advent Calendar 2021はまだまだ続きます!明日の投稿もお楽しみに!

*1:詳細はAWS Fargateをご覧ください。

*2:オートスケーリングを設定することで自動でコンテナ数を設定してくれます。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service-auto-scaling.html

*3:詳細はこちらの記事をご覧ください。
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/instance-connect.html

*4:先日のSRE定例の時に「ECS Flagの発明がなかったらFargate移行は頓挫してた、とてもよかった。」と反響がありました。頑張った甲斐がありますね。