ヘンリーで SRE をやっている
id:nabeop です。
これは株式会社ヘンリー Advent Calendar 2025 (シーズン1) の2日目の記事です。昨日は VPoP (VP of Product) の縣 (
id:agtn / @agatan) による事業戦略は技術戦略に影響を与えるが、技術戦略もまた事業戦略に影響を与えるべきでした。
今年の SRE チームの大きなトピックとしてクラウド基盤を Google Cloud から AWS に移設するプロジェクトが進んでいます。プロジェクト自体は去年から始まっており、粛々と進めていたのですが、ある程度の目処が立ってきたので今年の10月に外部向けにもプロジェクトの存在を公開しました。
カジュアル面談やイベントなどで AWS 移設について言及することがあったのですが、一番質問されたのは「なぜ、クラウド基盤の移設をするのか?」という内容でした。そこで、今回は Google Cloud を選択した経緯と、クラウド基盤の移設を決定した背景について説明したいと思います。
筆者の考えではプロダクトの性質や事業や組織の状況によって最適なクラウド基盤は変わってくると思っており、必ずしも AWS が最適解とは限らないと考えています。そのため、本エントリではサービスの立ち上げ当初で Google Cloud を選択し、サービスの成長に伴い AWS に移設することにした背景について説明したいと思います。
サービス立ち上げ時に Google Cloud を選択した背景
筆者はサービスの立ち上げ時にはヘンリーに所属していなかったため、伝聞や社内に残された記録を調査1したところ、以下のような背景で Google Cloud を選択したようです。
Henry の開発が開始した2019年当時はインフラ部分をフルタイムでみることができるエンジニアはおろか、開発メンバーはそれぞれ何かしらの本業を持った状態だったので、できるだけマネージドサービスを利用してインフラ運用の負荷を下げたいという要求があることは想像に難しくありません。また、この時期は AWS では Amazon ECS on Fargate や Amazon EKS といったサービスがすでに GA となっており、利用が広がっていたところに、Google Cloud からマネージドなコンテナ実行基盤である Cloud Run がリリース2されていました。このような状況でより良い開発体験をもとめて Clooud Run が選択されました。
実際にフルタイムの1人目 SRE として戸田 (
id:eller / @Kengo_TODA) がジョインするまでは社内の開発者と業務委託のインフラ担当者によって維持されており、Google Cloud のマネージドサービスを活用することでインフラ運用の負荷を下げることができていました。また、フルタイムの SRE がジョインしたあともインフラ部分が抽象化された Google Cloud のマネージドサービスによってインフラ運用の負荷を下げつつ、サービスの信頼性の確保に開発工数をさくことができていました。
実際に Google Cloud を採用したことによるメリットをまとめたエントリが技術ブログに残っています。
クラウド基盤の変更を決定した背景
Henry はクリニック向けのレセコン一体型の電子カルテとして開発を開始しましたが、今は対象を病院に切り替えています。医療ドメインでは「クリニック」と「病院」は明確に区別されていて、外来診療中心のクリニックに対して病院では入院に伴う様々な業務が発生します。このため、クリニックと病院では求められる機能の複雑さや多様性が異なり、インフラ部分で求められる信頼性や可観測性も異なります。
このような状況で、クラウド基盤の変更を決定した要因はいくつかありますが、一言でいうとクラウド基盤と我々のアプリケーションの特性の相性がわるく、今後のサービス展開ではより一層高い信頼性を求められることが予想されたため、移行を決断したということになります。
ここではクラウド基盤の変更を決定した要因のうち2つについて解説します。
インフラレイヤーを我々でコントロールできるようにする
Google Cloud を選択した理由に開発体験の高さがありましたが、筆者は Google Cloud の開発体験の高さの要因の1つとしてインフラ側が高度に抽象化されていることにあると考えています。インフラ側が高度に抽象化されることで、開発者は自身のサービスの開発に集中することができます。
しかし、クラウド基盤を Google Cloud から AWS に変更することを決定した要因も Google Cloud で高度に抽象化されたインフラが我々のサービスの構成とミスマッチしていると考えたことにあります。
たとえば、Amazon ECS は ECS サービスでリクエストを受ける場合は ALB や NLB といったロードバランサーや Service Connect と組み合わせる必要がありますが、Cloud Run では機能の一部として内部的にロードバランサーのようなものが組み込まれています3。
Cloud Trace を有効にしている場合は Cloud Run の内部ロードバランサーは Component が AppServer という値をもつトレース4で観測することができます。Cloud Run 同士の通信などでエラーが発生し、問題を切り分ける時に内部ロードバランサーの情報が欲しくなるときがありますが、Cloud Trace は確率的にトレースを保存しない5ため、問題の切り分けに苦労することがありました。
このように抽象化されたインフラレイヤーで問題の発生が疑われる場合、クラウド基盤のユーザである弊社側では調査する手段がなく手詰まりとなってしまいます。過去に実際に発生した障害ではインフラレイヤーで発生していた事象を弊社側で確認できなかったため、問題解決まで時間がかかりお客様にご迷惑をおかけしたことがありました。
前述した通り、Amazon ECS の場合は ALB などと組み合わせる必要がありますが、ALB で発生している問題についてログやメトリクスから調査ができるため、弊社側で運用の手間は多くなりますが、問題が発生した時にコントロール可能な箇所が広がるので解決までのリードタイムの短縮を見込むことができます。インフラレイヤーの責務が我々にうつるため信頼性の低下が懸念されますが、AWS サポートを活用することでカバーが可能と判断しました。
Kotlin アプリケーションとの相性
弊社ではバックエンドのほとんどの機能を Kotlin で実装しています。VP of Product の縣 (
id:agtn / @agatan) が Server-Side Kotlin Night 2025 で発表しているとおり、レセコン一体型の電子カルテを開発するにあたり、Kotlin のもつ言語特性は最適な選択だったと思っています。
しかし、Kotlin アプリケーション、言い換えると JVM アプリケーションはコンテナ起動からアプリケーションが利用可能になるまでの時間 (コールドスタートレイテンシ) が長くなる傾向があり、コンテナの実行基盤と相性が悪い側面があります。この傾向は当初から認識しており、複数のアプローチを組み合わせることで、コールドスタートレイテンシを10秒程度まで短縮することに成功していました。Kotlin アプリケーションのコールドスタートレイテンシの取り組みについては過去に解説のエントリを出しています。
しかし、Cloud Run ではコールドスタートレイテンシを10秒以内に収める必要がある6ため、この取り組みでも十分とは言えない状況でした。このため、スケールアウトのチューニングが重要になってきます。Cloud Run のオートスケールのチューニングポイントは以下の2つに限定されます7。
- CPU 利用率の平均が60%になるように調整する
- コンテナインスタンスに割り当てているリクエスト数が処理可能なリクエスト数の60%になるように調整する
上記の2つの指標を材料にコンテナインスタンスの vCPU 割り当ての変更や最大リクエスト数の調整をすることでスケールアウトをコントロールしていましたが、Kotlin アプリケーションを使った Cloud Run のオートスケールのチューニングはかなり難しく、過剰な数のインスタンスを起動させつつ、リソースの余裕を確保することで極力オートスケールが発生しないようにするアプローチを採用しました8。
このような状況のため、Cloud Run から GKE への移行も検討しましたが、前述の抽象化されたインフラレイヤーが引き起こす不便さに加え、Google Cloud の特性が弊社のアプリケーション特性と相性が悪かったため、より自由度が高い AWS への移行を選択しました。
適材適所でクラウド基盤を選択する
AWS 移設にあたり、Henry を構成するコンポーネントの全てを AWS に移設するわけではなく、適材適所でクラウド基盤を選択しています。
例えば、Henry のレセコンとしての側面では診療報酬会計を担当しており、医療機関さんの経営の重要な指標となるデータをもっています。そこで、Henry に保存されているデータを使って医療機関さん向けに BI ツールを提供しています。この BI ツールで表示するデータは BigQuery に依存しています。
AWS にも BigQuery の代替となる Amazon Redshift が存在しますが、移設のための作業に伴うリスクやダウンタイム、移設後の保守性などを勘案して、データの一次情報は AWS に移行するものの、BI ツールのデータバックエンドは移設の対象外とする判断をしました。また、弊社では AWS 移設と並行してデータ基盤の整備を始めており、しばらくは BI ツールのデータバックエンドとして BigQuery は使い続けることになりそうです。
さらに昨今は AI によるコーディング支援などによって開発者以外でも PoC を作成したり、社内向けのツールの作成が可能になっています。実際に弊社でも開発者以外でこのようなツールを作るケースも出てきました。このようなツールのデプロイ先として AWS を選択するにはハードルが高く、インフラ部分で考慮する必要が少ない Google Cloud がデプロイ先として適切だと考えています。
まとめ
今回はクラウド基盤の移設を決定した背景として Google Cloud を選択したときからサービスの成長に伴いクラウド基盤への要求が変化した様子をについて解説しました。
開発開始当初に Google Cloud を選択したことは間違っていなかったし、当時の少ない開発リソースのなかで Cloud Run がタイミングよくリリースされたことは Henry にとって幸運だったと思いました。また、開発開時の様子をみることができて、当時からヘンリーに関わっていたメンバーへの敬意もあらたにできました。
AWS 移設はまだ完了しておらず、完了後も高い信頼性を実現するためのチャレンジが待っています。ヘンリーではこの挑戦を一緒に手伝ってもらえるエンジニアを募集しています。興味のあるかたはカジュアル面談などで談義したいです。
ヘンリーでは今年もアドベントカレンダーを実施しており、今年はシリーズ1とシリーズ2の2トラックを予定しています。明日のエントリも楽しみにしていてください。
- 今回のエントリの執筆にあたり、社内に残されている開発開始当時の資料を調査しましたが、スタートアップの開始当初の熱気を感じることができてとても面白かったです。↩
- Cloud Run のリリースノートによると2019年4月にベータリリースとなり、2019年11月に GA となっています。↩
- ここでは Google Cloud の Cloud Load Balancing ではなく、Cloud Run のコンテナインスタンスの前段でコンテナインスタンスにリクエストを振り分けている機能を「ロードバランサーのようなもの」と言及しています。例えば、Cloud Run でリクエストを割り当て可能なインスタンスが存在しない時に 429 エラーが応答することなどから、コンテナインスタンスの前段にロードバランサー的な動きをするコンポーネントが存在していると理解しています。↩
-
Cloud Run のセキュリティデザインのドキュメントによると「App server」というコンポーネントが「HTTP Proxy」からきたリクエストを Sandbox に閉じ込められた顧客のコンテナに中継しています。Cloud Trace で出ている
AppServerは、このドキュメントにおける「App server」が相当していると理解しています。↩ - Cloud Trace でトレースが間引かれる様子については事例から学ぶクラウドへのOpenTelemetry導入のハマりどころで解説しています。↩
- 執筆時点の該当する Cloud Run のドキュメントでは「Requests will pend for up to 3.5 times average startup time of container instances of this service, or 10 seconds, whichever is greater.」と記載されていて、コンテナインスタンスの平均起動時間の3.5倍までは待つと記述されていますが、チューニングを実施していた時点では該当する記述がなく、10秒以内に収める必要があるという認識で諸々の調整をしていました。↩
- About instance autoscaling in Cloud Run services | Google Cloud Documentation↩
- ここでは Kotlin アプリケーションにフォーカスしていますが、他にも基本的にシングルスレッドでうごく Node.js アプリケーションでも CPU 利用率の平均値を使用したスケールアウトのチューニングにも苦労をしていました。↩