クロスリージョン内部アプリケーションロードバランサを試してみた

記事タイトルとURLをコピーする

G-gen の藤岡です。当記事では、Google Cloud(旧称 GCP)の 2023 年 8 月にリリース された Cloud Load Balancing のクロスリージョン内部アプリケーションロードバランサを紹介します。

はじめに

Cloud Load Balancing とは

Cloud Load Balancing とは Google Cloud が提供する仮想的なロードバランサです。 以下の記事では、External Application Load Balancer だけでなく Cloud Load Balancing の内部的な仕組みについて触れていますので、当記事と併せてご参照ください。 blog.g-gen.co.jp

Cloud Load Balancing は以下の 9 種類 が提供されています。当記事では図内の Cross-region internal Application Load Balancer であるクロスリージョン内部アプリケーションロードバランサに焦点を当てています。

公式ドキュメントから引用

内部アプリケーションロードバランサとは

内部アプリケーションロードバランサ は、Envoy プロキシベースのレイヤ 7 ロードバランサで、接続元が Google Cloud 内や Cloud VPN、Cloud Interconnect で接続されたオンプレミスの他、Amazon Web Services(AWS)等からのトラフィックをバックエンドサービスへ分散します。

内部アプリケーションロードバランサは、バックエンドのタイプによってリージョンモードとクロスリージョンモードの 2 種類が提供されています。

  • リージョン内部アプリケーションロードバランサ
  • クロスリージョン内部アプリケーションロードバランサ(Preview 版)

リージョン内部アプリケーションロードバランサでは、バックエンドはロードバランサと同一リージョンに配置します。

バックエンドがリージョンを跨ぐ場合には、クロスリージョン内部アプリケーションロードバランサを選択します。 これによって、オフィスやデータセンター拠点から Google Cloud へ国内であれば東京(asia-northeast1)と大阪(asia-northeast2)への負荷分散やフェイルオーバーができ、単一リージョンにおける障害回避が可能になります。

クロスリージョン内部アプリケーションロードバランサがリリースされる前は、バックエンドがリージョンを跨ぐ場合には以下の記事あるように Cloud DNS による分散が候補に挙げられましたが、バックエンドに異常が発生した場合の自動フェイルオーバー機能は用意されていないため、独自に実装する必要がある等の制限がありました。

blog.g-gen.co.jp

アーキテクチャ

クロスリージョン内部アプリケーションロードバランサのアーキテクチャは以下の通りです。

クロスリージョン内部アプリケーションロードバランサからバックエンドサービス (インスタンスグループやサーバレス NEG 等) へのパケットは「プロキシ専用サブネット」から送信されます。また、バックエンドサービスはヘルスチェックによってバックエンド (VM 等) の正常性を確認します。

そのため VPC ファイアウォールではそれらの通信を許可する必要があります。

アーキテクチャ

実施内容

構成図

当記事で作成するリソースは以下の通りです。

構成図

前提

gcloud コマンドでリソースを作成します。実行環境は Cloud Shell で、Google Cloud SDK バージョンは以下の通りです。

fujioka@cloudshell:~ (xxxx)$ gcloud version | grep "Google Cloud SDK"
Google Cloud SDK 445.0.0
fujioka@cloudshell:~ (xxxx)$ 

構築

事前準備

プロジェクトの作成と請求先アカウントの紐づけ

プロジェクトを作成し、作成したプロジェクトに請求先アカウントを紐づけます。

$ gcloud projects create ${PROJECT_ID} --name=${PROJECT_NAME} --organization=${ORGANIZATION_ID} && \
gcloud beta billing projects link ${PROJECT_ID} --billing-account=${BILLING_ACCOUNT_ID}

デフォルトプロジェクトのセット

作成したプロジェクトをデフォルトプロジェクトとしてセットし、結果を確認します。

$ gcloud config set project ${PROJECT_ID} && \
gcloud config list project

API の有効化

今回の検証で必要な API を有効化します。

$ gcloud services enable compute.googleapis.com dns.googleapis.com

リソースの作成

VPC とサブネットの作成

VPC とサブネットを作成します。

# VPC の作成
$ gcloud compute networks create lb-network --subnet-mode=custom

# asia-northeast1(Tokyo)にサブネットの作成
$ gcloud compute networks subnets create lb-subnet-asia-northeast1 \
    --network=lb-network \
    --range=10.1.2.0/24 \
    --region=asia-northeast1

# asia-northeast2(Osaka)にサブネットの作成
$ gcloud compute networks subnets create lb-subnet-asia-northeast2 \
    --network=lb-network \
    --range=10.1.3.0/24 \
    --region=asia-northeast2

プロキシ専用サブネットの作成

プロキシ専用サブネットを作成します。バックエンドサービスへのアクセスは、プロキシ専用サブネットからになるため、後述のファイアウォールの設定でプロキシ専用サブネットからのアクセスを許可する必要があります。
プロキシ専用サブネットは 64 個以上の IP アドレスが必要であり、推奨されるサブネットサイズは /23 です。

# asia-northeast1(Tokyo)にプロキシ専用サブネットの作成
$ gcloud beta compute networks subnets create proxy-only-subnet-asia-northeast1 \
    --purpose=GLOBAL_MANAGED_PROXY \
    --role=ACTIVE \
    --region=asia-northeast1 \
    --network=lb-network \
    --range=10.129.0.0/23

# asia-northeast2(Osaka)にプロキシ専用サブネットの作成
$ gcloud beta compute networks subnets create proxy-only-subnet-asia-northeast2 \
    --purpose=GLOBAL_MANAGED_PROXY \
    --role=ACTIVE \
    --region=asia-northeast2 \
    --network=lb-network \
    --range=10.130.0.0/23

プロキシ専用サブネットを作成すると、コンソールでは以下のように表示されます。

プロキシ専用サブネットの表記

ファイアウォールルールの作成

3 つのファイアウォールルールを作成します。

  • fw-allow-ssh:Compute Engine へ SSH 用
  • fw-allow-health-check: ヘルスチェック用
  • fw-allow-proxies:プロキシ専用サブネットからバックエンドサービスへのアクセス用(今回は 80/tcp)

フェイルオーバーの検証をタグの削除によるヘルスチェックの失敗で確認をするため、ファイアウォールのターゲットはタグにします。

# fw-allow-ssh
$ gcloud compute firewall-rules create fw-allow-ssh \
    --network=lb-network \
    --action=allow \
    --direction=ingress \
    --source-ranges=0.0.0.0/0 \
    --target-tags=allow-ssh \
    --rules=tcp:22

# fw-allow-health-check
$ gcloud compute firewall-rules create fw-allow-health-check \
    --network=lb-network \
    --action=allow \
    --direction=ingress \
    --source-ranges=130.211.0.0/22,35.191.0.0/16 \
    --target-tags=load-balanced-backend \
    --rules=tcp

# fw-allow-proxies
$ gcloud compute firewall-rules create fw-allow-proxies \
    --network=lb-network \
    --action=allow \
    --direction=ingress \
    --source-ranges=10.129.0.0/23,10.130.0.0/23 \
    --target-tags=load-balanced-backend \
    --rules=tcp:80

マネージドインスタンスグループの作成

インスタンステンプレートを作成します。

# asia-northeast1(Tokyo)にインスタンステンプレートの作成
$ gcloud compute instance-templates create gil7-backend-asia-northeast1-template \
  --region=asia-northeast1 \
  --network=lb-network \
  --subnet=lb-subnet-asia-northeast1 \
  --tags=allow-ssh,load-balanced-backend \
  --image-family=debian-10 \
  --image-project=debian-cloud \
  --metadata=startup-script='#! /bin/bash
    apt-get update
    apt-get install apache2 -y
    a2ensite default-ssl
    a2enmod ssl
    vm_hostname="$(curl -H "Metadata-Flavor:Google" \
    http://169.254.169.254/computeMetadata/v1/instance/name)"
    echo "Page served from: $vm_hostname" | \
    tee /var/www/html/index.html
    systemctl restart apache2'

