通过 Istio 网格扩展功能为迁移提供支持:教程

本教程介绍了如何初始化和配置服务网格,以将功能逐个从本地(旧版)数据中心迁移到 Google Cloud Platform (GCP)。本教程及其随附的概念介绍文章适用于想要使用服务网格将流量动态路由到旧版环境或 GCP 的系统管理员、开发者和工程师。

服务网格会将网络功能与服务功能分离开来,因此可以大幅度降低迁移操作和重构工作的复杂度。此外,服务网格还可提供负载平衡、流量管理、监控和可观察性,从而可降低网络操作的复杂度。

下图展示了如何使用服务网格将流量路由到在旧版环境中运行的微服务或 GCP:

使用服务网格将流量路由到旧版环境中运行的微服务或 GCP

在本教程中,您将使用以下软件:

目标

  • 初始化模拟本地数据中心的环境。
  • 将示例工作负载部署到本地数据中心。
  • 测试在本地数据中心内运行的工作负载。
  • 在 GCP 上配置目标环境。
  • 将工作负载从本地数据中心迁移到目标环境。
  • 测试在目标环境中运行的工作负载。
  • 停用本地数据中心。

费用

本教程使用 GCP 的收费组件,包括:

请使用价格计算器根据您的预计使用情况来估算费用。

准备工作

  1. 登录您的 Google 帐号。

    如果您还没有 Google 帐号,请注册新帐号

  2. 选择或创建 Google Cloud Platform 项目。

    转到“管理资源”页面

  3. 确保您的 Google Cloud Platform 项目已启用结算功能。

    了解如何启用结算功能

  4. 启用Compute Engine and GKE API。

    启用 API

完成本教程后,您可以删除所创建的资源以避免继续计费。如需了解详情,请参阅清理

准备环境

本教程的大部分步骤将在 Cloud Shell 中执行。

  1. 打开 Cloud Shell:

    打开 Cloud Shell

  2. 将工作目录更改为 $HOME 目录:

    cd "$HOME"
    
  3. 克隆包含用于部署和配置演示应用的脚本和清单文件的 Git 代码库:

    git clone https://github.com/GoogleCloudPlatform/solutions-istio-mesh-expansion-migration
    
  4. 设置默认区域和地区:

    gcloud config set compute/region us-east1
    gcloud config set compute/zone us-east1-b
    
  5. 初始化以下环境变量以存储 Istio 版本标识符:

    export ISTIO_VERSION=1.1.1
    
  6. 下载并解压 Istio:

    wget https://github.com/istio/istio/releases/download/"$ISTIO_VERSION"/istio-"$ISTIO_VERSION"-linux.tar.gz
    tar -xvzf istio-"$ISTIO_VERSION"-linux.tar.gz
    
  7. 初始化以下环境变量,以分别存储 Istio 解压路径、Helm 版本标识符和 Helm 解压路径:

    ISTIO_PATH="$HOME"/istio-"$ISTIO_VERSION"
    HELM_VERSION=v2.13.0
    HELM_PATH="$HOME"/helm-"$HELM_VERSION"
    
  8. 下载并解压 Helm:

    wget https://storage.googleapis.com/kubernetes-helm/helm-"$HELM_VERSION"-linux-amd64.tar.gz
    tar -xvzf helm-"$HELM_VERSION"-linux-amd64.tar.gz
    mv linux-amd64 "$HELM_PATH"
    

示例工作负载

在本教程中,您将使用 Bookinfo 应用,这是一个显示图书相关信息的四层 Polyglot 微服务应用。此应用设计为在 Kubernetes 上运行,但您首先需要使用 Docker 和 Docker Compose 将其部署到 Compute Engine 实例上。借助 Docker Compose,您可以使用 YAML 描述符来描述多容器应用。然后,可通过执行单个命令来启动该应用。

尽管此示例工作负载已经容器化,但此方法也适用于非容器化服务。在此类情况下,您可以添加“现代化改造阶段”,即将要迁移的服务容器化

Bookinfo 应用包含四个微服务组件:

  • productpage:用于调用 detailsratingsreviews 微服务以填充图书信息页面
  • details:用于提供图书的相关信息
  • reviews:包含书评
  • ratings:用于返回图书排名信息以随附于书评

设置环境

第一步是配置本教程所需的环境:

  • 模拟(旧版)本地数据中心的环境
  • 模拟迁移目标的环境

本教程旨在帮助您从非 GCP 环境(例如本地或其他云服务商)迁移到 GCP。此类迁移具有一定程度的网络复杂度,因为您需要在非 GCP 环境与 GCP 环境之间建立一条安全通信通道

在本教程中,这两个环境均在 GCP 中运行。因此,您只需一个引导阶段,从而简化了设置过程。

