このドキュメントでは、次のタスクを行う方法について説明します。
- GKE Gateway と Cloud Service Mesh を介して公開されるグローバルに分散されたアプリケーションをデプロイします。
- Cloud Load Balancing と Cloud Service Mesh を組み合わせて、アプリケーションを複数のクライアントに公開します。
- ロードバランサを、複数の Google Cloud リージョンにデプロイされた Service Mesh と統合します。
このデプロイガイドは、プラットフォーム管理者を対象としています。また、Cloud Service Mesh を実行する上級者を対象としています。この手順は Istio on GKE でも機能します。
アーキテクチャ
次の図は、サービス メッシュのデフォルトの Ingress トポロジを示しています。これは、単一のクラスタで Ingress ゲートウェイ プロキシを公開する外部 TCP/UDP ロードバランサです。
このデプロイガイドでは、Google Kubernetes Engine(GKE)Gateway リソースを使用します。具体的には、マルチクラスタ ゲートウェイを使用して、2 つのリージョンに分散された複数の Autopilot クラスタの前にマルチリージョン ロード バランシングを構成します。
上の図は、データが Cloud Ingress と Mesh Ingress のシナリオを通過する方法を示しています。詳細については、関連するリファレンス アーキテクチャ ドキュメントのアーキテクチャ図の説明をご覧ください。
目標
- Google Cloud 上の GKE Autopilot クラスタのペアを同じフリートにデプロイします。
- Istio ベースの Cloud Service Mesh を同じフリートにデプロイします。
- GKE Gateway を使用してロードバランサを構成し、パブリック HTTPS トラフィックを終端します。
- 複数のクラスタとリージョンにデプロイされた Cloud Service Mesh がホストするアプリケーションにパブリック HTTPS トラフィックを転送します。
- whereami サンプル アプリケーションを両方の Autopilot クラスタにデプロイします。
費用の最適化
このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。
- Google Kubernetes Engine
- Cloud Load Balancing
- Cloud Service Mesh
- Multi Cluster Ingress
- Google Cloud Armor
- Certificate Manager
- Cloud Endpoints
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。
始める前に
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
このデプロイでは、Cloud Shell からすべてのターミナル コマンドを実行します。
デフォルトの Google Cloud プロジェクトを設定します。
export PROJECT=YOUR_PROJECT export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)") gcloud config set project PROJECT_ID
PROJECT_ID
は、このデプロイで使用するプロジェクトの ID に置き換えます。作業ディレクトリを作成します。
mkdir -p ${HOME}/edge-to-mesh-multi-region cd ${HOME}/edge-to-mesh-multi-region export WORKDIR=`pwd`
GKE クラスタを作成する
このセクションでは、アプリケーションとサポート インフラストラクチャをホストする GKE クラスタを作成します。このクラスタは、このデプロイガイドの後半で作成します。
Cloud Shell で、新しい
kubeconfig
ファイルを作成します。この手順により、既存の(デフォルト)kubeconfig
ファイルと競合しなくなります。touch edge2mesh_mr_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig
GKE クラスタとそのリソースの作成時に使用される環境変数を定義します。目的に合わせてデフォルトのリージョンの選択を変更します。
export CLUSTER_1_NAME=edge-to-mesh-01 export CLUSTER_2_NAME=edge-to-mesh-02 export CLUSTER_1_REGION=us-central1 export CLUSTER_2_REGION=us-east4 export PUBLIC_ENDPOINT=frontend.endpoints.PROJECT_ID.cloud.goog
このガイドで使用される Google Cloud APIs を有効にします。
gcloud services enable \ container.googleapis.com \ mesh.googleapis.com \ gkehub.googleapis.com \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ certificatemanager.googleapis.com
CLUSTER_1_REGION
に プライベート ノードを含む GKE Autopilot クラスタを作成します。最初のクラスタがプロビジョニングされてフリートに登録されるのを待たないようにするには、--async
フラグを使用します。gcloud container clusters create-auto --async \ ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} \ --release-channel rapid --labels mesh_id=proj-${PROJECT_NUMBER} \ --enable-private-nodes --enable-fleet
CLUSTER_2_REGION
に 2 番目の Autopilot クラスタを作成して登録します。gcloud container clusters create-auto \ ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} \ --release-channel rapid --labels mesh_id=proj-${PROJECT_NUMBER} \ --enable-private-nodes --enable-fleet
クラスタが実行されていることを確認します。すべてのクラスタが実行されるまでに最大 20 分かかることがあります。
gcloud container clusters list
出力は次のようになります。
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS edge-to-mesh-01 us-central1 1.27.5-gke.200 34.27.171.241 e2-small 1.27.5-gke.200 RUNNING edge-to-mesh-02 us-east4 1.27.5-gke.200 35.236.204.156 e2-small 1.27.5-gke.200 RUNNING
CLUSTER_1_NAME
の認証情報を収集します。CLUSTER_1_NAME
は非同期で作成したため、クラスタのプロビジョニング中に追加のコマンドを実行できます。gcloud container clusters get-credentials ${CLUSTER_1_NAME} \ --region ${CLUSTER_1_REGION}
Kubernetes コンテキストの名前を明確にするために、クラスタの名前に変更します。
kubectl config rename-context gke_PROJECT_ID_${CLUSTER_1_REGION}_${CLUSTER_1_NAME} ${CLUSTER_1_NAME} kubectl config rename-context gke_PROJECT_ID_${CLUSTER_2_REGION}_${CLUSTER_2_NAME} ${CLUSTER_2_NAME}
サービス メッシュをインストールする
このセクションでは、Fleet API を使用してマネージド Cloud Service Mesh を構成します。fleet API を使用して Cloud Service Mesh を有効にすると、サービス メッシュを宣言的にプロビジョニングできます。
Cloud Shell で、フリートで Cloud Service Mesh を有効にします。
gcloud container fleet mesh enable
コントロール プレーンとデータプレーンの自動管理を有効にします。
gcloud container fleet mesh update \ --management automatic \ --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}
20 分ほど待ちます。次に、コントロール プレーンのステータスが
ACTIVE
であることを確認します。gcloud container fleet mesh describe
出力は次のようになります。
createTime: '2023-11-30T19:23:21.713028916Z' membershipSpecs: projects/603904278888/locations/us-central1/memberships/edge-to-mesh-01: mesh: management: MANAGEMENT_AUTOMATIC projects/603904278888/locations/us-east4/memberships/edge-to-mesh-02: mesh: management: MANAGEMENT_AUTOMATIC membershipStates: projects/603904278888/locations/us-central1/memberships/edge-to-mesh-01: servicemesh: controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' implementation: ISTIOD state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: |- Revision ready for use: asm-managed-rapid. All Canonical Services have been reconciled successfully. updateTime: '2024-06-27T09:00:21.333579005Z' projects/603904278888/locations/us-east4/memberships/edge-to-mesh-02: servicemesh: controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' implementation: ISTIOD state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: |- Revision ready for use: asm-managed-rapid. All Canonical Services have been reconciled successfully. updateTime: '2024-06-27T09:00:24.674852751Z' name: projects/e2m-private-test-01/locations/global/features/servicemesh resourceState: state: ACTIVE spec: {} updateTime: '2024-06-04T17:16:28.730429993Z'
外部アプリケーション ロードバランサをデプロイして Ingress ゲートウェイを作成する
このセクションでは、GKE Gateway コントローラを介して外部アプリケーション ロードバランサをデプロイし、両方のクラスタに Ingress ゲートウェイを作成します。gateway
リソースと gatewayClass
リソースは、ロードバランサとバックエンドのヘルスチェックのプロビジョニングを自動化します。ロードバランサで TLS 終端を行うには、Certificate Manager リソースを作成し、ロードバランサに接続します。また、Endpoints を使用して、アプリケーションのパブリック DNS 名を自動的にプロビジョニングします。
両方のクラスタに Ingress ゲートウェイをインストールする
セキュリティのベスト プラクティスとして、Ingress ゲートウェイは、メッシュ コントロール プレーンとは異なる名前空間にデプロイすることをおすすめします。
Cloud Shell で、各クラスタに専用の
asm-ingress
Namespace を作成します。kubectl --context=${CLUSTER_1_NAME} create namespace asm-ingress kubectl --context=${CLUSTER_2_NAME} create namespace asm-ingress
asm-ingress
Namespace に名前空間ラベルを追加します。kubectl --context=${CLUSTER_1_NAME} label namespace asm-ingress istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} label namespace asm-ingress istio-injection=enabled
出力は次のようになります。
namespace/asm-ingress labeled
asm-ingress
Namespace にistio-injection=enabled
というラベルを付けると、Pod がデプロイされたときに Envoy サイドカー プロキシを自動的に挿入するよう Cloud Service Mesh に指示します。後で使用できるように自己署名証明書を生成します。
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \ -subj "/CN=frontend.endpoints.PROJECT_ID.cloud.goog/O=Edge2Mesh Inc" \ -keyout ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ -out ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt
この証明書により、ロードバランサとサービス メッシュ Ingress ゲートウェイの間に暗号化レイヤが追加されます。また、gRPC などの HTTP/2 ベースのプロトコルのサポートも可能になります。自己署名証明書を Ingress ゲートウェイに接続する手順については、後述の外部 IP アドレス、DNS レコード、TLS 証明書リソースを作成するをご覧ください。
Ingress ゲートウェイ証明書の要件の詳細については、ロードバランサからバックエンドへの暗号化をご覧ください。
各クラスタに Kubernetes Secret を作成して、自己署名証明書を保存します。
kubectl --context ${CLUSTER_1_NAME} -n asm-ingress create secret tls \ edge2mesh-credential \ --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt kubectl --context ${CLUSTER_2_NAME} -n asm-ingress create secret tls \ edge2mesh-credential \ --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt
外部アプリケーション ロードバランサと統合するには、kustomize バリアントを作成して、Ingress ゲートウェイ リソースを構成します。
mkdir -p ${WORKDIR}/asm-ig/base cat <<EOF > ${WORKDIR}/asm-ig/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/anthos-service-mesh-samples/docs/ingress-gateway-asm-manifests/base EOF mkdir ${WORKDIR}/asm-ig/variant cat <<EOF > ${WORKDIR}/asm-ig/variant/role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: asm-ingressgateway namespace: asm-ingress rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: asm-ingressgateway namespace: asm-ingress roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: asm-ingressgateway subjects: - kind: ServiceAccount name: asm-ingressgateway EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/service-proto-type.yaml apiVersion: v1 kind: Service metadata: name: asm-ingressgateway namespace: asm-ingress spec: ports: - name: status-port port: 15021 protocol: TCP targetPort: 15021 - name: http port: 80 targetPort: 8080 appProtocol: HTTP - name: https port: 443 targetPort: 8443 appProtocol: HTTP2 type: ClusterIP EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/gateway.yaml apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: asm-ingressgateway namespace: asm-ingress spec: servers: - port: number: 443 name: https protocol: HTTPS hosts: - "*" # IMPORTANT: Must use wildcard here when using SSL, as SNI isn't passed from GFE tls: mode: SIMPLE credentialName: edge2mesh-credential EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/kustomization.yaml namespace: asm-ingress resources: - ../base - role.yaml - rolebinding.yaml patches: - path: service-proto-type.yaml target: kind: Service - path: gateway.yaml target: kind: Gateway EOF
Ingress ゲートウェイ構成を両方のクラスタに適用します。
kubectl --context ${CLUSTER_1_NAME} apply -k ${WORKDIR}/asm-ig/variant kubectl --context ${CLUSTER_2_NAME} apply -k ${WORKDIR}/asm-ig/variant
マルチクラスタ サービスを使用して Ingress ゲートウェイ Pod をロードバランサに公開する
このセクションでは、ServiceExport
カスタム リソースを介して上り(内向き)ゲートウェイ Pod をエクスポートします。次の理由から、ServiceExport
カスタム リソースを介して Ingress Gateway Pod をエクスポートする必要があります。
- ロードバランサが複数のクラスタにまたがる Ingress ゲートウェイ Pod にアクセスできるようにします。
- Ingress ゲートウェイ Pod がサービス メッシュ内で実行されているサービスにリクエストをプロキシできるようにします。
Cloud Shell で、フリートのマルチクラスタ Service(MCS)を有効にします。
gcloud container fleet multi-cluster-services enable
プロジェクトまたはフリートに対する必要な IAM 権限を MCS に付与します。
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]" \ --role "roles/compute.networkViewer"
ServiceExport
YAML ファイルを作成します。cat <<EOF > ${WORKDIR}/svc_export.yaml kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: asm-ingressgateway namespace: asm-ingress EOF
ServiceExport
YAML ファイルを両方のクラスタに適用します。kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/svc_export.yaml
次のエラー メッセージが表示された場合は、MCS カスタム リソース定義(CRD)がインストールされるまで数分待ちます。次に、コマンドを再実行して、
ServiceExport
YAML ファイルを両方のクラスタに適用します。error: resource mapping not found for name: "asm-ingressgateway" namespace: "asm-ingress" from "svc_export.yaml": no matches for kind "ServiceExport" in version "net.gke.io/v1" ensure CRDs are installed first
外部 IP アドレス、DNS レコード、TLS 証明書リソースを作成する
このセクションでは、このデプロイの後半で作成するロード バランシング リソースをサポートするネットワーキング リソースを作成します。
Cloud Shell で、静的外部 IP アドレスを予約します。
gcloud compute addresses create mcg-ip --global
静的 IP アドレスは、GKE Gateway リソースで使用されます。これにより、外部ロードバランサが再作成されても、IP アドレスを同じままにできます。
静的 IP アドレスを取得して環境変数として保存します。
export MCG_IP=$(gcloud compute addresses describe mcg-ip --global --format "value(address)") echo ${MCG_IP}
Gateway IP アドレスとの安定した理解しやすいマッピングを作成するには、パブリック DNS レコードが必要です。
任意の DNS プロバイダと自動化スキームを使用できます。このデプロイでは、マネージド DNS ゾーンを作成する代わりに Endpoints を使用します。Endpoints は、外部 IP アドレス用に無料の Google 管理 DNS レコードを提供します。
次のコマンドを実行して、
dns-spec.yaml
という名前の YAML ファイルを作成します。cat <<EOF > ${WORKDIR}/dns-spec.yaml swagger: "2.0" info: description: "Cloud Endpoints DNS" title: "Cloud Endpoints DNS" version: "1.0.0" paths: {} host: "frontend.endpoints.PROJECT_ID.cloud.goog" x-google-endpoints: - name: "frontend.endpoints.PROJECT_ID.cloud.goog" target: "${MCG_IP}" EOF
dns-spec.yaml
ファイルでは、frontend.endpoints.PROJECT_ID.cloud.goog
の形式でパブリック DNS レコードが定義されます。ここで、PROJECT_ID
は一意のプロジェクト ID です。dns-spec.yaml
ファイルをデプロイして DNS エントリを作成します。この処理には数分かかります。gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml
前の手順で作成した DNS エントリ名のCertificate Manager を使用して証明書を作成します。
gcloud certificate-manager certificates create mcg-cert \ --domains="frontend.endpoints.PROJECT_ID.cloud.goog"
Google マネージド TLS 証明書は、ロードバランサでインバウンド クライアント リクエストを終端するために使用されます。
証明書マップを作成します。
gcloud certificate-manager maps create mcg-cert-map
ロードバランサは、次の手順で作成する証明書マップ エントリを介して証明書を参照します。
このセクションで作成した証明書の証明書マップエントリを作成します。
gcloud certificate-manager maps entries create mcg-cert-map-entry \ --map="mcg-cert-map" \ --certificates="mcg-cert" \ --hostname="frontend.endpoints.PROJECT_ID.cloud.goog"
バックエンド サービス ポリシーとロードバランサ リソースを作成する
このセクションでは、次のタスクを行います。
- ルールを含む Google Cloud Armor セキュリティ ポリシーを作成します。
- 前に作成した
ServiceExport
YAML ファイルを使用して、ロードバランサが Ingress ゲートウェイ Pod の応答性をチェックできるようにするポリシーを作成します。 - GKE Gateway API を使用してロードバランサ リソースを作成します。
GatewayClass
カスタム リソースを使用して、特定のロードバランサ タイプを設定します。- フリートでマルチクラスタ ロード バランシングを有効にし、クラスタの 1 つをフリートの構成クラスタとして指定します。
Cloud Shell で、Google Cloud Armor セキュリティ ポリシーを作成します。
gcloud compute security-policies create edge-fw-policy \ --description "Block XSS attacks"
セキュリティ ポリシーのルールを作成します。
gcloud compute security-policies rules create 1000 \ --security-policy edge-fw-policy \ --expression "evaluatePreconfiguredExpr('xss-stable')" \ --action "deny-403" \ --description "XSS attack filtering"
セキュリティ ポリシーの YAML ファイルを作成し、対応する
ServiceImport
YAML ファイルからServiceExport
YAML ファイルを参照します。cat <<EOF > ${WORKDIR}/cloud-armor-backendpolicy.yaml apiVersion: networking.gke.io/v1 kind: GCPBackendPolicy metadata: name: cloud-armor-backendpolicy namespace: asm-ingress spec: default: securityPolicy: edge-fw-policy targetRef: group: net.gke.io kind: ServiceImport name: asm-ingressgateway EOF
Google Cloud Armor ポリシーを両方のクラスタに適用します。
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
両方のクラスタの Ingress ゲートウェイ Pod の Envoy ヘルスエンドポイント(パス
/healthz/ready
のポート15021
)に対してロードバランサがヘルスチェックを実行できるように、カスタム YAML ファイルを作成します。cat <<EOF > ${WORKDIR}/ingress-gateway-healthcheck.yaml apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy metadata: name: ingress-gateway-healthcheck namespace: asm-ingress spec: default: config: httpHealthCheck: port: 15021 portSpecification: USE_FIXED_PORT requestPath: /healthz/ready type: HTTP targetRef: group: net.gke.io kind: ServiceImport name: asm-ingressgateway EOF
前の手順で作成したカスタム YAML ファイルを両方のクラスタに適用します。
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml
フリートでマルチクラスタ ロード バランシングを有効にして、
CLUSTER_1_NAME
を構成クラスタとして指定します。gcloud container fleet ingress enable \ --config-membership=${CLUSTER_1_NAME} \ --location=${CLUSTER_1_REGION}
フリート内の Gateway コントローラに IAM 権限を付与します。
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-multiclusteringress.iam.gserviceaccount.com" \ --role "roles/container.admin"
gke-l7-global-external-managed-mc
gatewayClass
と、前に作成した静的 IP アドレスを参照する Gateway カスタム リソースを使用して、ロードバランサの YAML ファイルを作成します。cat <<EOF > ${WORKDIR}/frontend-gateway.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http namespace: asm-ingress annotations: networking.gke.io/certmap: mcg-cert-map spec: gatewayClassName: gke-l7-global-external-managed-mc listeners: - name: http # list the port only so we can redirect any incoming http requests to https protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 allowedRoutes: kinds: - kind: HTTPRoute addresses: - type: NamedAddress value: mcg-ip EOF
frontend-gateway
YAML ファイルを両方のクラスタに適用します。別の構成クラスタを権威あるクラスタとして指定しない限り、CLUSTER_1_NAME
のみが権威があります。kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
Ingress ゲートウェイにリクエストを送信するように Gateway リソースに指示する
default-httproute.yaml
という名前のHTTPRoute
YAML ファイルを作成します。cat << EOF > ${WORKDIR}/default-httproute.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: default-httproute namespace: asm-ingress spec: parentRefs: - name: external-http namespace: asm-ingress sectionName: https rules: - backendRefs: - group: net.gke.io kind: ServiceImport name: asm-ingressgateway port: 443 EOF
前の手順で作成した
HTTPRoute
YAML ファイルを両方のクラスタに適用します。kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute.yaml
HTTP から HTTP(S) へのリダイレクトを実行するには、
default-httproute-redirect.yaml
という追加のHTTPRoute
YAML ファイルを作成します。cat << EOF > ${WORKDIR}/default-httproute-redirect.yaml kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-to-https-redirect-httproute namespace: asm-ingress spec: parentRefs: - name: external-http namespace: asm-ingress sectionName: http rules: - filters: - type: RequestRedirect requestRedirect: scheme: https statusCode: 301 EOF
リダイレクト
HTTPRoute
YAML ファイルを両方のクラスタに適用します。kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml
Gateway リソースを調べて、ロードバランサのデプロイの進行状況を確認します。
kubectl --context=${CLUSTER_1_NAME} describe gateway external-http -n asm-ingress
出力には、このセクションで入力した情報が表示されます。
whereami サンプル アプリケーションをデプロイする
このガイドでは、サンプル アプリケーションとして whereami を使用して、リクエストに応答しているクラスタに関する直接的なフィードバックを取得します。次のセクションでは、両方のクラスタに frontend
Deployment と backend
Deployment の 2 つの個別の Deployment を設定します。
frontend
デプロイは、リクエストを最初に受信するワークロードです。次に、backend
デプロイを呼び出します。
このモデルは、マルチサービス アプリケーション アーキテクチャを示すために使用されます。frontend
サービスと backend
サービスの両方が両方のクラスタにデプロイされます。
Cloud Shell で、両方のクラスタに whereami
frontend
と whereamibackend
の名前空間を作成し、Namespace インジェクションを有効にします。kubectl --context=${CLUSTER_1_NAME} create ns frontend kubectl --context=${CLUSTER_1_NAME} label namespace frontend istio-injection=enabled kubectl --context=${CLUSTER_1_NAME} create ns backend kubectl --context=${CLUSTER_1_NAME} label namespace backend istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} create ns frontend kubectl --context=${CLUSTER_2_NAME} label namespace frontend istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} create ns backend kubectl --context=${CLUSTER_2_NAME} label namespace backend istio-injection=enabled
whereami
backend
の kustomize バリアントを作成します。mkdir -p ${WORKDIR}/whereami-backend/base cat <<EOF > ${WORKDIR}/whereami-backend/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s EOF mkdir ${WORKDIR}/whereami-backend/variant cat <<EOF > ${WORKDIR}/whereami-backend/variant/cm-flag.yaml apiVersion: v1 kind: ConfigMap metadata: name: whereami data: BACKEND_ENABLED: "False" # assuming you don't want a chain of backend calls METADATA: "backend" EOF cat <<EOF > ${WORKDIR}/whereami-backend/variant/service-type.yaml apiVersion: "v1" kind: "Service" metadata: name: "whereami" spec: type: ClusterIP EOF cat <<EOF > ${WORKDIR}/whereami-backend/variant/kustomization.yaml nameSuffix: "-backend" namespace: backend commonLabels: app: whereami-backend resources: - ../base patches: - path: cm-flag.yaml target: kind: ConfigMap - path: service-type.yaml target: kind: Service EOF
whereami
backend
バリアントを両方のクラスタに適用します。kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-backend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-backend/variant
whereami
frontend
の kustomize バリアントを作成します。mkdir -p ${WORKDIR}/whereami-frontend/base cat <<EOF > ${WORKDIR}/whereami-frontend/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s EOF mkdir whereami-frontend/variant cat <<EOF > ${WORKDIR}/whereami-frontend/variant/cm-flag.yaml apiVersion: v1 kind: ConfigMap metadata: name: whereami data: BACKEND_ENABLED: "True" BACKEND_SERVICE: "http://whereami-backend.backend.svc.cluster.local" EOF cat <<EOF > ${WORKDIR}/whereami-frontend/variant/service-type.yaml apiVersion: "v1" kind: "Service" metadata: name: "whereami" spec: type: ClusterIP EOF cat <<EOF > ${WORKDIR}/whereami-frontend/variant/kustomization.yaml nameSuffix: "-frontend" namespace: frontend commonLabels: app: whereami-frontend resources: - ../base patches: - path: cm-flag.yaml target: kind: ConfigMap - path: service-type.yaml target: kind: Service EOF
whereami
frontend
バリアントを両方のクラスタに適用します。kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-frontend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
リクエストを whereami
frontend
に転送するVirtualService
YAML ファイルを作成します。cat << EOF > ${WORKDIR}/frontend-vs.yaml apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: whereami-vs namespace: frontend spec: gateways: - asm-ingress/asm-ingressgateway hosts: - 'frontend.endpoints.PROJECT_ID.cloud.goog' http: - route: - destination: host: whereami-frontend port: number: 80 EOF
frontend-vs
YAML ファイルを両方のクラスタに適用します。kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-vs.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
frontend-vs.yaml
を両方のクラスタにデプロイしたので、クラスタのパブリック エンドポイントを呼び出します。curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq
出力は次のようになります。
{ "backend_result": { "cluster_name": "edge-to-mesh-02", "gce_instance_id": "8396338201253702608", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "whereami-backend.backend.svc.cluster.local", "metadata": "backend", "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-645h", "pod_ip": "10.124.0.199", "pod_name": "whereami-backend-7cbdfd788-8mmnq", "pod_name_emoji": "📸", "pod_namespace": "backend", "pod_service_account": "whereami-backend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T03:46:24", "zone": "us-east4-b" }, "cluster_name": "edge-to-mesh-01", "gce_instance_id": "1047264075324910451", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog", "metadata": "frontend", "node_name": "gk3-edge-to-mesh-01-pool-2-d687e3c0-5kf2", "pod_ip": "10.54.1.71", "pod_name": "whereami-frontend-69c4c867cb-dgg8t", "pod_name_emoji": "🪴", "pod_namespace": "frontend", "pod_service_account": "whereami-frontend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T03:46:24", "zone": "us-central1-c" }
curl
コマンドを数回実行すると、レスポンス(frontend
と backend
の両方)が異なるリージョンから返されることがわかります。レスポンスで、ロードバランサは位置情報ルーティングを提供しています。つまり、ロードバランサはクライアントから最も近いアクティブなクラスタにリクエストをルーティングしていますが、リクエストはランダムにランディングされています。リクエストがリージョン間で転送されると、レイテンシと費用が増加します。
次のセクションでは、サービス メッシュにローカリティ ロード バランシングを実装して、リクエストをローカルに保持します。
whereami のローカル ロード バランシングを有効にしてテストする
このセクションでは、サービス メッシュにローカリティ ロード バランシングを実装して、リクエストをローカルに保持します。また、いくつかのテストを行い、whereami がさまざまな障害シナリオをどのように処理するかを確認します。
whereami frontend
サービスにリクエストを送信すると、ロードバランサはクライアントに対するレイテンシが最も低いクラスタにリクエストを送信します。つまり、メッシュ内の Ingress ゲートウェイ Pod は、両方のクラスタの whereami frontend
Pod にリクエストをロードバランスします。このセクションでは、メッシュ内の局所的なロード バランシングを有効にして、この問題に対処します。
Cloud Shell で、
frontend
サービスへのローカリティ ロード バランシング リージョン フェイルオーバーを有効にするDestinationRule
YAML ファイルを作成します。cat << EOF > ${WORKDIR}/frontend-dr.yaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: frontend namespace: frontend spec: host: whereami-frontend.frontend.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 0 loadBalancer: simple: LEAST_REQUEST localityLbSetting: enabled: true outlierDetection: consecutive5xxErrors: 1 interval: 1s baseEjectionTime: 1m EOF
上記のコードサンプルでは、
frontend
サービスのローカル ルーティングのみが有効になっています。また、バックエンドを処理する追加の構成も必要です。frontend-dr
YAML ファイルを両方のクラスタに適用します。kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
backend
サービスへのリージョン フェイルオーバーのローカリティ ロード バランシングを有効にするDestinationRule
YAML ファイルを作成します。cat << EOF > ${WORKDIR}/backend-dr.yaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: n ame: backend namespace: backend spec: host: whereami-backend.backend.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 0 loadBalancer: simple: LEAST_REQUEST localityLbSetting: enabled: true outlierDetection: consecutive5xxErrors: 1 interval: 1s baseEjectionTime: 1m EOF
backend-dr
YAML ファイルを両方のクラスタに適用します。kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/backend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/backend-dr.yaml
両方のクラスタに両方の
DestinationRule
YAML ファイルが適用されている場合、リクエストはリクエストがルーティングされるクラスタにローカルのままになります。frontend
サービスのフェイルオーバーをテストするには、プライマリ クラスタのイングレス ゲートウェイのレプリカ数を減らします。マルチリージョン ロードバランサの観点から、このアクションはクラスタ障害をシミュレートします。これにより、そのクラスタのロードバランサのヘルスチェックが失敗します。この例では、
CLUSTER_1_REGION
のクラスタを使用します。CLUSTER_2_REGION
のクラスタからのレスポンスのみが表示されます。プライマリ クラスタの Ingress ゲートウェイのレプリカ数を 0 に減らし、公開エンドポイントを呼び出して、リクエストが他のクラスタにフェイルオーバーされたことを確認します。
kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=0 deployment/asm-ingressgateway
出力は次のようになります。
$ curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq { "backend_result": { "cluster_name": "edge-to-mesh-02", "gce_instance_id": "2717459599837162415", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "whereami-backend.backend.svc.cluster.local", "metadata": "backend", "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-dxs2", "pod_ip": "10.124.1.7", "pod_name": "whereami-backend-7cbdfd788-mp8zv", "pod_name_emoji": "🏌🏽♀", "pod_namespace": "backend", "pod_service_account": "whereami-backend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T05:41:18", "zone": "us-east4-b" }, "cluster_name": "edge-to-mesh-02", "gce_instance_id": "6983018919754001204", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog", "metadata": "frontend", "node_name": "gk3-edge-to-mesh-02-pool-3-d42ddfbf-qmkn", "pod_ip": "10.124.1.142", "pod_name": "whereami-frontend-69c4c867cb-xf8db", "pod_name_emoji": "🏴", "pod_namespace": "frontend", "pod_service_account": "whereami-frontend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T05:41:18", "zone": "us-east4-b" }
通常のトラフィック ルーティングを再開するには、Ingress ゲートウェイのレプリカをクラスタ内の元の値に復元します。
kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=3 deployment/asm-ingressgateway
プライマリ リージョンのレプリカ数を 0 に減らして、
backend
サービスの障害をシミュレートします。kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=0 deployment/whereami-backend
frontend
サービスからのレスポンスがロードバランサを介してus-central1
プライマリ リージョンから送信され、backend
サービスからのレスポンスがus-east4
セカンダリ リージョンから送信されていることを確認します。出力には、プライマリ リージョン(
us-central1
)のfrontend
サービスと、セカンダリ リージョン(us-east4
)のbackend
サービスのレスポンスも含まれます。バックエンド サービス レプリカを元の値に復元して、通常のトラフィック ルーティングを再開します。
kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=3 deployment/whereami-backend
これで、サービス メッシュでホストされるマルチリージョン アプリケーションのフロントエンドとして機能するグローバル HTTP(S) ロードバランサが作成されました。
クリーンアップ
このデプロイで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。
プロジェクトの削除
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
個々のリソースの削除
このデプロイで使用した Google Cloud プロジェクトを保持する場合は、次のとおり個別のリソースを削除します。
Cloud Shell で、次のとおり
HTTPRoute
リソースを削除します。kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute.yaml
GKE Gateway リソースを削除します。
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml
ポリシーを削除します。
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
サービス エクスポートを削除します。
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yaml
Google Cloud Armor リソースを削除します。
gcloud --project=PROJECT_ID compute security-policies rules delete 1000 --security-policy edge-fw-policy --quiet gcloud --project=PROJECT_ID compute security-policies delete edge-fw-policy --quiet
Certificate Manager リソースを削除します。
gcloud --project=PROJECT_ID certificate-manager maps entries delete mcg-cert-map-entry --map="mcg-cert-map" --quiet gcloud --project=PROJECT_ID certificate-manager maps delete mcg-cert-map --quiet gcloud --project=PROJECT_ID certificate-manager certificates delete mcg-cert --quiet
Endpoints DNS エントリを削除します。
gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quiet
静的 IP アドレスを削除します。
gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quiet
GKE Autopilot クラスタを削除します。このステップには数分かかります。
gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} --quiet gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} --quiet
次のステップ
- サービス メッシュで使用できる GKE Gateway によって提供されるその他の機能について学習する。
- GKE で使用できるさまざまなタイプの Cloud Load Balancing について学ぶ。
- Cloud Service Mesh の特徴や提供される機能について学ぶ。
- Cloud アーキテクチャ センターで、リファレンス アーキテクチャ、図、ベスト プラクティスを確認する。
寄稿者
作成者:
- Alex Mattson | アプリケーション スペシャリスト エンジニア
- Mark Chilvers | アプリケーション スペシャリスト エンジニア
その他の寄稿者:
- Abdelfettah Sghiouar | Cloud デベロッパー アドボケイト
- Greg Bray | カスタマー エンジニア
- Paul Revello | クラウド ソリューション アーキテクト
- Valavan Rajakumar | キー エンタープライズ アーキテクト