Cloud Service Mesh を使用した GKE 限定公開クラスタでの分散サービスの実行
このドキュメントでは、Cloud Service Mesh を使用して、Google Cloud の複数の Google Kubernetes Engine(GKE)クラスタで分散サービスを実行する方法について説明します。また、マルチクラスタ Ingress と Cloud Service Mesh を使用して分散サービスを公開する方法についても説明します。このドキュメントを使用して、非限定公開 GKE クラスタを構成できます。このドキュメントでは、限定公開クラスタを念頭に置いた構成について説明します。
このドキュメントは、Kubernetes の基本的な知識を持つプラットフォーム管理者とサービス オペレータを対象としています。必須ではありませんが、サービス メッシュに関する知識は約に立ちます。Cloud Service Mesh は、オープンソースの Istio テクノロジーをベースとしています。サービス メッシュと Istio の詳細については、istio.io をご覧ください。
分散サービスは、単一の論理サービスとして機能する Kubernetes Service です。分散 Service は、同じ Namespace 内の複数の Kubernetes クラスタで実行されるため、Kubernetes サービスよりも復元力があります。正常なクラスタが目的の負荷を処理できる限り、1 つ以上の GKE クラスタが停止しても、分散サービスは引き続き機能します。
Kubernetes Services が認識するのは、実行するクラスタの Kubernetes API サーバーのみです。Kubernetes クラスタがダウンしている場合(定期メンテナンス中など)、そのクラスタ上で実行されているすべての Kubernetes Services もダウンします。分散サービスを実行すると、他のクラスタがトラフィックを処理している間に、メンテナンスやアップグレードのためにクラスタを止めることができます。分散サービスを作成するには、Cloud Service Mesh のサービス メッシュ機能を使用して、複数のクラスタで実行中のサービスをリンクし、1 つの論理サービスとして機能させます。
GKE 限定公開クラスタを使用すると、Virtual Private Cloud(VPC)ネットワーク上でのみ利用可能なプライベート リソースとしてノードと API サーバーを構成できます。GKE 限定公開クラスタで分散サービスを実行すると、企業に安全で信頼性の高いサービスが提供されます。
アーキテクチャ
このチュートリアルでは、次の図に示すアーキテクチャを使用します。
上図では、アーキテクチャに次のクラスタが含まれています。
- 2 つのクラスタ(
gke-central-priv
とgke-west-priv
)は、2 つの異なるリージョンで同じ GKE 限定公開クラスタとして機能します。 - 別のクラスタ(
ingress-config
)。マルチクラスタ Ingress を構成するコントロール プレーン クラスタとして機能します。
このチュートリアルでは、2 つの GKE 限定公開クラスタ(gke-central-priv
と gke-west-priv
)に Bank of Anthos のサンプル アプリケーションをデプロイします。Bank of Anthos は、オンライン バンキング アプリをシミュレートする複数のマイクロサービスと SQL データベースで構成されるマイクロサービス アプリケーションのサンプルです。このアプリケーションは、クライアントがアクセスできるウェブ フロントエンドと、銀行サービスをシミュレートする残高、台帳、アカウント サービスなどの複数のバックエンド サービスから構成されます。
アプリケーションには 2 つの PostgreSQL データベースがあり、Kubernetes に StatefulSet としてインストールされています。1 つのデータベースがトランザクション用、もう 1 つのデータベースがユーザー アカウント用に使われます。この 2 つのデータベースを除くすべてのサービスは分散サービスとして実行されます。つまり、すべてのサービスの Pod が、同じ名前空間内の両方のアプリケーション クラスタ内で実行され、各サービスが 1 つの論理サービスとして扱われるように Cloud Service Mesh が構成されます。
目標
- 3 つの GKE クラスタを作成します。
- GKE クラスタのうち 2 つを限定公開クラスタ(
gke-central-priv
とgke-west-priv
)として構成します。 - 1 つの GKE クラスタ(
ingress-config
)を中央構成クラスタとして構成します。このクラスタはマルチクラスタ Ingress の構成クラスタとして機能します。 - クラスタ間のトラフィックと 2 つの限定公開 GKE のクラスタからの下り(外向き)トラフィックを許可するように、ネットワーキング(NAT ゲートウェイ、Cloud Router、ファイアウォール ルール)を構成します。
- Cloud Shell から 2 つの限定公開 GKE クラスタへの API サービスによるアクセスを許可するように、承認済みネットワークを構成します。
- マルチクラスタの Cloud Service Mesh をマルチプライマリ モードで 2 つの限定公開クラスタにデプロイして構成します。マルチプライマリ モードでは、Cloud Service Mesh コントロール プレーンが両方のクラスタにデプロイされます。
- Bank of Anthos アプリケーションを 2 つの限定公開クラスタにデプロイします。データベースを除くすべてのサービスは、分散サービス(両方の限定公開クラスタで実行されている Pod)としてデプロイされます。
- Cloud Service Mesh を使用してサービスをモニタリングします。
- Bank of Anthos の
frontend
サービスでマルチクラスタ Ingress を構成します。これにより、外部クライアント(ウェブブラウザなど)は、限定公開 GKE クラスタのフリートで実行されている分散サービスにアクセスできます。
費用
このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
始める前に
-
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.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
このチュートリアルでは、Cloud Shell からすべてのコマンドを実行します。
このチュートリアル全体を通して使用する環境変数を定義します。変数は、このチュートリアルで使用するクラスタ名、リージョン、ゾーン、IP アドレス指定、Cloud Service Mesh バージョンを定義します。
YOUR_PROJECT_ID
は、プロジェクト ID で置き換えてください。export PROJECT_ID=YOUR_PROJECT_ID gcloud config set project ${PROJECT_ID}
残りの環境変数を設定します。
export CLUSTER_1=gke-west-priv export CLUSTER_2=gke-central-priv export CLUSTER_1_ZONE=us-west2-a export CLUSTER_1_REGION=us-west2 export CLUSTER_1_MASTER_IPV4_CIDR=172.16.0.0/28 export CLUSTER_2_ZONE=us-central1-a export CLUSTER_2_REGION=us-central1 export CLUSTER_2_MASTER_IPV4_CIDR=172.16.1.0/28 export CLUSTER_INGRESS=gke-ingress export CLUSTER_INGRESS_ZONE=us-west1-a export CLUSTER_INGRESS_REGION=us-west1 export CLUSTER_INGRESS_MASTER_IPV4_CIDR=172.16.2.0/28 export WORKLOAD_POOL=${PROJECT_ID}.svc.id.goog export ASM_VERSION=1.10 export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
環境を準備する
Cloud Shell で API を有効にします。
gcloud services enable \ --project=${PROJECT_ID} \ container.googleapis.com \ mesh.googleapis.com \ gkehub.googleapis.com
プロジェクトで Cloud Service Mesh Fleet を有効にします。
gcloud container fleet mesh enable --project=${PROJECT_ID}
限定公開 GKE クラスタのネットワーキングを準備する
このセクションでは、分散サービスの実行に使用する限定公開 GKE クラスタ用にネットワーキングを準備します。
限定公開 GKE クラスタノードには、パブリック IP アドレスが割り当てられません。限定公開 GKE クラスタ内のすべてのノードには、プライベート VPC の IP アドレス(RFC 1918 アドレス空間)が割り当てられます。つまり、VPC ネットワーク外にある外部リソースにアクセスする必要がある Pod には Cloud NAT ゲートウェイが必要です。Cloud NAT ゲートウェイは、内部 IP アドレスを持つ Pod がインターネットと通信できるようにするリージョン NAT ゲートウェイです。このチュートリアルでは、2 つのリージョンのそれぞれで Cloud NAT ゲートウェイを構成します。リージョン内の複数のクラスタは同じ NAT ゲートウェイを使用できます。
Cloud Shell で、2 つの NAT ゲートウェイ用に 2 つの外部 IP アドレスを作成して予約します。
gcloud compute addresses create ${CLUSTER_1_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_1_REGION} gcloud compute addresses create ${CLUSTER_2_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_2_REGION}
IP アドレスと IP アドレスの名前を変数に保存します。
export NAT_REGION_1_IP_ADDR=$(gcloud compute addresses describe ${CLUSTER_1_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_1_REGION} \ --format='value(address)') export NAT_REGION_1_IP_NAME=$(gcloud compute addresses describe ${CLUSTER_1_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_1_REGION} \ --format='value(name)') export NAT_REGION_2_IP_ADDR=$(gcloud compute addresses describe ${CLUSTER_2_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_2_REGION} \ --format='value(address)') export NAT_REGION_2_IP_NAME=$(gcloud compute addresses describe ${CLUSTER_2_REGION}-nat-ip \ --project=${PROJECT_ID} \ --region=${CLUSTER_2_REGION} \ --format='value(name)')
限定公開 GKE クラスタの 2 つのリージョンに Cloud NAT ゲートウェイを作成します。
gcloud compute routers create rtr-${CLUSTER_1_REGION} \ --network=default \ --region ${CLUSTER_1_REGION} gcloud compute routers nats create nat-gw-${CLUSTER_1_REGION} \ --router=rtr-${CLUSTER_1_REGION} \ --region ${CLUSTER_1_REGION} \ --nat-external-ip-pool=${NAT_REGION_1_IP_NAME} \ --nat-all-subnet-ip-ranges \ --enable-logging gcloud compute routers create rtr-${CLUSTER_2_REGION} \ --network=default \ --region ${CLUSTER_2_REGION} gcloud compute routers nats create nat-gw-${CLUSTER_2_REGION} \ --router=rtr-${CLUSTER_2_REGION} \ --region ${CLUSTER_2_REGION} \ --nat-external-ip-pool=${NAT_REGION_2_IP_NAME} \ --nat-all-subnet-ip-ranges \ --enable-logging
Pod 間の通信と Pod から API サーバーへの通信を可能にするファイアウォール ルールを作成します。Pod 間の通信により、分散サービスが GKE クラスタ間で相互に通信できるようになります。Pod から API サーバーへの通信により、Cloud Service Mesh のコントロール プレーンは GKE クラスタに対してサービス ディスカバリのクエリを行います。
gcloud compute firewall-rules create all-pods-and-master-ipv4-cidrs \ --project ${PROJECT_ID} \ --network default \ --allow all \ --direction INGRESS \ --source-ranges 10.0.0.0/8,${CLUSTER_1_MASTER_IPV4_CIDR},${CLUSTER_2_MASTER_IPV4_CIDR},${CLUSTER_INGRESS_MASTER_IPV4_CIDR}
これでネットワークの準備が整いました。このチュートリアルでは、すべての Pod 範囲を含む 10.0.0.0/8
IP アドレス範囲全体を使用します。本番環境では、条件と要件に基づいて、より厳格なファイアウォール ルールを作成することをおすすめします。
限定公開 GKE クラスタを作成する
このセクションでは、サンプルアプリがデプロイされる 2 つの限定公開 GKE クラスタを作成します。このチュートリアルでは、プライベート GKE クラスタノードにプライベート IP アドレスがあり、API サーバーにパブリック エンドポイントがあります。ただし、API サーバーへのアクセスは、承認済みネットワークを使用して制限されます。
Cloud Shell で、認可済みネットワークを持つ 2 つの限定公開クラスタを作成します。ターミナルからクラスタにアクセスできるように、(Cloud Service Mesh コントロール プレーンの)Pod IP CIDR 範囲と、Cloud Shell からのアクセスを許可するようにクラスタを構成します。
gcloud container clusters create ${CLUSTER_1} \ --project ${PROJECT_ID} \ --zone=${CLUSTER_1_ZONE} \ --machine-type "e2-standard-4" \ --num-nodes "3" --min-nodes "3" --max-nodes "5" \ --enable-ip-alias --enable-autoscaling \ --workload-pool=${WORKLOAD_POOL} \ --enable-private-nodes \ --master-ipv4-cidr=${CLUSTER_1_MASTER_IPV4_CIDR} \ --enable-master-authorized-networks \ --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32 \ --labels=mesh_id=${MESH_ID} --async gcloud container clusters create ${CLUSTER_2} \ --project ${PROJECT_ID} \ --zone=${CLUSTER_2_ZONE} \ --machine-type "e2-standard-4" \ --num-nodes "3" --min-nodes "3" --max-nodes "5" \ --enable-ip-alias --enable-autoscaling \ --workload-pool=${WORKLOAD_POOL} \ --enable-private-nodes \ --master-ipv4-cidr=${CLUSTER_2_MASTER_IPV4_CIDR} \ --enable-master-authorized-networks \ --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32 \ --labels=mesh_id=${MESH_ID}
認可済みネットワークには、Cloud NAT ゲートウェイのパブリック IP アドレスが含まれています。限定公開クラスタの API サーバー エンドポイントは、パブリック エンドポイントのため、限定公開クラスタで実行される Pod は、Cloud NAT ゲートウェイを使用してパブリック API サーバー エンドポイントにアクセスする必要があります。
Cloud Shell の IP アドレスは認可済みネットワークの一部でもあり、Cloud Shell ターミナルからクラスタにアクセスして管理できます。Cloud Shell の一般公開 IP アドレスは動的なアドレスのため、Cloud Shell を起動するたびに、異なるパブリック IP アドレスが取得される場合があります。新しい IP アドレスを取得すると、その新しい IP アドレスは 2 つのクラスタの認可済みネットワークに含まれていないため、クラスタにアクセスできなくなります。
クラスタにアクセスできなくなった場合は、クラスタの認可済みネットワークを更新して新しい Cloud Shell IP アドレスを追加します。
更新された Cloud Shell パブリック IP アドレスを取得します。
export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
2 つのクラスタの認可済みネットワークを更新します。
gcloud container clusters update ${CLUSTER_1} \ --zone=${CLUSTER_1_ZONE} \ --enable-master-authorized-networks \ --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32 gcloud container clusters update ${CLUSTER_2} \ --zone=${CLUSTER_2_ZONE} \ --enable-master-authorized-networks \ --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
すべてのクラスタが実行されていることを確認します。
gcloud container clusters list
出力は次のようになります。
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS gke-central-priv us-central1-a 1.16.15-gke.6000 35.238.99.104 e2-standard-4 1.16.15-gke.6000 3 RUNNING gke-west-priv us-west2-a 1.16.15-gke.6000 34.94.188.180 e2-standard-4 1.16.15-gke.6000 3 RUNNING
両方のクラスタに接続して、kubeconfig ファイルにエントリを生成します。
touch ~/asm-kubeconfig && export KUBECONFIG=~/asm-kubeconfig gcloud container clusters get-credentials ${CLUSTER_1} --zone ${CLUSTER_1_ZONE} gcloud container clusters get-credentials ${CLUSTER_2} --zone ${CLUSTER_2_ZONE}
kubeconfig ファイルを使用して、クラスタごとにユーザーとコンテキストを作成し、クラスタに対する認証を行います。kubeconfig ファイルでエントリを生成したら、クラスタ間でコンテキストをすばやく切り替えることができます。
利便性のため、クラスタ コンテキストの名前を変更します。
kubectl config rename-context \ gke_${PROJECT_ID}_${CLUSTER_1_ZONE}_${CLUSTER_1} ${CLUSTER_1} kubectl config rename-context \ gke_${PROJECT_ID}_${CLUSTER_2_ZONE}_${CLUSTER_2} ${CLUSTER_2}
両方のクラスタ コンテキストの名前が正しく変更され構成されていることを確認します。
kubectl config get-contexts --output="name"
出力は次のようになります。
gke-central-priv gke-west-priv
フリートにクラスタを登録します。
gcloud container fleet memberships register ${CLUSTER_1} --gke-cluster=${CLUSTER_1_ZONE}/${CLUSTER_1} --enable-workload-identity gcloud container fleet memberships register ${CLUSTER_2} --gke-cluster=${CLUSTER_2_ZONE}/${CLUSTER_2} --enable-workload-identity
これで、限定公開 GKE クラスタの作成と名前の変更が完了しました。
Cloud Service Mesh をインストールする
このセクションでは、Cloud Service Mesh を 2 つの GKE クラスタにインストールし、クラスタ間でサービス ディスカバリを行うようにクラスタを構成します。
Cloud Shell で、
fleet API
を使用して両方のクラスタに Cloud Service Mesh をインストールします。gcloud container fleet mesh update --management automatic --memberships ${CLUSTER_1},${CLUSTER_2}
クラスタでマネージド Cloud Service Mesh が有効になったら、メッシュがインストールされるように監視します。
watch -g "gcloud container fleet mesh describe | grep 'code: REVISION_READY'"
両方のクラスタに Cloud Service Mesh Ingress ゲートウェイをインストールします。
kubectl --context=${CLUSTER_1} create namespace asm-ingress kubectl --context=${CLUSTER_1} label namespace asm-ingress istio-injection=enabled --overwrite kubectl --context=${CLUSTER_2} create namespace asm-ingress kubectl --context=${CLUSTER_2} label namespace asm-ingress istio-injection=enabled --overwrite cat <<'EOF' > asm-ingress.yaml apiVersion: v1 kind: Service metadata: name: asm-ingressgateway namespace: asm-ingress spec: type: LoadBalancer selector: asm: ingressgateway ports: - port: 80 name: http - port: 443 name: https --- apiVersion: apps/v1 kind: Deployment metadata: name: asm-ingressgateway namespace: asm-ingress spec: selector: matchLabels: asm: ingressgateway template: metadata: annotations: # This is required to tell Anthos Service Mesh to inject the gateway with the # required configuration. inject.istio.io/templates: gateway labels: asm: ingressgateway spec: containers: - name: istio-proxy image: auto # The image will automatically update each time the pod starts. --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: asm-ingressgateway-sds namespace: asm-ingress rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: asm-ingressgateway-sds namespace: asm-ingress roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: asm-ingressgateway-sds subjects: - kind: ServiceAccount name: default EOF kubectl --context=${CLUSTER_1} apply -f asm-ingress.yaml kubectl --context=${CLUSTER_2} apply -f asm-ingress.yaml
Cloud Service Mesh Ingress ゲートウェイがデプロイされていることを確認します。
kubectl --context=${CLUSTER_1} get pod,service -n asm-ingress kubectl --context=${CLUSTER_2} get pod,service -n asm-ingress
両方のクラスタの出力は次のようになります。
NAME READY STATUS RESTARTS AGE pod/asm-ingressgateway-5894744dbd-zxlgc 1/1 Running 0 84s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/asm-ingressgateway LoadBalancer 10.16.2.131 34.102.100.138 80:30432/TCP,443:30537/TCP 92s
両方のクラスタに Cloud Service Mesh コントロール プレーンと Ingress ゲートウェイがインストールされると、Fleet API でのクラスタ間のサービス ディスカバリが有効になります。クラスタ間のサービス ディスカバリを使用すると、2 つのクラスタで異なるクラスタからサービス エンドポイントを検出できます。分散サービスは、同じ Namespace 内の複数のクラスタで実行されます。
Cloud Service Mesh の両方のコントロール プレーンが分散サービスのすべてのエンドポイントを検出するには、Cloud Service Mesh が分散サービスを実行しているすべてのクラスタにアクセスできる必要があります。この例では 2 つのクラスタを使用しているため、両方のクラスタで相手のクラスタに対してサービス エンドポイントのクエリを実行できる必要があります。Fleet API でマネージド Cloud Service Mesh を有効にすると、エンドポイントの検出が自動的に構成されます。
これで、クラスタと Cloud Service Mesh が構成されました。
Bank of Anthos アプリケーションをデプロイする
Cloud Shell で、Bank of Anthos の GitHub リポジトリのクローンを作成します。
git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git ${HOME}/bank-of-anthos
両方のクラスタで
bank-of-anthos
Namespace を作成してラベルを付けます。このラベルを使用すると、ラベルが付けられた Namespace 内のすべての Pod にサイドカー Envoy プロキシを自動的に挿入できます。# cluster_1 kubectl create --context=${CLUSTER_1} namespace bank-of-anthos kubectl label --context=${CLUSTER_1} namespace bank-of-anthos istio-injection=enabled # cluster_2 kubectl create --context=${CLUSTER_2} namespace bank-of-anthos kubectl label --context=${CLUSTER_2} namespace bank-of-anthos istio-injection=enabled
Bank of Anthos アプリケーションを
bank-of-anthos
Namespace の両方のクラスタにデプロイします。# The following secret is used for user account creation and authentication kubectl --context=$CLUSTER_1 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/extras/jwt/jwt-secret.yaml kubectl --context=$CLUSTER_2 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/extras/jwt/jwt-secret.yaml # Deploy all manifests to both clusters kubectl --context=$CLUSTER_1 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/kubernetes-manifests kubectl --context=$CLUSTER_2 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/kubernetes-manifests
サービス ディスカバリを行うには、Kubernetes サービスが両方のクラスタに存在する必要があります。いずれかのクラスタのサービスがリクエストを試みると、まずホスト名の DNS ルックアップが行われ、IP アドレスが取得されます。GKE では、クラスタで実行されている
kube-dns
サーバーがこのルックアップを処理するため、構成済みの Service 定義が必要になります。一方のクラスタから
StatefulSets
を削除し、2 つの PostgreSQL データベースがもう一方のクラスタにのみ存在するようにします。# Delete the two DB statefulSets from Cluster2 kubectl --context=$CLUSTER_2 -n bank-of-anthos delete statefulset accounts-db kubectl --context=$CLUSTER_2 -n bank-of-anthos delete statefulset ledger-db
すべての Pod が両方のクラスタで実行されるようにします。
cluster_1
から Pod を取得します。kubectl --context=${CLUSTER_1} -n bank-of-anthos get pod
出力は次のようになります。
NAME READY STATUS RESTARTS AGE accounts-db-0 2/2 Running 0 9m54s balancereader-c5d664b4c-xmkrr 2/2 Running 0 9m54s contacts-7fd8c5fb6-wg9xn 2/2 Running 1 9m53s frontend-7b7fb9b665-m7cw7 2/2 Running 1 9m53s ledger-db-0 2/2 Running 0 9m53s ledgerwriter-7b5b6db66f-xhbp4 2/2 Running 0 9m53s loadgenerator-7fb54d57f8-g5lz5 2/2 Running 0 9m52s transactionhistory-7fdb998c5f-vqh5w 2/2 Running 1 9m52s userservice-76996974f5-4wlpf 2/2 Running 1 9m52s
cluster_2
から Pod を取得します。kubectl --context=${CLUSTER_2} -n bank-of-anthos get pod
出力は次のようになります。
NAME READY STATUS RESTARTS AGE balancereader-c5d664b4c-bn2pl 2/2 Running 0 9m54s contacts-7fd8c5fb6-kv8cp 2/2 Running 0 9m53s frontend-7b7fb9b665-bdpp4 2/2 Running 0 9m53s ledgerwriter-7b5b6db66f-297c2 2/2 Running 0 9m52s loadgenerator-7fb54d57f8-tj44v 2/2 Running 0 9m52s transactionhistory-7fdb998c5f-xvmtn 2/2 Running 0 9m52s userservice-76996974f5-mg7t6 2/2 Running 0 9m51s
Cloud Service Mesh の構成を両方のクラスタにデプロイします。これにより、
asm-ingress
Namespace に Gateway が作成され、frontend
Service のbank-of-anthos
Namespace に VirtualService が作成され、上り(内向き)トラフィックをfrontend
サービスに転送できるようになります。Gateways
は通常、プラットフォーム管理者またはネットワーク管理者チームが所有します。したがって、Gateway
リソースは、プラットフォーム管理者が所有する Ingress Gateway Namespace に作成され、独自のVirtualService
エントリを介して他の Namespace で使用できます。これが「共有ゲートウェイ」モデルです。cat <<'EOF' > asm-vs-gateway.yaml apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: asm-ingressgateway namespace: asm-ingress spec: selector: asm: ingressgateway servers: - port: number: 80 name: http protocol: HTTP hosts: - "*" --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: frontend namespace: bank-of-anthos spec: hosts: - "*" gateways: - asm-ingress/asm-ingressgateway http: - route: - destination: host: frontend port: number: 80 EOF kubectl --context=$CLUSTER_1 apply -f asm-vs-gateway.yaml kubectl --context=$CLUSTER_2 apply -f asm-vs-gateway.yaml
これで、Bank of Anthos アプリケーションが 2 つの限定公開 GKE クラスタにデプロイされました。データベースを除くすべてのサービスは、分散サービスとして実行されます。
分散サービスを検査する
このセクションでは、istioctl
ツールを使用して、いずれかのプロキシの proxy-config を検査します。これにより、サイドカー プロキシがサービスごとに 2 つの Pod を検出し、各クラスタで 1 つの Pod が実行されていることがわかります。
Cloud Shell で、
cluster_1
のfrontend
Pod のプロキシ構成エンドポイント リストを調べます。export FRONTEND1=$(kubectl get pod -n bank-of-anthos -l app=frontend \ --context=${CLUSTER_1} -o jsonpath='{.items[0].metadata.name}') istioctl proxy-config endpoints \ --context $CLUSTER_1 -n bank-of-anthos $FRONTEND1 | grep bank-of-anthos
出力は次のようになります。
10.12.0.6:5432 HEALTHY OK outbound|5432||accounts-db.bank-of-anthos.svc.cluster.local 10.12.0.7:8080 HEALTHY OK outbound|8080||balancereader.bank-of-anthos.svc.cluster.local 10.12.0.8:8080 HEALTHY OK outbound|8080||transactionhistory.bank-of-anthos.svc.cluster.local 10.12.0.9:8080 HEALTHY OK outbound|8080||userservice.bank-of-anthos.svc.cluster.local 10.12.1.10:8080 HEALTHY OK outbound|8080||ledgerwriter.bank-of-anthos.svc.cluster.local 10.12.1.9:8080 HEALTHY OK outbound|8080||contacts.bank-of-anthos.svc.cluster.local 10.12.2.11:5432 HEALTHY OK outbound|5432||ledger-db.bank-of-anthos.svc.cluster.local 10.12.2.13:8080 HEALTHY OK outbound|80||frontend.bank-of-anthos.svc.cluster.local 10.76.1.10:8080 HEALTHY OK outbound|8080||transactionhistory.bank-of-anthos.svc.cluster.local 10.76.1.8:8080 HEALTHY OK outbound|8080||balancereader.bank-of-anthos.svc.cluster.local 10.76.1.9:8080 HEALTHY OK outbound|80||frontend.bank-of-anthos.svc.cluster.local 10.76.2.10:8080 HEALTHY OK outbound|8080||userservice.bank-of-anthos.svc.cluster.local 10.76.2.8:8080 HEALTHY OK outbound|8080||contacts.bank-of-anthos.svc.cluster.local 10.76.2.9:8080 HEALTHY OK outbound|8080||ledgerwriter.bank-of-anthos.svc.cluster.local
上記の出力では、各分散サービスに 2 つのエンドポイント IP アドレスがあります。これらは Pod の IP アドレスで、クラスタごとに 1 つあります。
Bank of Anthos にアクセスする
Bank of Anthos アプリケーションにアクセスするには、いずれかのクラスタの asm-ingressgateway
Service のパブリック IP アドレスを使用します。
両方のクラスタから
asm-ingressgateway
IP アドレスを取得します。kubectl --context ${CLUSTER_1} \ --namespace asm-ingress get svc asm-ingressgateway -o jsonpath='{.status.loadBalancer}' | grep "ingress" kubectl --context ${CLUSTER_2} \ --namespace asm-ingress get svc asm-ingressgateway -o jsonpath='{.status.loadBalancer}' | grep "ingress"
出力は次のようになります。
{"ingress":[{"ip":"35.236.4.18"}]} {"ingress":[{"ip":"34.68.94.81"}]}
IP アドレスの 1 つをコピーして、次のステップで使用します。
ウェブブラウザで新しいタブを開き、前の出力の IP アドレスのいずれかに移動します。Bank of Anthos のフロントエンドが表示され、ログイン、口座への入金、他の口座への送金を行うことができます。このアプリケーションは完全に機能します。
分散サービスを可視化する
分散サービスは Cloud Service Mesh で可視化できます。
サービスを表示するには、Google Cloud コンソールの [Anthos] > [サービス メッシュ] ページに移動します。
サービスは、テーブルビューまたはトポロジビューで確認できます。デフォルトのビューは表形式で、実行中のすべての分散サービスが表形式で表示されます。ビューを変更するには、表示するビューをクリックします。
[テーブル] ビューで
frontend distributed service
をクリックします。個々のサービスをクリックすると、サービスの詳細と接続されたサービスが表示されます。サービスの詳細ビューで [タイムラインを表示] をクリックすると、SLO を作成し、サービスの履歴タイムラインを表示できます。
ゴールデン シグナルを表示するには、サイドパネルで [指標] をクリックします。
Requests per seconds のグラフで、[データの内訳基準] をクリックして [ロケーション] を選択します。
結果では、2 つのリージョンに存在する両方のクラスタからの 1 秒あたりのリクエスト数が表示されます。分散サービスは正常であり、両方のエンドポイントがトラフィックを処理しています。
サービス メッシュのトポロジを表示するには、サイドパネルで [Anthos Service Mesh] をクリックし、[Topology View] をクリックします。
補足データを表示するには、マウスポインタを
frontend
サービスの上に置きます。これにより、フロントエンドから他のサービスに対する 1 秒あたりの送受信リクエスト数などの情報が表示されます。さらに詳細を表示するには、
frontend
サービスで [展開] をクリックします。[Service] と [Workload] が表示されます。つづいて、[Workload] を 2 つの [Deployment] に展開し、[Deployment] を [ReplicaSet] に展開して、[ReplicaSet] を [Pod] に展開できます。すべての要素を展開すると、分散frontend
サービスを確認できます。これは、基本的には 1 つの Service と 2 つの Pod です。
複数クラスタ Ingress を構成する
このセクションでは、両方のクラスタで実行されている Bank of GKE Enterprise の frontend
サービスにトラフィックを送信するマルチクラスタ Ingress を作成します。Cloud Load Balancing を使用して、両方のクラスタで asm-ingressgateway
Service をバックエンドとして使用するロードバランサを作成します。ingress-config
クラスタは、マルチクラスタ Ingress 構成のオーケストレーションに使用されます。
ロードバランサを作成するには、MultiClusterIngress
と 1 つ以上の MultiClusterServices
を使用します。MultiClusterIngress
オブジェクトと MultiClusterService
オブジェクトには、単一クラスタ コンテキストで使用される既存の Kubernetes Ingress および Service リソースとのマルチクラスタの類似性があります。
必要な GKE Enterprise、GKE フリート、マルチクラスタ Ingress API を有効にします。
gcloud services enable \ anthos.googleapis.com \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com
ingress-config
クラスタを作成します。任意のクラスタを使用できますが、ここでは個別のクラスタを作成することをおすすめします。gcloud container clusters create ${CLUSTER_INGRESS} \ --zone ${CLUSTER_INGRESS_ZONE} \ --num-nodes=1 \ --enable-ip-alias \ --workload-pool=${WORKLOAD_POOL}
クラスタの認証情報を取得し、利便性のためにコンテキストの名前を変更します。
gcloud container clusters get-credentials ${CLUSTER_INGRESS} \ --zone ${CLUSTER_INGRESS_ZONE} --project ${PROJECT_ID} kubectl config rename-context \ gke_${PROJECT_ID}_${CLUSTER_INGRESS_ZONE}_${CLUSTER_INGRESS} ${CLUSTER_INGRESS}
マルチクラスタ Ingress を使用するには、参加するすべてのクラスタ(構成クラスタを含む)を GKE Enterprise フリートに登録します。
構成クラスタを登録します。
gcloud container fleet memberships register ${CLUSTER_INGRESS} \ --project=${PROJECT_ID} \ --gke-cluster=${CLUSTER_INGRESS_ZONE}/${CLUSTER_INGRESS} \ --enable-workload-identity
すべてのクラスタが GKE Enterprise フリートに登録されていることを確認します。
gcloud container fleet memberships list
出力は次のようになります。
NAME EXTERNAL_ID gke-west 7fe5b7ce-50d0-4e64-a9af-55d37b3dd3fa gke-central 6f1f6bb2-a3f6-4e9c-be52-6907d9d258cd gke-ingress 3574ee0f-b7e6-11ea-9787-42010a8a019c
ingress-config
クラスタで、マルチクラスタ Ingress 機能を有効にします。これにより、クラスタにMulticlusterService
とMulticlusterIngress
CustomResourceDefinitions(CRD)が作成されます。gcloud container fleet ingress enable \ --config-membership=projects/${PROJECT_ID}/locations/global/memberships/${CLUSTER_INGRESS}
ingress-config
クラスタで、マルチクラスタ Ingress が有効になっていることを確認します。gcloud container fleet ingress describe
出力は次のようになります。
membershipStates: projects/986443280307/locations/global/memberships/gke-central-priv: state: code: OK updateTime: '2022-09-29T13:57:02.972748202Z' projects/986443280307/locations/global/memberships/gke-ingress: state: code: OK updateTime: '2022-09-29T13:57:02.972744692Z' projects/986443280307/locations/global/memberships/gke-west-priv: state: code: OK updateTime: '2022-09-29T13:57:02.972746497Z'
2 つの CRD が
ingress-config
クラスタにデプロイされていることを確認します。kubectl --context=${CLUSTER_INGRESS} get crd | grep multicluster
出力は次のようになります。
multiclusteringresses.networking.gke.io 2020-10-29T17:32:50Z multiclusterservices.networking.gke.io 2020-10-29T17:32:50Z
ingress-config
クラスタにasm-ingress
名前空間を作成します。kubectl --context ${CLUSTER_INGRESS} create namespace asm-ingress
MultiClusterIngress
リソースを作成します。cat <<EOF > ${HOME}/mci.yaml apiVersion: networking.gke.io/v1beta1 kind: MultiClusterIngress metadata: name: asm-ingressgateway-multicluster-ingress spec: template: spec: backend: serviceName: asm-ingressgateway-multicluster-svc servicePort: 80 EOF
MultiClusterService
リソースを作成します。cat <<'EOF' > $HOME/mcs.yaml apiVersion: networking.gke.io/v1beta1 kind: MultiClusterService metadata: name: asm-ingressgateway-multicluster-svc annotations: beta.cloud.google.com/backend-config: '{"ports": {"80":"gke-ingress-config"}}' spec: template: spec: selector: asm: ingressgateway ports: - name: frontend protocol: TCP port: 80 # servicePort defined in Multi Cluster Ingress clusters: - link: "us-west2-a/gke-west-priv" - link: "us-central1-a/gke-central-priv" EOF
ヘルスチェック用の
BackendConfig
リソースを作成します。cat <<EOF > $HOME/backendconfig.yaml apiVersion: cloud.google.com/v1beta1 kind: BackendConfig metadata: name: gke-ingress-config spec: healthCheck: type: HTTP port: 15021 requestPath: /healthz/ready EOF
BackendConfig
、MultiClusterService
、MultiClusterIngress
の各マニフェストを適用します。kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/backendconfig.yaml kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/mci.yaml kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/mcs.yaml
Ingress クラスタにデプロイした
MultiClusterService
によって、クラスタ 1 とクラスタ 2 にヘッドレスService
が作成されます。ヘッドレスServices
が作成されていることを確認します。kubectl --context=${CLUSTER_1} -n asm-ingress \ get services | grep multicluster-svc kubectl --context=${CLUSTER_2} -n asm-ingress \ get services | grep multicluster-svc
出力は次のようになります。
mci-frontend-multi-cluster-service-svc-f7rcyqry22iq8nmw ClusterIP None <none> 80/TCP 77s mci-frontend-multi-cluster-service-svc-f7rcyqry22iq8nmw ClusterIP None <none> 80/TCP 78s
次のコマンドを実行し、Cloud Load Balancing IP アドレスを取得するまで待ちます。
watch kubectl --context ${CLUSTER_INGRESS} -n asm-ingress get multiclusteringress \ -o jsonpath="{.items[].status.VIP}"
出力は次のようになります。
35.35.23.11
watch コマンドを終了するには、Ctrl+C キーを押します。
ウェブブラウザで Cloud Load Balancing の IP アドレスに移動し、Bank of Anthos のフロントエンドに移動します。
kubectl --context ${CLUSTER_INGRESS} \ -n asm-ingress get multiclusteringress \ -o jsonpath="{.items[].status.VIP}"
404 エラー(または 502 エラー)が表示された場合は、数分待ってから、ウェブブラウザでページを更新します。
クリーンアップ
アカウントに課金されないようにするには、プロジェクトまたはクラスタを削除します。
プロジェクトの削除
課金を停止する最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。
- 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 で、
blue
クラスタとgreen
クラスタの登録を解除して削除します。gcloud container fleet memberships unregister ${CLUSTER_1} \ --project=${PROJECT} \ --gke-uri=${CLUSTER_1_URI} gcloud container clusters delete ${CLUSTER_1} \ --zone ${CLUSTER_1_ZONE} \ --quiet gcloud container fleet memberships unregister ${CLUSTER_2} \ --project=${PROJECT} \ --gke-uri=${CLUSTER_2_URI} gcloud container clusters delete ${CLUSTER_2} \ --zone ${CLUSTER_2_ZONE} \ --quiet
ingress-config クラスタから
MuticlusterIngress
リソースを削除します。kubectl --context ${CLUSTER_INGRESS} -n istio-system delete -f $HOME/mci.yaml
これにより、プロジェクトから Cloud Load Balancing リソースが削除されます。
ingress-config
クラスタの登録を解除して削除します。gcloud container fleet memberships unregister ${CLUSTER_INGRESS} \ --project=${PROJECT} \ --gke-uri=${CLUSTER_INGRESS_URI} gcloud container clusters delete ${CLUSTER_INGRESS} \ --zone ${CLUSTER_INGRESS_ZONE} \ --quiet
すべてのクラスタが削除されていることを確認します。
gcloud container clusters list
次のような出力が表示されます。
<null>
kubeconfig
ファイルをリセットします。unset KUBECONFIG