# asia-northeast2(Osaka)にインスタンステンプレートの作成
$ gcloud compute instance-templates create gil7-backend-asia-northeast2-template \
  --region=asia-northeast2 \
  --network=lb-network \
  --subnet=lb-subnet-asia-northeast2 \
  --tags=allow-ssh,load-balanced-backend \
  --image-family=debian-10 \
  --image-project=debian-cloud \
  --metadata=startup-script='#! /bin/bash
    apt-get update
    apt-get install apache2 -y
    a2ensite default-ssl
    a2enmod ssl
    vm_hostname="$(curl -H "Metadata-Flavor:Google" \
    http://169.254.169.254/computeMetadata/v1/instance/name)"
    echo "Page served from: $vm_hostname" | \
    tee /var/www/html/index.html
    systemctl restart apache2'

インスタンステンプレートを使って、マネージドインスタンスグループを作成します。

# asia-northeast1(Tokyo)にインスタンスグループの作成
$ gcloud compute instance-groups managed create l7-ilb-backend-asia-northeast1 \
    --zone=asia-northeast1-a \
    --size=2 \
    --template=gil7-backend-asia-northeast1-template

# asia-northeast2(Osaka)にインスタンスグループの作成
$ gcloud compute instance-groups managed create l7-ilb-backend-asia-northeast2 \
    --zone=asia-northeast2-a \
    --size=2 \
    --template=gil7-backend-asia-northeast2-template

クロスリージョン内部アプリケーションロードバランサの作成

ヘルスチェックを作成します。
ここでは HTTP ヘルスチェックを作成しますが、クロスリージョン内部アプリケーションロードバランサでは他にも TCP、SSL、HTTPS 等もサポートしています。

# HTTP ヘルスチェックの作成
$ gcloud compute health-checks create http gil7-basic-check \
   --use-serving-port \
   --global

バックエンドサービスを定義します。
ロギングはバックエンドサービス単位で有効にできます。ロギングはトラブルシューティング時に有用です。

$ gcloud compute backend-services create gil7-backend-service \
  --load-balancing-scheme=INTERNAL_MANAGED \
  --protocol=HTTP \
  --enable-logging \
  --logging-sample-rate=1.0 \
  --health-checks=gil7-basic-check \
  --global-health-checks \
  --global

バックエンドサービスにインスタンスグループを追加します。

# asia-northeast1(Tokyo)にインスタンスグループをバックエンドに追加
$ gcloud compute backend-services add-backend gil7-backend-service \
  --balancing-mode=UTILIZATION \
  --instance-group=l7-ilb-backend-asia-northeast1 \
  --instance-group-zone=asia-northeast1-a \
  --global

# asia-northeast2(Osaka)にインスタンスグループをバックエンドに追加
$ gcloud compute backend-services add-backend gil7-backend-service \
  --balancing-mode=UTILIZATION \
  --instance-group=l7-ilb-backend-asia-northeast2 \
  --instance-group-zone=asia-northeast2-a \
  --global

URL マップを作成します。

$ gcloud compute url-maps create gil7-map \
  --default-service=gil7-backend-service \
  --global

ターゲットプロキシを作成します。

$ gcloud compute target-http-proxies create gil7-http-proxy \
  --url-map=gil7-map \
  --global

今回はターゲットプロキシを HTTP としていますが、HTTPS で DNS 認証を使う場合、以下の記事を参考にしてください。 blog.g-gen.co.jp

フォワーディングルールを作成します。

# asia-northeast1(Tokyo)
$ gcloud compute forwarding-rules create gil7-forwarding-rule-asia-northeast1 \
  --load-balancing-scheme=INTERNAL_MANAGED \
  --network=lb-network \
  --subnet=lb-subnet-asia-northeast1 \
  --subnet-region=asia-northeast1 \
  --address=10.1.2.99 \
  --ports=80 \
  --target-http-proxy=gil7-http-proxy \
  --global

# asia-northeast2(Osaka)
$ gcloud compute forwarding-rules create gil7-forwarding-rule-asia-northeast2 \
  --load-balancing-scheme=INTERNAL_MANAGED \
  --network=lb-network \
  --subnet=lb-subnet-asia-northeast2 \
  --subnet-region=asia-northeast2 \
  --address=10.1.3.99 \
  --ports=80 \
  --target-http-proxy=gil7-http-proxy \
  --global

