
はじめに
こんにちは。プラットフォーム事業本部 CSプラットフォームグループの吉田です。
CSプラットフォームグループでは、主に問い合わせシステムやヘルプシステムといったDMMカスタマーサポートが利用するプロダクトの保守運用・改善業務を行っています。
そんなCSプラットフォームグループですが、2021年7月から2023年8月にかけて上記プロダクトに対する抜本的なリプレイスプロジェクトを進めていました。
今回はこのリプレイスプロジェクトの一環として行った問い合わせシステムのクラウド移行について、当時の課題や取り組みを交えてご紹介していきます。
アプリケーションやDBサーバーのクラウド移行を検討されている方、もしくは現在対応されている方の参考となれば幸いです。
クラウド移行の背景・目的と方法
問い合わせシステムについて
今回クラウド移行を行ったヘルプ検索システム、問い合わせシステムは、どちらも別グループによって設計・開発・保守運用されていたプロダクトです。
2018年頃に現在のCSプラットフォームグループで管轄することになりましたが、アプリケーションの断片化やブラックボックス化により、その後の機能追加や保守運用が進まない状況が続いていました。
この状態から脱却すべく、2021年7月頃からCSプラットフォームのクラウド移行とリプレイスを行うことにしました。
リプレイスプロジェクトの概要やシステムの全体像については『新ヘルプセンターシステム#1 リプレイスプロジェクトの概要と結果』をご覧ください。
パブリッククラウドへの移行方法
リプレイスを進めるにあたり、まずはオンプレ環境に残っている各種サーバーやアプリケーションをパブリッククラウドに移行することにしました。パブリッククラウドはグループ内で最も知見のあるAWSを採用しています。
今回ご紹介する問い合わせシステムは、CSプラットフォームグループが管理しているプロダクトで最もシステム規模が大きく、仕様も複雑なプロダクトです。
- 問い合わせユーザー ... ユーザーフロントとBFFをもつアプリケーション(React, Node js)
- 問い合わせ管理 ... 管理フロントとバックエンド(API・メール受信・JOB)をもつアプリケーション(Vue.js, Laravel PHP)
WebサーバーやJOBサーバー、NFSサーバー、DBサーバーなど多くのサーバー群で構成されており、その中で2つのアプリケーションをもっています。当時のシステム構成は以下の通りです。

問い合わせシステムをクラウド移行する上で課題になったのが、システム規模の大きさに加え、24時間365日稼働・運用しているプロダクトである点です。
そのため通常はメンテナンスを実施する時間がなく、仮にメンテナンスを入れる場合は、例外的に最小限の時間で行う必要があります。当然今回のクラウド移行においても、なるべくダウンタイムをなくすよう対応する必要がありました。
このような背景から通常業務中にビッグバンリリースでクラウド移行(と不測の事態に備えた切り戻し)を実施するのは厳しいと判断し、問い合わせシステムのクラウド移行は以下のフェーズに分けて進めていくことにしました。
- 問い合わせDB / NFSのクラウド移行
- 問い合わせシステムのメール受信 / JOBアプリケーションのクラウド移行
- 問い合わせシステムのアプリケーション全体のクラウド移行
- アプリケーションのリプレイスとクラウド環境の最適化
次の章からは各フェーズにおける課題や問題と、それらの解決に向けた取り組みを、移行方式を含めてご紹介していきます。
移行方式と各フェーズにおける問題と課題
問い合わせDB / NFSのクラウド移行
私たちが最初に行ったのは、問い合わせシステムで利用しているNFSおよびDBと、そこで保管しているファイルやDBデータのクラウド移行でした。
NFSはエンドユーザーとオペレーターのやりとりで添付されたファイル管理を、DBはそれらファイルの保管先や問い合わせに関する各種データ管理を行っています。
DB / NFS移行後のシステム構成は以下のようなイメージです。オンプレ環境にあったDBとNFSを、AWS AuroraとEFSというサービスに移行します。

NFS移行時に10秒程度のダウンタイムが発生する
まずはNFSサーバーをAWS EFSに移行しました。
このファイルサーバーにあるファイルへのアクセス方法は、各アプリケーションがファイルパスを取得するAPIを実行してアクセスしていました。つまりすべてのWebサーバー上に同一ディレクトリを用意しておき、そこに対して同一NFSをマウントする必要があります。
そのため今回は新旧NFSを双方向で同期させておき、その上で各オンプレWebサーバーにマウントするNFSを切り替える方法を採用しました。システム構成は下図を参照ください。
なお、DBレコードのファイルパスを新マウントポイントに上書きする案もありましたが、レコード数が多く、上書きに時間を要することから断念しました。

