このドキュメントでは、次のタスクを行う方法について説明します。
- GKE Gateway と Cloud Service Mesh を介して公開されるグローバルに分散されたアプリケーションをデプロイします。
- Cloud Load Balancing と Cloud Service Mesh を組み合わせて、アプリケーションを複数のクライアントに公開します。
- 複数のGoogle Cloud リージョンにデプロイされたサービス メッシュとロードバランサを統合します。
このデプロイガイドは、プラットフォーム管理者を対象としています。また、Cloud Service Mesh を実行する上級者も対象としています。この手順は Istio on GKE でも使用できます。
アーキテクチャ
次の図は、サービス メッシュのデフォルトの Ingress トポロジを示しています。これは、単一クラスタで Ingress ゲートウェイ プロキシを公開する外部 TCP/UDP ロードバランサです。
このデプロイガイドでは、Google Kubernetes Engine(GKE)Gateway リソースを使用します。具体的には、マルチクラスタ 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.
-
Verify 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`
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}
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'
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 に 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
- ロードバランサが複数のクラスタにわたって上り(内向き)ゲートウェイ Pod をアドレス指定できるようにします。
- Ingress ゲートウェイ Pod がサービス メッシュ内で実行されているサービスにリクエストをプロキシできるようにします。
Cloud Shell で、フリートのマルチクラスタ Service(MCS)を有効にします。
gcloud container fleet multi-cluster-services enable
MCS に、プロジェクトまたはフリートに必要な IAM 権限を付与します。
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
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"
- ルールを含む Cloud Armor セキュリティ ポリシーを作成します。
- ロードバランサが、先ほど作成した
ServiceExport
YAML ファイルを使用して上り(内向き)ゲートウェイ Pod の応答性をチェックできるようにするポリシーを作成します。 - GKE Gateway API を使用してロードバランサ リソースを作成します。
GatewayClass
カスタム リソースを使用して、特定のロードバランサ タイプを設定します。- フリートのマルチクラスタ ロード バランシングを有効にして、クラスタの 1 つをフリートの構成クラスタとして指定します。
Cloud Shell で、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
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
Gateway リソースに Ingress ゲートウェイにリクエストを送信するように指示する
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
出力には、このセクションで入力した情報が表示されます。
Cloud Shell で、両方のクラスタに whereami
frontend
と whereamibackend
の Namespace を作成し、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" }
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: name: 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
サービスのフェイルオーバーをテストするには、プライマリ クラスタの Ingress ゲートウェイのレプリカ数を減らします。マルチリージョン ロードバランサの観点から見ると、このアクションはクラスタ障害をシミュレートします。これにより、クラスタのロードバランサのヘルスチェックが失敗します。この例では、
CLUSTER_1_REGION
のクラスタを使用します。CLUSTER_2_REGION
のクラスタからのレスポンスのみが表示されます。プライマリ クラスタの Ingress ゲートウェイのレプリカ数をゼロに減らし、パブリック エンドポイントを呼び出して、リクエストが他のクラスタにフェイルオーバーしたことを確認します。
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
- 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.
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
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 | キー エンタープライズ アーキテクト
GKE クラスタを作成する
このセクションでは、アプリケーションとサポート インフラストラクチャをホストする GKE クラスタを作成します。これらは、このデプロイガイドの後半で作成します。
サービス メッシュをインストールする
このセクションでは、Fleet API を使用してマネージド Cloud Service Mesh を構成します。Fleet API を使用して Cloud Service Mesh を有効にすると、サービス メッシュをプロビジョニングするための宣言型アプローチが提供されます。
外部アプリケーション ロードバランサをデプロイして、上り(内向き)ゲートウェイを作成する
このセクションでは、GKE Gateway Controller を介して外部アプリケーション ロードバランサをデプロイし、両方のクラスタの Ingress ゲートウェイを作成します。gateway
リソースと gatewayClass
リソースは、ロードバランサとバックエンドのヘルスチェックのプロビジョニングを自動化します。ロードバランサで TLS 終端を提供するには、Certificate Manager リソースを作成してロードバランサに接続します。また、Endpoints を使用して、アプリケーションのパブリック DNS 名が自動的にプロビジョニングされます。
両方のクラスタに Ingress ゲートウェイをインストールする
セキュリティのベスト プラクティスとして、Ingress ゲートウェイは、メッシュ コントロール プレーンとは異なる名前空間にデプロイすることをおすすめします。
マルチクラスタ サービスを使用して Ingress ゲートウェイ Pod をロードバランサに公開する
このセクションでは、ServiceExport
カスタム リソースを使用して上り(内向き)ゲートウェイ Pod をエクスポートします。次の理由から、ServiceExport
カスタム リソースを使用して Ingress Gateway Pod をエクスポートする必要があります。
外部 IP アドレス、DNS レコード、TLS 証明書リソースを作成する
このセクションでは、このデプロイで後で作成するロード バランシング リソースをサポートするネットワーキング リソースを作成します。
バックエンド サービス ポリシーとロードバランサ リソースを作成する
このセクションでは、次のタスクを行います。
whereami サンプル アプリケーションをデプロイする
このガイドでは、whereami をサンプル アプリケーションとして使用して、リクエストに応答しているクラスタに関するフィードバックを直接提供します。次のセクションでは、両方のクラスタに whereami の 2 つの別々のデプロイ(frontend
デプロイと backend
デプロイ)を設定します。
frontend
デプロイは、リクエストを受信する最初のワークロードです。次に、backend
デプロイを呼び出します。
このモデルは、マルチサービス アプリケーション アーキテクチャを示すために使用されます。frontend
サービスと backend
サービスの両方が両方のクラスタにデプロイされます。
curl
コマンドを数回実行すると、レスポンス(frontend
と backend
の両方)が異なるリージョンから返されることがわかります。ロードバランサは、レスポンスで地理情報ルーティングを提供しています。つまり、ロードバランサはクライアントからのリクエストを最も近いアクティブなクラスタにルーティングしていますが、リクエストはランダムに転送されています。リクエストがリージョン間で頻繁に移動すると、レイテンシと費用が増加します。
次のセクションでは、リクエストをローカルに維持するために、サービス メッシュに地域ロード バランシングを実装します。
whereami の地域によるロード バランシングを有効にしてテストする
このセクションでは、リクエストをローカルに維持するために、サービス メッシュにローカリティ ロード バランシングを実装します。また、whereami がさまざまな障害シナリオをどのように処理するかを確認するテストも実施します。
whereami frontend
サービスにリクエストを送信すると、ロードバランサはクライアントに対するレイテンシが最も低いクラスタにリクエストを送信します。つまり、メッシュ内の Ingress ゲートウェイ Pod は、両方のクラスタの whereami frontend
Pod にリクエストをロードバランスします。このセクションでは、メッシュ内で局所性ロード バランシングを有効にして、この問題に対処します。
これで、サービス メッシュでホストされるマルチリージョン アプリケーションのフロントエンドとして機能するグローバル HTTP(S) ロードバランサが作成されました。
クリーンアップ
このデプロイで使用したリソースについて、 Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。
プロジェクトの削除
個々のリソースの削除
このデプロイで使用した Google Cloud プロジェクトを残しておく場合は、個々のリソースを削除します。
次のステップ
寄稿者
作成者:
その他の寄稿者: