1. ALPHA WORKSHOP
工作坊 Codelab 的链接:bit.ly/asm-workshop
2. 概览
架构图

本研讨会是一次实践性沉浸式体验,将介绍如何在 GCP 上设置全球分布式生产服务。使用的主要技术包括用于计算的 Google Kubernetes Engine (GKE) 和用于创建安全连接、可观测性和高级流量整形功能的 Istio 服务网格。本研讨会中使用的所有实践和工具都是您在生产环境中会使用的。
内容安排
- 第 0 模块 - 简介和平台设置
- 简介和架构
- Service Mesh 和 Istio/ASM 简介
- 实验:基础架构设置:用户工作流
- 休息
- QnA
- 模块 1 - 使用 ASM 安装、保护和监控应用
- 代码库模型:基础设施代码库和 Kubernetes 代码库说明
- 实验:部署示例应用
- 分布式服务和可观测性
- 午餐
- 实验:使用 Stackdriver 实现可观测性
- QNA
- 模块 2 - DevOps - Canary 发布、政策/RBAC
- 多集群服务发现和安全性/政策
- 实验:双向 TLS
- Canary 部署
- 实验:Canary 部署
- 安全的多集群全球负载均衡
- 休息
- 实验:授权政策
- QNA
- 模块 3 - 基础设施运营 - 平台升级
- 分布式服务构建块
- 实验:基础架构扩缩
- 后续步骤
幻灯片
如需查看本次研讨会的幻灯片,请访问以下链接:
前提条件
在继续学习本研讨会之前,您需要满足以下要求:
- GCP 组织节点
- 结算账号 ID(您的用户必须是相应结算账号的结算管理员)
- 您的用户在组织级层具有组织管理员 IAM 角色
3. 基础架构设置 - 管理员工作流
引导研讨会脚本说明
一个名为 bootstrap_workshop.sh 的脚本用于设置研讨会的初始环境。如果您要将此研讨会作为培训提供给多位用户,可以使用此脚本为自己设置单个环境,也可以为多位用户设置多个环境。
引导研讨会脚本需要以下输入内容:
- 组织名称(例如
yourcompany.com)- 这是您在其中为研讨会创建环境的组织。 - 结算 ID(例如
12345-12345-12345)- 此结算 ID 用于结算研讨会期间使用的所有资源。 - 工作坊编号(例如
01)- 一个两位数。如果您要在一天内举办多场研讨会,并希望分别跟踪这些研讨会,则可以使用此功能。研讨会编号也用于派生项目 ID。使用单独的研讨会编号可确保您每次都能获得唯一的项目 ID。除了研讨会编号之外,项目 ID 还使用当前日期(格式为YYMMDD)。日期和研讨会编号的组合可提供唯一的项目 ID。 - 起始用户编号(例如
1)- 此编号表示工作坊中的第一个用户。例如,如果您想为 10 位用户创建研讨会,则起始用户编号可能为 1,结束用户编号可能为 10。 - 最终用户编号(例如
10)- 此编号表示研讨会中的最后一位用户。例如,如果您想为 10 位用户创建研讨会,则起始用户编号可能为 1,结束用户编号可能为 10。如果您要设置单个环境(例如,供自己使用),请将起始用户数和结束用户数设为相同的值。此操作将创建一个环境。
- 管理员 GCS 存储分区(例如
my-gcs-bucket-name)- GCS 存储分区用于存储与研讨会相关的信息。cleanup_workshop.sh 脚本会使用此信息来正常删除在引导研讨会脚本期间创建的所有资源。创建研讨会的管理员必须拥有此存储分区的读写权限。
引导研讨会脚本使用上述值,并充当调用 setup-terraform-admin-project.sh 脚本的封装脚本。setup-terraform-admin-project.sh 脚本会为单个用户创建研讨会环境。
引导启动研讨会所需的管理员权限
本研讨会中有两种类型的用户。一位 ADMIN_USER,负责为此研讨会创建和删除资源。第二种是 MY_USER,负责执行研讨会中的步骤。MY_USER 只能访问自己的资源。ADMIN_USER 有权访问所有用户设置。如果您是自行创建此设置,则 ADMIN_USER 和 MY_USER 相同。如果您是为多名学生创建此研讨会的教师,则您的 ADMIN_USER 和 MY_USER 将有所不同。
ADMIN_USER 需要以下组织级权限:
- Owner - 组织中所有项目的 Project Owner 权限。
- Folder Admin - 能够在组织中创建和删除文件夹。每位用户都会获得一个文件夹,其中包含项目中的所有资源。
- 组织管理员
- Project Creator - 能够在组织中创建项目。
- Project Deleter - 能够删除组织中的项目。
- Project IAM Admin - 能够在组织中的所有项目中创建 IAM 规则。
除了上述条件外,ADMIN_USER 还必须是研讨会所用结算 ID 的结算管理员。
执行研讨会的用户架构和权限
如果您打算为组织中的用户(您自己除外)创建此研讨会,则必须为 MY_USERs 遵循特定的用户命名方案。在 bootstrap_workshop.sh 脚本运行期间,您需要提供起始用户编号和结束用户编号。这些数字用于创建以下用户名:
user<3 digit user number>@<organization_name>
例如,如果您运行启动研讨会脚本,并将起始用户编号设为 1,结束用户编号设为 3,那么在名为 yourcompany.com 的组织中,系统会为以下用户创建研讨会环境:
user001@yourcompany.comuser002@yourcompany.comuser003@yourcompany.com
这些用户名在 setup_terraform_admin_project.sh 脚本运行期间创建的特定项目中被分配了项目所有者角色。使用引导脚本时,您必须遵守此用户命名架构。请参阅如何在 G Suite 中一次添加多位用户。
工作坊所需的工具
本研讨会旨在从 Cloud Shell 启动。本研讨会需要使用以下工具。
- gcloud(版本 >= 270)
- kubectl
- sed(适用于 Cloud Shell/Linux 上的 sed,但不适用于 Mac OS)
- git(确保您使用的是最新版本)
sudo apt updatesudo apt install git- jq
- envsubst
- kustomize
为自己设置工作坊(单用户设置)
- 打开 Cloud Shell,并在 Cloud Shell 中执行以下所有操作。点击下方链接。
- 验证您是否已使用目标管理员用户账号登录 gcloud。
gcloud config list
- 创建
WORKDIR并克隆研讨会代码库。
mkdir asm-workshop
cd asm-workshop
export WORKDIR=`pwd`
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git asm
- 定义您的组织名称、结算 ID、研讨会编号以及用于研讨会的管理员 GCS 存储分区。请查看上文各部分中有关设置研讨会所需的权限。
gcloud organizations list
export ORGANIZATION_NAME=<ORGANIZATION NAME>
gcloud beta billing accounts list
export ADMIN_BILLING_ID=<ADMIN_BILLING ID>
export WORKSHOP_NUMBER=<two digit number for example 01>
export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
- 运行 bootstrap_workshop.sh 脚本。此脚本可能需要几分钟才能完成。
cd asm
./scripts/bootstrap_workshop.sh --org-name ${ORGANIZATION_NAME} --billing-id ${ADMIN_BILLING_ID} --workshop-num ${WORKSHOP_NUMBER} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET} --set-up-for-admin
bootstrap_workshop.sh 脚本完成后,系统会为组织中的每位用户创建一个 GCP 文件夹。系统会在该文件夹中创建一个 Terraform 管理员项目。Terraform 管理员项目用于创建本研讨会所需的其余 GCP 资源。在 Terraform 管理项目中启用所需的 API。您可以使用 Cloud Build 应用 Terraform 方案。您需要为 Cloud Build 服务账号授予适当的 IAM 角色,以便其能够在 GCP 上创建资源。最后,您可以在 Google Cloud Storage (GCS) 存储分区中配置远程后端,以存储所有 GCP 资源的 Terraform 状态。
如需在 Terraform 管理员项目中查看 Cloud Build 任务,您需要 Terraform 管理员项目 ID。此变量存储在 asm 目录下的 vars/vars.sh 文件中。只有在您以管理员身份自行设置研讨会时,此目录才会保留。
- 获取变量文件以设置环境变量
echo "export WORKDIR=$WORKDIR" >> $WORKDIR/asm/vars/vars.sh
source $WORKDIR/asm/vars/vars.sh
为多位用户设置工作坊(多用户设置)
- 打开 Cloud Shell,并在 Cloud Shell 中执行以下所有操作。点击下方链接。
- 验证您是否已使用目标管理员用户账号登录 gcloud。
gcloud config list
- 创建
WORKDIR并克隆研讨会代码库。
mkdir asm-workshop
cd asm-workshop
export WORKDIR=`pwd`
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git asm
- 定义您的组织名称、结算 ID、研讨会编号、初始和最终用户数量,以及用于研讨会的管理员 GCS 存储分区。请查看上文各部分中有关设置研讨会所需的权限。
gcloud organizations list
export ORGANIZATION_NAME=<ORGANIZATION NAME>
gcloud beta billing accounts list
export ADMIN_BILLING_ID=<BILLING ID>
export WORKSHOP_NUMBER=<two digit number for example 01>
export START_USER_NUMBER=<number for example 1>
export END_USER_NUMBER=<number greater or equal to START_USER_NUM>
export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
- 运行 bootstrap_workshop.sh 脚本。此脚本可能需要几分钟才能完成。
cd asm
./scripts/bootstrap_workshop.sh --org-name ${ORGANIZATION_NAME} --billing-id ${ADMIN_BILLING_ID} --workshop-num ${WORKSHOP_NUMBER} --start-user-num ${START_USER_NUMBER} --end-user-num ${END_USER_NUMBER} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET}
- 从管理员 GCS 存储分区中获取 workshop.txt 文件,以检索 Terraform 项目 ID。
export WORKSHOP_ID="$(date '+%y%m%d')-${WORKSHOP_NUMBER}"
gsutil cp gs://${ADMIN_STORAGE_BUCKET}/${ORGANIZATION_NAME}/${WORKSHOP_ID}/workshop.txt .
4. 实验设置和准备工作
选择实验路线
本研讨会中的实验可通过以下两种方式之一来完成:
- “简易快速轨道互动式脚本”方式
- “手动复制并粘贴每条指令”的方式
借助快速通道脚本方法,您可以针对每个实验运行一个交互式脚本,该脚本会自动运行相应实验的命令,引导您完成实验。这些命令分批运行,并简要说明了每个步骤及其实现的功能。在每个批次完成后,系统会提示您继续执行下一批命令。这样,您就可以按照自己的节奏完成实验。快速通道脚本是幂等的,这意味着您可以多次运行这些脚本,但结果相同。
快速通道脚本将显示在每个实验的顶部,并以绿色框突出显示,如下所示。
复制粘贴方法是复制粘贴单个命令块(附带命令说明)的传统方法。此方法仅用于运行一次。无法保证重新运行此方法中的命令会得到相同的结果。
在完成实验时,请选择以下两种方法之一。
快速轨道脚本设置
获取用户信息
本研讨会使用由研讨会管理员创建的临时用户账号(或实验账号)进行。实验账号拥有研讨会中的所有项目。研讨会管理员会向参加研讨会的用户提供实验账号凭据(用户名和密码)。所有用户项目都以实验账号的用户名作为前缀,例如,对于实验账号 user001@yourcompany.com,Terraform 管理员项目 ID 为 user001-200131-01-tf-abcde,其余项目的 ID 也依此类推。每位用户都必须使用研讨会管理员提供的实验账号登录,并使用该账号完成研讨会。
- 点击以下链接打开 Cloud Shell。
- 使用实验账号凭据登录(请勿使用公司账号或个人账号登录)。实验账号类似于
userXYZ@<workshop_domain>.com。
- 由于这是新账号,系统会提示您接受 Google 服务条款。点击“接受”。
4. 在下一个界面中,选中复选框以同意 Google 服务条款,然后点击 Start Cloud Shell。

