本教程介绍如何使用 Istio 多集群服务网格跨多个 Kubernetes 集群部署应用。通过 Istio 多集群服务网格,多个 Kubernetes 集群上运行的服务之间可彼此安全通信。Kubernetes 集群可在任何位置运行,甚至可在不同的云平台上运行,例如在 Google Cloud 中运行的 Kubernetes Engine (GKE) 集群或在本地数据中心内运行的 Kubernetes 集群。
本教程的目标读者是希望在多个网络中跨多个 GKE 集群创建服务网格的操作人员。要学习本教程,您必须具备 Kubernetes 基础知识(包括 Deployment、Service 和 Ingress 等内容)。具备 Istio 基础知识有助于您学习教程,但这并非必要条件。
Istio 是服务网格的一种开源实现,您可用它来发现、动态路由并安全连接到 Kubernetes 集群上运行的 Service。Istio 还提供了一个政策驱动型框架,用于在网格中实现路由、负载平衡、节流、遥测、断路、身份验证和服务调用授权,且只需极少或完全不需要更改应用代码。Istio 安装在 Kubernetes 集群中时,使用 Kubernetes 服务注册表自动发现在多个 GKE 集群中运行的互连服务(或微服务)并为其创建一个服务网格。Istio 使用每个 Pod 中运行的 Envoy Sidecar 代理来管理 Pod 到 Pod 的流量路由和安全性,并对集群中运行的所有微服务和工作负载提供可监测性。
一个 Kubernetes 集群中运行的微服务可能需要与在其他 Kubernetes 集群中运行的微服务进行通信。例如,可能微服务需要跨地区和跨环境通信,也可能微服务的所有者要维护自己的 Kubernetes 集群。利用 Istio,您可以跨多个 Kubernetes 集群创建服务网格,将远程集群中运行的微服务(甚至 Kubernetes 之外的虚拟机中运行的外部微服务)包含在内。
Istio 为多集群部署提供下面两种主要配置:
- 具有主要远程控制平面的多集群服务网格
- 具有多主控制平面的多集群服务网格
在多主控制平面配置中,每个集群都有自己的 Istio 控制平面安装项,并且每个控制平面都管理自己的本地服务网格。借助 Istio 网关(常见的根证书授权机构 (CA))和跨多个 GKE 集群的自动服务发现,您可以配置单个逻辑服务网格,且该网格由每个集群上参与的微服务组成。其结果是每个集群都管理自己的多集群服务网格,所有集群入站访问都经过 Istio 东-西网关。只要 Istio 东-西网关在所有集群中都可访问,此方法就无特殊的网络要求。
在本教程中,您将使用多主控制平面架构在两个 GKE 集群中部署 Istio。在本教程中,您将使用一个演示微服务应用 Online Boutique,它被拆分到两个 GKE 集群中。要了解每个微服务所用的语言,请查看 README 页面。
您需在 Cloud 项目中构建以下架构。
在此架构中,您有一个 west
集群和一个 central
集群位于两个单独的网络(或 VPC)中,每个网络都有一个 Istio 东-西网关。这两个集群与本地(在同一集群中)和非本地(在另一集群中)的各种微服务进行通信。
目标
- 在两个不同的地区和两个不同的 VPC 中创建两个 GKE 集群:
west
和central
。 - 在这两个 GKE 集群上以多主模式安装 Istio。
- 安装在这两个集群中拆分的 Online Boutique 应用。
- 检查这两个集群中的服务网格。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
您可使用价格计算器根据您的预计使用情况来估算费用。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
准备工作
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
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.
-
Enable the GKE and Cloud Source Repositories APIs.
-
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.
-
Enable the GKE and Cloud Source Repositories APIs.
设置环境
您将通过 Cloud Shell 运行本教程中的所有终端命令。
在 Google Cloud Console 中,打开 Cloud Shell:
克隆以下 GitHub 代码库,下载本教程所需的文件:
cd $HOME git clone https://github.com/GoogleCloudPlatform/istio-multicluster-gke.git
将代码库文件夹设为
$WORKDIR
文件夹,您将在该文件夹中执行与本教程相关的所有任务:cd $HOME/istio-multicluster-gke WORKDIR=$(pwd)
完成本教程后,您可以删除该文件夹。
安装
kubectx
/kubens
:git clone https://github.com/ahmetb/kubectx $WORKDIR/kubectx export PATH=$PATH:$WORKDIR/kubectx
借助这些工具,您可通过切换上下文或命名空间更轻松地处理多个 Kubernetes 集群。
创建 VPC 和 GKE 集群
在本部分,您将创建两个 VPC 和两个 GKE 集群(每个集群对应一个 VPC)。您需要两个不同的 VPC,以证明多个网络上的 Istio 多主实现不需要其他网络要求。集群之间服务到服务的流量会安全地流经互联网。在集群之间通过公共互联网路由流量具有以下优势:
- 支持集群之间的 IP 地址重叠。Node IP 地址、Pod IP 地址和 Service IP 地址可以跨集群重叠。
- 集群之间无需额外连接,且集群网络之间无需对等互连、互连或 VPN。
- 集群可以存在于多个环境中。这意味着集群可以存在于 Google Cloud 和本地数据中心;在这些环境中,虽然操作人员可能无法控制网络或 IP 地址,但可能仍需要安全地连接到 Kubernetes 集群中运行的微服务。
请注意,即使在不同集群之间,您也可以使用双向 TLS (mTLS) 连接来确保集群之间的服务到服务通信安全。这些连接通过验证由 Citadel 颁发的有效证书,有助于避免中间人攻击。
对于集群之间的通信,您可以使用专用 IP 地址。不过,这种方法需要考虑更多的网络设计因素。例如,您可以在参与多集群网格的所有集群之间添加不重叠的 IP 地址。您还可以确保所有 Pod 均能通过专用 (RFC 1918) 地址空间进行通信,这意味着如果您要连接到非 Google Cloud 网络,Google Cloud 全局 VPC 或互连/VPN 中需存在恰当的防火墙规则。在本教程中,您将配置一个专注于公共互联网中服务到服务安全通信的架构,此架构可提高网络灵活性。
在 Cloud Shell 中,创建两个 VPC:
gcloud compute networks create vpc-west --subnet-mode=auto gcloud compute networks create vpc-central --subnet-mode=auto
在本教程中,将
KUBECONFIG
变量设置为使用新的kubeconfig
文件:export KUBECONFIG=${WORKDIR}/istio-kubeconfig
创建两个 GKE 集群:一个名为
west
,位于vpc-west
网络下的us-west2-a
区域中;另一个名为central
,位于vpc-central
网络下的us-central1-a
区域中:gcloud container clusters create west --zone us-west2-a \ --machine-type "e2-standard-2" --disk-size "100" \ --scopes "https://www.googleapis.com/auth/compute",\ "https://www.googleapis.com/auth/devstorage.read_only",\ "https://www.googleapis.com/auth/logging.write",\ "https://www.googleapis.com/auth/monitoring",\ "https://www.googleapis.com/auth/servicecontrol",\ "https://www.googleapis.com/auth/service.management.readonly",\ "https://www.googleapis.com/auth/trace.append" \ --num-nodes "4" --network "vpc-west" --async gcloud container clusters create central --zone us-central1-a \ --machine-type "e2-standard-2" --disk-size "100" \ --scopes "https://www.googleapis.com/auth/compute",\ "https://www.googleapis.com/auth/devstorage.read_only",\ "https://www.googleapis.com/auth/logging.write",\ "https://www.googleapis.com/auth/monitoring",\ "https://www.googleapis.com/auth/servicecontrol",\ "https://www.googleapis.com/auth/service.management.readonly",\ "https://www.googleapis.com/auth/trace.append" \ --num-nodes "4" --network "vpc-central"
稍等几分钟,直到这两个集群都创建完成。验证每个集群的状态是否为
RUNNING
:gcloud container clusters list
输出内容类似如下:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS central us-central1-a 1.17.14-gke.1600 104.197.127.140 e2-standard-2 1.17.14-gke.1600 4 RUNNING west us-west2-a 1.17.14-gke.1600 34.94.217.4 e2-standard-2 1.17.14-gke.1600 4 RUNNING
连接到这两个集群,以在
kubeconfig
文件中生成相关条目:export PROJECT_ID=$(gcloud info --format='value(config.project)') gcloud container clusters get-credentials west --zone us-west2-a --project ${PROJECT_ID} gcloud container clusters get-credentials central --zone us-central1-a --project ${PROJECT_ID}
使用
kubeconfig
文件为每个集群创建用户和上下文,从而创建针对集群的身份验证。创建kubeconfig
文件后,您可以快速切换集群之间的上下文。为方便起见,请使用
kubectx
重命名上下文名称:kubectx west=gke_${PROJECT_ID}_us-west2-a_west kubectx central=gke_${PROJECT_ID}_us-central1-a_central
向自己(您的 Google 用户)授予这两个集群的
cluster-admin
角色:kubectl create clusterrolebinding user-admin-binding \ --clusterrole=cluster-admin --user=$(gcloud config get-value account) \ --context west kubectl create clusterrolebinding user-admin-binding \ --clusterrole=cluster-admin --user=$(gcloud config get-value account) \ --context central
您可使用此角色对这些集群执行管理任务。
在两个集群上配置证书
在 Istio 中,Citadel 是 Istio 的证书授权机构 (CA),负责对证书签名并将证书分发到服务网格中的所有 Envoy 代理(工作负载 Sidecar 代理、入站网关代理、东-西网关和出站网关代理)。默认情况下,Citadel 会生成自签名根证书和密钥,并使用它们对工作负载证书进行签名。Citadel 还可以使用操作人员指定的证书和密钥来对工作负载证书签名。在本教程中,west
和 central
集群维护单独的服务证书,使用单独的 Citadel 服务对各自的工作负载进行签名。
若要跨集群在微服务之间建立信任,这两个 Citadel 签名 (CA) 证书必须由一个共同的根证书授权机构(根 CA)签名。工作负载还需要证书链文件来验证 Citadel 签名证书与根 CA 之间所有中间 CA 的信任链。可通过在 Kubernetes 集群中使用 Secret 实现此配置。本教程中提供有这些证书文件。在生产环境中,您可以使用由您的 PKI 系统或安全团队生成的证书(例如,您可以自己充当 CA)。创建的 Secret 由 Citadel 使用且具有以下属性:
- Secret 必须命名为
cacert
。 - Secret 根据 4 个证书文件创建而成(由本教程的 Istio 代码提供),其名称必须如下所示:
root-cert.pem
包含根 CA。对于west
和central
集群中的 Citadel 服务,此文件是相同的。这两个 Citadel 证书均由此根 CA 签名。ca-cert.pem
和ca-key.pem
是 Citadel 服务的签名 (CA) 证书和私钥。两个 Citadel 证书都必须由根 CA (root-cert.pem
) 签名。ca-cert.pem
用于对每个集群内的工作负载进行签名。cert-chain.pem
是工作负载证书与根 CA 之间的信任链。在本例中,cert-chain.pem
仅包含ca-cert.pem
证书;因此,这些文件均相同。此文件在跨集群运行的微服务之间建立信任。
默认的 Citadel 安装项会设置命令行选项,使其根据命令中使用的预定义 Secret 名称和文件名来配置证书和密钥的位置,即 Secret 名为 cacert
,根证书位于 root-cert.pem
文件中,Citadel 密钥位于 ca-key.pem
中,依此类推。
在 Cloud Shell 中,下载 Istio:
cd ${WORKDIR} export ISTIO_VERSION=1.9.0 curl -L https://istio.io/downloadIstio | ISTIO_VERSION=${ISTIO_VERSION} TARGET_ARCH=x86_64 sh - cd istio-${ISTIO_VERSION} export PATH=$PWD/bin:$PATH
在 Cloud Shell 中,使用适当的证书文件创建 Secret:
for cluster in $(kubectx) do kubectl --context $cluster create namespace istio-system kubectl --context $cluster create secret generic cacerts -n istio-system \ --from-file=${WORKDIR}/istio-${ISTIO_VERSION}/samples/certs/ca-cert.pem \ --from-file=${WORKDIR}/istio-${ISTIO_VERSION}/samples/certs/ca-key.pem \ --from-file=${WORKDIR}/istio-${ISTIO_VERSION}/samples/certs/root-cert.pem \ --from-file=${WORKDIR}/istio-${ISTIO_VERSION}/samples/certs/cert-chain.pem; done
安装 Istio
在本部分中,您将在 west
和 central
集群上安装 Istio。
在 Cloud Shell 中,为
west
集群设置默认网络。kubectl --context=west label namespace istio-system topology.istio.io/network=network1
使用专用的东-西网关为
west
集群创建 Istio 配置:cd ${WORKDIR} cat <<EOF > istio-west.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: values: global: meshID: mesh1 multiCluster: clusterName: west network: network1 components: ingressGateways: - name: istio-eastwestgateway label: istio: eastwestgateway app: istio-eastwestgateway topology.istio.io/network: network1 enabled: true k8s: env: # sni-dnat adds the clusters required for AUTO_PASSTHROUGH mode - name: ISTIO_META_ROUTER_MODE value: "sni-dnat" # traffic through this gateway should be routed inside the network - name: ISTIO_META_REQUESTED_NETWORK_VIEW value: network1 service: ports: - name: status-port port: 15021 targetPort: 15021 - name: tls port: 15443 targetPort: 15443 - name: tls-istiod port: 15012 targetPort: 15012 - name: tls-webhook port: 15017 targetPort: 15017 EOF
将配置应用于
west
集群:istioctl install --context=west -f istio-west.yaml
按
y
以继续。检查
istio-system
命名空间中的部署。kubectl --context=west -n istio-system get deployments
输出如下所示:
NAME READY UP-TO-DATE AVAILABLE AGE istio-eastwestgateway 1/1 1 1 2m11s istio-ingressgateway 1/1 1 1 8m43s istiod 1/1 1 1 8m56s
等待为东-西网关分配一个外部 IP 地址:
kubectl --context=west get svc istio-eastwestgateway -n istio-system
输出如下所示:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-eastwestgateway LoadBalancer 10.3.241.43 34.94.214.249 15021:30369/TCP,15443:30988/TCP,15012:31358/TCP,15017:32625/TCP 3m42s
由于集群位于不同的网络中,因此您需要在这两个集群中的东-西网关上公开所有服务 (*.local) 。因为东-西网关是在互联网上公开的,所以只有具有可信 mTLS 证书和工作负载 ID 的服务才能访问其背后的服务,就如它们位于同一网络上一样。
kubectl --context=west apply -n istio-system -f \ ${WORKDIR}/istio-${ISTIO_VERSION}/samples/multicluster/expose-services.yaml
为
central
集群设置默认网络。kubectl --context=central label namespace istio-system topology.istio.io/network=network2
使用专用的东-西网关为
central
集群创建 Istio 配置:cd ${WORKDIR} cat <<EOF > istio-central.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator spec: values: global: meshID: mesh1 multiCluster: clusterName: central network: network2 components: ingressGateways: - name: istio-eastwestgateway label: istio: eastwestgateway app: istio-eastwestgateway topology.istio.io/network: network2 enabled: true k8s: env: # sni-dnat adds the clusters required for AUTO_PASSTHROUGH mode - name: ISTIO_META_ROUTER_MODE value: "sni-dnat" # traffic through this gateway should be routed inside the network - name: ISTIO_META_REQUESTED_NETWORK_VIEW value: network2 service: ports: - name: status-port port: 15021 targetPort: 15021 - name: tls port: 15443 targetPort: 15443 - name: tls-istiod port: 15012 targetPort: 15012 - name: tls-webhook port: 15017 targetPort: 15017 EOF
将配置应用于
central
集群:istioctl install --context=central -f istio-central.yaml
按
y
以继续。检查
istio-system
命名空间中的部署。kubectl --context=central -n istio-system get deployments
输出如下所示:
NAME READY UP-TO-DATE AVAILABLE AGE istio-eastwestgateway 1/1 1 1 2m11s istio-ingressgateway 1/1 1 1 8m43s istiod 1/1 1 1 8m56s
等待为东-西网关分配一个外部 IP 地址:
kubectl --context=central get svc istio-eastwestgateway -n istio-system
输出如下所示:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE istio-eastwestgateway LoadBalancer 10.3.250.201 35.232.125.62 15021:30810/TCP,15443:31125/TCP,15012:30519/TCP,15017:30743/TCP 37s
在中央集群的东-西网关上公开所有服务 (*.local)。
kubectl --context=central apply -n istio-system -f \ ${WORKDIR}/istio-${ISTIO_VERSION}/samples/multicluster/expose-services.yaml
启用端点发现
在
west
集群中安装远程 Secret,从而提供对central
集群的 API 服务器的访问权限。istioctl x create-remote-secret \ --context=central \ --name=central | \ kubectl apply -f - --context=west
在
central
集群中安装远程 Secret,从而提供对west
集群的 API 服务器的访问权限。istioctl x create-remote-secret \ --context=west \ --name=west | \ kubectl apply -f - --context=central
部署 Online Boutique 应用
在本部分中,您将在两个集群中安装 Online Boutique 应用。Online Boutique 由 10 个用不同编程语言编写的微服务组成。您可在 central
和 west
集群之间拆分这些微服务,如以下架构所示。
在这两个集群中为 Online Boutique 应用创建命名空间:
kubectl --context central create namespace online-boutique kubectl --context west create namespace online-boutique
对命名空间添加标签以自动执行 Istio Sidecar 代理注入:
kubectl --context central label namespace online-boutique istio-injection=enabled kubectl --context west label namespace online-boutique istio-injection=enabled
在
west
和central
集群上部署 Online Boutique 应用:kubectl --context central -n online-boutique apply -f $WORKDIR/istio-multi-primary/central kubectl --context west -n online-boutique apply -f $WORKDIR/istio-multi-primary/west
Online Boutique 应用需要几分钟时间才能启动并运行所有部署。
等待所有部署在这两个集群均可用。
# In central cluster kubectl --context=central -n online-boutique wait --for=condition=available deployment emailservice --timeout=5m kubectl --context=central -n online-boutique wait --for=condition=available deployment checkoutservice --timeout=5m kubectl --context=central -n online-boutique wait --for=condition=available deployment shippingservice --timeout=5m kubectl --context=central -n online-boutique wait --for=condition=available deployment paymentservice --timeout=5m kubectl --context=central -n online-boutique wait --for=condition=available deployment adservice --timeout=5m kubectl --context=central -n online-boutique wait --for=condition=available deployment currencyservice --timeout=5m # In west cluster kubectl --context=west -n online-boutique wait --for=condition=available deployment frontend --timeout=5m kubectl --context=west -n online-boutique wait --for=condition=available deployment recommendationservice --timeout=5m kubectl --context=west -n online-boutique wait --for=condition=available deployment productcatalogservice --timeout=5m kubectl --context=west -n online-boutique wait --for=condition=available deployment cartservice --timeout=5m kubectl --context=west -n online-boutique wait --for=condition=available deployment redis-cart --timeout=5m kubectl --context=west -n online-boutique wait --for=condition=available deployment loadgenerator --timeout=5m
所有部署的输出如下所示:
deployment.apps/frontend condition met
访问 Online Boutique 应用
您可以通过任一集群中的 istio-ingressgatway
公共 IP 地址访问 Online Boutique 应用。
从这两个集群中获取
istio-ingressgateway
服务的公共 IP 地址。kubectl --context west get -n istio-system service istio-ingressgateway -o json | jq -r '.status.loadBalancer.ingress[0].ip' kubectl --context central get -n istio-system service istio-ingressgateway -o json | jq -r '.status.loadBalancer.ingress[0].ip'
输出会显示外部 IP 地址。
从任一个群集复制 Istio 入站网关 IP 地址并粘贴到网络浏览器标签页中,然后刷新页面。您会看到 Online Boutique 首页。
请在应用中导航、浏览各种产品,并将产品放入购物车和进行结帐等等。
您会发现,Online Boutique 正在两个环境中的两个 Kubernetes 集群上完全正常地运行。
监控服务网格
您可以使用 Kiali 来监控和直观呈现服务网格。Kiali 是一种在 Istio 安装期间安装的服务网格可监测性工具。
将 Prometheus 和 Kiali 部署到
west
集群。kubectl --context west apply -f https://raw.githubusercontent.com/istio/istio/release-${ISTIO_VERSION:0:3}/samples/addons/prometheus.yaml kubectl --context west apply -f https://raw.githubusercontent.com/istio/istio/release-${ISTIO_VERSION:0:3}/samples/addons/kiali.yaml
如果 Kiali 安装因出错而失败,请尝试再次运行相同的命令。再次运行命令时,可能存在一些计时问题。
确保 Prometheus 和 Kiali Pod 正在运行:
kubectl --context west get pods -n istio-system
输出如下所示:
kiali-6d5c4bbb64-wpsqx 1/1 Running 0 72s prometheus-6d87d85c88-h2cwl 2/2 Running 0 92s
在 Cloud Shell 中,在
west
集群上公开 Kiali:kubectl --context west port-forward svc/kiali 8080:20001 -n istio-system >> /dev/null &
在
west
集群上打开 Kiali 网页界面:在 Cloud Shell 中,选择网页预览,然后选择在端口 8080 上预览。从左侧菜单中选择图表。
在选择命名空间下拉列表中,选择 online-boutique。
从图表下方的菜单中,选择服务图表 (Service Graph)。
或者,在显示菜单中,选择流量动画 (Traffic Animation) 来观看
loadgenerator
对您的应用生成流量的过程。
您已成功安装一个拆分到多个集群之间的应用。 这些微服务使用具有 mTLS 的 Istio 东-西网关在集群之间安全地进行通信。每个集群都维护和控制自己的 Istio 控制平面,以避免出现任何单点故障。
清理
完成本教程后,请清理您在 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.
重置 kubeconfig
重置您的
kubeconfig
文件:unset KUBECONFIG rm istio-kubeconfig
后续步骤
- 详细了解在 Google Cloud 上使用 Istio。
- 如需了解服务网格和混合云的作用,请阅读服务网格时代:Istio 在未来混合云中的作用。
- 探索有关 Google Cloud 的参考架构、图表和最佳实践。查看我们的 Cloud Architecture Center。