EC2からFargateへのサービス移行

GMOメイクショップ コアグループ エンジニアの越川です。 最近ローンチしたサービスは、コンテナやLambdaなどで作成することが多い弊社ですが、 長く運用されているサービスはEC2で動いているものも多いです。 この度、決済サービスの一部をEC2からFargateへ乗せ替えを行いました。 その際のノウハウや苦労した部分をまとめさせていただきます。

1. 動機・モチベーション

弊社のサービスは、ECに紐づくサービスがほとんどのため、ピークと平時のアクセス数の差が大きいです。 ピークの負荷を想定してのスペックになっていたので、平時はかなりオーバースペックになってしまっておりました。 また、インフラチームの保守コストなどもかかっていたため、コストメリットを考えてECSへの乗せ替えを検討し始めました。

2. やったこと

  • Dockerfileの作成(生成AIに作らせてみました)

httpd.confやphp.iniを読ませたり、要件に合わせたり一部の変更はしましたが、 簡単に動かす程度なら、このままでも問題なさそうです。

# ビルドステージ
FROM composer:2 AS build

# 作業ディレクトリを設定
WORKDIR /app

# composer.json と composer.lock をコピー
COPY composer.json composer.lock ./

# 依存関係をインストール(ベンダーディレクトリを生成)
RUN composer install --no-dev --prefer-dist --no-scripts --no-autoloader

# アプリケーションのソースコードをコピー
COPY src/ /app/

# オートローダーを生成
RUN composer dump-autoload --optimize

# ランタイムステージ
FROM php:8.1-apache

# 作業ディレクトリを設定
WORKDIR /var/www/html

# 必要なPHP拡張をインストール
RUN docker-php-ext-install mysqli pdo pdo_mysql

# Apacheのmod_rewriteを有効化
RUN a2enmod rewrite

# ビルドステージから必要なファイルをコピー
COPY --from=build /app/ /var/www/html/

# ファイルとディレクトリの権限を設定
RUN chown -R www-data:www-data /var/www/html \
    && chmod -R 755 /var/www/html

# 必要に応じて設定ファイルを追加
# 例: Apacheの設定ファイル
# COPY apache-config.conf /etc/apache2/sites-available/000-default.conf

# 環境変数の設定(必要に応じて)
# ENV APP_ENV=production

# ホストとコンテナ間でポート80を公開
EXPOSE 80

# コンテナ起動時にApacheをフォアグラウンドで実行
CMD ["apache2-foreground"]
  • httpd.confの修正(一部抜粋)
# ECSのタスクに合わせて修正(ECSのタスクに合わせて設定してください)
ServerLimit xxx 
MaxRequestWorkers xxx   
MinSpareServers xxx 
MaxSpareServers xxx 
StartServers xxx
MaxConnectionsPerChild xxxx

# ログを標準出力に修正
ErrorLog /proc/self/fd/2    ErrorLog logs/error_log
CustomLog /proc/self/fd/1 json

# ヘルスチェック用のパスを用意
<Location "/health">  
    RewriteEngine On    
RewriteRule ^ - [R=200,L]
</Location>
  • php.iniの修正(一部抜粋)
; エラーログを標準出力に修正
error_log = /proc/self/fd/2

; opcacheを有効化
zend_extension=opcache.so   
opcache.enable=1    
opcache.memory_consumption=128  
opcache.interned_strings_buffer=8   
opcache.max_accelerated_files=10000 
opcache.revalidate_freq=2   
opcache.enable_cli=1    
zend_extension=opcache.so

あとは、こちらでご紹介させていただきましたfluentbitを使った サイドカーでエラーログと標準出力ログをCloudwatchとS3に分けて格納する仕組みにしました。 tech.makeshop.co.jp

ここまでは、正直簡単に移行できそうだなという印象でした。

3. ハマった部分①

ECSのターゲットグループの上限。 簡単に図解しますが、元々EC2で動いていた決済サーバには100個のターゲットグループが設定されておりました。 ただ、ECSで設定できるターゲットグループは5個までのため、同じ構成はとれませんでした。

旧決済構成

対策 アクセス元をまとめるNLB1つ挟んで回避することにしました。

新決済構成

4. ハマった部分②

タスクの再起動が止まらない・・・。 動かし始めて、数十分くらいからECSのタスクのヘルスチェックが失敗してしまい、再起動してしまう事象が発生。

試した対策① 不正なパスへのアクセスを遮断→解消せず

試した対策② サーバスペックを増強して、apacheの同時接続数を増やす→解消せず

試した対策③ ハマった部分①にもあるようにALBのヘルスチェックが多いので、間隔を伸ばす→解消せず

原因 httpd.confのKeepAliveTimeoutが長すぎたためでした。

MaxKeepAliveRequests 500
KeepAliveTimeout 120

こちらを調整した結果、再起動しなくなりました。

5. 結論・まとめ

乗せ替え自体にはそれほど手間や工数はかからずに実施できましたが、 本番稼働後にコンテナの再起動が止まらなくなったのは焦りました。 AWSがこの改善をやってくれていたのは助かりました。

dev.classmethod.jp

今後、Fargate移行予定の方に参考になれば幸いです。 makeshopでは、これからも移行を続けていきます。