此步骤会为您预配一个小型 Linux Debian 虚拟机,供您用来访问 GCP 资源。每个账号都会获得一个 Cloud Shell 虚拟机。使用实验账号登录会使用实验账号凭据为您预配并登录。除了 Cloud Shell 之外,系统还会预配一个代码编辑器,以便您更轻松地修改配置文件(Terraform、YAML 等)。默认情况下,Cloud Shell 屏幕会分为 Cloud Shell shell 环境(位于底部)和 Cloud Code 编辑器(位于顶部)。
右上角的铅笔图标
和 shell 提示符图标
可让您在 shell 和代码编辑器之间切换。您还可以拖动中间的分隔栏(向上或向下),手动更改每个窗口的大小。5. 为此研讨会创建 WORKDIR。WORKDIR 是一个文件夹,您将在此文件夹中完成本研讨会的所有实验。在 Cloud Shell 中运行以下命令以创建 WORKDIR。
mkdir -p ${HOME}/asm-workshop
cd ${HOME}/asm-workshop
export WORKDIR=`pwd`
- 将实验账号用户导出为变量,以用于本次研讨会。这是您登录 Cloud Shell 时所用的账号。
export MY_USER=<LAB ACCOUNT EMAIL PROVIDED BY THE WORKSHOP ADMIN>
# For example export MY_USER=user001@gcpworkshops.com
- 运行以下命令,输出 WORKDIR 和 MY_USER 变量,以确保两者均已正确设置。
echo "WORKDIR set to ${WORKDIR}" && echo "MY_USER set to ${MY_USER}"
- 克隆研讨会代码库。
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git ${WORKDIR}/asm
5. 基础设施设置 - 用户工作流
目标:验证基础架构和 Istio 安装
- 安装工作坊工具
- 克隆研讨会代码库
- 验证
Infrastructure安装 - 验证
k8s-repo安装 - 验证 Istio 安装
复制和粘贴方法实验说明
获取用户信息
设置研讨会的管理员需要向用户提供用户名和密码信息。用户的所有项目都将以用户名作为前缀,例如,对于用户 user001@yourcompany.com,Terraform 管理员项目 ID 将为 user001-200131-01-tf-abcde,其余项目依此类推。每位用户只能访问自己的研讨会环境。
工作坊所需的工具
本研讨会旨在从 Cloud Shell 启动。本研讨会需要使用以下工具。
- gcloud(版本 >= 270)
- kubectl
- sed(适用于 Cloud Shell/Linux 上的 sed,但不适用于 Mac OS)
- git(确保您使用的是最新版本)
sudo apt updatesudo apt install git- jq
- envsubst
- kustomize
- pv
访问 Terraform 管理员项目
bootstrap_workshop.sh 脚本完成后,系统会为组织中的每位用户创建一个 GCP 文件夹。系统会在该文件夹中创建一个 Terraform 管理员项目。Terraform 管理员项目用于创建本研讨会所需的其余 GCP 资源。setup-terraform-admin-project.sh 脚本会在 Terraform 管理项目中启用所需的 API。Cloud Build 用于应用 Terraform 方案。通过该脚本,您可以为 Cloud Build 服务账号授予适当的 IAM 角色,以便其能够在 GCP 上创建资源。最后,在 Google Cloud Storage (GCS) 存储分区中配置远程后端,以存储所有 GCP 资源的 Terraform 状态。
如需在 Terraform 管理员项目中查看 Cloud Build 任务,您需要 Terraform 管理员项目 ID。此文件存储在引导脚本中指定的管理员 GCS 存储分区中。如果您为多个用户运行引导脚本,则所有 Terraform 管理员项目 ID 都会位于 GCS 存储分区中。
- 点击以下链接,打开 Cloud Shell(如果尚未在“实验设置和准备”部分中打开)。
- 在
$HOME/bin文件夹中安装 kustomize(如果尚未安装),并将$HOME/bin文件夹添加到 $PATH。
mkdir -p $HOME/bin
cd $HOME/bin
curl -s "https://raw.githubusercontent.com/\
kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
cd $HOME
export PATH=$PATH:${HOME}/bin
echo "export PATH=$PATH:$HOME/bin" >> $HOME/.bashrc
- 安装 pv 并将其移至 $HOME/bin/pv。
sudo apt-get update && sudo apt-get -y install pv
sudo mv /usr/bin/pv ${HOME}/bin/pv
- 更新您的 Bash 提示。
cp $WORKDIR/asm/scripts/krompt.bash $HOME/.krompt.bash
echo "export PATH=\$PATH:\$HOME/bin" >> $HOME/.asm-workshop.bash
echo "source $HOME/.krompt.bash" >> $HOME/.asm-workshop.bash
alias asm-init='source $HOME/.asm-workshop.bash' >> $HOME/.bashrc
echo "source $HOME/.asm-workshop.bash" >> $HOME/.bashrc
source $HOME/.bashrc
- 验证您是否已使用所需的用户账号登录 gcloud。
echo "Check logged in user output from the next command is $MY_USER"
gcloud config list account --format=json | jq -r .core.account
- 运行以下命令,获取您的 Terraform 管理员项目 ID:
export TF_ADMIN=$(gcloud projects list | grep tf- | awk '{ print $1 }')
echo $TF_ADMIN
- 与研讨会相关的所有资源都以变量的形式存储在 terraform 管理员项目中的 GCS 存储分区内存储的 vars.sh 文件中。获取 Terraform 管理员项目的 vars.sh 文件。
mkdir $WORKDIR/asm/vars
gsutil cp gs://$TF_ADMIN/vars/vars.sh $WORKDIR/asm/vars/vars.sh
echo "export WORKDIR=$WORKDIR" >> $WORKDIR/asm/vars/vars.sh
- 点击显示的链接,打开 Terraform 管理员项目的 Cloud Build 页面,并验证构建是否已成功完成。
source $WORKDIR/asm/vars/vars.sh
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_ADMIN}"
如果您是首次访问 Cloud 控制台,请同意 Google 服务条款。
- 现在,您正在查看 Cloud Build 页面,点击左侧导航栏中的
History链接,然后点击最新 build 以查看初始 Terraform 应用的详细信息。以下资源是作为 Terraform 脚本的一部分创建的。您还可以参考上方的架构图。
- 组织中的 4 个 GCP 项目。所提供的结算账号与每个项目相关联。
- 一个项目是共享 VPC 的
network host project。此项目中未创建其他资源。 - 一个项目是用于 Istio 控制平面 GKE 集群的
ops project。 - 这两个项目分别代表两个不同的开发团队,他们各自负责开发自己的服务。
- 在
ops、dev1和dev2这三个项目中,分别创建两个 GKE 集群。 - 系统会创建一个名为
k8s-repo的 CSR 代码库,其中包含六个用于存放 Kubernetes 清单文件的文件夹。每个 GKE 集群对应一个文件夹。此代码库用于以 GitOps 方式将 Kubernetes 清单部署到集群。 - 系统会创建一个 Cloud Build 构建触发器,以便在每次向
k8s-repo的 master 分支提交内容时,将 Kubernetes 清单从各自的文件夹部署到 GKE 集群。
- 构建在
terraform admin project中完成后,系统会在运营项目中启动另一个构建。点击显示的链接以打开ops project的 Cloud Build 页面,并验证 k8s-repo Cloud Build 是否已成功完成。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
验证安装
- 为所有集群创建 kubeconfig 文件。运行以下脚本:
$WORKDIR/asm/scripts/setup-gke-vars-kubeconfig.sh
此脚本会在 gke 文件夹中创建一个名为 kubemesh 的新 kubeconfig 文件。
- 更改
KUBECONFIG变量,使其指向新的 kubeconfig 文件。
source $WORKDIR/asm/vars/vars.sh
export KUBECONFIG=$WORKDIR/asm/gke/kubemesh
- 将 vars.sh 和 KUBECONFIG 变量添加到 Cloud Shell 中的 .bashrc,以便在每次重启 Cloud Shell 时都获取这些变量。
echo "source ${WORKDIR}/asm/vars/vars.sh" >> $HOME/.bashrc
echo "export KUBECONFIG=${WORKDIR}/asm/gke/kubemesh" >> $HOME/.bashrc
- 列出集群上下文。您应该会看到 6 个聚类。
kubectl config view -ojson | jq -r '.clusters[].name'
`Output (do not copy)`
gke_tf05-01-ops_us-central1_gke-asm-2-r2-prod gke_tf05-01-ops_us-west1_gke-asm-1-r1-prod gke_tf05-02-dev1_us-west1-a_gke-1-apps-r1a-prod gke_tf05-02-dev1_us-west1-b_gke-2-apps-r1b-prod gke_tf05-03-dev2_us-central1-a_gke-3-apps-r2a-prod gke_tf05-03-dev2_us-central1-b_gke-4-apps-r2b-prod
验证 Istio 安装
- 检查所有 pod 是否都在运行以及作业是否已完成,确保 Istio 已安装在两个集群上。
kubectl --context ${OPS_GKE_1} get pods -n istio-system
kubectl --context ${OPS_GKE_2} get pods -n istio-system
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE grafana-5f798469fd-z9f98 1/1 Running 0 6m21s istio-citadel-568747d88-qdw64 1/1 Running 0 6m26s istio-egressgateway-8f454cf58-ckw7n 1/1 Running 0 6m25s istio-galley-6b9495645d-m996v 2/2 Running 0 6m25s istio-ingressgateway-5df799fdbd-8nqhj 1/1 Running 0 2m57s istio-pilot-67fd786f65-nwmcb 2/2 Running 0 6m24s istio-policy-74cf89cb66-4wrpl 2/2 Running 1 6m25s istio-sidecar-injector-759bf6b4bc-mw4vf 1/1 Running 0 6m25s istio-telemetry-77b6dfb4ff-zqxzz 2/2 Running 1 6m24s istio-tracing-cd67ddf8-n4d7k 1/1 Running 0 6m25s istiocoredns-5f7546c6f4-g7b5c 2/2 Running 0 6m39s kiali-7964898d8c-5twln 1/1 Running 0 6m23s prometheus-586d4445c7-xhn8d 1/1 Running 0 6m25s
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE grafana-5f798469fd-2s8k4 1/1 Running 0 59m istio-citadel-568747d88-87kdj 1/1 Running 0 59m istio-egressgateway-8f454cf58-zj9fs 1/1 Running 0 60m istio-galley-6b9495645d-qfdr6 2/2 Running 0 59m istio-ingressgateway-5df799fdbd-2c9rc 1/1 Running 0 60m istio-pilot-67fd786f65-nzhx4 2/2 Running 0 59m istio-policy-74cf89cb66-4bc7f 2/2 Running 3 59m istio-sidecar-injector-759bf6b4bc-grk24 1/1 Running 0 59m istio-telemetry-77b6dfb4ff-6zr94 2/2 Running 4 60m istio-tracing-cd67ddf8-grs9g 1/1 Running 0 60m istiocoredns-5f7546c6f4-gxd66 2/2 Running 0 60m kiali-7964898d8c-nhn52 1/1 Running 0 59m prometheus-586d4445c7-xr44v 1/1 Running 0 59m
- 确保在两个
dev1集群上都安装了 Istio。只有 Citadel、sidecar-injector 和 coredns 在dev1集群中运行。它们共享在 ops-1 集群中运行的 Istio 控制平面。
kubectl --context ${DEV1_GKE_1} get pods -n istio-system
kubectl --context ${DEV1_GKE_2} get pods -n istio-system
- 确保在两个
dev2集群上都安装了 Istio。只有 Citadel、sidecar-injector 和 coredns 在dev2集群中运行。它们共享在 ops-2 集群中运行的 Istio 控制层面。
kubectl --context ${DEV2_GKE_1} get pods -n istio-system
kubectl --context ${DEV2_GKE_2} get pods -n istio-system
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE istio-citadel-568747d88-4lj9b 1/1 Running 0 66s istio-sidecar-injector-759bf6b4bc-ks5br 1/1 Running 0 66s istiocoredns-5f7546c6f4-qbsqm 2/2 Running 0 78s
验证共享控制平面的服务发现
- (可选)验证 Secret 是否已部署。
kubectl --context ${OPS_GKE_1} get secrets -l istio/multiCluster=true -n istio-system
kubectl --context ${OPS_GKE_2} get secrets -l istio/multiCluster=true -n istio-system
`Output (do not copy)`
For OPS_GKE_1: NAME TYPE DATA AGE gke-1-apps-r1a-prod Opaque 1 8m7s gke-2-apps-r1b-prod Opaque 1 8m7s gke-3-apps-r2a-prod Opaque 1 44s gke-4-apps-r2b-prod Opaque 1 43s For OPS_GKE_2: NAME TYPE DATA AGE gke-1-apps-r1a-prod Opaque 1 40s gke-2-apps-r1b-prod Opaque 1 40s gke-3-apps-r2a-prod Opaque 1 8m4s gke-4-apps-r2b-prod Opaque 1 8m4s
在此研讨会中,您将使用单个共享 VPC,所有 GKE 集群都将在其中创建。如需跨集群发现服务,您可以使用在运维集群中创建为 Secret 的 kubeconfig 文件(适用于每个应用集群)。Pilot 通过查询应用集群的 Kube API 服务器(通过上述 Secret 进行身份验证)来发现服务。您会看到,两个运维集群都可以使用 kubeconfig 创建的 Secret 向所有应用集群进行身份验证。运维集群可以使用 kubeconfig 文件作为一种隐秘方法来自动发现服务。这要求运维集群中的 Pilot 能够访问所有其他集群的 Kube API 服务器。如果 Pilot 无法访问 Kube API 服务器,您需要手动添加远程服务作为 ServiceEntries。您可以将 ServiceEntry 视为服务注册表中的 DNS 条目。ServiceEntry 使用完全限定 DNS 名称 ( FQDN) 和可访问的 IP 地址来定义服务。如需了解详情,请参阅 Istio 多集群文档。
6. 基础架构代码库说明
基础架构 Cloud Build
研讨会的 GCP 资源是使用 Cloud Build 和 infrastructure CSR 代码库构建的。您刚刚从本地终端运行了一个引导脚本(位于 scripts/bootstrap_workshop.sh)。引导脚本会为 Cloud Build 服务账号创建 GCP 文件夹、Terraform 管理员项目和相应的 IAM 权限。Terraform 管理项目用于存储 Terraform 状态、日志和其他脚本。它包含 infrastructure 和 k8s_repo CSR 代码库。下一部分将详细介绍这些 repo。在 Terraform 管理员项目中,没有构建其他研讨会资源。Terraform 管理员项目中的 Cloud Build 服务账号用于构建研讨会的资源。
位于 infrastructure 文件夹中的 cloudbuild.yaml 文件用于构建研讨会的 GCP 资源。它会创建一个自定义构建器映像,其中包含创建 GCP 资源所需的所有工具。这些工具包括 gcloud SDK、Terraform 和其他实用程序,例如 Python、Git、jq 等。自定义构建器映像会针对每个资源运行 terraform plan 和 apply。每个资源的 Terraform 文件都位于单独的文件夹中(详细信息请参阅下一部分)。资源会按通常的构建顺序(例如,先构建 GCP 项目,然后再在该项目中创建资源)一次构建一个。如需了解详情,请参阅 cloudbuild.yaml 文件。
只要 infrastructure 代码库中有提交,Cloud Build 就会被触发。对基础架构所做的任何更改都会以基础设施即代码 (IaC) 的形式存储并提交到代码库。您的研讨会的最新状态始终存储在此代码库中。
文件夹结构 - 团队、环境和资源
基础架构代码库用于为研讨会设置 GCP 基础架构资源。它以文件夹和子文件夹的形式进行结构化。代码库中的基本文件夹表示拥有特定 GCP 资源的 team。下一层文件夹表示团队的特定 environment(例如开发、暂存、生产)。环境中的下一层文件夹表示特定的 resource(例如 host_project、gke_clusters 等)。所需的脚本和 Terraform 文件位于资源文件夹中。