预配旧版环境

在本部分中,您将通过初始化 Compute Engine 实例并部署要迁移的工作负载来配置 GCP 环境,以模拟单独的非 GCP 环境。下图演示了旧版环境的目标架构:

用于预配旧版环境的架构

创建防火墙规则

您可以创建防火墙规则,以允许对微服务和数据库进行外部访问。

  • 在 Cloud Shell 中,创建节点间通信所需的防火墙规则:

    gcloud compute firewall-rules create bookinfo \
        --description="Bookinfo App rules" \
        --action=ALLOW \
        --rules=tcp:9080,tcp:9081,tcp:9082,tcp:9083,tcp:9084 \
        --target-tags=bookinfo-legacy-vm
    

初始化服务帐号以管理 Compute Engine 实例

在本教程中,您将创建一个服务帐号来管理 Compute Engine 实例。最佳做法是仅向该服务帐号提供运行应用所需的角色和访问权限。在本教程中,该服务帐号所需的唯一角色是 Compute Viewer 角色 (roles/compute.viewer)。此角色提供对 Compute Engine 资源的只读访问权限。

  1. 在 Cloud Shell 中,初始化以下环境变量以存储服务帐号名称:

    GCE_SERVICE_ACCOUNT_NAME=istio-migration-gce
    
  2. 创建服务帐号:

    gcloud iam service-accounts create "$GCE_SERVICE_ACCOUNT_NAME" --display-name="$GCE_SERVICE_ACCOUNT_NAME"
    
  3. 初始化以下环境变量以存储完整的服务帐号电子邮件地址:

    GCE_SERVICE_ACCOUNT_EMAIL="$(gcloud iam service-accounts list \
        --format='value(email)' \
        --filter=displayName:"$GCE_SERVICE_ACCOUNT_NAME")"
    
  4. compute.viewer 角色与该服务帐号绑定:

    gcloud projects add-iam-policy-binding "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GCE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/compute.viewer
    

初始化运行时环境

下一步是创建和配置 Compute Engine 实例以用于托管要迁移的工作负载。

  1. 在 Cloud Shell 中,使用 Compute Engine 实例名称初始化以下变量并导出该变量:

    export GCE_INSTANCE_NAME=legacy-vm
    
  2. 创建 Compute Engine 实例:

    gcloud compute instances create "$GCE_INSTANCE_NAME" \
        --boot-disk-device-name="$GCE_INSTANCE_NAME" \
        --boot-disk-size=10GB \
        --boot-disk-type=pd-ssd \
        --image-family=ubuntu-1804-lts \
        --image-project=ubuntu-os-cloud \
        --machine-type=n1-standard-1 \
        --metadata-from-file startup-script="$HOME"/solutions-istio-mesh-expansion-migration/gce-startup.sh \
        --scopes=storage-ro,logging-write,monitoring-write,service-control,service-management,trace \
        --service-account="$GCE_SERVICE_ACCOUNT_EMAIL" \
        --tags=bookinfo-legacy-vm
    

    此命令中指定的 n1-standard-1 机器类型是在不影响性能的情况下运行示例工作负载所需的最小机器类型。完成此命令后,Console 会显示新实例的相关详细信息:

    NAME           ZONE        MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP   STATUS
    legacy-vm      us-east1-b  n1-standard-1               10.142.0.38  34.73.53.145  RUNNING
    

启动脚本通过以下方式配置 Compute Engine 实例:

  • 安装 Docker
  • 安装 Docker Compose
  • 安装 Dnsmasq

在旧版环境中部署工作负载

在本教程中,您需要将 Istio Bookinfo 应用部署为工作负载以进行迁移。

  1. 在 Cloud Shell 中,将 Docker Compose 描述符复制到 Compute Engine 实例:

    gcloud compute scp --recurse \
    "$HOME"/solutions-istio-mesh-expansion-migration/compose \
    "$GCE_INSTANCE_NAME":/tmp --zone=us-east1-b
    
  2. 等待 Docker Compose 安装完成:

    gcloud compute ssh "$GCE_INSTANCE_NAME" \
        --zone=us-east1-b \
        --command='while ! command -v docker-compose; do echo "Waiting for docker-compose to be installed"; sleep 5; done'
    
  3. 使用 Docker Compose 启动 Bookinfo 应用:

    gcloud compute ssh "$GCE_INSTANCE_NAME" \
        --zone=us-east1-b \
        --command='sudo docker-compose -f /tmp/compose/bookinfo.yaml up -d'
    

在旧版环境中测试您的部署

