ANDPAD本体サービスをEKSに移行しました

株式会社アンドパッドのエンジニアの浜田です。
現在、コンテナ化プロジェクトの活動をしています。

アンドパッドは多くのサービスを提供しておりますが、その中で最も歴史が長く、コード量が多い、社内ではANDPAD本体と呼ばれるサービスがあります。
コンテナ化プロジェクトはこのANDPAD本体をコンテナ環境に移行するプロジェクトです。
プロジェクトは2020/11頃から開始し、2021/12に第一弾の本番リリースが完了しました。今回はその活動について共有します。

プロジェクトの発足

アンドパッドにおける下記課題を解消することを目的として、コンテナ化プロジェクトを開始しました。

リリース作業にかかる時間が長い

以前のANDPADでは本番リリース作業に数時間かかっていました。本番作業なので複数人で作業を行い、人数×時間ぶんの工数が取られることになります。
また夜間に作業することも多く、リリース担当者の作業負荷が高まってしまう状態になっていました。
また長時間に渡るリリース作業やその負荷により、以下が問題となっていました。

  • リリース頻度が落ちる
  • Hotfixをリリースするためのコストが高い
  • 疲れから作業ミスを誘発してしまう

Blue/Greenデプロイの環境を分けきれていない

ANDPAD本体のリリースはBlue/Greenデプロイを実施しています。
以前の下記記事で紹介していますので、詳細はそちらをご参照ください。

tech.andpad.co.jp

ANDPAD本体のサービスではVMで提供している3つのサーバ群が存在していました。(今回は社内での呼び方で紹介させていただきます。)

  • フロントサーバ
    • NGINX,Railsが乗っているWeb/APサーバ
  • バックサーバ
    • Sidekiqを実行して、ユーザリクエストを非同期処理するサーバ
  • バッチサーバ
    • sidekiq-schedulerとcrontabで幾つかの定期的な処理を実行するサーバ

フロントサーバはBlue/Greenデプロイとなっているのですが、他のサーバはBlue/Greenに対応していませんでした。デプロイの流れを意識しないと、公開前に行う作業によって本番環境に影響を与えてしまう可能性があり、データやサーバの更新タイミングによってはエラーを招いてしまいます。

インフラのメンテナンス(OSやパッケージのアップデートなど)が大変

先述の記事にある通り、以前からインフラ部分はある程度コード化されていました。
ただ、大元のAMI(Amazon Machine Image)に変更が入ることがあり、変更を検証するためにOSを立ち上げる必要があり作業に時間がかかっていました。
これにより、アップデートができずに古いバージョンで動いているパッケージなどが存在していました。

プロジェクトの流れ

このプロジェクトは約1年という期間で初回リリースになりました。
1年間にわたる期間のなかで、時期によって実施内容が変遷していきました。ざっくりと4半期毎に分けて紹介します。

  • ECSでの検証からEKSへの乗り換え
  • EKSで開発サイクルを回すための環境作り
  • デプロイのフロー構築や負荷試験の実施
  • 本番リリース準備と課題潰し

ECSでの検証からEKSへの乗り換え

このプロジェクトが発足した当初、新規に立ち上げるサービスは既存のサービスとは別のEKSクラスタで動いてました。ANDPAD本体もいつかは新規サービスのEKSクラスタに乗せたいと考えておりますが、コンテナ化はスモールスタートで進め、ECS on Fargateを選定していました。

バックサーバで実行しているジョブの一部に数時間動き続ける可能性のあるものが含まれており、これによってECS on Fargateの構成ではグレースフルシャットダウンが実現できないという課題に直面しました。
ECS on Fargateのグレースフルシャットダウンについてはこちらのブログを参考にさせていただきました。

aws.amazon.com ECS on Fargateによって問題なく稼働できれば、運用コストも少なく済み良かったのですが、この課題が解決できそうになく、断念しました。

そもそも数時間かかっているジョブが存在している状況が問題ではあったのですが、すぐに解決できる問題ではなかったため、別の選択肢を取る議論を行いました。 議論の結果、下記の理由からEKS on EC2の構成で進めることに決めました。

  • プロジェクト発足時にはいなかった、Kubernetesに知見のあるメンバーが参画した
  • Kubernetesでグレースフルシャットダウンを実現できるイメージを持てていた
  • いつかはEKSに移行する予定のため、少し時間がかかってもそれ以上のメリットがある

またバッチサーバは考慮する点が多く、時間がかかるため、初回リリースではフロントサーバ・バックサーバのみコンテナに移行することに決めました。

EKSで開発サイクルを回すための環境作り

EKSで構築する、と決めたことを受けて、EKS上で一般的な開発サイクルを回すための環境作りを進めました。
ANDPAD本体は、複数の検証環境を持っているのですが、どこから進めるか?を深く検討せずに構築し始めたことで、結構時間を溶かしてしまいました。
以下のような流れで、開発環境の構築を進めては頓挫することを繰り返した結果、3番の方法で進めることになりました。

  1. defaultブランチへのマージ時に自動デプロイされる検証環境の切り替え
    • サイトのFQDNから変えるようなことを考えていました。
    • 当然、ANDPAD本体に接続する他サービスにも影響があるため、断念しました。
    • 今考えると、エンジニアが自由にデプロイして良い環境ではないため、コンテナ化を検証する環境としては望ましくありませんでした。
  2. 複数ある検証環境に、新たな環境を追加構築
    • 既存の環境に影響を与えないために新しい環境を作ることを考えました。
    • 当然、新規に様々なリソースを作っていくことになり、その分だけ時間がかかるため、断念しました。
  3. 複数ある検証環境からピックアップしVM、コンテナそれぞれの環境が並行稼働するように構築
    • 各環境が基本的に並行稼働できるようにして、どうしても切り替えが必要な場合のみ環境を専有して検証を実施しました。
    • Webアクセスは、特別なヘッダーが付いたリクエストのみコンテナに振り分けるようにALBに設定しました。
    • フロントサーバとバックサーバを繋ぐジョブは、コンテナ版とVM版でRedisのNamespaceを分けることでJobを取り合わないようにしました。

デプロイのフロー構築や負荷試験の実施

コンテナ移行に伴って、パフォーマンス劣化と、高負荷に因るサービス継続が困難な状況になることを恐れていました。
今回の移行にあたってはLocustを用いて負荷試験を実施することでこれらの不安を軽減させる対応を進めました。
負荷試験にあたっては以下のような観点で対象のエンドポイントを選定しました。

  1. リクエストが急増する時間帯にリクエスト数が多いエンドポイント
    • リクエストが急増する時間帯によく接続されるリクエストをテストすることで、KubernetesのAutoScaleの設定チューニングができると考えました。
    • Locustには、 spawn-rate という設定値があり、接続ユーザ数を徐々に増やすことができるようになっています。これによって実際のリクエストに近い、急増するケースを再現できました。
    • Pumaのパラメータ、Kubernetesのパラメータをチューニングしながら負荷試験を実施しました。
  2. 1リクエストでCPU使用時間が長いエンドポイント
    • 重い処理が一度に多く来た場合でも耐えられるようにしたいと考え、この観点で洗い出しました。
    • 結果的に時間の関係で、このエンドポイントのシナリオは作成できませんでした。

本番リリース準備と課題対応

今回のリリースでは、負荷試験はしていましたが、それでも実際の稼働に向けて性能面に不安を抱えていたため、カナリアリリースをすることにしました。弊社でカナリアリリースの実績はなく、方法を一から作り上げる形になりました。

またこの時期は本番環境構築の準備をしながら、開発者向けに動作確認のお願いをしていました。この動作確認によって画面表示周りの不整合や機能が一部動いてないことなどが分かりました。

画面表示の不整合に対応するため、assets(Railsで配信しているJavascript、CSS、画像などを指します)と向き合う必要があり、理解が深まりました。
理解が深まったことによって、カナリアリリース時に旧バージョン環境と新環境バージョンでassetsのダイジェストが異なり、CDNにキャッシュしていないとオリジンへのリクエストで404エラーを返す可能性があることに気づきました。(ANDPAD本体では、assetsのoriginはフロントサーバになってます)
この問題はCDNに事前にキャッシュさせることで乗り切ることができました。

機能が一部動かなかった件は、ライブラリのバージョン依存が原因ですぐに解決することはできず、ライブラリのダウングレードをすることになりました。しかし、このダウングレードによって別の部分に課題が出てしまい、今でも対応を進めている状況です。他に対応手段がなくやむを得ず実施しましたが、ダウングレードは本当にしたくないと思わされる結果でした。

このプロジェクトがひと段落しての成果

デプロイ時間の削減

デプロイ作業は全てCodeBuildで自動化されているため、デプロイに関わるCodeBuildの実行結果の時間を足し合わせて移行前後で比較しました。
EKSに移行する前は40〜60分程度かかっていましたが、EKSに移行した後は、25〜35分程度になりました。確かに削減されたものの、さらに改善の余地があると考えています。

弊社の一部検証環境は本番環境と同等のビルド&デプロイ手順を実施していました。本番と同様の手厚いデプロイ手順が非連続となっており作業に時間がかかっていました。
このプロジェクトを通じて検証環境のデプロイ方法を変更し、15分程度でビルド&デプロイできるようにしました。まだ改善は必要なものの、改善の実績になりました。
開発者から感謝の言葉が届いてます!

デプロイ時間が短縮されることによって全体の生産性が上がり、ANDPAD利用者に向けて、より早くより多くの機能を提供できるため、もっと改善していきたいと考えています。

インフラ構成のコード化

大元のAMIに不明な変更が入っていた課題は、今回の移行で解決しました。 ANDPAD本体のインフラ設定に用いるDockerfileにEKSの構成も含めてコード化しましたので、OSにsshでログインしないとわからない変更はなくなりました。(バッチサーバには残ってます)

レスポンスタイムの改善

EKS移行の副産物として、レスポンスタイムが良くなりました。これが実は一番の成果だったのかもしれません。
下記グラフはアプリケーションサーバのレスポンスタイムをパーセンタイルで表示しています。上が移行前で、下が移行後です。
コンテナに移行したことでスケールアウトにかかる時間が縮小したことが一つの要因と考えています。移行前はピーク時間帯とピーク時間外でグラフが波打っています。移行後はグラフの波が穏やかになっているのが見て取れます。移行後はPodの起動数のグラフが代わりに波打っていました。

f:id:hmd34:20220405110958p:plain:w720
移行前のレスポンスタイム
f:id:hmd34:20220405110909p:plain:w720
移行後のレスポンスタイム

これからの課題

元々の課題に対して現在は下記の状態と考えています。

  • △(道半ば) リリース作業にかかる時間が長くて疲れる
  • △(道半ば) Blue/Greenデプロイの環境を分けきれていない
  • ◯(解決!) インフラのメンテナンス(OSやパッケージのアップデートなど)が大変

バッチサーバの解体と移行

バッチサーバが、まだVMとして残っています。このサーバの役割を解体して移行していく予定です。

Blue/Greenデプロイの環境を分けきれていない

今回のリリースでは、Blue/Greenの構成変更はできませんでした。バッチサーバの移行が完了した後にこの辺りの構成変更をしていきたいと考えています。

リリース時間の改善

デプロイ作業全体の処理時間は確かに短くはなったものの、リリース作業全体がもともと長く、デプロイ作業が非連続であるため拘束時間が長いという課題が依然として残っています。 この課題を解決することでリリース頻度を高め、ANDPAD利用者により早くより多くの機能を提供できるようにしていきたいと考えています。

さいごに

今回はコンテナプロジェクトの取り組みについて紹介させていただきました。まだまだ課題も多く、やりがいのあるプロジェクトです。より良くしていくために、一緒に働く仲間を募集中です!
「取り敢えず話だけでも聞いてみたい!」な人向けのカジュアル面談の制度もありますので話を聞きに来ていただくだけでも歓迎です!

engineer.andpad.co.jp