※プレゼントキャンペーンのクイズを公開しました!
クイズの回答はこちらから!


皆さんこんにちは。
クラウドインテグレーション事業部MSP開発セクションの山﨑慎太郎です!

iretスペシャリスト認定制度では2021年度「シニアスペシャリスト」に選ばれました。

インタビュー記事: https://cloudpack.media/57856

この記事は、ブログリレーによるプレゼントキャンペーン「iretスペシャリストからの挑戦状」 の2本目ということで、私からは、Cloud Runを使ったマルチリージョンなWebアプリケーションについてご紹介します。

はじめに

まずはモチベーションについてお話ししたいと思います。

私の所属するチームは、弊社運用チームの運用業務の効率化をメインに様々な社内サービスを展開し、運用しています。

こちらのページにサービスの一覧を載せています。
[運用自動化ツールで効率的な運用を実現

その中に、例えば、「AMS」という、監視業務の一次対応を自動化し、対応時間の短縮や対応レベルの均一化・対応ミスの防止を実現するためのサービスがあります。
このサービスは24365で稼働する運用チームを支えるために、高い可用性を維持することを重要な要件としています。
その方法の一つとして、複数リージョンに展開する構成とし、加えて、構成要素についても高い可用性を持つクラウドサービスを採用しています。例えば、一部にGoogle Cloudの「Cloud Run」や「Cloud Functions」といったサーバーレスなクラウドサービスを採用しています。

これに限らず、我々のチームではマネージドなサービスを積極的に活用して、高可用の実現かつ運用保守の最小化を意識して開発しています。

今回は、今後より利用していきたい「Cloud Run」について調査したことをアウトプットしたいと思います。

Cloud Runとは

Cloud Runは、コンテナ実行のためのフルマネージドなコンピュート環境を提供するGoogle Cloudのサービスです。

Cloud Run : https://cloud.google.com/run

高速にWebサーバーをデプロイすることができ、プロビジョニングやスケーリングといったインフラ管理が不要となるサーバーレスなサービスです。

セキュリティ面の機能も十分に備わっており、また、課金体系についてもリクエストベースの従量課金で無料枠も十分に用意されているため、非常に安価に利用できます。

マルチリージョン構成にするには

Cloud Runはリージョン単位に展開されるリソースですが、Load Balancingと組み合わせると複数リージョンに跨ったグローバルな構成にすることができます。

Google CloudのLoad Balancingには、「グローバル外部HTTP(S)ロードバランサー」というグローバルに展開されるロードバランサーサービスがあります。

グローバル外部HTTP(S)ロードバランサー
https://cloud.google.com/load-balancing/docs/https/setting-up-https

このグローバル 外部HTTP(S)ロードバランサーと組み合わせることで、複数リージョンに展開されたCloud Runサービスに分散するWebアプリケーションを構成することができます。

また、Cloud Runをこのロードバランサーと組み合わせる際は「サーバーレス ネットワーク エンドポイント グループ (サーバーレスNEG)」を使用します。
https://cloud.google.com/load-balancing/docs/negs/serverless-neg-concepts

これはCloud RunやCloud Functions、App Engineといったサーバーレスリソースのエンドポイントグループを作るものであり、サーバーレスNEGを使ってCloud RunサービスをロードバランサーのBackendに追加します。

システム構成

今回は、東京リージョンと大阪リージョンの2リージョンに展開するWebアプリケーションを構成してみます。

全体の構成はこのようになります。

それぞれのリージョンに展開されたCloud Runサービスは、それぞれがサーバーレスNEGによってグローバル 外部HTTP(S)ロードバランサーのBackend Serviceに登録されます。

構築手順

今回はコンソール画面で設定します。大まかな手順のみ記載して詳細は割愛します。

Cloud Run

まず、Cloud Runの構築です。同じアプリケーションを両リージョンにそれぞれ展開します。
具体的なデプロイ方法は以下を参照ください。

参考: https://cloud.google.com/run/docs/deploying?hl=ja

今回デプロイしたアプリケーションのソースコードはこちらになります。
https://github.com/mmclsntr/go-web-app-sample
デプロイすると、サービス一覧画面はこのようになります。

Load Balancer

次に、Load Balancerの構築です。

まずLoad Balancerの選択ですが、今回利用するのは「HTTP(S) Load Balancing」になります。

次に「Backend Configuration」「Host and Path rules」「Frontend Configuration」を設定していきます。

Backend Configuration

Backend Configurationについて、ここで上で構築したCloud RunサービスをLoad Balancerに紐付けます。

Backend typeに「Serverless network endpoint group」を選択します。

これでBackendsにサーバーレスNEGを追加できるようになるので、「Add Backend」からサーバーレスNEGをリージョンごとにそれぞれ追加し、展開したCloud Runサービスを登録します。追加すると画像のように2つ並ぶような状態になります。


Backend Configurationは以上です。

Host and Path rules

「Host and Path rules」については今回はデフォルトのままです。ここの設定次第ではリクエストパスによってバックエンドのリージョンを分けるようなこともできます。
参考: https://cloud.google.com/load-balancing/docs/https/setting-up-https-serverless#setting_up_regional_routing

Frontend Configuration

「Frontend Configuration」についても、ここでは一旦、HTTPを使うように設定します。

これで、2リージョンに分散するWebサーバーの構築は完了です。リクエストを送ると、どちらかのCloud Runサービスからレスポンスが返ってきます。

ルーティングのルール

ここで、複数リージョンに対してどのようなルーティングのルールで分散されるかについても補足したいと思います。ルールとしては以下の仕様のようです。

  • リクエストを最も近くの使用可能なリージョン内のサーバーレス NEG に転送
  • 最も近いリージョンが利用できないか、そのリージョンの容量が不足している場合、リクエストは別のリージョンにルーティングされます。

参考: https://cloud.google.com/load-balancing/docs/https/setting-up-https-serverless#multi_region_lb

つまり、リクエストを送る場所からネットワーク的に最も近いリージョンにルーティングするというルールになるそうです。

実際に、今私が住んでいる大阪からリクエストを送ると大阪リージョン側のCloud Runに到達し、東京経由となるVPNに繋いでからリクエストを送ってみると、東京リージョン側の方にルーティングしました。

また、仕様上は片方をリージョンが落ちたら別のリージョンにフェールオーバーするように読み取れますが、実際の動作確認は出来なさそうでした。

ちなみに、Backends Serviceはターゲットに対してヘルスチェックを行う機能がありますが、サーバーレスNEGでは使えません (そもそも不要という考えだと思います)
https://cloud.google.com/load-balancing/docs/negs/setting-up-serverless-negs#additional_configuration_options

セキュリティ

次にセキュリティ周りについても説明します。

Cloud Run側

まず、Cloud Run側のセキュリティ対策について。

今回は、前段にLoad Balancerを置くため、Cloud Runに直接のリクエストは遮断しLoad Balancerからのアクセスのみに制限するように、Cloud Runの「上り(内向き)の制限」を設定できます。

この内向き制限により、Load Balancerからのリクエストのみを受けるように設定可能です。
https://cloud.google.com/run/docs/securing/ingress

Cloud RunサービスのTrigger設定で、画像のように「Allow internal traffic and trafic from Cloud Load Balancing」を選択します。

Load Balancer側

次にLoad Balancer側のセキュリティ対策について。

まず、そのままだとプロトコルはHTTPとなっているため、これをHTTPSにしておきたいですね。
そのために、IPアドレスの固定化と、ドメインネームの割り当て、SSL証明書の設定を行います。

ネームサーバーにはCloud DNSを、証明書はGoogle マネージド SSL 証明書を使用できます。

Cloud DNS: https://cloud.google.com/dns/docs/overview/
Google マネージド SSL 証明書:https://cloud.google.com/load-balancing/docs/ssl-certificates/google-managed-certs

また、DDoS対策やWAFは、「Cloud Armor」で実装が可能です。
https://cloud.google.com/armor/docs/cloud-armor-overview

その他、認証については、「Identity-Aware Proxy (IAP)」を利用した認証を実装することが可能です。
※注意 執筆時点では、Cloud RunにおけるIAPの利用はPre-GAの状態です。
https://cloud.google.com/iap/docs/concepts-overview
以上をまとめると、画像のように各所にセキュリティ対策を施すことができます。

まとめ

高い可用性/耐障害性かつ低コストな運用の実現の1つとして考えた、Google CloudのサーバーレスなサービスであるCloud Runを使ったマルチリージョンアプリケーションについてアウトプットしました。

Cloud Runの手軽さはもちろん、そこにグローバルロードバランサーをプラスするだけで比較的簡単に構築できます。Load Balancingとの組み合わせることで出来ることの幅は広がるため、シングルリージョンであっても組み合わせて利用していきたいと思いました。

今回調査した内容も活用して、これからもcloudpackの運用品質向上のためのツールを作っていきたいと思います。