您已完成示例工作负载的配置,因此现在可以对其进行测试。

  1. 在 Cloud Shell 中,找到运行示例工作负载的 Compute Engine 实例的外部 IP 地址:

    gcloud compute instances describe "$GCE_INSTANCE_NAME" \
        --zone=us-east1-b \
        --format='value(networkInterfaces[0].accessConfigs[0].natIP)'
    
  2. 打开浏览器并转到以下网址,其中 [EXTERNAL_IP] 是上一步中找到的 IP 地址:

    http://[EXTERNAL_IP]:9083/productpage
    

    随即会显示一个页面,其中包含有关图书和相关评分的详细信息:

    有关图书和相关评分的详细信息

预配目标运行时环境

在本部分中,您将通过初始化 GKE 集群并使用 Istio 提供旧版服务,在 GCP 中配置目标环境。下图显示了目标运行时环境的目标架构:

用于预配目标运行时环境的架构

初始化服务帐号以管理 GKE 集群

在本教程中,您将创建一个服务帐户来管理 GKE 集群中的 Compute Engine 实例。GKE 集群节点使用此服务帐号而非默认服务帐号,因为您希望提供的权限比授予给默认服务帐号的权限要少。

该服务帐号所需的角色包括 monitoring.viewermonitoring.metricWriterlogging.logWriter,具体请参阅强化集群的安全性

  1. 在 Cloud Shell 中,初始化以下环境变量以存储服务帐号名称:

    GKE_SERVICE_ACCOUNT_NAME=istio-migration-gke
    
  2. 创建服务帐号:

    gcloud iam service-accounts create "$GKE_SERVICE_ACCOUNT_NAME" \
        --display-name="$GKE_SERVICE_ACCOUNT_NAME"
    
  3. 初始化以下环境变量以存储该服务帐号的电子邮件帐号名称:

    GKE_SERVICE_ACCOUNT_EMAIL="$(gcloud iam service-accounts list \
        --format='value(email)' \
        --filter=displayName:"$GKE_SERVICE_ACCOUNT_NAME")"
    
  4. 向该服务帐号授予 monitoring.viewermonitoring.metricWriterlogging.logWriter 角色:

    gcloud projects add-iam-policy-binding \
        "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/monitoring.viewer
    gcloud projects add-iam-policy-binding \
        "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/monitoring.metricWriter
    gcloud projects add-iam-policy-binding \
        "$(gcloud config get-value project 2> /dev/null)" \
        --member serviceAccount:"$GKE_SERVICE_ACCOUNT_EMAIL" \
        --role roles/logging.logWriter
    

准备 GKE 集群

在本部分中,您将启动 GKE 集群、安装 Istio、提供 Istio 服务,并完成集群配置。第一步是创建并启动 GKE 集群。

  1. 在 Cloud Shell 中,初始化以下环境变量以存储 GKE 集群名称,并导出该变量:

    export GKE_CLUSTER_NAME=istio-migration
    
  2. 创建一个区域级 GKE 集群,该集群具有一个节点池且每个节点对应一个地区:

    gcloud container clusters create "$GKE_CLUSTER_NAME" \
        --addons=HorizontalPodAutoscaling,HttpLoadBalancing \
        --enable-autoupgrade \
        --enable-network-policy \
        --enable-ip-alias \
        --machine-type=n1-standard-4 \
        --metadata disable-legacy-endpoints=true \
        --node-locations us-east1-b,us-east1-c,us-east1-d \
        --no-enable-legacy-authorization \
        --no-enable-basic-auth \
        --no-issue-client-certificate \
        --num-nodes=1 \
        --region us-east1 \
        --service-account="$GKE_SERVICE_ACCOUNT_EMAIL"
    

    此命令将创建一个名为 istio-migration 的 GKE 集群。执行此命令可能最多需要五分钟。该命令完成后,Console 会显示有关新创建的集群的详细信息:

    NAME             LOCATION  MASTER_VERSION  MASTER_IP      MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
    istio-migration  us-east1  1.11.7-gke.4    35.196.136.88  n1-standard-8  1.11.7-gke.4  3          RUNNING
    

