TANP Blog

株式会社Graciaが運営するギフトEC「TANP」の開発ブログです。

【エンジニア】TANPのインフラ構成の変遷について

こんにちは、GraciaのCTOの林です。

2021年3月25日、オンラインで開催された AWS Startup Tech Meetup #3 にて登壇の機会をいただき、「TANPのインフラ構成の変化」についてお話しをさせていただきました。今回は当日お話しきれなかった詳細についても補足しながらご紹介させていただければと思います。

 当日のイベントは下記にてアーカイブ動画やレポートが公開されておりますので、よろしければそちらもご覧下さい。 

[ 使用スライド]

speakerdeck.com

 

[目次・変遷概要] 

 

1:ElasticBeanstalk (EC2 + RDS(MySQL))

f:id:gracia_tanp:20210406170329p:plain

まず、創業期にサービスをリリースした際の構成が上記になります。ElasticBeanstalkでEC2とRDSを管理する、という構成です。

Graciaは2017年6月に創業しましたが、当時は自分を含めエンジニアが2名のみ、かつ2人ともインフラに関する知識はあまり無い状態でした。サービスを公開するだけでも精一杯という中で、ElasticBeanstalkはGUIから簡単に操作することができ、広範囲の設定をカバーできるため、インフラの知識が乏しい状態でも簡単にアプリケーションを立ち上げられるという利点がありました。

 

しかしながら、サービスが順調に伸びたことによりついにRDSの容量がパンク。サービスはダウン。さらにサービスダウンに対応する中、「Beanstalkで管理しているリソースの変更は基本的にBeanstalkから変更しなければならない」ということを知らず、直接RDSコンソールから設定をいじってしまった事により、その後Beanstalkの画面から一切RDSに関する設定がいじれなくなるという二次災害もありました。

 

2:ElasticBeanstalk(EC2) + RDS(MySQL)

f:id:gracia_tanp:20210406170406p:plain

上記の問題を受けてBeanstalk環境を新しく作り直そうしたのですが、Beanstalk環境でRDSを管理した場合、Beanstalk側を停止・クローンするとRDSも停止・クローンされてしまうため、例えば完全なBlue/Greenデプロイができない等の問題がありました。さらにAWSの開発者ガイドにはBeanstalkでRDSを管理するのは実稼働に理想的では無いと記載されている事に気付き、RDSは外部で管理する構成に変更しました。

 

これらの対応により、それぞれBeanstalkに依存させず運用しやすい状態で稼働させることはできたのですが、事前にドキュメントの内容を把握した上で構築しておくべきだったなと反省しています。

 

3:ElasticBeanstalk(EC2複数台) + RDS(MySQL)

f:id:gracia_tanp:20210406170531p:plain

その後、さらにユーザー数が増加したため、EC2複数台でのオートスケーリングで負荷分散を行うようになりました。サーバーを増やす・減らす判断軸となるCPU使用率の設定等もBeanstalkのGUIから簡単にできるため非常に便利です。

 

しかし、この頃から度々セッションが切れるという問題が発生していました。これは結論から言うとセッション管理がサーバーに依存していたことが原因でした。

 

TANPはログイン状態やカートの商品情報等をセッションで管理していますが、当時はセッションをサーバー内部にファイルとして保管する仕組みでした。この場合、セッションが生成されたユーザーは自分のセッションが置かれているサーバーに接続し続けないとセッションが切れてしまう事になるため、セッション切れを回避するため「スティッキーセッション」で対応するという方法を取っていました。

 

f:id:gracia_tanp:20210406170627p:plain

スティッキーセッションとは、ユーザーがアクセスした際に、対象ユーザーのcookieに保存されている値を参照してロードバランサーが必ず適切なインスタンスに振り分けてくれる、というものですが、これには下記のような問題がありました。

  • 有効期限に限界がある。
  • アクセスが固定されてしまうため負荷分散の恩恵を完全には受けられない。
  • デプロイの最中など、振り分け対象のインスタンスのヘルスチェックが失敗している時は、強制的に他のサーバーに振り分けられてしまう。

これらの状況を考慮し、セッション管理がサーバー依存しない構成へと移行しました。

 

さらに詳細については過去にnoteを公開していますので、よろしければこちらもご参照ください。

note.com

 

4:ElasticBeanstalk(EC2) + RDS(MySQL) + Redis

f:id:gracia_tanp:20210406170701p:plain

前述のセッションが切れる問題を解決すべく、ElastiCacheのRedisでセッション管理を行う体制を構築しました。これにより、セッション切れに気兼ねせずデプロイを行うことが可能になり、スティッキーセッションを無効化することで負荷分散の恩恵も受けられるようになりました。

 

 

5:ElasticBeanstalk(EC2) + RDS(Aurora) + Redis

f:id:gracia_tanp:20210406170737p:plain

