使用 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 服务,分布式服务比 Kubernetes 服务更为灵活,因为它们在同一命名空间内的多个 Kubernetes 集群上运行。即使一个或多个 GKE 集群已关闭,只要运行状况良好的集群能够处理所需的负载,分布式服务仍会保持开启。
只有运行它们的集群的 Kubernetes API 服务器知道 Kubernetes Service。如果 Kubernetes 集群关闭(例如在计划性维护期间),则在该集群上运行的所有 Kubernetes 服务也会关闭。运行分布式服务可以简化集群生命周期管理,因为您可以关闭集群以进行维护或升级,而其他集群处理流量。为了创建分布式服务,服务网格 Cloud Service Mesh 提供的功能用于关联 同时在多个集群上充当单个逻辑服务。
GKE 专用集群可让您将节点和 API 服务器配置为仅在 Virtual Private Cloud (VPC) 网络中可用的专用资源。在 GKE 专用集群中运行分布式服务可为企业提供安全可靠的服务。
架构
本教程使用如下图所示的架构:
在上图中,架构包含以下集群:
- 两个集群(
gke-central-priv
和gke-west-priv
)在两个不同的区域中充当相同的 GKE 专用集群。 - 单独的集群 (
ingress-config
) 充当配置多集群 Ingress 的控制层面集群。
在本教程中,您将部署
Anthos Bank
两个 GKE 专用集群上的示例应用
(gke-central-priv
和 gke-west-priv
)。Bank of Anthos 只是一个示例
由多个微服务和 SQL
模拟网上银行应用的数据库。该应用由一个 Web 服务器
客户端可以访问的前端,以及余额等多个后端服务
分类账和模拟银行的账户服务。
该应用包括两个作为 StatefulSet 安装在 Kubernetes 中的 PostgreSQL 数据库。一个数据库用于事务,另一个数据库用于用户账号。除两个数据库以外的所有服务均作为分布式服务运行。这意味着所有服务的 Pod 都会在 Cloud Service Mesh 是 让每项服务都显示为单项逻辑服务。
目标
- 创建三个 GKE 集群。
- 将两个 GKE 集群配置为专用集群(
gke-central-priv
和gke-west-priv
)。 - 配置一个 GKE 集群 (
ingress-config
) 作为中央配置集群。 此集群充当多集群 Ingress 的配置集群。 - 配置网络(NAT 网关、Cloud Router 和防火墙规则)以允许来自两个专用 GKE 集群的集群间和出站流量。
- 配置授权网络以允许 API 服务从 Cloud Shell 访问两个专用 GKE 集群。
- 将多集群 Cloud Service Mesh 部署并配置为多主模式下的两个专用集群。多主模式会在 两个集群中的 Cloud Service Mesh 控制平面。
- 在两个专用集群上部署 Bank of Anthos 应用。除数据库之外的所有服务均部署为分布式服务(两个专用集群上运行的 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 舰队:
gcloud container fleet mesh enable --project=${PROJECT_ID}
为专用 GKE 集群准备网络
在本部分中,您将为用于运行分布式服务的专用 GKE 集群准备网络。
专用 GKE 集群节点不会分配公共 IP 地址。专用 GKE 集群中的所有节点都会分配一个专用 VPC IP 地址(RFC 1918 地址空间中)。这意味着需要访问外部资源(VPC 网络外部)的 Pod 需要 Cloud NAT 网关。Cloud NAT 网关是地区性 NAT 网关,允许具有内部 IP 地址的 Pod 与互联网进行通信。在本教程中,您将在两个区域中分别配置 Cloud NAT 网关。一个区域内的多个集群可以使用同一个 NAT 网关。
在 Cloud Shell 中,为两个 NAT 网关创建并预留两个外部 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 集群的两个区域中创建 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 的通信和 Pod 到 API 的服务器通信。Pod 到 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}
网络现已准备就绪。在本教程中,您将使用整个 10.0.0.0/8
IP 地址范围,其中包括所有 Pod 范围。我们建议您根据条件和要求在生产环境中创建更严格的防火墙规则。
创建专用 GKE 集群
在本部分中,您将创建部署了示例应用的两个专用 GKE 集群。在本教程中,专用 GKE 集群节点具有专用 IP 地址,并且 API 服务器具有一个公共端点。但是,对 API 服务器的访问仅限于使用已获授权的网络。
在 Cloud Shell 中,创建两个具有授权网络的专用集群。配置集群,以允许从 Pod IP CIDR 范围(针对 Cloud Service Mesh 控制平面)和 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 地址不属于两个集群的授权网络的一部分。
如果您无法访问集群,请更新集群已获授权的网络以包含新的 Cloud Shell IP 地址:
获取更新后的 Cloud Shell 公共 IP 地址:
export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
更新两个集群的授权网络:
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 SQL 或 Cloud SQL 的 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 入站流量网关:
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 入站流量网关:
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 控制平面和入站流量网关后,跨集群服务发现使用舰队 API 来启用。跨集群服务发现可让两个集群从远程集群中发现服务端点。分布式服务在同一命名空间中的多个集群上运行。
对于这两个 Cloud Service Mesh 控制平面,可以发现 因此 Cloud Service Mesh 必须有权访问所有集群 运行分布式服务的容器此示例使用两个集群,因此两个集群都必须能够查询远程集群的服务端点。使用舰队 API 启用代管式 Cloud Service Mesh 后,系统会自动配置端点发现。
集群和 Cloud Service Mesh 现已配置完毕。
部署 Bank of Anthos 应用
在 Cloud Shell 中,克隆 Anthos Bank 代码库:
git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git ${HOME}/bank-of-anthos
在这两个集群中创建和标记
bank-of-anthos
命名空间。此标签允许自动在已加标签的命名空间内的每个 Pod 中注入 Sidecar 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
将 Anthos 银行应用部署到
bank-of-anthos
命名空间中的两个集群。# 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
,以便这两个 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 配置部署到这两个集群。这将为
frontend
服务在asm-ingress
命名空间中创建 Gateway,在bank-of-anthos
命名空间中创建 VirtualService,从而可让您将流量传入frontend
服务。Gateways
通常由平台管理员或网络管理员团队拥有。因此,Gateway
资源在由平台管理员负责管理的 Ingress Gateway 命名空间中创建,可通过他们自己的VirtualService
条目在其他命名空间中使用。这是一种“共享网关”模型。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
您现在已在两个专用 GKE 集群上部署了 Bank of Anthos 应用。除数据库之外,所有服务都作为分布式服务运行。
检查分布式服务
在本部分中,您将使用 istioctl
工具检查任意代理的 proxy-config。这样,您就可以看到边车代理查看每项服务的两个 Pod,每个集群中运行一个 Pod。
在 Cloud Shell 中,检查
cluster_1
中frontend
Pod 的 proxy-config 端点列表: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
在上面的输出中,每个分布式服务都有两个端点 IP 地址。这些是 pod IP 地址,每个集群对应一个 IP 地址。
访问 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 地址以在下一步中使用。
在网络浏览器中打开新标签页,然后转到上述输出中的任一 IP 地址。系统应该显示 Bank of Anthos 前端,以便您登录、将资金存入您的账号,并将资金转移到其他账号。应用应能够完全正常运行。
直观呈现分布式服务
您可以在 Cloud Service Mesh 中直观呈现分布式服务。
要查看您的服务,请前往 Anthos >服务网格 页面。
您可以在表视图或拓扑视图中查看服务。默认视图是表格视图,以表格格式运行的所有分布式服务。要更改视图,请点击要显示的视图。
在表视图中,点击
frontend distributed service
。点击某个服务时,您会看到该服务的详细信息以及关联的服务。在服务详情视图中,您可以点击显示时间轴,以创建 SLO 并查看服务的历史时间轴。
如需查看黄金信号,请点击侧边栏中的指标。
在每秒请求次数图表中,点击细分依据,然后选择位置。
结果会显示这两个地区内两个集群的每秒请求数。分布式服务运行状况良好,两个端点都在处理流量。
如需查看服务网格的拓扑,请在侧边栏上点击 Anthos Service Mesh,然后点击拓扑视图。
如需查看其他数据,请将鼠标指针悬停在
frontend
服务上。这会显示每秒从前端到其他服务的请求数。如需查看更多详细信息,请点击
frontend
服务上的展开。系统会显示服务和工作负载。您可以进一步将工作负载扩展到两个 Deployment,将 Deployment 扩展到 ReplicaSet,并将 ReplicaSet 扩展到 Pod。展开所有元素时,您可以看到分布式frontend
服务,该服务实际上是一个 Service 和两个 Pod。
配置多集群 Ingress
在本部分中,您将创建一个多集群 Ingress,它会将流量发送到在两个集群中运行的 Bank of GKE Enterprise frontend
服务。您可以使用 Cloud Load Balancing 创建一个负载均衡器,它会将两个集群中的 asm-ingressgateway
Service 用作后端。ingress-config
集群用于编排多集群 Ingress 配置。
如需创建负载均衡器,请使用 MultiClusterIngress
以及一个或多个 MultiClusterServices
。MultiClusterIngress
和 MultiClusterService
对象是多集群模拟,类似于在单个集群上下文中使用的现有 Kubernetes Ingress 和 Service 资源。
启用所需的 GKE Enterprise、GKE Fleet 和 Multi Cluster 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
CustomResourceDefinition (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'
验证两个 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
如需退出监视命令,请按 Ctrl+C。
在网络浏览器中导航到 Cloud Load Balancing IP 地址,以访问 Anthos Bank 前端:
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
后续步骤
- 详细了解多集群 Ingress。
- 了解如何跨集群部署多集群 Ingress。