下一步是使用 Helm 在集群中安装 Istio。

  1. 在 Cloud Shell 中,初始化以下环境变量以存储 Istio 命名空间名称,并导出该变量:

    export ISTIO_NAMESPACE=istio-system
    
  2. 创建 Istio 命名空间:

    kubectl apply -f "$ISTIO_PATH"/install/kubernetes/namespace.yaml
    
  3. Tiller(即 Helm 的服务器部分)创建一个 Kubernetes 服务帐号

    kubectl apply -f "$ISTIO_PATH"/install/kubernetes/helm/helm-service-account.yaml
    
  4. 在您的集群中安装 Tiller:

    "$HELM_PATH"/helm init --service-account tiller
    
  5. 安装 istio-init 图表以引导 Istio 的所有自定义资源定义

    "$HELM_PATH"/helm install "$ISTIO_PATH"/install/kubernetes/helm/istio-init --name istio-init --namespace "$ISTIO_NAMESPACE"
    

    此命令完成后,Console 会显示 GKE 集群中新安装的对象的摘要:

    NAME:   istio-init
    LAST DEPLOYED: Wed Mar 20 11:39:12 2019
    NAMESPACE: istio-system
    STATUS: DEPLOYED
    RESOURCES:
    ==> v1/ClusterRole
    NAME                     AGE
    istio-init-istio-system  1s
    ==> v1/ClusterRoleBinding
    NAME                                        AGE
    istio-init-admin-role-binding-istio-system  1s
    ==> v1/ConfigMap
    NAME          DATA  AGE
    istio-crd-10  1     1s
    istio-crd-11  1     1s
    ==> v1/Job
    NAME               COMPLETIONS  DURATION  AGE
    istio-init-crd-10  0/1          1s        1s
    istio-init-crd-11  0/1          1s        1s
    ==> v1/Pod(related)
    NAME                     READY  STATUS             RESTARTS  AGE
    istio-init-crd-10-2s28z  0/1    ContainerCreating  0         1s
    istio-init-crd-11-28n9r  0/1    ContainerCreating  0         1s
    ==> v1/ServiceAccount
    NAME                        SECRETS  AGE
    istio-init-service-account  1        1s
    
  6. 验证 Istio CRD 是否已提交到 Kubernetes api-server

    kubectl get crds | grep 'istio.io\|certmanager.k8s.io' | wc -l
    

    预期输出为 53

  7. 安装 Istio 图表:

    "$HELM_PATH"/helm install "$ISTIO_PATH"/install/kubernetes/helm/istio \
        --name istio \
        --namespace "$ISTIO_NAMESPACE" \
        --set gateways.istio-ilbgateway.enabled=true \
        --set global.meshExpansion.enabled=true \
        --set global.meshExpansion.useILB=true \
        --set grafana.enabled=true \
        --set kiali.enabled=true \
        --set kiali.createDemoSecret=true \
        --set kiali.dashboard.grafanaURL=http://grafana:3000 \
        --set prometheus.enabled=true \
        --set tracing.enabled=true
    

    执行此命令可能最多需要两分钟。此命令完成后,Console 会显示 GKE 集群中新安装的对象的摘要:

    NAME:   istio
    LAST DEPLOYED: Wed Mar 20 11:43:08 2019
    NAMESPACE: istio-system
    STATUS: DEPLOYED
    RESOURCES:
    

    此摘要后面会显示已部署资源的列表。

由于要添加到服务网格的 Compute Engine 实例必须有权访问 Istio 控制层面服务(Pilot、Mixer、Citadel),因此您必须通过 istio-ingressgatewayistio-ilbgateway 服务提供这些服务。您需要使用内部负载平衡器提供 Kubernetes DNS 服务器,以便查询该服务器来解析集群中运行的服务的名称。此外,您还需要提供 Kiali 来直观呈现服务网格。

  1. 在 Cloud Shell 中,创建内部负载均衡器以提供 Kubernetes DNS 服务器:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/kube-dns-ilb.yaml
    
  2. 等待系统为名为 kube-dns-ilb 的服务对象分配一个外部 IP 地址:

    kubectl get svc kube-dns-ilb -n kube-system --watch
    

    输出会显示 EXTERNAL-IP 的 IP 地址:

    NAME           TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
    kube-dns-ilb   LoadBalancer   10.35.252.144   10.128.0.3    53:31054/UDP   4d
    

    要停止该命令,请按 Control+C

  3. 等待系统为名为 istio-ingressgateway 的服务对象分配一个外部 IP 地址:

    kubectl get svc istio-ingressgateway -n "$ISTIO_NAMESPACE" --watch
    

    输出会显示 EXTERNAL-IP 的 IP 地址:

    NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)                                                                                                                   AGE
    istio-ingressgateway   LoadBalancer   10.48.2.195   34.73.84.179   80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:31145/TCP,8060:30381/TCP,853:30784/TCP,15030:32124/TCP,15031:32703/TCP   4d
    

    要停止该命令,请按 Control+C

  4. 等待系统为名为 istio-ilbgateway 的服务对象分配一个外部 IP 地址:

    kubectl get svc istio-ilbgateway -n "$ISTIO_NAMESPACE" --watch
    

    输出会显示 EXTERNAL-IP 的 IP 地址:

    NAME               TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                                         AGE
    istio-ilbgateway   LoadBalancer   10.48.14.190   10.142.0.31   15011:30805/TCP,15010:31082/TCP,8060:30953/TCP,5353:30536/TCP   2m
    

    要停止该命令,请按 Control+C

  5. 使用 GatewayVirtualService 提供 Kiali:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/kiali.yaml
    