クロスリージョン内部アプリケーションロードバランサはコンソールで見た時に、「リージョン」が空欄になるのに対し、リージョン内部アプリケーション ロードバランサは属するリージョンが表示されます。

コンソール表示

検証クライアントの作成

検証クライアントとして、Compute Engine インスタンスを作成します。

# asia-northeast1(Tokyo)
$ gcloud compute instances create l7-ilb-client-asia-northeast1-a \
    --image-family=debian-10 \
    --image-project=debian-cloud \
    --network=lb-network \
    --subnet=lb-subnet-asia-northeast1 \
    --zone=asia-northeast1-a \
    --tags=allow-ssh \
    --metadata=startup-script='#!/bin/bash
      apt-get update
      apt-get install -y dnsutils'

# asia-northeast2(Osaka)
gcloud compute instances create l7-ilb-client-asia-northeast2-a \
    --image-family=debian-10 \
    --image-project=debian-cloud \
    --network=lb-network \
    --subnet=lb-subnet-asia-northeast2 \
    --zone=asia-northeast2-a \
    --tags=allow-ssh \
    --metadata=startup-script='#!/bin/bash
      apt-get update
      apt-get install -y dnsutils'

フェイルオーバーとフェイルバックの検証

正常時のトラフィック

検証クライアントからクロスリージョン内部アプリケーションロードバランサ(10.1.2.99 / 10.1.3.99)へ 100 個のリクエストをし、負荷分散されていることを確認します。

正常時のアクセス

ヘルスチェックが正常時のバックエンドサービス

インスタンス名は l7-ilb-backend-<リージョン名>-<乱数> です。

インスタンスグループのインスタンス

以下のように、各リージョンのバックエンドの 2 インスタンスへトラフィックが分散されていることがわかります。

# asia-northeast1 のインスタンスグループへ分散
fujioka@l7-ilb-client-asia-northeast1-a:~$   {
>     RESULTS=
>     for i in {1..100}
>     do
>         RESULTS="$RESULTS:$(curl --silent 10.1.2.99)"
>     done
>     echo ""
>     echo " Results of load-balancing to 10.1.2.99: "
>     echo "***"
>     echo "$RESULTS" | tr ':' '\n' | grep -Ev "^$" | sort | uniq -c
>     echo
>   }


 Results of load-balancing to 10.1.2.99: 
***
     49  l7-ilb-backend-asia-northeast1-cn22
     51  l7-ilb-backend-asia-northeast1-pdtr
    100 Page served from
fujioka@l7-ilb-client-asia-northeast1-a:~$ 
# asia-northeast2 のインスタンスグループへ分散
fujioka@l7-ilb-client-asia-northeast2-a:~$   {
>     RESULTS=
>     for i in {1..100}
>     do
>       RESULTS="$RESULTS:$(curl --silent 10.1.3.99)"
>     done
>     echo ""
>     echo " Results of load-balancing to 10.1.3.99: "
>     echo "***"
>     echo "$RESULTS" | tr ':' '\n' | grep -Ev "^$" | sort | uniq -c
>     echo
>   }


 Results of load-balancing to 10.1.3.99: 
***
     49  l7-ilb-backend-asia-northeast2-088t
     51  l7-ilb-backend-asia-northeast2-zqtx
    100 Page served from

fujioka@l7-ilb-client-asia-northeast2-a:~$  

フェイルオーバー

asia-northeast1 のバックエンドのインスタンスグループに付与された load-balanced-backend タグを削除します。これによってファイアウォールのタグで許可されていたヘルスチェックのアクセスが拒否されるため、ヘルスチェックが失敗し asia-northeast1 のインスタンスグループへトラフィックが流れなくなります。

異常時のアクセス

# l7-ilb-backend-asia-northeast1-cn22 からタグを削除
$ gcloud compute instances remove-tags l7-ilb-backend-asia-northeast1-cn22 \
--zone=asia-northeast1-a \
--tags=load-balanced-backend

# l7-ilb-backend-asia-northeast1-pdtr からタグを削除
$ gcloud compute instances remove-tags l7-ilb-backend-asia-northeast1-pdtr \
--zone=asia-northeast1-a \
--tags=load-balanced-backend

タグの削除により、ヘルスチェックが失敗しています。

ヘルスチェックが異常時のバックエンドサービス

この状態で再度クロスリージョン内部アプリケーションロードバランサ(10.1.2.99 / 10.1.3.99)へ 100 個のリクエストをすると、10.1.2.99 へのリクエストは asia-northeast1 のバックエンドではなく、asia-northeast2 のバックエンドへトラフィックが流れるようになります。

# asia-northeast2 のインスタンスグループへトラフィックが流れるようになる
fujioka@l7-ilb-client-asia-northeast1-a:~$   {
>     RESULTS=
>     for i in {1..100}
>     do
>         RESULTS="$RESULTS:$(curl --silent 10.1.2.99)"
>     done
>     echo ""
>     echo " Results of load-balancing to 10.1.2.99: "
>     echo "***"
>     echo "$RESULTS" | tr ':' '\n' | grep -Ev "^$" | sort | uniq -c
>     echo
>   }


 Results of load-balancing to 10.1.2.99: 
***
     51  l7-ilb-backend-asia-northeast2-088t
     49  l7-ilb-backend-asia-northeast2-zqtx
    100 Page served from

fujioka@l7-ilb-client-asia-northeast1-a:~$
# asia-northeast2 のインスタンスグループへ分散
fujioka@l7-ilb-client-asia-northeast2-a:~$   {
>     RESULTS=
>     for i in {1..100}
>     do
>       RESULTS="$RESULTS:$(curl --silent 10.1.3.99)"
>     done
>     echo ""
>     echo " Results of load-balancing to 10.1.3.99: "
>     echo "***"
>     echo "$RESULTS" | tr ':' '\n' | grep -Ev "^$" | sort | uniq -c
>     echo
>   }


 Results of load-balancing to 10.1.3.99: 
***
     51  l7-ilb-backend-asia-northeast2-088t
     49  l7-ilb-backend-asia-northeast2-zqtx
    100 Page served from

fujioka@l7-ilb-client-asia-northeast2-a:~$

フェイルバック

タグを再度付与し、ヘルスチェックが成功後のトラフィックを確認します。

# タグを付与
$ gcloud compute instances add-tags l7-ilb-backend-asia-northeast1-cn22 --tags=load-balanced-backend --zone=asia-northeast1-a &&
gcloud compute instances add-tags l7-ilb-backend-asia-northeast1-pdtr --tags=load-balanced-backend --zone=asia-northeast1-a

タグ再付与後のヘルスチェックが正常なバックエンドサービス

10.1.2.99 へのトラフィックが元通り asia-northeast2 ではなく、asia-northeast1 のバックエンドに流れていることがわかります。

fujioka@l7-ilb-client-asia-northeast1-a:~$   {
>     RESULTS=
>     for i in {1..100}
>     do
>         RESULTS="$RESULTS:$(curl --silent 10.1.2.99)"
>     done
>     echo ""
>     echo " Results of load-balancing to 10.1.2.99: "
>     echo "***"
>     echo "$RESULTS" | tr ':' '\n' | grep -Ev "^$" | sort | uniq -c
>     echo
>   }


 Results of load-balancing to 10.1.2.99: 
***
     51  l7-ilb-backend-asia-northeast1-cn22
     49  l7-ilb-backend-asia-northeast1-pdtr
    100 Page served from

fujioka@l7-ilb-client-asia-northeast1-a:~$ 

実際の運用では Cloud DNS のルーティングポリシーも併せて使うことで、バックエンドのサービス停止だけでなく、リージョン停止やレイテンシ、ネットワーク転送費用を抑えることもできます。

藤岡 里美 (記事一覧)

クラウドソリューション部

数年前までチキン売ったりドレスショップで働いてました!2022年9月 G-gen にジョイン。ハイキューの映画を4回は見に行きたい。

Google Cloud All Certifications Engineer / Google Cloud Partner Top Engineer 2024