この方法はWebサーバー上でシンボリックリンクを切り替える作業が必要になります。具体的には以下のような作業手順を踏む必要があるため、作業中はNFSにアクセスできなくなる点に注意が必要でした。
- シンボリックリンクの設定を削除する
- その後新しいシンボリックリンクを再設定する
しかし、上記作業はオンプレミス環境を管轄するインフラ部隊へ依頼していることから、自チームではその後の作業内容まで把握できていませんでした。本番環境に切り替えた後で詳細とサービスへの影響有無について報告を受けた際に、作業中に10秒ほどNFSにアクセスできない時間が発生したことを知りました。
幸いにもファイル操作に関するエラーやログはなく、サービスへの影響はありませんでしたが、仮にファイルアップロードが発生した場合はファイルがWebサーバー内に取り残される可能性もありました。
今となってはファイルがアップロードされた場合に備えて、以下のような対応をとっておくべきだったと痛感しています。
- ファイルの構成データを復元できるような対処をしておく
- ファイルアップロードのリクエストを止めておく
また作業手順についても他部署にお任せではなく、問題なさそうかを自チームでも確認しておくべきだったと反省しています。
いろいろと反省すべきことはありましたが、NFSサーバーを無事にクラウド移行できました。
DB移行時に実行するSQLをバイナリログから正しく復元できない
次にDBサーバーをAWS Aurora for MySQLに移行しました。
DB移行で注意すべきはDBデータの更新時です。問い合わせシステムでDBへの更新が発生するケースは以下のいずれかでした。
- エンドユーザーが問い合わせ窓口メールアドレスに対してメールを送信する
- エンドユーザーが問い合わせユーザーシステムを利用して、問い合わせを作成・更新する
- オペレーターが問い合わせを作成・更新する
- オペレーターが問い合わせに関する各種情報を更新する
上記2~4に関しては、オペレーターの運用やシステムにメンテナンスモードを導入することでDB更新を回避できます。
しかし、1のメール受信処理に関してはメールサーバーにメールキュー等の機能を持っておらず、新たにメールサーバーを立てたり、メールキュー機能を実装したりするコストや時間が当時はなかったため、メンテナンスモードを導入できませんでした。
新旧DBで事前にレプリケーションを貼る方法も検討しましたが、問い合わせメールが届く頻度・開発リソース・工期を考えた結果、今回は以下の方法でDB移行を行うことにしました。
- 事前作業
- 新DBをAWSクラウド上に作成
- バイナリログを有効化
- mysql_dumpにて旧DBのテーブルやレコードを新DBに復元
- 本番作業
- システムの一部に対してメンテナンスモードに切り替え
- 比較的更新頻度の高いテーブルに対して再度mysql_dumpにて新旧DB間の差分を更新
- APIのDB接続設定(.envファイル)を新DBのエンドポイントに書き換える
- バイナリログを利用して2.1 ~ 2.2間で発生したInsert、Update処理を復元
- データ復元後にメンテナンスモードを解除
上記作業の流れをシステム構成図で示すと以下のようになります。

上記方法でDB移行を行う場合、旧DBのバイナリログ等を利用して新DBに対してデータ復元を行う必要があります。しかし上記の通り作業中に発生するInsert、Update処理も数件程度になる想定であり、大きな問題にはならないだろうと考えていました。
実際、当該作業中に発生した処理は数件でしたが、いくつか想定外の問題が発生してしまいました。具体的には以下の通りです。
- バイナリログを利用してInsert、Update後のデータが文字化けしてしまう
- バイナリログから復元したSQLをそのまま適用できない
1については、バイナリログから復元したSQLを実行した際のセッションにて、'character_set_client'が'latin1'になっていたことが原因でした。本番作業を行ったクライアント端末のみ、設定が'latin1'になっていたため事前検証では検知できず、当日作業中に問題が発覚しました。
2については非常に基本的なことですが、Insert対象テーブルのPKをオートインクリメントさせていることが原因でした。新DB切り替え後にInsertされたレコードとバイナリログから復元するレコードでPKがバッティングし、Insert処理が失敗するようになっていました。
当初は問い合わせが最も少ない早朝時間を選び、問い合わせがあった場合のみ対応すれば良いと軽く見積もっていましたが、上記1、2の対応中に問い合わせが続いたことも考えると、下記のようになるべく手作業をなくす形で移行すべきだと痛感しました。
- 新旧DBで事前にレプリケーションを貼っておき、APIのDB接続設定を変えるだけにしておく
- またはInsert、Update処理が入らないようシステム全体にメンテナンスモードを導入しておく
今回の場合であれば、そもそもメールを含めてInsert、Update処理が入らないようシステム全体にメンテナンスができる仕組みがあれば、サービスへの影響も最小限に抑えられたと考えています。今後のためにもメンテナンス中はキューイングや転送などを行い、メンテナンス解除後にDBへ取り込むような仕組みを整えていきたいです。
問い合わせシステムの周辺アプリケーションのクラウド移行
次に、問い合わせ管理がもつメール受信、JOBといった機能をクラウドに移行することにしました。
問い合わせ管理は一つのLaravelアプリケーションに集約する形で構成されています。このアプリケーションのバックエンド部分は、別のアプリケーションから呼び出されるAPI部分とメール受信やJOBから呼び出されるアプリケーション部分に分かれて稼働している状態でした。
そこで、まずはオンプレミス環境で動作していた上記バックエンドアプリケーションをクラウド上でも稼働させ、メール受信とJOBではクラウド上のアプリケーションを呼び出すような構成にしました。システム構成については次の章でご紹介します。
結果的に影響が少ない範囲から移行できましたが、ここでもいくつか問題がありました。
オンプレWebサーバーの設定値が分からない
オンプレWebサーバーの各種設定等はAnsibleを利用していましたが、ここでAnsibleでも管理されていない設定値が多くあることが判明しました。
それまではEC2 + Ansibleの利用を検討していましたが、さすがにAnsibleを整えるところから始めるとなると移行計画が破綻してしまいます。
そのため個人開発環境用に利用していたDocker Imageを流用して、ECS上でアプリケーションを稼働するような構成に変更しました。JOBはAWSのEventBridge(cronトリガー)に置き換え、メール受信の機能はDNSを切り替えてAWS上で稼働するようにしています。システム構成図で示すと以下のようになります。