配置 Istio 网格扩展功能

在本部分中,您将配置 Istio 网格扩展功能,以允许 Compute Engine 实例加入服务网格。第一项任务是生成多个配置文件,以在要加入网格的每个 Compute Engine 实例中进行部署。

  1. 在 Cloud Shell 中,初始化以下环境变量以存储默认命名空间名称,并导出该变量:

    export SERVICE_NAMESPACE=default
    
  2. 提取 Istio 所用服务帐号的密钥:

    "$ISTIO_PATH"/install/tools/setupMeshEx.sh machineCerts default "$SERVICE_NAMESPACE" all
    
  3. 初始化以下环境变量以存储配置生成脚本的选项,并导出该变量:

    export GCP_OPTS="--region $(gcloud config get-value compute/region 2> /dev/null)"
    
  4. 运行集群环境配置生成脚本:

    "$ISTIO_PATH"/install/tools/setupMeshEx.sh generateClusterEnv "$GKE_CLUSTER_NAME"
    
  5. 运行 DNS 配置生成脚本:

    "$HOME"/solutions-istio-mesh-expansion-migration/gce-mesh-expansion-setup.sh
    

接下来,您需要配置要加入网格的 Compute Engine 实例。

  1. 取消设置 GCP_OPTS 变量,以让初始化脚本来选择默认值:

    unset GCP_OPTS
    
  2. 初始化以下环境变量以存储设置脚本的路径,并导出该变量:

    export SETUP_ISTIO_VM_SCRIPT="$ISTIO_PATH"/install/tools/setupIstioVM.sh
    
  3. 准备 Istio 版本描述符以进行 Compute Engine 实例初始化:

    cp "$ISTIO_PATH"/istio.VERSION "$HOME"
    
  4. 运行集群环境配置生成脚本:

    "$ISTIO_PATH"/install/tools/setupMeshEx.sh gceMachineSetup "$GCE_INSTANCE_NAME"
    
  5. 配置本地端口以对入站服务使用 Envoy Sidecar:

    gcloud compute ssh "$GCE_INSTANCE_NAME" \
        --zone=us-east1-b \
        --command='sudo sed -i -e "\$aISTIO_INBOUND_PORTS=9081,9082,9083,9084" /var/lib/istio/envoy/sidecar.env'
    
  6. 配置集群命名空间:

    gcloud compute ssh "$GCE_INSTANCE_NAME" \
        --zone=us-east1-b \
        --command='sudo sed -i -e "\$aISTIO_NAMESPACE='"$SERVICE_NAMESPACE"'" /var/lib/istio/envoy/sidecar.env'
    
  7. 重启 Istio:

    gcloud compute ssh "$GCE_INSTANCE_NAME" \
        --zone=us-east1-b \
        --command='sudo systemctl restart istio'
    
  8. 检查 Istio 是否已正确启动:

    gcloud compute ssh "$GCE_INSTANCE_NAME" \
        --zone=us-east1-b \
        --command='sudo systemctl --type=service --state=running list-units | grep "dnsmasq\|istio\|systemd-resolved"'
    

    输出会显示 dnsmasqistioistio-auth-node-agentsystemd-resolved 服务已加载、处于活跃状态且正在运行:

    dnsmasq.service                  loaded active running dnsmasq - A lightweight DHCP and caching DNS server
    istio-auth-node-agent.service    loaded active running istio-auth-node-agent: The Istio auth node agent
    istio.service                    loaded active running istio-sidecar: The Istio sidecar
    systemd-resolved.service         loaded active running Network Name Resolution
    

然后,您可以将在 Compute Engine 实例中运行的服务添加到 Istio 服务网格中。

  1. 在 Cloud Shell 中,创建无选择器的 Kubernetes 服务,以提供在 Compute Engine 实例中运行的服务:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/selectorless-services.yaml
    
  2. 初始化以下环境变量,以存储示例工作负载运行所在 Compute Engine 实例的 IP 地址:

    GCE_INSTANCE_IP="$(gcloud compute instances describe "$GCE_INSTANCE_NAME" --format='value(networkInterfaces[].networkIP)')"
    
  3. 将这些服务注册到网格中:

    "$ISTIO_PATH"/bin/istioctl register details "$GCE_INSTANCE_IP" http:9082 -n "$SERVICE_NAMESPACE"
    "$ISTIO_PATH"/bin/istioctl register productpage "$GCE_INSTANCE_IP" http:9083 -n "$SERVICE_NAMESPACE"
    "$ISTIO_PATH"/bin/istioctl register ratings "$GCE_INSTANCE_IP" http:9081 -n "$SERVICE_NAMESPACE"
    "$ISTIO_PATH"/bin/istioctl register reviews "$GCE_INSTANCE_IP" http:9084 -n "$SERVICE_NAMESPACE"
    