上記の状態でセッション周りの問題は解決されましたが、この間さらにユーザーが増加したことにより、RDSの負荷が本番環境に影響を及ぼすという別の問題が発生していました。ギフトECという事業性質上、クリスマスやホワイトデー等の繁忙期には負荷が飛躍的に上昇します。繁忙期にサービスへの影響が出てしまうことは致命的です。

 

そこでRDSをMySQLからAuroraに移行し、書込み1台 + 読込み複数台のクラスターを作成し、アプリケーション側で読込み処理を読込み用インスタンスに向けることで負荷分散を行いました。

f:id:gracia_tanp:20210406170812p:plain

オレンジ: 書込み 緑: 読込み

 

上記のグラフは移行した際のグラフですが、綺麗に分散されるようになっています。さらに今後、負荷の増加に伴い読込みインスタンスを増やすことで基本的には対応できるようになっています。

 

また、Graciaではデータ分析のため社内メンバーがRedashを通してクエリを叩くことが日常的に行われていますが、Auroraへ移行する前は1台しかないRDSに対して分析クエリを投げる状態になっており、処理によってはサービスへ影響を及ぼしかねない構成でした。Auroraに移行することでクラスター内に分析専用のインスタンスが作成でき、本番環境に影響しない体制にできたことも大きいです。

 

デプロイフローの変更

インフラについては都度整備を行ってきましたが、デプロイに関してはごく最近まで手動で行っていました。具体的に言うと、Beanstalkに用意されているEB CLIのeb deployコマンドを実行すると言う方法です。

これらはコマンドを叩くだけでデプロイが行えるため簡単ではあるのですが、css/jsのビルドは手元で行わなければならないという人為的なミスが起きやすい状態でもあり、CI/CDについても整備することにしました。CI/CDにはAWSのCodePipelineを使用し、Gihubにプッシュしたら自動でビルド・デプロイが走るような構成に変更。人為的なミスをする心配なく継続的にデプロイが行える構成へと移行しました。

 

6:ElasticBeanstalk(EC2) + RDS(Aurora) + Redis + S3 + CloudFront

f:id:gracia_tanp:20210406170920p:plain

さて、デプロイフローは整いましたが、この頃からcss/jsの静的ファイルの配信で問題が起きていることが発覚しました。これまでcss/jsは各EC2のサーバーに置いて配信していましたが、デプロイしている最中は「新しいバージョン」と「古いバージョン」が同じURLで共存してしまい、アクセスした際にどちらにヒットするか分からない、という状態になっていたのです。 

 

そこで、静的ファイルをサーバーに依存しない形で管理するため、S3 + CloudFrontで配信するよう構成を変更しました。具体的には、CodePipelineのビルド時に自動で該当ファイルをS3にアップロード、GitHubのコミットハッシュでS3のディレクトリを切るようにしています。

これにより、デプロイの最中でもcss/jsのバージョンの整合性を保つことができ、さらにCDN配信によるパフォーマンスの改善も実現しました。

 

ここまで色々とインフラ構成の変更を紹介してきましたが、現在は正にこの構成でサービスを運用しています。

 

まとめ

インフラの整備を通して、ビジネス要件・事業規模によりアーキテクチャは変化していくということを身を以て経験しました。創業時はリソースにも予算にも限りがありますし、問題に直面してアーキテクチャを移行していくことは事業の成長を実感できるためやりがいはあるのですが、基本的には事前にリスクを洗い出して対処することが理想ですので、メンバーも増えた今、より先を見据えたアクションをしていきたいと考えています。

今後の課題

今後の課題として、大きく下記の2点を意識しています。

  1. 脱ElasticBeanstalk
    Beanstalkにはebextensionsという設定ファイルでサーバーの設定を変更できる仕組みが用意されていますが、規模が拡大してくるとファイルが複雑になってしまい保守し辛い面があります。今後は自前でEC2を立てる、コンテナに移行する等何らかの対応を検討しています。
  2. DBスキーマ変更の自動化
    着手できる箇所から自動化を進めていますが、DBに係るスキーマの変更は手動で実施している部分があります。こちらも上手く自動化のフローに組み込んでいきたいと思っています。

最後に

事業の成長と共にインフラ周りは徐々に整備されてきましたが、まだまだ課題は多く、日々改善を進めています。これから一緒に改善していただけるエンジニアの方を絶賛募集中ですので、少しでも興味を持っていただけた方は気軽にご連絡いただけると嬉しいです! 

Twitter:https://twitter.com/takumin513 

Gracia Twitter:https://twitter.com/gracia_tanp
サービスグロースエンジニア:https://herp.careers/v1/gracia/8iShxaRK1ofK
基幹業務システムエンジニア:https://herp.careers/v1/gracia/okAApFG9c48Q
募集職種一覧:https://gra-cia.co.jp/careers

エンジニア採用:https://gra-cia.co.jp/engineer

 

twitter.com

 

編集:吉筋万記