本次工作坊中介绍了以下四种类型的团队:
- infrastructure - 表示云基础架构团队。他们负责为所有其他团队创建 GCP 资源。他们使用 Terraform 管理员项目来管理资源。基础设施代码库本身位于 Terraform 管理员项目中,Terraform 状态文件(如下所述)也是如此。这些资源是在引导过程中由 Bash 脚本创建的(有关详情,请参阅模块 0 - 管理员工作流)。
- network - 表示网络团队。他们负责 VPC 和网络资源。他们拥有以下 GCP 资源。
host project- 表示共享 VPC 宿主项目。shared VPC- 表示共享 VPC、子网、次要 IP 地址范围、路由和防火墙规则。- ops - 表示运营/DevOps 团队。他们拥有以下资源。
ops project- 表示所有操作资源的相应项目。gke clusters- 每个区域一个运维 GKE 集群。Istio 控制平面安装在每个运维 GKE 集群中。k8s-repo- 包含所有 GKE 集群的 GKE 清单的 CSR 代码库。- 应用 - 表示应用团队。本讲座将模拟两个团队,即
app1和app2。他们拥有以下资源。 app projects- 每个应用团队都拥有自己的项目集。这样,他们就可以控制特定项目的结算和 IAM。gke clusters- 这些是应用容器/Pod 运行的应用集群。gce instances- 可选,如果他们有在 GCE 实例上运行的应用。在此研讨会中,app1 有几个 GCE 实例,其中运行着部分应用。
在此研讨会中,同一应用(Hipster Shop 应用)同时代表 app1 和 app2。
提供程序、状态和输出 - 后端和共享状态
google 和 google-beta 提供方位于 gcp/[environment]/gcp/provider.tf。provider.tf 文件在每个资源文件夹中都是symlinked。这样一来,您只需在一个位置更改提供商,而无需为每个资源单独管理提供商。
每个资源都包含一个 backend.tf 文件,用于定义资源 tfstate 文件的位置。此 backend.tf 文件是使用脚本(位于 scripts/setup_terraform_admin_project)从模板(位于 templates/backend.tf_tmpl)生成的,然后放置在相应的资源文件夹中。Google Cloud Storage (GCS) 存储分区用于后端。GCS 存储分区文件夹名称与资源名称一致。所有资源后端都位于 Terraform 管理员项目中。
具有相互依赖的值的资源包含 output.tf 文件。所需的输出值存储在后端中为相应特定资源定义的 tfstate 文件中。例如,如需在项目中创建 GKE 集群,您需要知道项目 ID。项目 ID 通过 output.tf 输出到 tfstate 文件,该文件可通过 GKE 集群资源中的 terraform_remote_state 数据源使用。
shared_state 文件是指向资源 tfstate 文件的 terraform_remote_state 数据源。资源文件夹中存在需要其他资源输出的 shared_state_[resource_name].tf 文件。例如,在 ops_gke 资源文件夹中,有来自 ops_project 和 shared_vpc 资源的 shared_state 文件,因为您需要在 ops 项目中创建 GKE 集群,所以需要项目 ID 和 VPC 详细信息。shared_state 文件是使用脚本(位于 scripts/setup_terraform_admin_project)从模板(位于 templates/shared_state.tf_tmpl)生成的。所有资源的 shared_state 文件都放置在 gcp/[environment]/shared_states 文件夹中。所需的 shared_state 文件已在相应的资源文件夹中进行符号链接。将所有 shared_state 文件放在一个文件夹中,并将其符号链接到相应的资源文件夹中,这样可以轻松在一个位置管理所有状态文件。
变量
所有资源值都存储为环境变量。这些变量以导出语句的形式存储在名为 vars.sh 的文件中,该文件位于 Terraform 管理员项目中的 GCS 存储分区中。其中包含组织 ID、结算账号、项目 ID、GKE 集群详细信息等。您可以从任何终端下载并获取 vars.sh,以获取设置所需的值。
Terraform 变量以 TF_VAR_[variable name] 形式存储在 vars.sh 中。这些变量用于在相应的资源文件夹中生成 variables.tfvars 文件。variables.tfvars 文件包含所有变量及其值。variables.tfvars 文件是使用脚本(位于 scripts/setup_terraform_admin_project)从同一文件夹中的模板文件生成的。
K8s 代码库说明
k8s_repo 是位于 Terraform 管理员项目中的 CSR 代码库(与基础架构代码库分开)。它用于存储 GKE 清单并将其应用于所有 GKE 集群。k8s_repo 由基础架构 Cloud Build 创建(如需了解详情,请参阅上一部分)。在初始基础架构 Cloud Build 构建流程中,系统会创建总共六个 GKE 集群。在 k8s_repo 中,创建了 6 个文件夹。每个文件夹(名称与 GKE 集群名称一致)都对应于一个 GKE 集群,其中包含各自的资源清单文件。与构建基础架构类似,Cloud Build 用于使用 k8s_repo 将 Kubernetes 清单应用于所有 GKE 集群。只要向 k8s_repo 代码库提交内容,就会触发 Cloud Build。与基础架构类似,所有 Kubernetes 清单都以代码形式存储在 k8s_repo 代码库中,并且每个 GKE 集群的状态始终存储在其各自的文件夹中。
在初始基础设施构建过程中,系统会创建 k8s_repo,并在所有集群上安装 Istio。
项目、GKE 集群和命名空间
本研讨会中的资源分为不同的 GCP 项目。项目应与贵公司的组织(或团队)结构相符。负责不同项目/产品/资源的团队(在您的组织中)使用不同的 GCP 项目。通过使用单独的项目,您可以创建单独的 IAM 权限集,并在项目级管理结算。此外,配额还可以在项目级进行管理。
本次研讨会共有 5 个团队参加,每个团队都有自己的项目。
- 构建 GCP 资源的基础设施团队使用
Terraform admin project。他们以代码形式在 CSR 代码库(称为infrastructure)中管理基础架构,并将与在 GCP 中构建的资源相关的所有 Terraform 状态信息存储在 GCS 存储分区中。它们控制对 CSR 代码库和 Terraform 状态 GCS 存储分区的访问权限。 - 构建共享 VPC 的网络团队使用
host project。此项目包含 VPC、子网、路由和防火墙规则。借助共享 VPC,他们可以集中管理 GCP 资源的网络。所有项目都使用这一个共享 VPC 进行联网。 - 构建 GKE 集群和 ASM/Istio 控制平面的 ops/平台团队使用
ops project。它们管理 GKE 集群和服务网格的生命周期。他们负责对集群进行安全加固,管理 Kubernetes 平台的弹性和规模。在此研讨会中,您将使用 GitOps 方法将资源部署到 Kubernetes。运营项目中存在 CSR 代码库(称为k8s_repo)。 - 最后,构建应用的 dev1 和 dev2 团队(代表两个开发团队)使用各自的
dev1和dev2 projects。这些是您向客户提供的应用和服务。这些功能基于运营团队管理的平台构建。资源(部署、服务等)会被推送到k8s_repo,并部署到相应的集群。请务必注意,本研讨会不侧重于 CI/CD 最佳实践和工具。您可以使用 Cloud Build 自动将 Kubernetes 资源直接部署到 GKE 集群。在实际生产场景中,您可以使用合适的 CI/CD 解决方案将应用部署到 GKE 集群。
在此研讨会中,GKE 集群分为两种类型。
- 运维集群 - 由运维团队用于运行 DevOps 工具。在此研讨会中,它们运行 ASM/Istio 控制平面来管理服务网格。
- 应用集群 - 由开发团队用于运行应用。在此研讨会中,我们将使用 Hipster Shop 应用。
将运维/管理工具与运行应用的集群分离,可让您独立管理每个资源的生命周期。这两种类型的集群还存在于与使用它们的团队/产品相关的不同项目中,这使得 IAM 权限也更易于管理。
共有 6 个 GKE 集群。在运维项目中创建了两个区域级运维集群。ASM/Istio 控制平面已安装在两个运维集群上。每个运营集群都位于不同的区域。此外,还有 4 个可用区级应用集群。这些资源是在其自己的项目中创建的。本讲座将模拟两个开发团队,每个团队都有自己的项目。每个项目都包含两个应用集群。应用集群是位于不同可用区的可用区集群。这四个应用集群位于两个区域和四个可用区中。这样,您就可以获得区域级和可用区级冗余。
本讲座中使用的应用 Hipster Shop 应用已部署在所有四个应用集群上。每个微服务都位于每个应用集群中自己的命名空间内。Hipster Shop 应用部署(Pod)未部署在运维集群上。不过,所有微服务的命名空间和服务资源也会在运维集群中创建。ASM/Istio 控制平面使用 Kubernetes 服务注册表进行服务发现。如果运维集群中没有服务,您就必须为应用集群中运行的每项服务手动创建 ServiceEntry。
在本研讨会中,您将部署一个 10 层微服务应用。该应用是一款名为“Hipster Shop”的基于网络的电子商务应用,用户可以在其中浏览商品、将商品添加到购物车以及购买商品。
Kubernetes 清单和 k8s_repo
您可以使用 k8s_repo 将 Kubernetes 资源添加到所有 GKE 集群。为此,您可以复制 Kubernetes 清单并提交到 k8s_repo。对 k8s_repo 的所有提交都会触发 Cloud Build 作业,该作业会将 Kubernetes 清单部署到相应集群。每个集群的清单都位于一个单独的文件夹中,该文件夹的名称与集群名称相同。
这六个集群名称分别是:
- gke-asm-1-r1-prod - 区域 1 中的区域性运维集群
- gke-asm-2-r2-prod - 区域 2 中的区域性运维集群
- gke-1-apps-r1a-prod - 区域 1 地区 a 中的应用集群
- gke-2-apps-r1b-prod - 区域 1 可用区 b 中的应用集群
- gke-3-apps-r2a-prod - 区域 2 可用区 a 中的应用集群
- gke-4-apps-r2b-prod - 区域 2 可用区 b 中的应用集群
k8s_repo 具有与这些集群对应的文件夹。放置在这些文件夹中的任何清单都会应用于相应的 GKE 集群。每个集群的清单都放置在子文件夹(位于集群的主文件夹内)中,以便于管理。在此研讨会中,您将使用 Kustomize 来跟踪已部署的资源。如需了解详情,请参阅 Kustomize 官方文档。
7. 部署示例应用
目标:在应用集群上部署 Hipster Shop 应用
k8s-repo克隆- 将 Hipster Shop 清单复制到所有应用集群
- 在运维集群中为 Hipster Shop 应用创建服务
- 在运维集群中设置
loadgenerators以测试全局连接 - 验证与 Hipster Shop 应用的安全连接
复制和粘贴方法实验说明
克隆运营项目源代码库
在初始 Terraform 基础架构构建过程中,k8s-repo 已在运维项目中创建。
- 为 Git 代码库创建一个空目录:
mkdir $WORKDIR/k8s-repo
- 初始化 Git 代码库,添加远程代码库并从远程代码库拉取 master:
cd $WORKDIR/k8s-repo
git init && git remote add origin \
https://source.developers.google.com/p/$TF_VAR_ops_project_name/r/k8s-repo
- 设置本地 Git 本地配置。
git config --local user.email $MY_USER
git config --local user.name "K8s repo user"
git config --local \
credential.'https://source.developers.google.com'.helper gcloud.sh
git pull origin master
复制清单、提交并推送
- 将 Hipster Shop 命名空间和服务复制到所有集群的源代码库。
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/namespaces \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app/services \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/.
- 将应用文件夹 kustomization.yaml 复制到所有集群。
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/
cp $WORKDIR/asm/k8s_manifests/prod/app/kustomization.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/
- 将 Hipster Shop 部署、RBAC 和 PodSecurityPolicy 复制到应用集群的源代码库。
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/deployments \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/rbac \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/
cp -r $WORKDIR/asm/k8s_manifests/prod/app/podsecuritypolicies \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/
- 从一个开发集群以外的所有开发集群中移除 cartservice 部署、rbac 和 podsecuritypolicy。Hipstershop 不是为多集群部署而构建的,因此为避免结果不一致,我们仅使用一个 cartservice。
rm $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/deployments/app-cart-service.yaml
rm $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/podsecuritypolicies/cart-psp.yaml
rm $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/app/rbac/cart-rbac.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/deployments/app-cart-service.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/podsecuritypolicies/cart-psp.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app/rbac/cart-rbac.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/deployments/app-cart-service.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/podsecuritypolicies/cart-psp.yaml
rm $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/app/rbac/cart-rbac.yaml
- 仅在第一个开发集群中,向 kustomization.yaml 添加 cartservice 部署、rbac 和 podsecuritypolicy。
cd ${WORKDIR}/k8s-repo/${DEV1_GKE_1_CLUSTER}/app
cd deployments && kustomize edit add resource app-cart-service.yaml
cd ../podsecuritypolicies && kustomize edit add resource cart-psp.yaml
cd ../rbac && kustomize edit add resource cart-rbac.yaml
cd ${WORKDIR}/asm
- 从 ops 集群 kustomization.yaml 中移除了 podsecuritypolicies、部署和 rbac 目录
sed -i -e '/- deployments\//d' -e '/- podsecuritypolicies\//d' \
-e '/- rbac\//d' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app/kustomization.yaml
sed -i -e '/- deployments\//d' -e '/- podsecuritypolicies\//d' \
-e '/- rbac\//d' \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app/kustomization.yaml
- 替换 RBAC 清单中的 PROJECT_ID。
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev1_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV1_GKE_1_CLUSTER}/app/rbac/*
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev1_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV1_GKE_2_CLUSTER}/app/rbac/*
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev2_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV2_GKE_1_CLUSTER}/app/rbac/*
sed -i 's/\${PROJECT_ID}/'${TF_VAR_dev2_project_name}'/g' \
${WORKDIR}/k8s-repo/${DEV2_GKE_2_CLUSTER}/app/rbac/*
- 将 IngressGateway 和 VirtualService 清单复制到运维集群的源代码库。
cp -r $WORKDIR/asm/k8s_manifests/prod/app-ingress/* \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-ingress/
cp -r $WORKDIR/asm/k8s_manifests/prod/app-ingress/* \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-ingress/
- 将 Config Connector 资源复制到每个项目中的一个集群。
cp -r $WORKDIR/asm/k8s_manifests/prod/app-cnrm/* \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-cnrm/
cp -r $WORKDIR/asm/k8s_manifests/prod/app-cnrm/* \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app-cnrm/
cp -r $WORKDIR/asm/k8s_manifests/prod/app-cnrm/* \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app-cnrm/
- 替换 Config Connector 清单中的 PROJECT_ID。
sed -i 's/${PROJECT_ID}/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-cnrm/*
sed -i 's/${PROJECT_ID}/'$TF_VAR_dev1_project_name'/g' \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/app-cnrm/*
sed -i 's/${PROJECT_ID}/'$TF_VAR_dev2_project_name'/g' \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/app-cnrm/*
- 将
loadgenerator清单(Deployment、PodSecurityPolicy 和 RBAC)复制到运维集群。Hipster Shop 应用通过全球 Google Cloud 负载平衡器 (GCLB) 公开。GCLB 接收客户端流量(目标为frontend),并将其发送到距离最近的服务实例。在两个运维集群上放置loadgenerator将确保流量发送到在运维集群中运行的两个 Istio Ingress 网关。下一部分将详细介绍负载均衡。
cp -r $WORKDIR/asm/k8s_manifests/prod/app-loadgenerator/. \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/.
cp -r $WORKDIR/asm/k8s_manifests/prod/app-loadgenerator/. \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/.
- 替换两个运维集群的
loadgenerator清单中的运维项目 ID。
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/loadgenerator-deployment.yaml
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/loadgenerator-rbac.yaml
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/loadgenerator-deployment.yaml
sed -i 's/OPS_PROJECT_ID/'$TF_VAR_ops_project_name'/g' \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/loadgenerator-rbac.yaml
- 将
loadgenerator资源添加到两个运维集群的 kustomization.yaml 中。
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-loadgenerator/
kustomize edit add resource loadgenerator-psp.yaml
kustomize edit add resource loadgenerator-rbac.yaml
kustomize edit add resource loadgenerator-deployment.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-loadgenerator/
kustomize edit add resource loadgenerator-psp.yaml
kustomize edit add resource loadgenerator-rbac.yaml
kustomize edit add resource loadgenerator-deployment.yaml
- 提交到
k8s-repo。
cd $WORKDIR/k8s-repo
git add . && git commit -am "create app namespaces and install hipster shop"
git push --set-upstream origin master
- 在之前打开的标签页中或通过点击以下链接查看运营项目 Cloud Build 的状态:
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
验证应用部署
- 验证除购物车之外的所有应用命名空间中的 pod 在所有开发集群中是否都处于“正在运行”状态。
for ns in ad checkout currency email frontend payment product-catalog recommendation shipping; do
kubectl --context $DEV1_GKE_1 get pods -n $ns;
kubectl --context $DEV1_GKE_2 get pods -n $ns;
kubectl --context $DEV2_GKE_1 get pods -n $ns;
kubectl --context $DEV2_GKE_2 get pods -n $ns;
done;
Output (do not copy)
NAME READY STATUS RESTARTS AGE currencyservice-5c5b8876db-pvc6s 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE currencyservice-5c5b8876db-xlkl9 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE currencyservice-5c5b8876db-zdjkg 2/2 Running 0 115s NAME READY STATUS RESTARTS AGE currencyservice-5c5b8876db-l748q 2/2 Running 0 82s NAME READY STATUS RESTARTS AGE emailservice-588467b8c8-gk92n 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE emailservice-588467b8c8-rvzk9 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE emailservice-588467b8c8-mt925 2/2 Running 0 117s NAME READY STATUS RESTARTS AGE emailservice-588467b8c8-klqn7 2/2 Running 0 84s NAME READY STATUS RESTARTS AGE frontend-64b94cf46f-kkq7d 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE frontend-64b94cf46f-lwskf 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE frontend-64b94cf46f-zz7xs 2/2 Running 0 118s NAME READY STATUS RESTARTS AGE frontend-64b94cf46f-2vtw5 2/2 Running 0 85s NAME READY STATUS RESTARTS AGE paymentservice-777f6c74f8-df8ml 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE paymentservice-777f6c74f8-bdcvg 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE paymentservice-777f6c74f8-jqf28 2/2 Running 0 117s NAME READY STATUS RESTARTS AGE paymentservice-777f6c74f8-95x2m 2/2 Running 0 86s NAME READY STATUS RESTARTS AGE productcatalogservice-786dc84f84-q5g9p 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE productcatalogservice-786dc84f84-n6lp8 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE productcatalogservice-786dc84f84-gf9xl 2/2 Running 0 119s NAME READY STATUS RESTARTS AGE productcatalogservice-786dc84f84-v7cbr 2/2 Running 0 86s NAME READY STATUS RESTARTS AGE recommendationservice-5fdf959f6b-2ltrk 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE recommendationservice-5fdf959f6b-dqd55 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE recommendationservice-5fdf959f6b-jghcl 2/2 Running 0 119s NAME READY STATUS RESTARTS AGE recommendationservice-5fdf959f6b-kkspz 2/2 Running 0 87s NAME READY STATUS RESTARTS AGE shippingservice-7bd5f569d-qqd9n 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE shippingservice-7bd5f569d-xczg5 2/2 Running 0 13m NAME READY STATUS RESTARTS AGE shippingservice-7bd5f569d-wfgfr 2/2 Running 0 2m NAME READY STATUS RESTARTS AGE shippingservice-7bd5f569d-r6t8v 2/2 Running 0 88s
- 验证第一个开发集群中购物车命名空间中的 pod 是否处于“正在运行”状态。
kubectl --context $DEV1_GKE_1 get pods -n cart;
Output (do not copy)
NAME READY STATUS RESTARTS AGE cartservice-659c9749b4-vqnrd 2/2 Running 0 17m
访问 Hipster Shop 应用
全球负载平衡
现在,您已将 Hipster Shop 应用部署到所有四个应用集群。这些集群位于两个区域和四个可用区。客户端可以通过访问 frontend 服务来访问 Hipster Shop 应用。frontend 服务在所有四个应用集群上运行。Google Cloud 负载平衡器 ( GCLB) 用于将客户端流量路由到 frontend 服务的所有四个实例。
Istio Ingress 网关仅在运维集群中运行,并充当区域级负载平衡器,以均衡区域内的两个可用区级应用集群。GCLB 使用两个 Istio Ingress 网关(在两个运维集群中运行)作为全局前端服务的后端。Istio 入站网关从 GCLB 接收客户端流量,然后将客户端流量转发到应用集群中运行的前端 Pod。

或者,您也可以直接将 Istio 入口网关放在应用集群上,然后让 GCLB 将这些网关用作后端。
GKE Autoneg 控制器
Istio 入站流量网关 Kubernetes 服务使用网络端点组 (NEG) 将自身注册为 GCLB 的后端。NEG 支持使用 GCLB 进行容器原生负载均衡。NEG 是通过 Kubernetes 服务的特殊注释创建的,因此它可以向 NEG 控制器注册自身。Autoneg 控制器是一种特殊的 GKE 控制器,可自动创建 NEG,并使用服务注解将其分配为 GCLB 的后端。在初始基础设施 Terraform Cloud Build 期间,会部署 Istio 控制平面(包括 Istio 入口网关)。GCLB 和自动协商配置是在初始 Terraform 基础架构 Cloud Build 中完成的。
使用 Cloud Endpoints 和受管理的证书保护 Ingress
GCP 托管式证书用于保护客户端与 frontend GCLB 服务之间的流量。GCLB 使用受管理的证书来处理全球 frontend 服务,并且证书在 GCLB 处终止。在此研讨会中,您将使用 Cloud Endpoints 作为受管证书的网域。或者,您也可以使用自己的网域和 frontend 的 DNS 名称来创建 GCP 管理的证书。
- 如需访问 Hipster 商店,请点击以下命令的链接输出。
echo "https://frontend.endpoints.$TF_VAR_ops_project_name.cloud.goog"
- 您可以点击 Chrome 标签页网址栏中的锁形符号,检查证书是否有效。

验证全球负载均衡
在应用部署过程中,我们在两个运维集群中都部署了负载生成器,用于向 GCLB Hipster 商店 Cloud Endpoints 链接生成测试流量。验证 GCLB 是否在接收流量并将其发送到两个 Istio 入口网关。
- 获取创建了 Hipster 商店 GCLB 的运维项目的 GCLB > Monitoring 链接。
echo "https://console.cloud.google.com/net-services/loadbalancing/details/http/istio-ingressgateway?project=$TF_VAR_ops_project_name&cloudshell=false&tab=monitoring&duration=PT1H"
- 从“后端”下拉菜单中将 All backends 更改为 istio-ingressgateway,如下所示。

- 请注意,流量会同时流向
istio-ingressgateways。

每个 istio-ingressgateway 都会创建三个 NEG。由于运维集群是区域级集群,因此系统会为该区域中的每个可用区创建一个 NEG。不过,istio-ingressgateway Pod 在每个区域中仅在一个可用区内运行。流量显示为流向 istio-ingressgateway Pod。
负载生成器在两个运维集群中运行,模拟来自这两个区域的客户端流量。在运营集群区域 1 中生成的负载正在发送到区域 2 中的 istio-ingressgateway。同样,在操作集群区域 2 中生成的负载正在发送到区域 2 中的 istio-ingressgateway。
8. 使用 Stackdriver 实现可观测性
目标:将 Istio 遥测数据连接到 Stackdriver 并进行验证。
- 安装
istio-telemetry资源 - 创建/更新 Istio 服务信息中心
- 查看容器日志
- 在 Stackdriver 中查看分布式跟踪
复制和粘贴方法实验说明
Istio 的主要功能之一是内置的可观测性(简称“o11y”)。这意味着,即使是黑盒、未插桩的容器,运营商仍然可以观察进出这些容器的流量,从而为客户提供服务。这种观测采用几种不同的方法:指标、日志和轨迹。
我们还将利用 Hipster Shop 中的内置负载生成系统。可观测性在没有流量的静态系统中效果不佳,因此负载生成有助于我们了解其运作方式。此负载已在运行,现在我们只需查看即可。
- 安装 istio 到 Stackdriver 的配置文件。
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/istio-telemetry
kustomize edit add resource istio-telemetry.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/istio-telemetry
kustomize edit add resource istio-telemetry.yaml
- 提交到 k8s-repo。
cd $WORKDIR/k8s-repo
git add . && git commit -am "Install istio to stackdriver configuration"
git push
- 在之前打开的标签页中或通过点击以下链接查看运营项目 Cloud Build 的状态:
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
- 验证 Istio → Stackdriver 集成获取 Stackdriver 处理程序 CRD。
kubectl --context $OPS_GKE_1 get handler -n istio-system
输出应显示名为 stackdriver 的处理程序:
NAME AGE kubernetesenv 12d prometheus 12d stackdriver 69s # <== NEW!
- 验证 Istio 指标导出到 Stackdriver 是否正常运行。点击此命令输出的链接:
echo "https://console.cloud.google.com/monitoring/metrics-explorer?cloudshell=false&project=$TF_VAR_ops_project_name"
系统会提示您创建一个以运维项目命名的工作区,只需选择“确定”即可。如果系统提示您有关新界面的信息,只需关闭该对话框即可。
在 Metrics Explorer 中,在“查找资源类型和指标”下输入“istio”,即可看到“Kubernetes 容器”资源类型中提供了“服务器请求数”等选项。这表明指标正在从网格流入 Stackdriver。
(如果您想看到以下各行,则必须按 destination_service_name 标签进行分组。)

使用信息中心直观呈现指标:
现在,我们的指标已纳入 Stackdriver APM 系统,我们需要一种方法来直观呈现这些指标。在本部分中,我们将安装一个预建的信息中心,其中显示了四项“黄金信号”指标中的三项:流量(每秒请求数)、延迟时间(在本例中为第 99 百分位和第 50 百分位)和错误(在本例中,我们排除了饱和度)。
Istio 的 Envoy 代理提供了多种指标,但这些指标是很好的起点。(如需查看详尽列表,请点击此处)。请注意,每个指标都有一组可用于过滤和汇总的标签,例如:destination_service、source_workload_namespace、response_code、istio_tcp_received_bytes_total 等。
- 现在,我们来添加预设的指标信息中心。我们将直接使用 Dashboard API。这通常不是通过手动生成 API 调用来完成的,而是自动化系统的一部分,或者您可以在 Web 界面中手动构建信息中心。这样可以让我们快速开始:
sed -i 's/OPS_PROJECT/'${TF_VAR_ops_project_name}'/g' \
$WORKDIR/asm/k8s_manifests/prod/app-telemetry/services-dashboard.json
OAUTH_TOKEN=$(gcloud auth application-default print-access-token)
curl -X POST -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json" \
https://monitoring.googleapis.com/v1/projects/$TF_VAR_ops_project_name/dashboards \
-d @$WORKDIR/asm/k8s_manifests/prod/app-telemetry/services-dashboard.json
- 前往下方的输出链接,查看新添加的“服务信息中心”。
echo "https://console.cloud.google.com/monitoring/dashboards/custom/servicesdash?cloudshell=false&project=$TF_VAR_ops_project_name"
我们可以使用界面就地修改信息中心,但在本例中,我们将使用 API 快速添加新图表。为此,您应拉取最新版本的信息中心,应用您的编辑内容,然后使用 HTTP PATCH 方法将其推送回去。
- 您可以通过查询 Monitoring API 获取现有信息中心。获取刚刚添加的现有信息中心:
curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json" \
https://monitoring.googleapis.com/v1/projects/$TF_VAR_ops_project_name/dashboards/servicesdash > /tmp/services-dashboard.json
- 添加新图表(第 50 百分位延迟时间):[API 参考文档] 现在,我们可以在代码中向信息中心添加新的图表 widget。此更改可由同级人员审核,并纳入版本控制。以下是要添加的 widget,用于显示第 50 百分位延迟时间(中位延迟时间)。
尝试修改您刚刚获取的信息中心,添加一个新段落:
NEW_CHART=${WORKDIR}/asm/k8s_manifests/prod/app-telemetry/new-chart.json
jq --argjson newChart "$(<$NEW_CHART)" '.gridLayout.widgets += [$newChart]' /tmp/services-dashboard.json > /tmp/patched-services-dashboard.json
- 更新现有服务信息中心:
curl -X PATCH -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json" \
https://monitoring.googleapis.com/v1/projects/$TF_VAR_ops_project_name/dashboards/servicesdash \
-d @/tmp/patched-services-dashboard.json
- 点击以下输出链接,查看更新后的信息中心:
echo "https://console.cloud.google.com/monitoring/dashboards/custom/servicesdash?cloudshell=false&project=$TF_VAR_ops_project_name"
- 执行一些简单的日志分析。
Istio 为所有网格内网络流量提供了一组结构化日志,并将其上传到 Stackdriver Logging,以便在一个强大的工具中进行跨集群分析。日志会添加服务级元数据注释,例如集群、容器、应用、connection_id 等。
示例日志条目(在本例中为 Envoy 代理的 accesslog)可能如下所示(已截断):
*** DO NOT PASTE ***
logName: "projects/PROJECTNAME-11932-01-ops/logs/server-tcp-accesslog-stackdriver.instance.istio-system"
labels: {
connection_id: "fbb46826-96fd-476c-ac98-68a9bd6e585d-1517191"
destination_app: "redis-cart"
destination_ip: "10.16.1.7"
destination_name: "redis-cart-6448dcbdcc-cj52v"
destination_namespace: "cart"
destination_owner: "kubernetes://apis/apps/v1/namespaces/cart/deployments/redis-cart"
destination_workload: "redis-cart"
source_ip: "10.16.2.8"
total_received_bytes: "539"
total_sent_bytes: "569"
...
}
点击此处查看您的日志:
echo "https://console.cloud.google.com/logs/viewer?cloudshell=false&project=$TF_VAR_ops_project_name"
您可以通过选择“资源”>“Kubernetes 容器”,然后搜索“pilot”来查看 Istio 的控制平面日志 -

在此处,我们可以看到 Istio 控制平面将代理配置推送给每个示例应用服务的 Sidecar 代理。“CDS”“LDS”和“RDS”代表不同的 Envoy API(更多信息)。
除了 Istio 的日志之外,您还可以在同一界面中找到容器日志以及基础架构或其他 GCP 服务日志。以下是一些适用于 GKE 的日志查询示例。日志查看器还允许您根据日志创建指标(例如“统计与某个字符串匹配的每个错误”),这些指标可用于信息中心或作为提醒的一部分。日志还可以流式传输到 BigQuery 等其他分析工具。
以下是针对“潮店”的一些过滤条件示例:
resource.type="k8s_container" labels.destination_app="productcatalogservice"
resource.type="k8s_container" resource.labels.namespace_name="cart"
- 查看分布式跟踪记录。
现在,您正在使用分布式系统,因此调试需要一种新工具:分布式跟踪。借助此工具,您可以发现有关服务互动方式的统计信息(例如,在下图中找到异常缓慢的事件),还可以深入研究原始样本轨迹,以调查实际发生情况的详细信息。
时间轴视图会显示一段时间内的所有请求,并以延迟时间(即从初始请求开始,经过 Hipster 堆栈,最终响应最终用户所花费的时间)绘制成图表。点的位置越高,用户体验就越差(用户越不满意!)。
您可以点击某个点,找到相应请求的详细瀑布图视图。这种查找特定请求的原始详细信息(而不仅仅是汇总统计信息)的能力对于了解服务之间的相互作用至关重要,尤其是在查找服务之间罕见但不良的互动时。
使用过调试程序的人应该对瀑布视图很熟悉,但在此视图中,它不是显示单个应用在不同进程中花费的时间,而是显示在单独容器中运行的服务之间遍历网状网所花费的时间。
您可以在以下位置找到轨迹:
echo "https://console.cloud.google.com/traces/overview?cloudshell=false&project=$TF_VAR_ops_project_name"
工具的屏幕截图示例:

9. 双向 TLS 身份验证
目标:确保微服务之间的连接安全 (AuthN)。
- 启用网格级 mTLS
- 通过检查日志验证 mTLS
复制和粘贴方法实验说明
现在,我们的应用已安装完毕,可观测性也已设置好,接下来我们可以开始保护服务之间的连接,并确保其持续正常运行。
例如,我们可以在 Kiali 信息中心看到,我们的服务未使用 mTLS(没有“锁”形图标)。但流量正常,系统运行良好。我们的 StackDriver 黄金指标信息中心让我们安心,因为这表明一切都在正常运行。
- 检查运营集群中的 MeshPolicy。请注意,mTLS 为
PERMISSIVE,允许加密流量和非 mTLS 流量。
kubectl --context $OPS_GKE_1 get MeshPolicy -o json | jq '.items[].spec'
kubectl --context $OPS_GKE_2 get MeshPolicy -o json | jq '.items[].spec'
`Output (do not copy)`
{
"peers": [
{
"mtls": {
"mode": "PERMISSIVE"
}
}
]
}
所有集群上的 Istio 均使用 Istio 运算符进行配置,该运算符使用 IstioControlPlane 自定义资源 (CR)。我们将通过更新 IstioControlPlane CR 和更新 k8s-repo 在所有集群中配置 mTLS。在 IstioControlPlane CR 中将 global > mTLS > enabled 设置为 true 会导致 Istio 控制平面发生以下两项更改:
- MeshPolicy 设置为在所有集群中为所有正在运行的服务启用 mTLS 网格。
- 创建 DestinationRule 以允许在所有集群中运行的服务之间进行 ISTIO_MUTUAL 流量。
- 我们将对 istioControlPlane CR 应用 kustomize 补丁,以在集群范围内启用 mTLS。将补丁复制到所有集群的相关目录,并添加 kustomize 补丁。
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-replicated.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-replicated.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV1_GKE_1_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV1_GKE_2_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV2_GKE_1_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
cp -r $WORKDIR/asm/k8s_manifests/prod/app-mtls/mtls-kustomize-patch-shared.yaml \
$WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/istio-controlplane/mtls-kustomize-patch.yaml
cd $WORKDIR/k8s-repo/$DEV2_GKE_2_CLUSTER/istio-controlplane
kustomize edit add patch mtls-kustomize-patch.yaml
- 提交到 k8s-repo。
cd $WORKDIR/k8s-repo
git add . && git commit -am "turn mTLS on"
git push
- 在之前打开的标签页中或通过点击以下链接查看运营项目 Cloud Build 的状态:
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
验证 mTLS
- 在运维集群中再次检查 MeshPolicy。请注意,mTLS 不再是
PERMISSIVE,并且只会允许 mTLS 流量。
kubectl --context $OPS_GKE_1 get MeshPolicy -o json | jq .items[].spec
kubectl --context $OPS_GKE_2 get MeshPolicy -o json | jq .items[].spec
输出(请勿复制):
{
"peers": [
{
"mtls": {}
}
]
}
- 描述由 Istio 运算符控制器创建的 DestinationRule。
kubectl --context $OPS_GKE_1 get DestinationRule default -n istio-system -o json | jq '.spec'
kubectl --context $OPS_GKE_2 get DestinationRule default -n istio-system -o json | jq '.spec'
输出(请勿复制):
{
host: '*.local',
trafficPolicy: {
tls: {
mode: ISTIO_MUTUAL
}
}
}
我们还可以在日志中看到从 HTTP 到 HTTPS 的迁移。
我们可以通过以下方式在界面中显示日志中的这个特定字段:点击一个日志条目,然后点击要显示的值(在本例中,点击“protocol”旁边的“http”):

这样一来,您就可以直观地看到转换过程:

10. Canary 部署
目标:发布前端服务的新版本。
- 发布
frontend-v2(下一个正式版)服务位于一个区域中 - 使用
DestinationRules和VirtualServices将流量缓慢引导至frontend-v2 - 通过检查对
k8s-repo的一系列提交来验证 GitOps 部署流水线
复制和粘贴方法实验说明
Canary 部署是指逐步发布新服务。在 Canary 部署中,您会逐渐增加发送到新版本的流量,同时仍将剩余百分比的流量发送到当前版本。一种常见模式是在流量拆分的每个阶段执行 Canary 分析,并将新版本的“黄金信号”(延迟时间、错误率、饱和度)与基准进行比较。这有助于防止中断,并确保新的“v2”服务在流量拆分的每个阶段都保持稳定。
在本部分中,您将学习如何使用 Cloud Build 和 Istio 流量政策为新版 frontend 服务创建基本的 Canary 部署。
首先,我们将在 DEV1 区域 (us-west1) 中运行 Canary 版流水线,并在该区域中的两个集群上发布前端 v2。其次,我们将在 DEV2 区域 (us-central) 中运行 Canary 流水线,并将 v2 部署到该区域中的两个集群。按顺序在各个区域运行流水线,而不是在所有区域并行运行,有助于避免因配置错误或 v2 应用本身的 bug 而导致全球性服务中断。
注意:我们将在两个区域中手动触发 Canary 版流水线,但在生产环境中,您可以使用自动触发器,例如基于推送到注册表的新 Docker 映像标记。
- 在 Cloud Shell 中,定义一些环境变量,以简化其余命令的运行。
CANARY_DIR="$WORKDIR/asm/k8s_manifests/prod/app-canary/"
K8S_REPO="$WORKDIR/k8s-repo"
- 运行 repo_setup.sh 脚本,将基准清单复制到 k8s-repo 中。
$CANARY_DIR/repo-setup.sh
系统会复制以下清单:
- frontend-v2 部署
- frontend-v1 补丁(包含“v1”标签和带有“/version”端点的映像)
- respy,一个用于打印 HTTP 响应分布的小型 pod,可帮助我们实时直观呈现 Canary 部署。
- 前端 Istio DestinationRule - 根据“version”部署标签将前端 Kubernetes 服务拆分为两个子集:v1 和 v2
- 前端 Istio VirtualService - 将 100% 的流量路由到前端 v1。这会替换 Kubernetes 服务的默认轮询调度行为,该行为会立即将所有 Dev1 区域流量的 50% 发送到前端 v2。
- 提交对 k8s_repo 的更改:
cd $K8S_REPO
git add . && git commit -am "frontend canary setup"
git push
- 在之前打开的标签页中或通过点击以下链接查看运营项目 Cloud Build 的状态:
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
- 在 OPS1 项目的控制台中前往 Cloud Build。等待 Cloud Build 流水线完成,然后获取两个 DEV1 集群中前端命名空间中的 pod。您应该会看到以下内容:
watch -n 1 kubectl --context $DEV1_GKE_1 get pods -n frontend
Output (do not copy)
NAME READY STATUS RESTARTS AGE frontend-578b5c5db6-h9567 2/2 Running 0 59m frontend-v2-54b74fc75b-fbxhc 2/2 Running 0 2m26s respy-5f4664b5f6-ff22r 2/2 Running 0 2m26s
我们将使用 tmux 将 Cloud Shell 窗口拆分为 2 个窗格:
- 底部窗格将运行 watch 命令,以观察前端服务的 HTTP 响应分布。
- 顶部窗格将运行实际的 Canary 流水线脚本。
- 运行命令以拆分 Cloud Shell 窗口,并在底部窗格中执行 watch 命令。
RESPY_POD=$(kubectl --context $DEV1_GKE_1 get pod \
-n frontend -l app=respy -o jsonpath='{..metadata.name}')
export TMUX_SESSION=$(tmux display-message -p '#S')
tmux split-window -d -t $TMUX_SESSION:0 -p33 \
-v "export KUBECONFIG=$WORKDIR/asm/gke/kubemesh; \
kubectl --context $DEV1_GKE_1 exec -n frontend -it \
$RESPY_POD -c respy /bin/sh -- -c 'watch -n 1 ./respy \
--u http://frontend:80/version --c 10 --n 500'; sleep 2"
输出(请勿复制)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v1 | 100.0% | | | | +----------+-------------------+
- 在 Dev1 区域中执行 Canary 流水线。我们提供了一个脚本,用于更新 VirtualService 中的 frontend-v2 流量百分比(将权重更新为 20%、50%、80%,然后更新为 100%)。在更新之间,脚本会等待 Cloud Build 流水线完成。针对 Dev1 区域运行 Canary 部署脚本。注意 - 此脚本大约需要 10 分钟才能完成。
K8S_REPO=$K8S_REPO CANARY_DIR=$CANARY_DIR \
OPS_DIR=$OPS_GKE_1_CLUSTER OPS_CONTEXT=$OPS_GKE_1 \
${CANARY_DIR}/auto-canary.sh
您可以在运行 respy 命令的底部窗口中实时查看流量拆分情况。例如,在 20% 的标记处:
输出(请勿复制)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v1 | 79.4% | | | | | v2 | 20.6% | | | | +----------+-------------------+
- 当前端-v2 的 Dev2 发布完成后,您应该会在脚本末尾看到一条成功消息:
Output (do not copy)
✅ 100% successfully deployed 🌈 frontend-v2 Canary Complete for gke-asm-1-r1-prod
- 来自 Dev2 pod 的所有前端流量都应发送到 frontend-v2:
Output (do not copy)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v2 | 100.0% | | | | +----------+-------------------+
- 关闭拆分窗格。
tmux respawn-pane -t ${TMUX_SESSION}:0.1 -k 'exit'
- 前往生成的链接中的 Cloud Source Repos。
echo https://source.developers.google.com/p/$TF_VAR_ops_project_name/r/k8s-repo
您应该会看到每个流量百分比都有一个单独的提交,并且最新的提交位于列表顶部:

现在,您将针对 Dev2 区域重复相同的流程。请注意,在 v1 上,Dev2 区域仍处于“锁定”状态。这是因为在基准 repo_setup 脚本中,我们推送了一个 VirtualService,以明确将所有流量发送到 v1。这样,我们便能够在 Dev1 上安全地执行区域 Canary 测试,并确保其成功运行,然后再在全球范围内推出新版本。
- 运行命令以拆分 Cloud Shell 窗口,并在底部窗格中执行 watch 命令。
RESPY_POD=$(kubectl --context $DEV2_GKE_1 get pod \
-n frontend -l app=respy -o jsonpath='{..metadata.name}')
export TMUX_SESSION=$(tmux display-message -p '#S')
tmux split-window -d -t $TMUX_SESSION:0 -p33 \
-v "export KUBECONFIG=$WORKDIR/asm/gke/kubemesh; \
kubectl --context $DEV2_GKE_1 exec -n frontend -it \
$RESPY_POD -c respy /bin/sh -- -c 'watch -n 1 ./respy \
--u http://frontend:80/version --c 10 --n 500'; sleep 2"
输出(请勿复制)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v1 | 100.0% | | | | +----------+-------------------+
- 在 Dev2 区域中执行 Canary 流水线。我们提供了一个脚本,用于更新 VirtualService 中的 frontend-v2 流量百分比(将权重更新为 20%、50%、80%,然后更新为 100%)。在更新之间,脚本会等待 Cloud Build 流水线完成。针对 Dev1 区域运行 Canary 部署脚本。注意 - 此脚本大约需要 10 分钟才能完成。
K8S_REPO=$K8S_REPO CANARY_DIR=$CANARY_DIR \
OPS_DIR=$OPS_GKE_2_CLUSTER OPS_CONTEXT=$OPS_GKE_2 \
${CANARY_DIR}/auto-canary.sh
输出(请勿复制)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v1 | 100.0% | | | | +----------+-------------------+
- 在 Dev2 中的 Respy pod 中,观察来自 Dev2 pod 的流量从前端 v1 逐步转移到 v2。脚本完成后,您应该会看到:
输出(请勿复制)
500 requests to http://frontend:80/version... +----------+-------------------+ | RESPONSE | % OF 500 REQUESTS | +----------+-------------------+ | v2 | 100.0% | | | | +----------+-------------------+
- 关闭拆分窗格。
tmux respawn-pane -t ${TMUX_SESSION}:0.1 -k 'exit'
本部分介绍了如何使用 Istio 进行区域性 Canary 部署。在生产环境中,您可以使用触发器(例如推送到容器注册表的新标记映像)将此 Canary 脚本作为 Cloud Build 流水线自动触发,而不是手动触发。您还可以在每个步骤之间添加 Canary 分析,根据预定义的安全阈值分析 v2 的延迟时间和错误率,然后再发送更多流量。
11. 授权政策
目标:在微服务之间设置 RBAC (AuthZ)。
- 创建
AuthorizationPolicy以拒绝访问微服务 - 创建
AuthorizationPolicy以允许对微服务的特定访问
复制和粘贴方法实验说明
与可在同一位置运行的单体式应用不同,全球分布式微服务应用会跨网络边界执行调用。这意味着应用的入口点越多,遭遇恶意攻击的机会就越多。由于 Kubernetes pod 使用临时 IP,因此基于 IP 的传统防火墙规则不足以保护工作负载之间的访问。微服务架构需要采用新的安全机制。Istio 依托于服务账号等 Kubernetes 安全构建块,为您的应用提供了一组灵活的安全政策。
Istio 政策涵盖身份验证和授权。身份验证用于验证身份(此服务器是否具备自己声明的身份?),而授权用于验证权限(此客户端是否有权执行某项操作?)。我们在模块 1 (MeshPolicy) 的双向 TLS 部分介绍了 Istio 身份验证。在本部分中,我们将学习如何使用 Istio 授权政策来控制对我们的一个应用工作负载 currencyservice 的访问权限。
首先,我们将在所有 4 个开发集群中部署 AuthorizationPolicy,关闭对 currencyservice 的所有访问权限,并在前端触发错误。然后,我们将仅允许前端服务访问 currencyservice。
- 检查
currency-deny-all.yaml的内容。此政策使用部署标签选择器来限制对 currencyservice 的访问。请注意,没有spec字段 - 这意味着此政策将拒绝对所选服务的所有访问。
cat $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-deny-all.yaml
输出(请勿复制)
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "currency-policy"
namespace: currency
spec:
selector:
matchLabels:
app: currencyservice
- 将币种政策复制到 k8s-repo 中,以用于两个区域中的运维集群。
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-deny-all.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization/currency-policy.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization
kustomize edit add resource currency-policy.yaml
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-deny-all.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization/currency-policy.yaml
cd $WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization
kustomize edit add resource currency-policy.yaml
- 推送更改。
cd $WORKDIR/k8s-repo
git add . && git commit -am "AuthorizationPolicy - currency: deny all"
git push
- 在之前打开的标签页中或点击以下链接,查看运营项目 Cloud Build 的状态:
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
- 构建成功完成后,尝试在浏览器中通过以下链接访问 hipstershop 前端:
echo "https://frontend.endpoints.$TF_VAR_ops_project_name.cloud.goog"
您应该会看到来自 currencyservice 的授权错误:

- 我们来调查一下币种服务是如何强制执行此 AuthorizationPolicy 的。首先,在某个币种 Pod 的 Envoy 代理上启用跟踪记录级别的日志,因为默认情况下,日志中不会记录被阻止的授权调用。
CURRENCY_POD=$(kubectl --context $DEV1_GKE_2 get pod -n currency | grep currency| awk '{ print $1 }')
kubectl --context $DEV1_GKE_2 exec -it $CURRENCY_POD -n \
currency -c istio-proxy -- curl -X POST \
"http://localhost:15000/logging?level=trace"
- 从币种服务的边车代理获取 RBAC(授权)日志。您应该会看到一条“强制拒绝”消息,这表示 currencyservice 已设置为阻止所有入站请求。
kubectl --context $DEV1_GKE_2 logs -n currency $CURRENCY_POD \
-c istio-proxy | grep -m 3 rbac
输出(请勿复制)
[Envoy (Epoch 0)] [2020-01-30 00:45:50.815][22][debug][rbac] [external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:67] checking request: remoteAddress: 10.16.5.15:37310, localAddress: 10.16.3.8:7000, ssl: uriSanPeerCertificate: spiffe://cluster.local/ns/frontend/sa/frontend, subjectPeerCertificate: , headers: ':method', 'POST' [Envoy (Epoch 0)] [2020-01-30 00:45:50.815][22][debug][rbac] [external/envoy/source/extensions/filters/http/rbac/rbac_filter.cc:118] enforced denied [Envoy (Epoch 0)] [2020-01-30 00:45:50.815][22][debug][http] [external/envoy/source/common/http/conn_manager_impl.cc:1354] [C115][S17310331589050212978] Sending local reply with details rbac_access_denied
- 现在,我们允许前端(但其他后端服务除外)访问 currencyservice。打开
currency-allow-frontend.yaml并检查其内容。请注意,我们添加了以下规则:
cat ${WORKDIR}/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend.yaml
输出(请勿复制)
rules:
- from:
- source:
principals: ["cluster.local/ns/frontend/sa/frontend"]
在此示例中,我们将特定 source.principal(客户端)列入白名单,以允许其访问币种服务。此 source.principal 由 Kubernetes 服务账号定义。在这种情况下,我们要列入许可名单的服务账号是前端命名空间中的前端服务账号。
注意:在 Istio AuthorizationPolicies 中使用 Kubernetes 服务账号时,您必须先启用集群范围的双向 TLS,如我们在模块 1 中所做的那样。这是为了确保服务账号凭据已装载到请求中。
- 复制更新后的币种政策
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization/currency-policy.yaml
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization/currency-policy.yaml
- 推送更改。
cd $WORKDIR/k8s-repo
git add . && git commit -am "AuthorizationPolicy - currency: allow frontend"
git push
- 在之前打开的标签页中或通过点击以下链接查看运营项目 Cloud Build 的状态:
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
- 成功完成 build 后,再次打开 Hipstershop 前端。这次,您应该不会在首页中看到任何错误,这是因为前端明确允许访问当前服务。
- 现在,尝试通过将商品添加到购物车并点击“下单”来执行结账。这次,您应该会看到来自币种服务的价格转换错误 - 这是因为我们只将前端列入了许可名单,因此 checkoutservice 仍然无法访问 currencyservice。

- 最后,我们再向 currencyservice AuthorizationPolicy 添加一条规则,以允许结账服务访问币种。请注意,我们仅向需要访问货币的两个服务(前端和结账)开放货币访问权限。其他后端仍会被屏蔽。
- 打开
currency-allow-frontend-checkout.yaml并检查其内容。请注意,规则列表的作用类似于逻辑 OR - currency 将仅接受来自具有以下任一服务账号的工作负载的请求。
cat ${WORKDIR}/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend-checkout.yaml
输出(请勿复制)
apiVersion: "security.istio.io/v1beta1"
kind: "AuthorizationPolicy"
metadata:
name: "currency-policy"
namespace: currency
spec:
selector:
matchLabels:
app: currencyservice
rules:
- from:
- source:
principals: ["cluster.local/ns/frontend/sa/frontend"]
- from:
- source:
principals: ["cluster.local/ns/checkout/sa/checkout"]
- 将最终授权政策复制到 k8s-repo。
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend-checkout.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_1_CLUSTER/app-authorization/currency-policy.yaml
cp $WORKDIR/asm/k8s_manifests/prod/app-authorization/currency-allow-frontend-checkout.yaml \
$WORKDIR/k8s-repo/$OPS_GKE_2_CLUSTER/app-authorization/currency-policy.yaml
- 推送更改
cd $WORKDIR/k8s-repo
git add . && git commit -am "AuthorizationPolicy - currency: allow frontend and checkout"
git push
- 在之前打开的标签页中或通过点击以下链接查看运营项目 Cloud Build 的状态:
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
- 成功完成 build 后,尝试执行结账,应该可以成功完成。
本部分介绍了如何使用 Istio 授权政策在服务级别强制执行精细的访问权限控制。在生产环境中,您可能需要为每个服务创建一个 AuthorizationPolicy,并(例如)使用“全部允许”政策来允许同一命名空间中的所有工作负载相互访问。
12. 基础架构扩缩
目标:通过添加新区域、项目和集群来扩缩基础设施。
- 克隆
infrastructure代码库 - 更新 Terraform 文件以创建新资源
- 新区域中的 2 个子网(一个用于运维项目,一个用于新项目)
- 新区域(位于新子网中)中的新运维集群
- 新区域的新 Istio 控制平面
- 新区域中的新项目内有 2 个应用集群
- 提交到
infrastructure代码库 - 验证安装
复制和粘贴方法实验说明
有多种方法可以扩展平台。您可以通过向现有集群添加节点来增加计算能力。您可以在一个区域中添加更多集群。或者,您也可以向平台添加更多地区。具体扩缩平台的哪个方面取决于需求。例如,如果您在某个区域的所有三个可用区中都有集群,那么或许只需向现有集群添加更多节点(或节点池)即可。不过,如果您在单个区域的三个可用区中的两个可用区内有集群,那么在第三个可用区内添加新集群可让您实现扩缩,并提供额外的故障网域(即新可用区)。在某个区域中添加新集群的另一个原因可能是需要创建单租户集群,这可能是出于监管或合规性方面的考虑(例如 PCI 或包含 PII 信息的数据库集群)。随着您的业务和服务不断拓展,您必然需要添加新地区,以便更贴近客户地提供服务。
当前平台包含两个区域,每个区域中有两个可用区中的集群。您可以从以下两个方面考虑平台扩展:
- 纵向 - 在每个区域内通过增加更多计算资源来实现。为此,您可以向现有集群添加更多节点(或节点池),也可以在该区域内添加新集群。这是通过
infrastructure代码库完成的。最简单的方法是将节点添加到现有集群。您无需进行其他配置。添加新集群可能需要额外的子网(和次要范围)、添加适当的防火墙规则、将新集群添加到区域 ASM/Istio 服务网格控制平面,以及将应用资源部署到新集群。 - 横向 - 通过添加更多地区。当前平台为您提供区域模板。它包含一个区域级运维集群(ASM/Istio 控制平面位于其中)和两个(或更多)可用区级应用集群(应用资源部署在其中)。
在此研讨会中,您将“横向”扩缩平台,因为它也包含垂直用例步骤。为了通过向平台添加新区域 (r3) 来横向扩缩平台,需要添加以下资源:
- 宿主项目共享 VPC 中位于区域 r3 的子网,用于新的运维和应用集群。
- 位于区域 r3 中的区域级运维集群,ASM/Istio 控制平面位于该集群中。
- 两个可用区级应用集群,分别位于区域 r3 的两个可用区中。
- 更新为 k8s-repo:
- 将 ASM/Istio 控制平面资源部署到区域 r3 中的运维集群。
- 将 ASM/Istio 共享控制平面资源部署到区域 r3 中的应用集群。
- 虽然您无需创建新项目,但研讨会中的步骤演示了如何添加新项目 dev3,以涵盖将新团队添加到平台的使用情形。
基础架构代码库用于添加上述新资源。
- 在 Cloud Shell 中,前往 WORKDIR 并克隆
infrastructure代码库。
mkdir -p $WORKDIR/infra-repo
cd $WORKDIR/infra-repo
git init && git remote add origin https://source.developers.google.com/p/${TF_ADMIN}/r/infrastructure
git config --local user.email ${MY_USER}
git config --local user.name "infra repo user"
git config --local credential.'https://source.developers.google.com'.helper gcloud.sh
git pull origin master
- 将研讨会源代码库的
add-proj分支克隆到add-proj-repo目录中。
cd $WORKDIR
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git add-proj-repo -b add-proj
- 从源研讨会代码库中的
add-proj分支复制文件。add-proj分支包含此部分的更改。
cp -r $WORKDIR/add-proj-repo/infrastructure/* $WORKDIR/infra-repo/
- 将 add-proj 代码库目录中的
infrastructure目录替换为指向infra-repo目录的符号链接,以允许运行分支上的脚本。
rm -rf $WORKDIR/add-proj-repo/infrastructure
ln -s $WORKDIR/infra-repo $WORKDIR/add-proj-repo/infrastructure
- 运行
add-project.sh脚本,将共享状态和变量复制到新的项目目录结构。
$WORKDIR/add-proj-repo/scripts/add-project.sh app3 $WORKDIR/asm $WORKDIR/infra-repo
- 提交并推送更改以创建新项目
cd $WORKDIR/infra-repo
git add .
git status
git commit -m "add new project" && git push origin master
- 提交会触发
infrastructure代码库部署包含新资源的基础设施。点击以下链接的输出,然后前往顶部的最新 build,即可查看 Cloud Build 进度。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_ADMIN}"
infrastructure 的最后一步是在 k8s-repo 中创建新的 Kubernetes 资源。这会触发 k8s-repo(在运维项目中)的 Cloud Build。新的 Kubernetes 资源适用于上一步中添加的三个新集群。通过 k8s-repo Cloud Build 将 ASM/Istio 控制平面和共享控制平面资源添加到新集群。
- 基础架构 Cloud Build 成功完成后,点击以下输出链接,前往
k8s-repo最新 Cloud Build 运行。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
- 运行以下脚本,将新集群添加到变量和 kubeconfig 文件中。
$WORKDIR/add-proj-repo/scripts/setup-gke-vars-kubeconfig-add-proj.sh $WORKDIR/asm
- 更改
KUBECONFIG变量,使其指向新的 kubeconfig 文件。
source $WORKDIR/asm/vars/vars.sh
export KUBECONFIG=$WORKDIR/asm/gke/kubemesh
- 列出集群上下文。您应该会看到 8 个聚类。
kubectl config view -ojson | jq -r '.clusters[].name'
`Output (do not copy)`
gke_user001-200204-05-dev1-49tqc4_us-west1-a_gke-1-apps-r1a-prod gke_user001-200204-05-dev1-49tqc4_us-west1-b_gke-2-apps-r1b-prod gke_user001-200204-05-dev2-49tqc4_us-central1-a_gke-3-apps-r2a-prod gke_user001-200204-05-dev2-49tqc4_us-central1-b_gke-4-apps-r2b-prod gke_user001-200204-05-dev3-49tqc4_us-east1-b_gke-5-apps-r3b-prod gke_user001-200204-05-dev3-49tqc4_us-east1-c_gke-6-apps-r3c-prod gke_user001-200204-05-ops-49tqc4_us-central1_gke-asm-2-r2-prod gke_user001-200204-05-ops-49tqc4_us-east1_gke-asm-3-r3-prod gke_user001-200204-05-ops-49tqc4_us-west1_gke-asm-1-r1-prod
验证 Istio 安装
- 通过检查所有 pod 是否都在运行以及作业是否已完成,确保 Istio 已安装在新运维集群上。
kubectl --context $OPS_GKE_3 get pods -n istio-system
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE grafana-5f798469fd-72g6w 1/1 Running 0 5h12m istio-citadel-7d8595845-hmmvj 1/1 Running 0 5h12m istio-egressgateway-779b87c464-rw8bg 1/1 Running 0 5h12m istio-galley-844ddfc788-zzpkl 2/2 Running 0 5h12m istio-ingressgateway-59ccd6574b-xfj98 1/1 Running 0 5h12m istio-pilot-7c8989f5cf-5plsg 2/2 Running 0 5h12m istio-policy-6674bc7678-2shrk 2/2 Running 3 5h12m istio-sidecar-injector-7795bb5888-kbl5p 1/1 Running 0 5h12m istio-telemetry-5fd7cbbb47-c4q7b 2/2 Running 2 5h12m istio-tracing-cd67ddf8-2qwkd 1/1 Running 0 5h12m istiocoredns-5f7546c6f4-qhj9k 2/2 Running 0 5h12m kiali-7964898d8c-l74ww 1/1 Running 0 5h12m prometheus-586d4445c7-x9ln6 1/1 Running 0 5h12m
- 确保在两个
dev3集群上都安装了 Istio。只有 Citadel、sidecar-injector 和 coredns 在dev3集群中运行。它们共享在ops-3集群中运行的 Istio 控制层面。
kubectl --context $DEV3_GKE_1 get pods -n istio-system
kubectl --context $DEV3_GKE_2 get pods -n istio-system
`Output (do not copy)`
NAME READY STATUS RESTARTS AGE istio-citadel-568747d88-4lj9b 1/1 Running 0 66s istio-sidecar-injector-759bf6b4bc-ks5br 1/1 Running 0 66s istiocoredns-5f7546c6f4-qbsqm 2/2 Running 0 78s
验证共享控制平面的服务发现
- 验证 Secret 是否已部署在所有 6 个应用集群的所有运维集群中。
kubectl --context $OPS_GKE_1 get secrets -l istio/multiCluster=true -n istio-system
kubectl --context $OPS_GKE_2 get secrets -l istio/multiCluster=true -n istio-system
kubectl --context $OPS_GKE_3 get secrets -l istio/multiCluster=true -n istio-system
`Output (do not copy)`
NAME TYPE DATA AGE gke-1-apps-r1a-prod Opaque 1 14h gke-2-apps-r1b-prod Opaque 1 14h gke-3-apps-r2a-prod Opaque 1 14h gke-4-apps-r2b-prod Opaque 1 14h gke-5-apps-r3b-prod Opaque 1 5h12m gke-6-apps-r3c-prod Opaque 1 5h12m
13. 熔断
目标:为配送服务实现断路器。
- 为
shipping服务创建DestinationRule以实现断路器 - 使用
fortio(一种负载生成实用程序)通过强制跳闸来验证shipping服务的断路器
快速轨道脚本实验操作说明
Fast Track Script Lab 即将推出!
复制和粘贴方法实验说明
现在,我们已经了解了针对启用 Istio 的服务的一些基本监控和问题排查策略,接下来我们来看看 Istio 如何帮助您提高服务的弹性,从而减少您需要进行的问题排查。
微服务架构会带来级联故障的风险,即一项服务的故障可能会传播到其依赖项以及这些依赖项的依赖项,从而导致“连锁反应”式服务中断,进而可能会影响最终用户。Istio 提供了一种熔断流量政策,可帮助您隔离服务,防止下游(客户端)服务因等待失败的服务而受到影响,并防止上游(服务器端)服务在重新上线时突然涌入大量下游流量。总而言之,使用熔断器有助于避免所有服务因一个挂起的后端服务而未能达到其 SLO。
断路器模式得名于一种电气开关,当电流过大时,该开关会“跳闸”,从而保护设备免于过载。在 Istio 设置中,这意味着 Envoy 是断路器,用于跟踪服务的待处理请求数。在此默认的关闭状态下,请求会不间断地流经 Envoy。
但是,当待处理请求的数量超过您定义的阈值时,断路器会跳闸(打开),并且 Envoy 会立即返回错误。这样一来,服务器就可以快速向客户端返回失败结果,并防止服务器应用代码在过载时接收客户端的请求。
然后,在您定义的超时时间过后,Envoy 会进入半开放状态,服务器可以开始以试探性方式再次接收请求,如果服务器能够成功响应请求,断路器会再次关闭,并且对服务器的请求会再次开始流动。
此图总结了 Istio 断路器模式。蓝色矩形表示 Envoy,蓝色实心圆圈表示客户端,白色实心圆圈表示服务器容器:

您可以使用 Istio DestinationRules 定义断路器政策。在本部分中,我们将应用以下政策,以针对配送服务强制执行断路器:
Output (do not copy)
apiVersion: "networking.istio.io/v1alpha3"
kind: "DestinationRule"
metadata:
name: "shippingservice-shipping-destrule"
namespace: "shipping"
spec:
host: "shippingservice.shipping.svc.cluster.local"
trafficPolicy:
tls:
mode: ISTIO_MUTUAL
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutiveErrors: 1
interval: 1s
baseEjectionTime: 10s
maxEjectionPercent: 100
这里有两项 DestinationRule 字段需要注意。connectionPool 用于定义相应服务允许的连接数。在 outlierDetection 字段中,我们可以配置 Envoy 将如何确定打开断路器的阈值。在此示例中,Envoy 将每秒(间隔)统计从服务器容器收到的错误数量。如果超过 consecutiveErrors 阈值,Envoy 断路器将打开,并且 100% 的 productcatalog pod 将在 10 秒内免受新的客户端请求的影响。一旦 Envoy 断路器打开(即处于活动状态),客户端将收到 503(服务不可用)错误。我们来看看实际用例。
- 为 k8s-repo 和 asm 目录设置环境变量,以简化命令。
export K8S_REPO="${WORKDIR}/k8s-repo"
export ASM="${WORKDIR}/asm"
- 更新 k8s-repo
cd $WORKDIR/k8s-repo
git pull
cd $WORKDIR
- 更新两个 Ops 集群上的配送服务 DestinationRule。
cp $ASM/k8s_manifests/prod/istio-networking/app-shipping-circuit-breaker.yaml ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cp $ASM/k8s_manifests/prod/istio-networking/app-shipping-circuit-breaker.yaml ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit add resource app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit add resource app-shipping-circuit-breaker.yaml
- 将 Fortio 负载生成器 pod 复制到 Dev1 区域中的 GKE_1 集群。这是我们将用于“触发”shippingservice 断路器的客户端 pod。
cp $ASM/k8s_manifests/prod/app/deployments/app-fortio.yaml ${K8S_REPO}/${DEV1_GKE_1_CLUSTER}/app/deployments/
cd ${K8S_REPO}/${DEV1_GKE_1_CLUSTER}/app/deployments; kustomize edit add resource app-fortio.yaml
- 提交更改。
cd $K8S_REPO
git add . && git commit -am "Circuit Breaker: shippingservice"
git push
cd $ASM
- 等待 Cloud Build 完成。
- 返回 Cloud Shell,使用 fortio pod 向 shippingservice 发送 gRPC 流量,同时建立 1 个并发连接,总共发送 1000 个请求 - 这不会触发断路器,因为我们尚未超出
connectionPool设置。
FORTIO_POD=$(kubectl --context ${DEV1_GKE_1} get pod -n shipping | grep fortio | awk '{ print $1 }')
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c fortio /usr/bin/fortio -- load -grpc -c 1 -n 1000 -qps 0 shippingservice.shipping.svc.cluster.local:50051
输出(请勿复制)
Health SERVING : 1000 All done 1000 calls (plus 0 warmup) 4.968 ms avg, 201.2 qps
- 现在再次运行 fortio,将并发连接数增加到 2,但保持请求总数不变。我们应该会看到最多三分之二的请求返回“溢出”错误,因为断路器已跳闸:在定义的政策中,1 秒间隔内只允许 1 个并发连接。
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c fortio /usr/bin/fortio -- load -grpc -c 2 -n 1000 -qps 0 shippingservice.shipping.svc.cluster.local:50051
输出(请勿复制)
18:46:16 W grpcrunner.go:107> Error making grpc call: rpc error: code = Unavailable desc = upstream connect error or disconnect/reset before headers. reset reason: overflow ... Health ERROR : 625 Health SERVING : 375 All done 1000 calls (plus 0 warmup) 12.118 ms avg, 96.1 qps
- Envoy 会通过 upstream_rq_pending_overflow 指标跟踪断路器处于活跃状态时丢弃的连接数。我们来在 fortio pod 中找到它:
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c istio-proxy -- sh -c 'curl localhost:15000/stats' | grep shipping | grep pending
输出(请勿复制)
cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.circuit_breakers.default.rq_pending_open: 0 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.circuit_breakers.high.rq_pending_open: 0 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_active: 0 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_failure_eject: 9 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_overflow: 565 cluster.outbound|50051||shippingservice.shipping.svc.cluster.local.upstream_rq_pending_total: 1433
- 通过从两个区域中移除断路器政策进行清理。
kubectl --context ${OPS_GKE_1} delete destinationrule shippingservice-circuit-breaker -n shipping
rm ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit remove resource app-shipping-circuit-breaker.yaml
kubectl --context ${OPS_GKE_2} delete destinationrule shippingservice-circuit-breaker -n shipping
rm ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-shipping-circuit-breaker.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit remove resource app-shipping-circuit-breaker.yaml
cd $K8S_REPO; git add .; git commit -m "Circuit Breaker: cleanup"; git push origin master
本部分演示了如何为服务设置单个断路器政策。最佳实践是为任何可能挂起的上游(后端)服务设置断路器。通过应用 Istio 断路器政策,您可以帮助隔离微服务、在架构中构建容错能力,并降低在高负载下发生级联故障的风险。
14. 故障注入
目标:通过引入延迟(在推送到生产环境之前)来测试推荐服务的弹性。
- 为
recommendation服务创建VirtualService以引入 5 秒延迟 - 使用
fortio负载生成器测试延迟 - 移除
VirtualService中的延迟并进行验证
快速轨道脚本实验操作说明
Fast Track Script Lab 即将推出!
复制和粘贴方法实验说明
向服务添加断路器政策是提高生产环境中服务恢复能力的一种方法。但断路会导致故障(可能是面向用户的错误),这并不理想。为了提前应对这些错误情况,并更好地预测后端返回错误时下游服务可能会如何响应,您可以在预演环境中采用混沌测试。混沌测试是指故意中断服务,以便分析系统中的薄弱点并提高容错能力。您还可以使用混沌测试来确定在后端发生故障时如何缓解面向用户的错误,例如在前端显示缓存的结果。
使用 Istio 进行故障注入很有帮助,因为您可以直接使用生产版本映像,并在网络层添加故障,而无需修改源代码。在生产环境中,您可以使用成熟的混沌测试工具来测试 Kubernetes/计算层以及网络层的弹性。
您可以通过应用包含“fault”字段的 VirtualService,使用 Istio 进行混沌测试。Istio 支持两种类型的故障:延迟故障(注入超时)和中止故障(注入 HTTP 错误)。在此示例中,我们将向推荐服务注入 5 秒延迟故障。但这一次,我们不会使用断路器针对此挂起的服务“快速失败”,而是会强制下游服务承受完整的超时时间。
- 进入故障注入目录。
export K8S_REPO="${WORKDIR}/k8s-repo"
export ASM="${WORKDIR}/asm/"
cd $ASM
- 打开
k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml以检查其内容。请注意,Istio 提供了一个选项,可将故障注入到一定百分比的请求中 - 在此示例中,我们将超时引入到所有 recommendationservice 请求中。
输出(请勿复制)
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: recommendation-delay-fault
spec:
hosts:
- recommendationservice.recommendation.svc.cluster.local
http:
- route:
- destination:
host: recommendationservice.recommendation.svc.cluster.local
fault:
delay:
percentage:
value: 100
fixedDelay: 5s
- 将 VirtualService 复制到 k8s_repo 中。我们将在全球范围内(包括两个区域)注入故障。
cp $ASM/k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit add resource app-recommendation-vs-fault.yaml
cp $ASM/k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit add resource app-recommendation-vs-fault.yaml
- 推送更改
cd $K8S_REPO
git add . && git commit -am "Fault Injection: recommendationservice"
git push
cd $ASM
- 等待 Cloud Build 完成。
- 进入断路器部分中部署的 fortio Pod,并向 recommendationservice 发送一些流量。
FORTIO_POD=$(kubectl --context ${DEV1_GKE_1} get pod -n shipping | grep fortio | awk '{ print $1 }')
kubectl --context ${DEV1_GKE_1} exec -it $FORTIO_POD -n shipping -c fortio /usr/bin/fortio -- load -grpc -c 100 -n 100 -qps 0 recommendationservice.recommendation.svc.cluster.local:8080
Once the fortio command is complete, you should see responses averaging 5s:
输出(请勿复制)
Ended after 5.181367359s : 100 calls. qps=19.3 Aggregated Function Time : count 100 avg 5.0996506 +/- 0.03831 min 5.040237641 max 5.177559818 sum 509.965055
- 如需查看我们注入的故障的实际效果,另一种方法是在网络浏览器中打开前端,然后点击任意商品。由于产品页面会提取显示在页面底部的推荐内容,因此加载时间应增加 5 秒。
- 通过从两个 Ops 集群中移除故障注入服务进行清理。
kubectl --context ${OPS_GKE_1} delete virtualservice recommendation-delay-fault -n recommendation
rm ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_1_CLUSTER}/istio-networking/; kustomize edit remove resource app-recommendation-vs-fault.yaml
kubectl --context ${OPS_GKE_2} delete virtualservice recommendation-delay-fault -n recommendation
rm ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/app-recommendation-vs-fault.yaml
cd ${K8S_REPO}/${OPS_GKE_2_CLUSTER}/istio-networking/; kustomize edit remove resource app-recommendation-vs-fault.yaml
- 推送更改:
cd $K8S_REPO
git add . && git commit -am "Fault Injection cleanup / restore"
git push
cd $ASM
15. 监控 Istio 控制平面
ASM 会安装四个重要的控制平面组件:Pilot、Mixer、Galley 和 Citadel。每个组件都会将其相关的监控指标发送到 Prometheus,而 ASM 附带 Grafana 信息中心,可让运营者直观呈现这些监控数据,并评估控制平面的运行状况和性能。
查看信息中心
- 通过端口转发访问随 Istio 一起安装的 Grafana 服务
kubectl --context ${OPS_GKE_1} -n istio-system port-forward svc/grafana 3000:3000 >> /dev/null
- 在浏览器中打开 Grafana
- 点击 Cloud Shell 窗口右上角的“网页预览”图标
- 点击“在端口 3000 上预览”(注意:如果端口不是 3000,请点击“更改端口”,然后选择端口 3000)
- 系统随即会在浏览器中打开一个标签页,其中包含类似于“BASE_网址/?orgId=1&authuser=0&environment_id=default”的网址
- 查看可用的信息中心
- 将网址修改为“BASE_网址/dashboard”
- 点击“istio”文件夹以查看可用的信息中心
- 点击任一信息中心即可查看相应组件的效果。在以下部分中,我们将介绍每个组件的重要指标。
Monitoring Pilot
Pilot 是控制平面组件,可将网络和政策配置分发到数据层面(Envoy 代理)。Pilot 通常会随着工作负载和部署数量的增加而扩缩,但并不一定随着这些工作负载的流量增加而扩缩。运行状况不佳的 Pilot 可以:
- 消耗比必要更多的资源(CPU 和/或 RAM)
- 导致向 Envoy 推送更新后的配置信息时出现延迟
注意:即使 Pilot 出现故障或延迟,您的工作负载仍会提供流量。
- 在浏览器中前往“BASE_URL/dashboard/db/istio-pilot-dashboard”,查看 Pilot 指标。
重要的受监控指标
资源使用情况
请参阅 Istio 性能和可伸缩性页面,了解可接受的使用量。如果您发现持续的资源用量明显高于此值,请与 GCP 支持团队联系。

Pilot Push Information
此部分用于监控 Pilot 向 Envoy 代理推送配置的情况。
- 小规模测试推送显示了在任何给定时间推送的配置类型。
- ADS 监控显示系统中的虚拟服务、服务和已连接端点的数量。
- 没有已知端点的集群:显示已配置但没有任何正在运行的实例的端点(可能表示外部服务,例如 *.googleapis.com)。
- Pilot Errors(Pilot 错误)显示一段时间内遇到的错误数量。
- 冲突显示监听器上存在歧义配置的冲突数量。
如果您有错误或冲突,则表明您的一项或多项服务存在错误或不一致的配置。如需了解相关信息,请参阅“排查数据平面问题”。
Envoy 信息
本部分包含有关与控制平面通信的 Envoy 代理的信息。如果您反复看到 XDS 连接失败,请与 GCP 支持团队联系。
Monitoring Mixer
Mixer 是一种组件,可将遥测数据从 Envoy 代理输送到遥测后端(通常是 Prometheus、Stackdriver 等)。在这种情况下,它不在数据平面中。它以两个 Kubernetes 作业(称为 Mixer)的形式部署,这两个作业分别使用两个不同的服务名称(istio-telemetry 和 istio-policy)。
Mixer 还可用于与政策系统集成。在这种情况下,Mixer 会影响数据平面,因为对 Mixer 的政策检查失败会阻止对服务的访问。
Mixer 往往会随流量而扩缩。
- 在浏览器中前往“BASE_URL/dashboard/db/istio-mixer-dashboard”,查看 Mixer 指标。
重要的受监控指标
资源使用情况
请参阅 Istio 性能和可伸缩性页面,了解可接受的使用量。如果您发现持续的资源用量明显高于此值,请与 GCP 支持团队联系。

Mixer 概览
- 响应时长是一项重要指标。虽然向 Mixer 遥测发送的报告不在数据路径中,但如果这些延迟时间较长,肯定会降低边车代理的性能。您应该会发现,第 90 百分位延迟时间为个位数毫秒,第 99 百分位延迟时间低于 100 毫秒。

- 适配器调度时长表示 Mixer 在调用适配器(通过该适配器将信息发送到遥测和日志记录系统)时遇到的延迟。此处的延迟时间过长肯定会影响网状网的性能。同样,p90 延迟时间应小于 10 毫秒。

监控图库
Galley 是 Istio 的配置验证、提取、处理和分发组件。它将配置从 Kubernetes API 服务器传递到 Pilot。与 Pilot 类似,它往往会随着系统中的服务和端点数量而扩缩。
- 在浏览器中前往“BASE_URL/dashboard/db/istio-galley-dashboard”,以查看 Galley 指标。
重要的受监控指标
资源验证
最重要的跟踪指标,用于指示各种类型的资源(如目标规则、网关和服务条目)通过或未通过验证的数量。
已连接的客户端
表示有多少客户端连接到 Galley;通常为 3 个(pilot、istio-telemetry、istio-policy),并且会随着这些组件的扩缩而扩缩。
16. 排查 Istio 问题
排查数据平面问题
如果 Pilot 信息中心显示您存在配置问题,您应检查 Pilot 日志或使用 istioctl 查找配置问题。
如需检查 Pilot 日志,请运行 kubectl -n istio-system logs istio-pilot-69db46c598-45m44 discovery,并将 istio-pilot-... 替换为您要排查的 Pilot 实例的 pod 标识符。
在生成的日志中,搜索 Push Status 消息。例如:
2019-11-07T01:16:20.451967Z info ads Push Status: {
"ProxyStatus": {
"pilot_conflict_outbound_listener_tcp_over_current_tcp": {
"0.0.0.0:443": {
"proxy": "cartservice-7555f749f-k44dg.hipster",
"message": "Listener=0.0.0.0:443 AcceptedTCP=accounts.google.com,*.googleapis.com RejectedTCP=edition.cnn.com TCPServices=2"
}
},
"pilot_duplicate_envoy_clusters": {
"outbound|15443|httpbin|istio-egressgateway.istio-system.svc.cluster.local": {
"proxy": "sleep-6c66c7765d-9r85f.default",
"message": "Duplicate cluster outbound|15443|httpbin|istio-egressgateway.istio-system.svc.cluster.local found while pushing CDS"
},
"outbound|443|httpbin|istio-egressgateway.istio-system.svc.cluster.local": {
"proxy": "sleep-6c66c7765d-9r85f.default",
"message": "Duplicate cluster outbound|443|httpbin|istio-egressgateway.istio-system.svc.cluster.local found while pushing CDS"
},
"outbound|80|httpbin|istio-egressgateway.istio-system.svc.cluster.local": {
"proxy": "sleep-6c66c7765d-9r85f.default",
"message": "Duplicate cluster outbound|80|httpbin|istio-egressgateway.istio-system.svc.cluster.local found while pushing CDS"
}
},
"pilot_eds_no_instances": {
"outbound_.80_._.frontend-external.hipster.svc.cluster.local": {},
"outbound|443||*.googleapis.com": {},
"outbound|443||accounts.google.com": {},
"outbound|443||metadata.google.internal": {},
"outbound|80||*.googleapis.com": {},
"outbound|80||accounts.google.com": {},
"outbound|80||frontend-external.hipster.svc.cluster.local": {},
"outbound|80||metadata.google.internal": {}
},
"pilot_no_ip": {
"loadgenerator-778c8489d6-bc65d.hipster": {
"proxy": "loadgenerator-778c8489d6-bc65d.hipster"
}
}
},
"Version": "o1HFhx32U4s="
}
推送状态会指明尝试将配置推送到 Envoy 代理时出现的任何问题 - 在此示例中,我们看到多条“重复的集群”消息,表明上游目标重复。
如需有关诊断问题的帮助,请与 Google Cloud 支持团队联系。
查找配置错误
如需使用 istioctl 分析配置,请运行 istioctl experimental analyze -k --context $OPS_GKE_1。此命令将分析系统中的配置,指出任何问题以及建议的更改。如需查看此命令可检测到的配置错误的完整列表,请参阅文档。
17. 清理
管理员运行 cleanup_workshop.sh 脚本以删除 bootstrap_workshop.sh 脚本创建的资源。您需要提供以下信息,清理脚本才能运行。
- 组织名称 - 例如
yourcompany.com - 研讨会 ID - 格式为
YYMMDD-NN,例如200131-01 - 管理员 GCS 存储分区 - 在引导脚本中定义。
- 打开 Cloud Shell,并在 Cloud Shell 中执行以下所有操作。点击下方链接。
- 验证您是否已使用目标管理员用户账号登录 gcloud。
gcloud config list
- 导航到 asm 文件夹。
cd ${WORKDIR}/asm
- 定义要删除的组织名称和研讨会 ID。
export ORGANIZATION_NAME=<ORGANIZATION NAME>
export ASM_WORKSHOP_ID=<WORKSHOP ID>
export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
- 按如下方式运行清理脚本。
./scripts/cleanup_workshop.sh --workshop-id ${ASM_WORKSHOP_ID} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET} --org-name ${ORGANIZATION_NAME}