最后,您需要为网络中正在 Compute Engine 实例上运行的服务配置 VirtualService 和相应路由规则。此外,您还需要通过 Istio Ingress Gateway 网关提供 productpage 服务。

  1. 在 Cloud Shell 中,部署 Gateway 对象以提供服务:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/gateway.yaml
    
  2. 部署 VirtualService,以将来自 Gateway 对象的流量路由到 Compute Engine 中运行的 productpage 实例:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/virtualservice-productpage-vm.yaml
    
  3. 创建 ServiceEntries,以便为 Compute Engine 实例中运行的服务启用服务发现功能:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/serviceentry.yaml
    
  4. 等待系统为名为 istio-ingressgateway 的服务对象分配一个外部 IP 地址:

    kubectl get svc istio-ingressgateway -n istio-system --watch
    

    在输出中,您应会看到 EXTERNAL-IP 的 IP 地址:

    NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)                                                                                                                   AGE
    istio-ingressgateway   LoadBalancer   10.48.2.195   34.73.84.179   80:31380/TCP,443:31390/TCP,31400:31400/TCP,15011:31145/TCP,8060:30381/TCP,853:30784/TCP,15030:32124/TCP,15031:32703/TCP   4d
    
  5. 确认名为 bookinfo-gateway 的 Gateway 对象已创建:

    kubectl get gateway --watch
    

    在输出中,您应会在 Gateway 对象列表中看到 bookinfo-gateway

    NAME               AGE
    bookinfo-gateway   3h
    

测试 Istio 网格扩展功能

使用 Istio 提供 Compute Engine 实例中运行的示例工作负载后,您可以进行测试:

  1. 在 Cloud Shell 中,找到 Istio Ingress Gateway 的外部 IP 地址:

    kubectl get svc istio-ingressgateway -n istio-system
    
  2. 打开浏览器并转到以下网址,其中 [EXTERNAL_IP] 是上一步中找到的 IP 地址:

    http://[EXTERNAL_IP]/productpage
    

    随即会显示一个页面,其中包含有关图书和相关评分的信息:

    图书和相关评分

直观呈现服务网格

在本部分中,您将使用 Kiali 直观呈现服务网格。

  1. 在 Cloud Shell 中,找到 Istio Ingress Gateway 的外部 IP 地址:

    kubectl get svc istio-ingressgateway -n istio-system
        EXTERNAL_IP="$(kubectl get svc istio-ingressgateway -n istio-system -o=jsonpath="{.status.loadBalancer.ingress[0].ip}")"
    
  2. 打开浏览器并转到以下网址,其中 [EXTERNAL_IP] 是上一步中找到的 IP 地址:

    http://[EXTERNAL_IP]:15029/kiali/console/graph/namespaces/?  edges=requestsPercentOfTotal&graphType=versionedApp&namespaces=default&injectServiceNodes=true&duration=60&pi=5000&layout=dagre
    
  3. 在 Kiali 登录屏幕上,使用以下凭据进行登录:

    • 用户名:admin
    • 密码:admin

    Kiali 登录屏幕

  4. 对示例工作负载的主页多次运行请求:

    for i in {1..10000}; do curl -s -o /dev/null -w "%{http_code}\n"  http://"$EXTERNAL_IP"/productpage; done
    

    此命令会生成发送至 Bookinfo 应用的流量。输出应列出每个请求的 HTTP 返回代码(本例中为 200 OK):

    200
    200
    200
    [...]
    

    在 Kiali 服务信息中心内,您应该会看到一个有关当前网格的图表,其中所有流量均路由到 Compute Engine 中运行的服务。所有流量均从 istio-ingressgateway 路由到 Kubernetes 服务 productpage.default.svc.cluster.local,并指向 Compute Engine 实例中运行的 productpage 微服务。该图表不会显示其他微服务(detailsreviewsratings),因为 Docker Compose 在 Compute Engine 实例本地处理路由。

    如果您看不到该图表,请刷新 Kiali 信息中心页面。

    当前网格示意图

迁移工作负载

在本部分中,您需要将示例工作负载的组件从 Compute Engine 实例迁移到 GKE 集群。对于示例工作负载的每项服务,您可以执行以下操作:

  1. 部署一个 Pod,以在 GKE 集群中运行该服务。
  2. 配置流量拆分规则,以将流量拆分到 GKE 集群中运行的服务与 Compute Engine 实例中运行的服务之间。
  3. 逐步将流量从 Compute Engine 实例中运行的服务迁移到 GKE 集群。
  4. 停止 Compute Engine 实例中运行的服务。

下图显示了本部分采用的目标系统架构:

用于迁移工作负载的架构

启用 Istio Sidecar 注入功能

每项服务都需要运行 Envoy Sidecar 代理才能加入 Istio 服务网格。您可以启用自动 Sidecar 注入功能,以避免手动修改 pod 配置。

  1. 在 Cloud Shell 中,按 Control+C 停止流量生成命令。

  2. 在将用于部署服务实例的 Kubernetes 命名空间中,启用 Istio 管理的自动 Sidecar 注入功能:

    kubectl label namespace "$SERVICE_NAMESPACE" istio-injection=enabled
    

在 GKE 集群中部署服务

在本部分中,您将在 GKE 集群中部署实例,并将部分流量路由到这些实例。

  1. 在 Cloud Shell 中,删除 ServiceEntries 以在网格中部署其他服务。删除这些条目可防止将请求路由到尚不可用的实例:

    kubectl delete -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/serviceentry.yaml
    
  2. 为集群中的 productpagedetailsreviewsratings 微服务部署 pod 和 Kubernetes 服务:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/productpage.yaml
    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/details.yaml
    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/ratings.yaml
    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/reviews.yaml
    
  3. 更新 VirtualService 配置,以将传入流量拆分到 Compute Engine 机器中运行的实例与 GKE 集群中运行的实例之间:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/virtualservice-productpage-split.yaml
    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/virtualservice-details-split.yaml
    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/virtualservice-ratings-split.yaml
    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/virtualservice-reviews-split.yaml
    
  4. 创建 ServiceEntries 以为 Compute Engine 实例中运行的服务启用服务发现功能:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/serviceentry.yaml
    

下一项任务是检查被引导至两个环境(即 Compute Engine 和 GKE)中的所有微服务实例的流量,以此验证您的混合部署。

您可以使用 Kiali 来直观呈现服务网格:

  1. 在 Cloud Shell 中,找到 Istio Ingress Gateway 的外部 IP 地址:

    kubectl get svc istio-ingressgateway -n istio-system
    EXTERNAL_IP="$(kubectl get svc istio-ingressgateway -n istio-system -o=jsonpath="{.status.loadBalancer.ingress[0].ip}")"
    
  2. 打开浏览器并转到以下网址,其中 [EXTERNAL_IP] 是上一步中找到的 IP 地址:

    http://[EXTERNAL_IP]:15029/kiali/console/graph/namespaces/?edges=requestsPercentOfTotal&graphType=versionedApp&namespaces=default&injectServiceNodes=true&duration=60&pi=5000&layout=dagre
    
  3. 在 Kiali 登录屏幕上,使用以下凭据进行登录(如果需要):

    • 用户名:admin
    • 密码:admin
  4. 对示例工作负载的主页多次运行请求:

    for i in {1..10000}; do curl -s -o /dev/null -w "%{http_code}\n"  http://"$EXTERNAL_IP"/productpage; done
    

    此命令会生成发送至 Bookinfo 应用的流量。输出应列出每个请求的 HTTP 返回代码(本例中为 200 OK):

    200
    200
    200
    [...]
    

    在 Kiali 服务信息中心内,您应会看到流量几乎是均匀拆分到 Compute Engine 中运行的微服务实例与 GKE 中运行的微服务实例(服务标识符的第一部分带有 -gke 后缀)之间。这是因为您已将 VirtualService 中的路由配置为具有相同权重。

    如果您看不到该图表,请刷新 Kiali 信息中心页面。

    显示流量拆分的信息中心

仅将流量路由到 GKE 集群

如果您对 GKE 集群中的部署充满信心,可以更新 Service 和 VirtualService 以仅将流量路由到该集群。

下图显示了本部分采用的目标系统架构:

仅将流量路由至 GKE 集群

  1. 在 Cloud Shell 中,按 Control+C 停止流量生成命令。

  2. 更新 Service 和 VirtualService 以将流量路由到 GKE 集群中的微服务实例:

    kubectl apply -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/virtualservice-gke.yaml
    

要验证部署,您可以检查被引导至两个环境(即 Compute Engine 和 GKE)中的所有微服务实例的流量。