直前でアーキテクチャを変更することにはなりましたが、結果としてサーバー構成の更新フローを整備する必要がなくなりました。CI/CDについてもECRやGitHub Actionsを組み合わせることで簡単にデプロイフローを整備できたため工数削減につながりました。
また構成管理の重要さも実感したので、今回のクラウド移行で作成したリソースはすべてTerraformで構成管理しています。
ECS上の1コンテナに2プロセスが起動するようになる
コンテナ化によってさまざまな工数削減につながりました。一方で、ECS上の1コンテナにメール受信用のPostfixとLaravelアプリケーションの2プロセスが起動するような構成になってしまいました。PostfixとLaravelアプリケーション間のやりとりがstdoutを利用する仕組みになっていたためです。
これを解消するためにはアプリケーションの改修が必要でしたが、リリースまでのスピードと、いずれ置き換わる現行システムへの改修という点を考慮して、今回はアーキテクチャの改善にコストをかけないという判断をしました。1コンテナ1プロセスにしておくと、より細かい単位でメトリクスやログを分離できるので負荷試験やエラーログ調査がしやすくなります。
こちらについてはクラウド移行後のリプレイス時に1コンテナ1プロセスとなるようシフトしています。
問い合わせシステムのアプリ全体のクラウド移行
最後に行ったのが問い合わせシステム全体の移行です。
周辺アプリケーションのクラウド移行と同様、事前にクラウド環境にアプリケーションを移行しておき、DNS設定を少しずつAWS側に切り替える方法にしました。最終的なシステム構成は下図の通りです。

移行作業は特に問題なく完了し、これで問い合わせシステムのクラウド移行も完了したと考えていました。しかし移行後に次のような問題が発生しました。
DBが急激な負荷上昇に耐えられない
特定のリクエストが多発した際に、アプリケーションが負荷上昇に耐えられずタイムアウトが発生するようになりました。
DB移行後も問題なく動作していましたし、ECSのオートスケール設定やDBを含めた負荷試験も行っていました。しかしシステム全体がクラウド移行したことで通常よりも多くの利用者に触っていただいており、その結果負荷が発生するリクエストも多くなったことが原因でした。
負荷の大きいリクエストを捌けるようDBインスタンスを増やしたり、アプリケーションでもDBリーダーエンドポイントを多く使うよう見直したりして事象は解消しましたが、ある程度の負荷上昇を見越してキャパシティを検討すべきだったと感じました。
負荷状況やエラーを監視するモニターや通知類の整備も不十分だったため、これらも事前に用意しておくべきでした。
クラウドへの移行により簡単にスケーリングが可能になりました。ただそのメリットを活かすためには、負荷状況を適切にモニタリングして、すぐに検知・対応を行うことが重要だと改めて感じました。
その後
このようにいくつかの問題もありましたが、問い合わせシステムをオンプレミス環境からパブリッククラウドへ無事に移行できました。
まず、問い合わせシステムをAWSに移行することで、関連処理のブラックボックス化を解消できました。
最初はどのようなシステム構成なのか全くわからず戸惑いましたが、最終的にはアプリケーションにあわせてシフトしていける環境が構築できたと考えています。実際、アプリケーションのリプレイスフェーズではEFSからS3にシフトするなど、さまざまな最適化を図っています。
また、システム全体をクラウド上で稼働させたことでインフラ面の保守作業が楽になりました。例えばAuroraもB/Gデプロイなどで容易にメンテナンスを実施できる状態になっています。
このようにシステム全体の透明性が向上しているため、他の開発メンバーから見てもシステム構成が把握しやすくなり、メンバー自らAWS構成を運用保守する機会も増えてきました。システムの効率性と可用性も向上しているため、より信頼性のある問い合わせシステムを利用者に提供できるようにもなっています。
さまざまな問題もありましたが、クラウド移行したことで当初目標としていたインフラ面のブラックボックス化が解消され、運用保守性も大きく高められました。
今回は問い合わせシステムのクラウド移行方式をご紹介しましたが、プロダクトの特性や仕様、案件のスケジュールなどでクラウドへの移行方式は異なります。システムによってはクラウドへの移行が難しい場合もありますので、それぞれのプロダクトに最適な形で移行の要否、方式を設計することが重要です。
この記事がアプリケーションやDBサーバーのクラウド移行を検討されている方の一助となれば幸いです。