Serverless NEG でシステム開発をより柔軟に
はじめに
以前 Yuki Furuyama さんが「NEG とはなにか」という哲学的な(?)記事を書かれていましたが、このたび「Serverless NEG」(Serverless Network Endpoint Group)という新しいタイプの NEG が追加されました。(まずは Beta でのご提供です → EDIT(2020–10–14): 2020年10月14日に GA になりました。)
これで NEG は Zonal NEG、Internet NEG、Serverless NEG の三種類になりました。
Furuyama さんの Zonal NEG に関する記事には「NEG は Kubernetes の Service に相当するもの、Network Endpoint は Pod に相当するものです」とありましたが、Serverless NEG では「Network Endpoint は(Google Cloud の)サーバーレスサービスに相当するもの」となります。
サーバーレスサービスとは Cloud Run (fully managed)、Cloud Functions、App Engine を指します。
そして Zonal NEGが「Kubernetes の Service と Pod を GCP の世界で第一級市民として扱える」ようにすることが目的であったように、Serverless NEG はサーバーレスサービスを Serverless NEG という形で抽象化することで Google Cloud のグローバルなロードバランサーである HTTP(S) Load Balancing と組み合わせて使うことを目的としています。
上に挙げたサーバーレスサービスはいずれもそれ単体で HTTP(S) によるアクセスと内部的な負荷分散・スケーリングをサポートしていましたが、HTTP(S) Load Balancing と組み合わせることで、グローバルな Anycast IP アドレス、コンテンツベースのルーティング、マネージドな SSL 証明書、Cloud Armor によるウェブアプリケーションの保護、ユーザー定義ヘッダ、リダイレクトやURL書き換えなどの豊富な機能を使えるようになります。
構成
Google Compute Engine (GCE) や Google Kubernetes Engine (GKE) をバックエンドとする通常の HTTP(S) Load Balancing は以下のように構成されています。
これが Serverless NEG と組み合わさるとこんな感じになります。
バックエンドであるインスタンスグループが Serverless NEG になった以外に何も変わっていません。このように Serverless NEG はコンポーネントのちょうどいい具合の抽象化となっているのです。
構成例
同じサーバーレスアプリケーションを複数のリージョンに展開することで、エンドユーザーからのアクセスを最も近い拠点へと誘導し、より低遅延で安定したサービスを提供することができます。
また、URL にもとづいて異なるリージョン、異なるサーバーレスアプリケーションへとルーティングすることも可能です。
このように、一つの ドメイン(IP アドレス)を入り口として、GCE/GKE に加えて様々なサーバーレスサービス上に構築されたアプリケーションへと、エンドユーザーのロケーションや、コンテンツにもとづいてルーティングができるため、システムの開発・構築を柔軟におこなっていただけるようになります。
Serverless NEG の利用例
それでは実際にどう使えるのか見ていきましょう。(ドキュメントに詳細がありますので、そちらも合わせてご参照ください。)
大まかな流れとしては、上の図の右から左に向かってリソースを作っていくことになります。つまり、
- サーバーレスアプリケーション
- Serverless NEG
- バックエンドサービス
- URL マップ
- ターゲット HTTP プロキシ
- フォワーディングルール
の順番で作っていくことになります。
では、まずはサンプルアプリケーションを Cloud Run にデプロイします。
$ gcloud run deploy --image gcr.io/google-samples/hello-app:1.0 --platform managed --region asia-northeast1 --allow-unauthenticated hello-app
Deploying container to Cloud Run service [hello-app] in project [project-ongcp] region [asia-northeast1]
✓ Deploying new service... Done.
✓ Creating Revision... Revision deployment finished. Waiting for health check to begin.
✓ Routing traffic...
✓ Setting IAM Policy...
Done.
Service [hello-app] revision [hello-app-00001-qul] has been deployed and is serving 100 percent of traffic at https://hello-app-7525gqawya-an.a.run.app$ curl https://hello-app-7525gqawya-an.a.run.app
Hello, world!
Version: 1.0.0
Hostname: localhost
そしてこのアプリケーション(“hello-app”)を Serverless NEG で指定します。(リージョンを Cloud Run のアプリケーションに合わせます)
$ gcloud beta compute network-endpoint-groups create hello-app-serverless-neg --region=asia-northeast1 --network-endpoint-type=SERVERLESS --cloud-run-service=hello-app
Created [https://www.googleapis.com/compute/beta/projects/project-ongcp/regions/asia-northeast1/networkEndpointGroups/hello-app-serverless-neg].
Created network endpoint group [hello-app-serverless-neg].
次にバックエンドサービスを作って、この Serverless NEG をバックエンドとして追加します。(HTTP(S) Load Balancing はグローバルなリソースなので、バックエンドサービスもグローバルなリソースとして( — global)作ります。)
バックエンドサービスを作成$ gcloud compute backend-services create hello-app-backend-service --global
Created [https://www.googleapis.com/compute/v1/projects/project-ongcp/global/backendServices/hello-app-backend-service].
NAME BACKENDS PROTOCOL
hello-app-backend-service HTTPhello-app-serverless-neg をバックエンドとして追加$ gcloud beta compute backend-services add-backend hello-app-backend-service --global --network-endpoint-group=hello-app-serverless-neg --network-endpoint-group-region=asia-northeast1
Updated [https://www.googleapis.com/compute/beta/projects/project-ongcp/global/backendServices/hello-app-backend-service].
URL マップを作って、今作ったバックエンドサービスを指定します。
$ gcloud compute url-maps create hello-app-url-map --default-service=hello-app-backend-service
Created [https://www.googleapis.com/compute/v1/projects/project-ongcp/global/urlMaps/hello-app-url-map].
NAME DEFAULT_SERVICE
hello-app-url-map backendServices/hello-app-backend-service
ちなみにクラウドコンソール上ではこの URL マップの名前(hello-app-url-map)がロードバランサーの名前として載ります。
続いて、ターゲット HTTP プロキシを作って、URL マップを指定します。(なお、HTTPS Load Balancing を作りたい場合は、ここで証明書の作成と、ターゲット HTTPS プロキシを作成をおこないます。)
$ gcloud compute target-http-proxies create hello-app-target-http-proxy --url-map=hello-app-url-map
Created [https://www.googleapis.com/compute/v1/projects/project-ongcp/global/targetHttpProxies/hello-app-target-http-proxy].
NAME URL_MAP
hello-app-target-http-proxy hello-app-url-map
最後にフォワーディングルールで IP アドレスを付与したら Serverless NEG をバックエンドとする HTTP Load Balancing のできあがりです。(ここで予約しておいた IP アドレスを指定することもできます)
$ gcloud compute forwarding-rules create hello-app-forwarding-rule --target-http-proxy=hello-app-target-http-proxy --global --ports 80
Created [https://www.googleapis.com/compute/v1/projects/project-ongcp/global/forwardingRules/hello-app-forwarding-rule].
それでは早速アクセスしてみましょう。まず、付与された IP アドレスを確認します。
$ gcloud compute forwarding-rules describe hello-app-forwarding-rule --global --format="value(IPAddress)"
34.107.182.223
curl でアクセスしてみます。(HTTPS で作った場合は特に、アクセスできるようになるまで少し(10–15分くらい)時間がかかる場合があります)
$ curl http://34.107.182.223/
Hello, world!
Version: 1.0.0
Hostname: localhost
無事アクセスできることが確認できました。
できたロードバランサーはクラウドコンソール上ではこのように見えます。
下の「制限」の項にもある通り、クラウドコンソールは未対応のため、上図の「hello-app-serverless-neg」をクリックしてもエラーになります。
上に挙げたその他の構成例については、別の記事でご紹介しています。
制限
本記事執筆時点では以下の通りいくつか制限があります。
gcloud
コマンドでの作成のみがサポートされており、Cloud Console での作成は今後サポート予定です (EDIT(2020–10–14): 2020年10月14日に GA になり、現在は Cloud Console での設定も可能です)- 各サーバーレスサービスは作成した Serverless NEG と同一リージョンにある必要があります
- 各サーバーレスサービスはロードバランサーと同一プロジェクトに作られている必要があります
- ロードバランサーから各サーバーレスサービスへの個別の正常性は確認してないため、問題が発生した際に別リージョンへリダイレクト、といったことはできません
おわりに
これまでサーバーレスサービスによるシステム開発と、HTTP(S) Load Balancing + GCE/GKE によるシステム開発は別々のものとして扱われてきました。
またそのため、GCE/GKE でのシステム開発では受けられていたマネージドな SSL 証明書の利用や、Cloud Armor によるウェブアプリケーションへの保護といった恩恵を、サーバーレスアプリケーションでは受けることができませんでした。
今回ご提供を開始いたしました Serverless NEG によって、このギャップを埋めることができ、「トラフィックを受け」「ルーティングし」「アプリケーションで処理する」といった一連の流れを統一的に扱うことができるようになりました。
これによって Google Cloud 上でのシステム開発の自由度を最大限に活かしていただけるようになったものと考えております。
また、もしこれまで Cloud Run、Cloud Functions、App Engine をご利用いただいたことがなければ、この機会に、ぜひ Serverless NEG と合わせてお試しいただければ幸いです。🙏