您可以使用 Kiali 来直观呈现服务网格:

  1. 在 Cloud Shell 中,找到 Istio Ingress Gateway 的外部 IP 地址:

    kubectl get svc istio-ingressgateway -n istio-system
    EXTERNAL_IP="$(kubectl get svc istio-ingressgateway -n istio-system -o=jsonpath="{.status.loadBalancer.ingress[0].ip}")"
    
  2. 打开浏览器并转到以下网址,其中 [EXTERNAL_IP] 是上一步中找到的 IP 地址:

    http://[EXTERNAL_IP]:15029/kiali/console/graph/namespaces/?edges=requestsPercentOfTotal&graphType=versionedApp&namespaces=default&injectServiceNodes=true&duration=60&pi=5000&layout=dagre

  3. 在 Kiali 登录屏幕上,使用以下凭据进行登录(如果需要):

    • 用户名:admin
    • 密码:admin
  4. 对示例工作负载的主页多次运行请求:

    for i in {1..10000}; do curl -s -o /dev/null -w "%{http_code}\n"  http://"$EXTERNAL_IP"/productpage; done
    

    此命令会生成发送至 Bookinfo 应用的流量。输出应列出每个请求的 HTTP 返回代码(本例中为 200 OK):

    200
    200
    200
    [...]
    

    在 Kiali 服务信息中心内,您应会看到流量正被路由到 GKE 集群中运行的微服务实例(服务标识符的第一部分带有 -gke 后缀),而没有流量被路由到 Compute Engine 中运行的实例。如果您看不到该图表,请刷新 Kiali 信息中心页面。如果您为每项微服务部署了两个实例(一个在 Compute Engine 实例中运行,另一个在 GKE 集群中运行),那么您就是将 VirtualService 配置为仅将流量路由到 GKE 集群中运行的微服务实例。

    如果您看不到该图表,请刷新 Kiali 信息中心页面。

    仅路由到 GKE 集群中运行的实例的流量

停用旧版数据中心

由于所有流量均路由到 GKE 集群,因此您现在可以删除与 Compute Engine 中运行的微服务对应的 ServiceEntries 并停止 Docker Compose。

下图显示了本部分采用的目标系统架构:

用于停用旧版数据中心的架构

  1. 在 Cloud Shell 中,按 Control+C 停止流量生成命令。

  2. 删除 ServiceEntries 以在网格中部署其他服务:

    kubectl delete -f "$HOME"/solutions-istio-mesh-expansion-migration/kubernetes/bookinfo/istio/serviceentry.yaml
    
  3. 停止使用 Docker Compose 运行的示例工作负载:

    gcloud compute ssh "$GCE_INSTANCE_NAME" \
        --zone=us-east1-b \
        --command='sudo docker-compose -f /tmp/compose/bookinfo.yaml down --remove-orphans -v'
    

直观呈现扩展网格 - 仅在 GKE 中运行

在本部分中,您将检查被引导至两个环境(即 Compute Engine 和 GKE)中的所有微服务实例的流量,以此验证您的部署。

您可以使用 Kiali 来直观呈现服务网格:

  1. 在 Cloud Shell 中,找到 Istio Ingress Gateway 的外部 IP 地址:

    kubectl get svc istio-ingressgateway -n istio-system
    EXTERNAL_IP="$(kubectl get svc istio-ingressgateway -n istio-system -o=jsonpath="{.status.loadBalancer.ingress[0].ip}")"
    
  2. 打开浏览器并转到以下网址,其中 [EXTERNAL_IP] 是上一步中找到的 IP 地址:

    http://[EXTERNAL_IP]:15029/kiali/console/graph/namespaces/?edges=requestsPercentOfTotal&graphType=versionedApp&namespaces=default&injectServiceNodes=true&duration=60&pi=5000&layout=dagre
    
  3. 在 Kiali 登录屏幕上,使用以下凭据进行登录(如果需要):

    • 用户名:admin
    • 密码:admin
  4. 对示例工作负载的主页多次运行请求:

    for i in {1..10000}; do curl -s -o /dev/null -w "%{http_code}\n"  http://"$EXTERNAL_IP"/productpage; done
    

    此命令会生成发送至 Bookinfo 应用的流量。输出应列出每个请求的 HTTP 返回代码(本例中为 200 OK):

    200
    200
    200
    [...]
    

    在 Kiali 服务信息中心内,您应该只能看到指向 GKE 集群中运行的实例的服务(服务标识符的第一部分带有 -gke 后缀),而指向 Compute Engine 中运行的实例的服务不再属于网格,因为您已经删除了相关的 ServiceEntries。

    如果您看不到该图表,请刷新 Kiali 信息中心页面:

    直观呈现扩展网格

清理

为避免因本教程中使用的资源而导致系统向您的 Google Cloud Platform 帐号收取费用,请执行以下操作:

  1. 在 GCP Console 中,转到项目页面。

    转到“项目”页面

  2. 在项目列表中,选择您要删除的项目,然后点击删除 delete
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

后续步骤

此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页
解决方案