Anthos Service Mesh 研讨会:实验指南

1. Alpha 版研讨会

研讨会 Codelab bit.ly/asm-workshop 的链接

2. 概览

架构图

9a033157f44308f3

此研讨会提供沉浸式实操体验,介绍如何在生产环境中设置全球分布式服务。他们使用的主要技术是用于计算的 Google Kubernetes Engine (GKE) 和 Istio 服务网格,用于创建安全连接、可观测性和高级流量调整。本研讨会中使用的所有做法和工具都是您实际会用到的生产环境。

内容安排

  • 第 0 单元 - 简介和平台设置
  • 简介和架构
  • 服务网格和 Istio/ASM 简介
  • 实验:基础架构设置:用户工作流程
  • 休息时间
  • QnA
  • 第 1 单元 - 使用 ASM 安装、保护和监控应用
  • 代码库模型:基础架构和 Kubernetes 代码库说明
  • 实验:部署示例应用
  • 分布式服务和可观测性
  • 午餐
  • 实验:使用 Stackdriver 实现可观测性
  • QNA
  • 第 2 单元 - DevOps - Canary 发布、政策/RBAC
  • 多集群服务发现和安全/政策
  • 实验:双向 TLS
  • Canary 部署
  • 实验:Canary 部署
  • 安全的多集群全球负载均衡
  • 休息时间
  • 实验:授权政策
  • QNA
  • 第 3 单元 - 基础架构运维 - 平台升级
  • 分布式服务基础组件
  • 实验:基础架构扩缩
  • 后续步骤

幻灯片

本次研讨会的幻灯片可通过以下链接找到:

ASM 研讨会幻灯片

前提条件

在继续本研讨会之前,必须满足以下要求:

  1. 一个 GCP 组织节点
  2. 结算账号 ID(您的用户必须是此结算账号的 Billing Admin
  3. 您的用户的组织级 Organization Administrator IAM 角色

3. 基础架构设置 - 管理员工作流程

引导研讨会脚本说明

我们使用一个名为 bootstrap_workshop.sh 的脚本为研讨会设置初始环境。如果您要将此研讨会用作培训对象,可以使用此脚本为自己设置单个环境,或为多个用户设置多个环境。

引导研讨会脚本需要以下信息作为输入:

  • 组织名称(例如 yourcompany.com)- 您将在其中创建研讨会环境的组织。
  • 结算 ID(例如 12345-12345-12345)- 此结算 ID 用于对研讨会中使用的所有资源进行结算。
  • 车间编号(例如 01)- 两位数的编号。如果您在一天中开展了多个研讨会,并且希望分别跟踪这些研讨会,则可以使用此 ID。研讨会编号也用于派生项目 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_USERMY_USER 是相同的。如果您是教师,要为多位学生创建此研讨会,那么您的ADMIN_USERMY_USER会有所不同。

ADMIN_USER 需要以下组织级权限:

  • Owner - 组织中所有项目的 Project Owner 权限。
  • 文件夹管理员 - 能够在组织中创建和删除文件夹。每个用户都会获得一个文件夹,其所有资源都位于项目内。
  • 组织管理员
  • Project Creator - 能够在组织中创建项目。
  • 项目删除者 - 能够删除组织中的项目。
  • Project IAM Admin - 能够在组织的所有项目中创建 IAM 规则。

除此之外,ADMIN_USER 还必须是研讨会中使用的结算 ID 的 Billing Administrator

执行研讨会的用户架构和权限

如果您打算为组织中的用户(不包括您自己)创建此研讨会,则必须遵循特定 MY_USERs 用户命名方案。在 bootstrap_workshop.sh 脚本执行期间,您需要提供开始号码和最终用户号码。这些编号用于创建以下用户名:

  • user<3 digit user number>@<organization_name>

例如,如果您运行起始用户编号为 1、最终用户编号为 3 的引导研讨会脚本,则在名为 yourcompany.com 的组织中,系统会为以下用户创建研讨会环境:

  • user001@yourcompany.com
  • user002@yourcompany.com
  • user003@yourcompany.com

对于在 setup_terraform_admin_project.sh 脚本期间创建的特定项目,系统会为这些用户名分配 Project Owner 角色。使用引导加载程序脚本时,您必须遵循此用户命名架构。请参阅如何在 G Suite 中一次添加多名用户

研讨会所需的工具

本研讨会旨在从 Cloud Shell 引导。本次研讨会需要以下工具。

  • gcloud(版本 >= 270)
  • kubectl
  • sed(在 Cloud Shell/Linux 上适用于 sed,不适用于 Mac OS)
  • git(确保您使用的是最新版本)
  • sudo apt update
  • sudo apt install git
  • jq
  • envsubst
  • kustomize

自行设置研讨会(单用户设置)

  1. 打开 Cloud Shell,在 Cloud Shell 中执行以下所有操作。请点击下面的链接。

Cloud Shell

  1. 确认您已使用预期的管理员用户登录 gcloud。
gcloud config list
 
  1. 创建 WORKDIR 并克隆研讨会代码库。
mkdir asm-workshop
cd asm-workshop
export WORKDIR=`pwd`
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git asm
 
  1. 定义您的组织名称、结算 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>
 
  1. 运行 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 Admin 项目。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 文件中。只有在您以管理员身份为自己设置研讨会时,此目录才会保留。

  1. 找到变量文件以设置环境变量
echo "export WORKDIR=$WORKDIR" >> $WORKDIR/asm/vars/vars.sh
source $WORKDIR/asm/vars/vars.sh 
 

为多用户设置工作坊(多用户设置)

  1. 打开 Cloud Shell,在 Cloud Shell 中执行以下所有操作。请点击下面的链接。

Cloud Shell

  1. 确认您已使用预期的管理员用户登录 gcloud。
gcloud config list
 
  1. 创建 WORKDIR 并克隆研讨会代码库。
mkdir asm-workshop
cd asm-workshop
export WORKDIR=`pwd`
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git asm
 
  1. 定义您的组织名称、结算 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>
 
  1. 运行 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}
 
  1. 从管理员 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. 实验设置和准备

选择实验路径

本研讨会中的实验可以通过以下两种方式之一开展:

  • 轻松快捷的交互式脚本”路
  • 手动复制和粘贴每条说明”路

使用快速跟踪脚本方法,您可以为每个实验运行一个交互式脚本,通过自动运行该实验的命令来引导您完成实验。这些命令会批量运行,并简要说明每个步骤及其完成的任务。每批命令运行完成后,系统都会提示您继续执行下一批命令。这样,您就可以按照自己的节奏开展实验。快速跟踪脚本具有幂等性,也就是说,您可以多次运行这些脚本,得到相同的结果。

Fast Track 脚本将显示在每个实验顶部的绿色框中,如下所示。

“复制和粘贴”方法是复制粘贴各个命令块的传统方法,其中包含命令的解释说明。此方法只能运行一次。无法保证在此方法中重新运行命令后会得到相同的结果。

执行实验时,请从以下两种方法中选择一种。

Fast Track 脚本设置

获取用户信息

本次研讨会使用研讨会管理员创建的临时用户账号(或实验账号)进行。研讨会中的所有项目均归该实验账号所有。研讨会管理员向执行研讨会的用户提供实验账号凭据(用户名和密码)。用户的所有项目均以实验账号的用户名前缀。例如,对于实验账号 user001@yourcompany.com,terraform 管理员项目 ID 为 user001-200131-01-tf-abcde,其余项目依此类推。每位用户都必须使用研讨会管理员提供的实验账号登录,并使用实验账号进行研讨会。

  1. 点击下面的链接,打开 Cloud Shell。

Cloud Shell

  1. 使用实验账号凭据登录(请勿使用您的公司或个人账号登录)。实验账号类似于 userXYZ@<workshop_domain>.com3101eca1fd3722bf.png
  2. 由于这是一个新账号,因此系统会提示您接受 Google 服务条款。点击“接受”。

fb0219a89ece5168.png 4.在下一个屏幕中,选中复选框以同意 Google 服务条款,然后点击 Start Cloud Shell

7b198cf2e32cb457

此步骤将预配一个小型 Linux Debian 虚拟机,供您用于访问 GCP 资源。每个账号都会获得一个 Cloud Shell 虚拟机。使用实验账号配置登录,并使用实验账号凭据登录。除了 Cloud Shell 之外,我们还预配了代码编辑器,使您可以更轻松地修改配置文件(Terraform、YAML 等)。默认情况下,Cloud Shell 屏幕分为 Cloud Shell shell 环境(位于底部)和 Cloud Code 编辑器(位于顶部)。5643bb4ebeafd00a 通过右上角的铅笔 “8bca25ef1421c17e” 和 shell 提示 eaeb4ac333783ba8.png 图标,您可以在两者(shell 和代码编辑器)之间切换。您还可以(向上或向下)拖动中间的分隔符,手动更改每个窗口的大小。5. 为此研讨会创建一个 WORKDIR。WORKDIR 是一个文件夹,您可以在该文件夹中执行此研讨会的所有实验。在 Cloud Shell 中运行以下命令以创建 WORKDIR。

mkdir -p ${HOME}/asm-workshop
cd ${HOME}/asm-workshop
export WORKDIR=`pwd` 
 
  1. 将实验账号用户导出为变量,以用于此研讨会。此账号与您登录 Cloud Shell 时所用的账号相同。
export MY_USER=<LAB ACCOUNT EMAIL PROVIDED BY THE WORKSHOP ADMIN>
# For example export MY_USER=user001@gcpworkshops.com 
 
  1. 通过运行以下命令,对 WORKDIR 和 MY_USER 变量执行 echo 操作,确保这两者均正确设置。
echo "WORKDIR set to ${WORKDIR}" && echo "MY_USER set to ${MY_USER}"
 
  1. 克隆研讨会代码库。
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 update
  • sudo apt install git
  • jq
  • envsubst
  • kustomize
  • pv

访问 Terraform 管理项目

bootstrap_workshop.sh 脚本运行完毕后,系统会为组织内的每位用户创建一个 GCP 文件夹。在该文件夹中,会创建一个 terraform Admin 项目。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 存储分区中。

  1. 点击下面的链接,打开 Cloud Shell(如果尚未从“实验设置和准备”部分打开)。

Cloud Shell

  1. $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
 
  1. 安装 pv 并将其移至 $HOME/bin/pv。
sudo apt-get update && sudo apt-get -y install pv
sudo mv /usr/bin/pv ${HOME}/bin/pv
 
  1. 更新 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
 
  1. 确认您已使用目标用户账号登录 gcloud。
echo "Check logged in user output from the next command is $MY_USER"
gcloud config list account --format=json | jq -r .core.account
 
  1. 运行以下命令来获取 Terraform 管理项目 ID:
export TF_ADMIN=$(gcloud projects list | grep tf- | awk '{ print $1 }')
echo $TF_ADMIN
 
  1. 与研讨会相关的所有资源都以变量的形式存储在 vars.sh 文件中,这个文件存储在 Terraform 管理项目的 GCS 存储分区中。获取 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
 
  1. 点击显示的链接,打开 Terraform 管理项目的 Cloud Build 页面,并验证构建是否成功完成。
source $WORKDIR/asm/vars/vars.sh
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_ADMIN}"
 

如果是首次访问 Cloud Console,请同意《Google 服务条款》。

  1. 您现在看到的是 Cloud Build 页面,接下来请点击左侧导航栏中的 History 链接,然后点击最新 build,以查看初始 Terraform 应用的详细信息。以下资源是作为 Terraform 脚本的一部分创建的。您还可以参阅上面的架构图。
  • 组织内的 4 个 GCP 项目。所提供的结算账号与每个项目相关联。
  • 一个项目是共享 VPC 的 network host project。未在此项目中创建其他资源。
  • 一个项目是用于 Istio 控制平面 GKE 集群的 ops project
  • 两个项目代表两个不同的开发团队,他们致力于提供各自的服务。
  • 在这三个 opsdev1dev2 项目中分别创建了两个 GKE 集群。
  • 创建了一个名为 k8s-repo 的 CSR 代码库,其中包含六个用于 Kubernetes 清单文件的文件夹。每个 GKE 集群有一个文件夹。此代码库用于以 GitOps 方式将 Kubernetes 清单部署到集群。
  • 系统会创建一个 Cloud Build 触发器,以便在向 k8s-repo 的主分支提交内容时,它会将 Kubernetes 清单从其各自的文件夹部署到 GKE 集群。
  1. terraform admin project 中完成构建后,将在 ops 项目中启动另一个构建。点击显示的链接以打开 ops project 的 Cloud Build 页面,验证 k8s-repo Cloud Build 是否已成功完成。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
 

验证安装

  1. 为所有集群创建 kubeconfig 文件。运行以下脚本。
$WORKDIR/asm/scripts/setup-gke-vars-kubeconfig.sh
 

此脚本会在 gke 文件夹中创建一个名为 kubemesh 的新 kubeconfig 文件。

  1. KUBECONFIG 变量更改为指向新的 kubeconfig 文件。
source $WORKDIR/asm/vars/vars.sh
export KUBECONFIG=$WORKDIR/asm/gke/kubemesh
 
  1. 将 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
 
  1. 列出您的集群上下文。您应该会看到六个集群。
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 安装

  1. 通过检查所有 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
  1. 确保这两个 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
 
  1. 确保这两个 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

验证共享控制平面的服务发现

  1. (可选)验证是否已部署 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 集群。要跨集群发现服务,请使用在 Ops 集群中创建为 Secret 的 kubeconfig 文件(针对每个应用集群)。Pilot 通过查询应用集群的 Kube API 服务器(通过上述密钥进行身份验证),以利用这些密钥来发现服务。您可以看到,这两个 Ops 集群都可以使用 kubeconfig 创建的密钥向所有应用集群进行身份验证。Ops 集群可以使用 kubeconfig 文件作为 Secret 方法自动发现服务。这要求运维集群中的 Pilot 能够访问所有其他集群的 Kube API 服务器。如果 Pilot 无法连接到 Kube API 服务器,您需要手动添加远程服务作为 ServiceEntries。您可以将 ServiceEntry 视为服务注册表中的 DNS 条目。ServiceEntry 使用完全限定的 DNS 名称 ( FQDN) 和可访问的 IP 地址来定义服务。如需了解详情,请参阅 Istio 多集群文档

6. 基础设施代码库说明

基础架构 Cloud Build

本次研讨会的 GCP 资源使用 Cloud Buildinfrastructure CSR 代码库构建而成。您刚刚从本地终端运行了一个引导脚本(位于 scripts/bootstrap_workshop.sh)。该引导脚本会为 Cloud Build 服务账号创建一个 GCP 文件夹、一个 Terraform 管理项目以及相应的 IAM 权限。Terraform 管理项目用于存储 Terraform 状态、日志和其他脚本。它包含 infrastructurek8s_repo CSR 代码库。下一部分将详细介绍这些代码库。未在 Terraform 管理项目中构建任何其他研讨会资源。Terraform 管理项目中的 Cloud Build 服务账号用于为研讨会构建资源。

位于 infrastructure 文件夹中的 cloudbuild.yaml 文件用于为研讨会构建 GCP 资源。它会创建一个自定义构建器映像,其中包含创建 GCP 资源所需的所有工具。这些工具包括 gcloud SDK、terraform 和其他实用程序(如 python、git、jq 等)。自定义构建器映像会针对每个资源运行 terraform planapply。每个资源的 Terraform 文件都位于不同的文件夹中(详见下一部分)。这些资源是按照通常的构建方式逐步构建的(例如,先构建 GCP 项目,再在项目中创建资源)。如需了解详情,请参阅 cloudbuild.yaml 文件。

只要对 infrastructure 代码库进行提交,系统就会触发 Cloud Build。对基础架构所做的任何更改都将存储为基础架构即代码 (IaC) 并提交到代码库中。研讨会的状态始终存储在此代码库中。

文件夹结构 - 团队、环境和资源

Infrastructure 仓库用于为研讨会设置 GCP 基础架构资源。它采用文件夹和子文件夹的结构。代码库中的基本文件夹表示拥有特定 GCP 资源的 team。下一层文件夹代表团队的特定 environment(例如开发、阶段、生产)。环境中的下一层文件夹代表特定 resource(例如 host_project、gke_clusters 等)。所需的脚本和 Terraform 文件位于资源文件夹中。

434fc1769bb49b8c

本次研讨会涉及以下四种类型的团队:

  1. infrastructure - 代表云基础架构团队。他们负责为所有其他团队创建 GCP 资源。他们使用 Terraform 管理项目作为其资源。基础设施代码库本身位于 Terraform 管理项目中,以及 Terraform 状态文件(如下所述)。这些资源在引导过程中由 bash 脚本创建(如需了解详情,请参阅模块 0 - 管理员工作流程)。
  2. network - 代表网络团队。它们负责 VPC 和网络资源。他们拥有以下 GCP 资源。
  3. host project - 表示共享 VPC 宿主项目。
  4. shared VPC - 表示共享 VPC、子网、次要 IP 范围、路由和防火墙规则。
  5. ops - 表示运营/开发运营团队。他们拥有以下资源。
  6. ops project - 表示包含所有运维资源的项目。
  7. gke clusters - 每个区域的运维 GKE 集群。Istio 控制平面安装在每个运维 GKE 集群中。
  8. k8s-repo - 一个 CSR 代码库,其中包含所有 GKE 集群的 GKE 清单。
  9. apps - 表示应用团队。此研讨会模拟了两个团队,即 app1app2。他们拥有以下资源。
  10. app projects - 每个应用团队都有自己的一组项目。这使他们可以控制特定项目的结算和 IAM。
  11. gke clusters - 这些是运行应用容器/Pod 的应用集群。
  12. gce instances -(如果它们有在 GCE 实例上运行的应用,则为可选)。在本研讨会中,app1 有几个 GCE 实例,其中部分应用运行。

在此研讨会中,同一个应用 (Hipster Shop app) 同时代表 app1 和 app2。

提供程序、状态和输出 - 后端和共享状态

googlegoogle-beta 提供方位于 gcp/[environment]/gcp/provider.tfprovider.tf 文件在每个资源文件夹中都进行符号链接。这样,您就可以在一个位置更改提供程序,而不必单独管理每个资源的提供程序。

每个资源都包含一个 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_projectshared_vpc 资源的 shared_state 文件,因为您需要项目 ID 和 VPC 详细信息才能在 ops 项目中创建 GKE 集群。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 Repo 说明

k8s_repo 是位于 Terraform 管理项目中的 CSR 代码库(独立于基础设施代码库)。它用于存储 GKE 清单并将其应用于所有 GKE 集群。k8s_repo 由基础架构 Cloud Build 创建(如需了解详情,请参阅上一部分)。在初始基础架构 Cloud Build 流程中,总共会创建 6 个 GKE 集群。在 k8s_repo 中,创建了六个文件夹。每个文件夹(与 GKE 集群名称匹配的名称)都对应于一个包含其相应资源清单文件的 GKE 集群。与构建基础架构类似,Cloud Build 用于通过 k8s_repo 将 Kubernetes 清单应用于所有 GKE 集群。只要有内容提交到 k8s_repo 代码库,就会触发 Cloud Build。与基础架构类似,所有 Kubernetes 清单都以代码的形式存储在 k8s_repo 代码库中,并且每个 GKE 集群的状态始终存储在其各自的文件夹中。

在初始基础架构构建过程中,系统会创建 k8s_repo,并在所有集群上安装 Istio。

项目、GKE 集群和命名空间

本研讨会中的资源分为不同的 GCP 项目。项目应与贵公司的组织(或团队)结构一致。(贵组织中)负责不同项目/产品/资源的团队使用不同的 GCP 项目。通过设置单独的项目,您可以创建一组单独的 IAM 权限,并在项目级别管理结算。此外,配额也是在项目级别管理。

本次研讨会涉及五个团队,每个团队都有自己的项目。

  1. 构建 GCP 资源的基础架构团队使用 Terraform admin project。他们在 CSR 代码库(称为 infrastructure)中以代码形式管理基础架构,并将与在 GCP 中构建的资源相关的所有 Terraform 状态信息存储在 GCS 存储分区中。它们控制对 CSR 代码库和 Terraform 状态 GCS 存储分区的访问权限。
  2. 构建共享 VPC 的网络团队使用 host project。此项目包含 VPC、子网、路由和防火墙规则。拥有共享 VPC 可以让他们集中管理 GCP 资源的网络。所有项目都将这个共享 VPC 用于网络。
  3. 构建 GKE 集群和 ASM/Istio 控制平面的运维/平台团队使用 ops project。它们管理 GKE 集群和服务网格的生命周期。他们负责强化集群安全,管理 Kubernetes 平台的弹性和规模。在本研讨会中,您将使用 gitops 方法将资源部署到 Kubernetes。Ops 项目中存在 CSR 代码库(称为 k8s_repo)。
  4. 最后,构建应用的 dev1 和 dev2 团队(代表两个开发团队)使用自己的 dev1dev2 projects。这些是您向客户提供的应用和服务。它们构建在运营团队管理的平台上。资源(Deployment、Service 等)会被推送到 k8s_repo 并部署到相应的集群。值得注意的是,本研讨会并不关注 CI/CD 最佳实践和工具。您可以使用 Cloud Build 将 Kubernetes 资源直接自动部署到 GKE 集群。在实际生产场景中,您将使用适当的 CI/CD 解决方案将应用部署到 GKE 集群。

本研讨会中有两种类型的 GKE 集群。

  1. 运维集群 - 运营团队用来运行 DevOps 工具。在本次研讨会中,他们运行 ASM/Istio 控制平面来管理服务网格。
  2. 应用(应用)集群 - 开发团队用来运行应用。本研讨会使用“Hipster Shop”应用。

通过将操作/管理工具与运行应用的集群分离,您可以独立管理每个资源的生命周期。这两种集群也存在于与使用它们的团队/产品相关的不同项目中,这使得 IAM 权限也更易于管理。

共有六个 GKE 集群。在 Ops 项目中创建了两个区域级操作集群。ASM/Istio 控制平面安装在两个 Ops 集群中。每个运维集群都位于不同的区域。此外,还有四个可用区级应用集群。这些过滤器在各自的项目中创建。此研讨会模拟了两个开发团队,每个团队都有自己的项目。每个项目包含两个应用集群。应用集群是不同可用区的可用区级集群。四个应用集群位于两个区域和四个可用区。这样,您就可以实现区域和可用区级冗余。

本研讨会中使用的应用“Hipster Shop”应用全部部署在四个应用集群中。每个微服务都位于每个应用集群中各自的命名空间中。Hipster Shop 应用 Deployment (Pod) 未部署在运维集群上。但是,所有微服务的命名空间和 Service 资源也会在 Ops 集群中创建。ASM/Istio 控制平面使用 Kubernetes 服务注册表进行服务发现。在 Ops 集群中没有 Service 时,您必须手动为应用集群中运行的每项服务创建 ServiceEntry。

在本研讨会中,您将部署一个 10 层的微服务应用。此应用是一个基于网络的电子商务应用,名为“Hipster Shop”在这里,用户可以浏览商品、将商品添加到购物车以及购买商品。

Kubernetes 清单和 k8s_repo

您可以使用 k8s_repo 将 Kubernetes 资源添加到所有 GKE 集群。为此,您需要复制 Kubernetes 清单并提交到 k8s_repo。对 k8s_repo 的所有提交都会触发 Cloud Build 作业,该作业会将 Kubernetes 清单部署到相应的集群。每个集群的清单都位于与集群名称相同的单独文件夹中。

这六个集群名称分别为:

  1. gke-asm-1-r1-prod - 区域 1 中的区域级操作集群
  2. gke-asm-2-r2-prod - 区域 2 中的区域级操作集群
  3. gke-1-apps-r1a-prod - 区域 1 可用区 a 中的应用集群
  4. gke-2-apps-r1b-prod - 区域 1 可用区 b 中的应用集群
  5. gke-3-apps-r2a-prod - 区域 2 可用区 a 中的应用集群
  6. gke-4-apps-r2b-prod - 区域 2 可用区 b 中的应用集群

k8s_repo 具有与这些集群对应的文件夹。放置在这些文件夹中的任何清单都会应用于相应的 GKE 集群。每个集群的清单都放在子文件夹(位于集群的主文件夹中)中,以方便管理。在本研讨会中,您将使用 Kustomize 跟踪部署的资源。如需了解详情,请参阅 Kustomize 官方文档。

7. 部署示例应用

目标:在应用集群上部署 Hipster Shop 应用

  • k8s-repo克隆
  • 将 Hipster 商店清单复制到所有应用集群
  • 在运营集群中为 Hipster 商店应用创建服务
  • 在操作集群中设置 loadgenerators 以测试全局连接
  • 验证与 Hipster Shop 应用的安全连接

复制和粘贴方法实验室说明

克隆 Ops 项目源代码库

在初始 Terraform 基础架构构建过程中,k8s-repo 已在 ops 项目中创建。

  1. 为 Git 代码库创建一个空目录:
mkdir $WORKDIR/k8s-repo
 
  1. 创建 Git 代码库,添加远程代码库并从远程代码库中拉取主实例:
cd $WORKDIR/k8s-repo
git init && git remote add origin \
https://source.developers.google.com/p/$TF_VAR_ops_project_name/r/k8s-repo
 
  1. 设置本地 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

复制清单、提交和推送

  1. 将 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/.
 
  1. 将应用文件夹 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/
 
  1. 将 Hipster Shop Deployment、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/
  1. 从所有开发集群中移除 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
 
  1. 仅在第一个开发集群中将 cartservice 部署、rbac 和 podsecuritypolicy 添加到 kustomization.yaml。
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
 
  1. 从操作集群 kustomization.yaml 中移除 podsecuritypolicies、deployment 和 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
  1. 替换 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/*
  
  1. 将 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/
 
  1. 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/
 
  1. 替换配置连接器清单中的 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/*
 
  1. loadgenerator 清单(Deployment、PodSecurityPolicy 和 RBAC)复制到 ops 集群。使用全球 Google Cloud 负载平衡器 (GCLB) 公开 Hipster Shop 应用。GCLB 会接收客户端流量(发往 frontend),并将其发送到最近的 Service 实例。在两个 ops 集群上放置 loadgenerator 可确保流量同时发送到在 ops 集群中运行的两个 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/. 
 
  1. 替换这两个操作集群的 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
 

  1. 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
 

  1. 提交到 k8s-repo
cd $WORKDIR/k8s-repo
git add . && git commit -am "create app namespaces and install hipster shop"
git push --set-upstream origin master 
 
  1. 请在之前打开的标签页中查看 Ops 项目 Cloud Build 的状态,或者点击下面的链接:
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
  

验证应用部署

  1. 验证所有应用命名空间(购物车除外)中的 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
  1. 验证购物车命名空间中的 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 应用部署到所有四个应用集群。这些集群位于 2 个区域和 4 个可用区中。客户可以通过访问 frontend 服务来访问 Hipster 商店应用。frontend 服务在所有四个应用集群上运行。使用 Google Cloud 负载平衡器 ( GCLB) 获取流向 frontend 服务的所有四个实例的客户端流量。

Istio Ingress 网关仅在 Ops 集群中运行,并充当区域内两个可用区级应用集群的区域负载平衡器。GCLB 使用两个 Istio 入站流量网关(在两个 Ops 集群中运行)作为全局前端服务的后端。Istio Ingress 网关从 GCLB 接收客户端流量,然后将客户端流量继续发送到应用集群中运行的前端 Pod。

4c618df35cb928ee.png

或者,您也可以直接将 Istio Ingress 网关放置在应用集群上,GCLB 可将其用作后端。

GKE Autoneg 控制器

Istio Ingress 网关 Kubernetes Service 使用网络端点组 (NEG) 将自身注册为 GCLB 的后端。NEG 允许使用 GCLB 进行容器原生负载均衡。NEG 通过针对 Kubernetes Service 的特殊注释创建,因此可以自行注册到 NEG 控制器。Autoneg 控制器是一种特殊的 GKE 控制器,它可以自动创建 NEG,并使用 Service 注解将其作为后端分配给 GCLB。包括 Istio Ingress 网关在内的 Istio 控制平面在初始基础架构 Terraform Cloud Build 期间部署。GCLB 和 Autoneg 配置在初始 Terraform 基础设施 Cloud Build 中完成。

使用 Cloud Endpoints 和代管式证书保护 Ingress

GCP 代管式证书用于保护流向 frontend GCLB 服务的客户端流量。GCLB 为全局 frontend 服务使用代管式证书,并且证书会在 GCLB 时终止。在此研讨会中,您将使用 Cloud Endpoints 作为托管式证书的网域。或者,您也可以使用您的域名和 frontend 的 DNS 名称来创建 GCP 管理的证书。

  1. 如需访问 Hipster 商店,请点击以下命令的输出结果。
echo "https://frontend.endpoints.$TF_VAR_ops_project_name.cloud.goog" 
 
  1. 您可以点击 Chrome 标签页网址栏中的锁形符号,检查该证书是否有效。

6c403a63caa06c84

验证全球负载均衡

作为应用部署的一部分,负载生成器部署在两个操作集群中,用于生成 GCLBHipster Shop Cloud Endpoints 链接的测试流量。验证 GCLB 是否在接收流量并发送到这两个 Istio Ingress 网关。

  1. 获取 GCLB >“监控”链接,找到创建其创建 Hipster Shop GCLB 的运维项目的链接。
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" 
 
  1. 在“后端”下拉菜单中,从所有后端更改为 istio-ingressgateway,如下所示。

6697c9eb67998d27

  1. 请注意流向 istio-ingressgateways 的流量。

ff8126e44cfd7f5e.png

每个 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 的内置负荷生成系统。在没有流量的静态系统中,可观测性效果不佳,因此负载生成可以帮助我们了解其工作原理。此加载作业已在运行,现在我们可以看到它了。

  1. 将 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
 
  1. 提交到 k8s-repo。
cd $WORKDIR/k8s-repo
git add . && git commit -am "Install istio to stackdriver configuration"
git push 
 
  1. 请在之前打开的标签页中查看 Ops 项目 Cloud Build 的状态,或者点击下面的链接:
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
 
  1. 验证 Istio → Stackdriver 集成 获取 Stackdriver Handler CRD。
kubectl --context $OPS_GKE_1 get handler -n istio-system
 

输出应显示名为 Stackdriver 的处理程序:

NAME            AGE
kubernetesenv   12d
prometheus      12d
stackdriver     69s      # <== NEW!
  1. 验证导出到 Stackdriver 的 Istio 指标是否正常运行。点击此命令输出的链接:
echo "https://console.cloud.google.com/monitoring/metrics-explorer?cloudshell=false&project=$TF_VAR_ops_project_name"
 

系统会提示您创建以 Ops 项目命名的新工作区,只需选择“确定”(OK)。如果系统提示您安装新界面,只需关闭该对话框即可。

在 Metrics Explorer 中的“查找资源类型和指标”下输入“istio”您可以看到“服务器请求数”等选项“Kubernetes 容器”资源类型。这表明指标正在从网格流向 Stackdriver。

(如果您想看到以下几行内容,就必须按 destination_service_name 标签分组。)

b9b59432ee68e695.png

使用信息中心直观呈现指标

既然指标已存储在 Stackdriver APM 系统中,接下来我们想通过一种方式直观呈现这些指标。在本部分中,我们将安装一个预构建的信息中心,该信息中心会显示Golden Signals”指标:流量(每秒请求数)、延迟时间(本例中为第 99 和第 50 百分位)和错误(本例中我们排除了“饱和度”)。

Istio 的 Envoy 代理为我们提供了几个指标,但这些指标很适合开始时使用。(完整列表请参见此处)。请注意,每个指标都有一组可用于过滤和汇总的标签,例如:destination_service、source_workload_namespace、response_code、istio_tcp_received_bytes_total 等。

  1. 现在,我们来添加预制指标信息中心。我们将直接使用 Dashboard API。这是您通常无法通过手动生成 API 调用来完成的操作、它是自动化系统的一部分,或者您可以在网页界面中手动构建信息中心。这些内容将帮助我们快速上手:
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
 
  1. 请导航至下面的输出链接,查看新添加的“服务信息中心”。
echo "https://console.cloud.google.com/monitoring/dashboards/custom/servicesdash?cloudshell=false&project=$TF_VAR_ops_project_name"
 
 

我们可以使用用户体验就地修改信息中心,但在本例中,我们将使用 API 快速添加新图表。为此,您应该下载最新版本的信息中心,应用您的修改,然后使用 HTTP PATCH 方法将其重新推回。

  1. 您可以通过查询 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
 
  1. 添加新图表:(第 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
 
  1. 更新现有服务信息中心:
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
 
  1. 您可以前往以下输出链接查看更新后的信息中心:
echo "https://console.cloud.google.com/monitoring/dashboards/custom/servicesdash?cloudshell=false&project=$TF_VAR_ops_project_name"
 
  1. 进行一些简单的日志分析。

Istio 为所有网状网络流量提供一组结构化日志,并将其上传到 Stackdriver Logging,以便在一个强大的工具中进行跨集群分析。日志使用服务级元数据(例如集群、容器、应用、连接 ID 等)进行注释。

示例日志条目(在本示例中为 Envoy 代理的访问日志)可能如下所示(经过整理):

*** 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"
 

您可以选择 Resource > 来查看 Istio 的控制平面日志Kubernetes Container,以及搜索“pilot”-

6f93b2aec6c4f520

在这里,我们可以看到 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"

  1. 查看分布式跟踪记录。

既然您正在处理分布式系统,现在调试需要一种新工具:Distributed Tracing。借助此工具,您可以发现有关服务如何交互的统计信息(例如,查找下图中的异常慢事件),并深入分析原始示例跟踪记录以调查实际发生的情况的详细信息。

Timeline 视图可以显示一段时间内所有请求,通过其延迟时间或初始请求通过 Hipster 堆栈最终响应最终用户所花费的时间。点越高,用户体验越慢,满意度也会越低。

您可以点击某个点,查看该特定请求的详细瀑布视图。查找特定请求的原始详细信息(而不仅仅是汇总统计信息)的能力对于理解服务之间的相互作用至关重要,尤其是在寻找服务间罕见但糟糕的交互时。

使用过调试程序的用户应该很熟悉瀑布视图,但在本例中,它显示的是遍历网格、在服务之间以及在单独的容器中运行所花费的时间,而不是显示单个应用的不同进程中所花费的时间。

您可以在这里找到您的跟踪记录:

echo "https://console.cloud.google.com/traces/overview?cloudshell=false&project=$TF_VAR_ops_project_name"
 

该工具的屏幕截图示例:

5ee238836dc9047f

9. 双向 TLS 身份验证

目标:微服务 (AuthN) 之间的安全连接。

  • 启用网格范围的 mTLS
  • 通过检查日志验证 mTLS

复制和粘贴方法实验室说明

现在,我们已经安装了应用并设置可观测性,接下来我们可以开始保护服务之间的连接并确保它继续正常运行。

例如,在 Kiali 信息中心,我们可以看到我们的服务未使用 MTLS(没有“锁定”图标)。但路况在传输,系统运行正常。整体而言,我们的 StackDriver Golden Metrics 信息中心让我们大体知道一切运作正常。

  1. 检查操作集群中的 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。设置全局 >mTLSenabled: true 会导致 Istio 控制平面出现以下两项更改:

  • MeshPolicy 设置为为所有集群中运行的所有 Service 启用 mTLS 网格范围。
  • 创建了 DestinationRule,以允许在所有集群中运行的 Service 之间提供 ISTIO_MUTUAL 流量。
  1. 我们将对 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
 
  1. 提交到 k8s-repo。
cd $WORKDIR/k8s-repo
git add . && git commit -am "turn mTLS on"
git push
 
  1. 请在之前打开的标签页中查看 Ops 项目 Cloud Build 的状态,或者点击下面的链接:
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"

 

验证 mTLS

  1. 在操作集群中再次检查 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": {}
    }
  ]
}
  1. 描述 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 的迁移。

我们可以在界面中显示此特定字段,具体方法是:点击一个日志条目,然后点击要显示的字段的值。在本例中,点击“http”“协议:

d92e0c88cd5b2132.png

这样可以很好地直观呈现转换效果:

ea3d0240fa6fed81.png

10. Canary 部署

目标:发布新版前端服务。

  • 在一个区域中发布 frontend-v2(下一个正式版)服务
  • 使用DestinationRulesVirtualServices缓慢引导流量前往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 应用本身的错误而导致的全球服务中断。

注意:我们将在这两个区域中手动触发 Canary 流水线,但在生产环境中,您需要使用自动触发器,例如基于推送到注册表的新 Docker 映像标记。

  1. 在 Cloud Shell 中,定义一些环境变量,以简化其余命令的运行过程。
CANARY_DIR="$WORKDIR/asm/k8s_manifests/prod/app-canary/"
K8S_REPO="$WORKDIR/k8s-repo"
 
  1. 运行 repo_setup.sh 脚本,以将基准清单复制到 k8s-repo 中。
$CANARY_DIR/repo-setup.sh 
 

系统会复制以下清单:

  • frontend-v2 部署
  • frontend-v1 补丁(包含“v1”标签和带有“/version”端点的映像)
  • respy,一个小型 Pod,用于输出 HTTP 响应分布,并帮助我们实时直观呈现 Canary 部署。
  • 前端 Istio DestinationRule - 根据“版本”将前端 Kubernetes 服务拆分为两个子集:v1 和 v2部署标签
  • frontend Istio VirtualService - 将 100% 的流量路由到前端 v1。这会替换 Kubernetes 服务的默认轮循行为,从而立即将 50% 的 Dev1 区域流量发送到 frontend v2。
  1. 提交对 k8s_repo 的更改
cd $K8S_REPO 
git add . && git commit -am "frontend canary setup"
git push
 
  1. 请在之前打开的标签页中查看 Ops 项目 Cloud Build 的状态,或者点击下面的链接:
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}" 
 
  1. 在控制台中,前往 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 将 cloudshell 窗口拆分为 2 个窗格

  • 底部窗格将运行 watch 命令,以观察前端服务的 HTTP 响应分布。
  • 顶部窗格将运行实际的 Canary 流水线脚本。
  1. 运行该命令拆分 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%            |
|          |                   |
+----------+-------------------+
  1. 在 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%             |
|          |                   |
+----------+-------------------+
  1. 在 frontend-v2 的 Dev2 发布完成后,您应该会在脚本末尾看到一条成功消息:
     Output (do not copy) 
    
✅ 100% successfully deployed
🌈 frontend-v2 Canary Complete for gke-asm-1-r1-prod
  1. 来自 Dev2 Pod 的所有前端流量都应进入 frontend-v2:
     Output (do not copy) 
    
500 requests to http://frontend:80/version...
+----------+-------------------+
| RESPONSE | % OF 500 REQUESTS |
+----------+-------------------+
| v2       | 100.0%            |
|          |                   |
+----------+-------------------+
  1. 关闭拆分窗格。
tmux respawn-pane -t ${TMUX_SESSION}:0.1 -k 'exit'
 
  1. 点击生成的链接,进入 Cloud Source Repos。
echo https://source.developers.google.com/p/$TF_VAR_ops_project_name/r/k8s-repo

您应该会看到每个流量百分比分别对应的提交内容,其中最近的提交内容位于列表顶部:

b87b85f52fd2ff0f.png

现在,您将对 Dev2 区域重复相同的过程。请注意,Dev2 区域仍处于“锁定”状态,。这是因为在基准 repo_setup 脚本中,我们推送了一项 VirtualService,将所有流量明确发送到 v1。这样,我们就可以安全地对 Dev1 进行区域级 Canary 版测试,并确保其成功运行,然后再面向全球发布新版本。

  1. 运行该命令拆分 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%            |
|          |                   |
+----------+-------------------+
  1. 在 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%            |
|          |                   |
+----------+-------------------+
  1. 从 Dev2 中的 Respy Pod,观察来自 Dev2 Pod 的流量从前端 v1 逐步迁移到 v2。脚本运行完毕后,您应该会看到以下内容:

输出(请勿复制)

500 requests to http://frontend:80/version...
+----------+-------------------+
| RESPONSE | % OF 500 REQUESTS |
+----------+-------------------+
| v2       | 100.0%            |
|          |                   |
+----------+-------------------+
  1. 关闭拆分窗格。
tmux respawn-pane -t ${TMUX_SESSION}:0.1 -k 'exit'

本部分介绍了如何使用 Istio 进行区域级 Canary 部署。在生产环境中,您可以使用触发器(例如推送到 Container Registry 的新标记映像)自动触发此 Canary 脚本作为 Cloud Build 流水线,而不是手动脚本。您还需要在每个步骤之间添加 Canary 分析,根据预定义的安全阈值分析 v2 的延迟时间和错误率,然后再发送更多流量。

11. 授权政策

目标:在微服务 (AuthZ) 之间设置 RBAC。

  • 创建 AuthorizationPolicy 以拒绝对微服务的访问
  • 创建 AuthorizationPolicy 以允许对微服务的特定访问权限

复制和粘贴方法实验室说明

与可能在一个位置运行的单体式应用不同,全球分布式微服务应用可以跨网络边界进行调用。这意味着有更多应用进入点,也就有更多机会遭到恶意攻击。此外,由于 Kubernetes Pod 具有瞬时 IP,基于 IP 的传统防火墙规则不足以保护工作负载之间的访问。在微服务架构中,需要一种新的安全方法。Istio 以服务账号等 Kubernetes 安全基础组件为基础,为您的应用提供一套灵活的安全政策

Istio 政策涵盖身份验证和授权。身份验证用于验证身份(服务器是否与其声称的身份相符?),而授权用于验证权限(允许此客户端这样做吗?)。我们在第 1 单元 (MeshPolicy) 的双向 TLS 部分介绍了 Istio 身份验证。在本节中,我们将学习如何使用 Istio 授权政策来控制对我们的应用工作负载 currencyservice 的访问权限。

首先,我们将在所有 4 个开发集群中部署 AuthorizationPolicy,从而关闭对 currencyservice 的所有访问,并在前端触发错误。然后,我们将仅允许前端服务访问 currencyservice。

  1. 检查 currency-deny-all.yaml 的内容。此政策使用 Deployment 标签选择器来限制对 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
  1. 针对这两个区域中的运维集群,将货币政策复制到 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
  1. 推送更改。
cd $WORKDIR/k8s-repo 
git add . && git commit -am "AuthorizationPolicy - currency: deny all"
git push 
  1. 请在之前打开的标签页中查看 Ops 项目 Cloud Build 的状态,或者点击下面的链接:
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name 
 
  1. 构建成功完成后,请尝试通过以下链接在浏览器中访问该程序的前端:
echo "https://frontend.endpoints.$TF_VAR_ops_project_name.cloud.goog" 
 

您应该会看到 currencyservice 中的授权错误:

f120f3d30d6ee9f.png

  1. 我们来研究一下货币服务如何执行此 AuthorizationPolicy。首先,在 Envoy 代理上为其中一个货币 Pod 启用跟踪记录级别的日志,因为默认情况下不会记录阻止的授权调用。
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"
 
  1. 从货币服务的 Sidecar 代理获取 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
  1. 现在,我们允许前端(但不允许其他后端服务)访问 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 AuthorizationPolicy 中使用 Kubernetes 服务账号时,您必须先启用集群范围的双向 TLS,就像我们在单元 1 中所做的那样。这是为了确保将服务账号凭据装载到请求中。

  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
 
  1. 推送更改。
cd $WORKDIR/k8s-repo
git add . && git commit -am "AuthorizationPolicy - currency: allow frontend"
git push
 
  1. 请在之前打开的标签页中查看 Ops 项目 Cloud Build 的状态,或者点击下面的链接:
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
  1. 构建成功完成后,再次打开 Hipstershop 前端。这一次,您应该不会在首页中看到错误 - 这是因为已明确允许前端访问当前服务。
  2. 现在,尝试执行结账操作,只需将商品添加到购物车并点击“下单”即可。这一次,您应该看到来自币种服务的价格转换错误 - 这是因为我们只将前端列入白名单,所以结账服务仍然无法访问 currencyservice。

7e30813d693675fe

  1. 最后,通过向 currencyservice AuthorizationPolicy 添加另一条规则,允许结账服务访问货币。请注意,我们仅向需要访问货币的两项服务(前端和结账)开放货币访问权限。其他后端仍将被屏蔽。
  2. 打开 currency-allow-frontend-checkout.yaml 并检查其内容。请注意,规则列表的功能为逻辑“或”- 币种将仅接受来自具有这两个服务账号之一的工作负载的请求。
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"]
  1. 将最终授权政策复制到 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
 
  1. 推送更改
cd $WORKDIR/k8s-repo 
git add . && git commit -am "AuthorizationPolicy - currency: allow frontend and checkout"
git push
 
  1. 请在之前打开的标签页中查看 Ops 项目 Cloud Build 的状态,或者点击下面的链接:
echo https://console.cloud.google.com/cloud-build/builds?project=$TF_VAR_ops_project_name
 
  1. 构建成功完成后,尝试执行签出 - 它应该可以成功执行。

本部分介绍如何使用 Istio 授权政策在每项服务层级实施精细的访问权限控制。在生产环境中,您可以为每项服务创建一个 AuthorizationPolicy,并(例如)使用 allow-all 政策,以允许同一命名空间中的所有工作负载相互访问。

12. 基础架构扩缩

目标:通过添加新的区域、项目和集群来扩展基础架构。

  • 克隆 infrastructure 代码库
  • 更新 Terraform 文件以创建新资源
  • 新区域中的 2 个子网(一个用于运维项目,一个用于新项目)
  • 新区域中的新操作集群(在新子网中)
  • 新区域的新 Istio 控制平面
  • 新区域中新项目中的 2 个应用集群
  • 提交到 infrastructure 代码库
  • 验证安装

复制和粘贴方法实验室说明

您可以通过多种方式扩展平台。您可以通过向现有集群添加节点来添加更多计算资源。您可以在一个区域中添加更多集群。或者,您可以向平台添加更多地区。扩展平台的哪个方面取决于具体要求。例如,如果您在一个区域中的所有三个可用区都有集群,向现有集群添加更多节点(或节点池)可能就足够了。但是,如果您在一个区域内的三个可用区中的两个可用区中都有集群,则通过在第三个可用区添加新集群,您可以进行扩缩,并额外添加一个故障网域(即一个新可用区)。在区域中添加新集群的另一个原因可能是,出于监管或合规性原因(例如 PCI,或包含 PII 信息的数据库集群),需要创建单个租户集群。随着您的业务和服务不断扩张,我们不可避免地要添加新的地区,以便提供更靠近客户的服务。

当前平台由两个区域以及每个区域两个可用区中的集群组成。您可以从以下两种方式着手扩展平台:

  • 垂直 - 在每个区域内添加更多计算。为此,您可以向现有集群添加更多节点(或节点池),或者在区域内添加新集群。此操作通过 infrastructure 代码库完成。最简单的方法是向现有集群添加节点。无需进行其他配置。添加新集群可能需要额外的子网(和次要范围)、添加适当的防火墙规则、将新集群添加到区域级 ASM/Istio 服务网格控制平面,以及将应用资源部署到新集群。
  • 横向 - 通过添加更多区域。当前平台为您提供了区域级模板。它包含一个区域级运维集群(ASM/Istio 控件位于其中)和两个(或更多)可用区级应用集群(部署应用资源)。

在本次研讨会中,您将“横向”扩缩该平台因为它也包含纵向应用场景步骤为了通过向平台添加新区域 (r3) 来横向扩缩平台,需要添加以下资源:

  1. 区域 r3 中宿主项目共享 VPC 中的子网,用于新操作和应用集群。
  2. ASM/Istio 控制平面所在的区域 r3 中的区域级操作集群。
  3. 区域 r3 上两个可用区中的两个可用区级应用集群。
  4. 更新到 k8s-repo:
  5. 将 ASM/Istio 控制平面资源部署到区域 r3 中的运维集群。
  6. 将 ASM/Istio 共享控制平面资源部署到区域 r3 中的应用集群。
  7. 虽然您不需要创建新项目,但此研讨会中的步骤演示了如何添加新项目 dev3,以涵盖向平台添加新团队这一用例。

基础架构代码库用于添加上述新资源。

  1. 在 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
  1. 将研讨会源代码库 add-proj 分支克隆到 add-proj-repo 目录中。
cd $WORKDIR
git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-workshop.git add-proj-repo -b add-proj

 
  1. 从源 Workshop 代码库中复制 add-proj 分支中的文件。add-proj 分支包含本部分的变更。
cp -r $WORKDIR/add-proj-repo/infrastructure/* $WORKDIR/infra-repo/
 
  1. 将 add-proj 代码库目录中的 infrastructure 目录替换为指向 infra-repo 目录的符号链接,以允许分支上的脚本运行。
rm -rf $WORKDIR/add-proj-repo/infrastructure
ln -s $WORKDIR/infra-repo $WORKDIR/add-proj-repo/infrastructure
 
  1. 运行 add-project.sh 脚本,将共享状态和变量复制到新的项目目录结构。
$WORKDIR/add-proj-repo/scripts/add-project.sh app3 $WORKDIR/asm $WORKDIR/infra-repo
  1. 提交并推送更改以创建新项目
cd $WORKDIR/infra-repo
git add .
git status
git commit -m "add new project" && git push origin master
 

  1. 提交操作会触发 infrastructure 代码库使用新资源部署基础架构。点击以下链接的输出,并在顶部找到最新的构建,以查看 Cloud Build 进度。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_ADMIN}"
 

infrastructure Cloud Build 的最后一步会在 k8s-repo 中创建新的 Kubernetes 资源。这将在 k8s-repo(在 ops 项目中)中触发 Cloud Build。新的 Kubernetes 资源适用于上一步中添加的三个新集群。ASM/Istio 控制平面和共享控制平面资源会通过 k8s-repo Cloud Build 添加到新集群中。

  1. 基础架构 Cloud Build 成功完成后,点击以下输出链接,转到 k8s-repo 最新的 Cloud Build 运行。
echo "https://console.cloud.google.com/cloud-build/builds?project=${TF_VAR_ops_project_name}"
 
  1. 运行以下脚本,将新集群添加到 vars 和 kubeconfig 文件中。
$WORKDIR/add-proj-repo/scripts/setup-gke-vars-kubeconfig-add-proj.sh $WORKDIR/asm
 
  1. KUBECONFIG 变量更改为指向新的 kubeconfig 文件。
source $WORKDIR/asm/vars/vars.sh
export KUBECONFIG=$WORKDIR/asm/gke/kubemesh
 
  1. 列出您的集群上下文。您应该会看到八个集群。
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 安装

  1. 通过检查所有 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
  1. 确保这两个 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

验证共享控制平面的服务发现

  1. 验证在所有六个应用集群的所有运维集群中都部署了密钥。
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 Service 创建 DestinationRule 以实现断路器
  • 使用 fortio(一种负载生成实用程序)通过强制剥离线路,验证 shipping 服务的断路器

Fast Track 脚本实验室说明

Fast Track 脚本实验室即将推出!!

复制和粘贴方法实验室说明

现在,我们已经了解了针对启用 Istio 的服务的一些基本的监控和问题排查策略,下面我们来看看 Istio 如何帮助您提高服务的弹性,从而减少您首先必须执行的问题排查工作。

微服务架构会带来级联故障的风险,在这种情况下,一项服务的故障可能会传播到其依赖项以及这些依赖项的依赖项,从而产生“涟漪效应”可能会影响最终用户的服务中断。Istio 提供 Circuit Breaker 流量政策来帮助您隔离服务,防止下游(客户端)服务等待发生故障的服务,并保护上游(服务器端)服务免遭下行流量突然涌现(当它们恢复在线状态时)。总体而言,使用断路器可帮助您避免所有服务因一项后端服务挂起而导致其 SLO 失败。

断路器模式以能够“跳动”的电开关命名从而防止设备过载在 Istio 设置中,这意味着 Envoy 是断路器,用于跟踪服务的待处理请求数量。在此默认关闭状态下,请求会不间断地流经 Envoy。

但是,如果待处理请求的数量超过您定义的阈值,断路器将跳动(打开),Envoy 会立即返回错误。这样可让服务器在客户端上快速出现故障,并防止服务器应用代码在过载时收到客户端请求。

然后,在您定义的超时之后,Envoy 将进入半开状态,此时服务器可以以试用的方式再次开始接收请求,如果它可以成功响应请求,断路器将再次关闭,并且发送到服务器的请求重新开始流。

图表总结了 Istio 断路器模式。蓝色矩形表示 Envoy,蓝色实心圆表示客户端,白色实心圆表示服务器容器:

2127a0a172ff4802

您可以使用 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% 的产品清单 Pod 将受到新的客户端请求的影响,为期 10 秒。Envoy 断路器开启(即活动)后,客户端将收到 503(服务不可用)错误。我们来看看实际用例。

  1. 为 k8s-repo 和 asm dir 设置环境变量以简化命令。
export K8S_REPO="${WORKDIR}/k8s-repo"
export ASM="${WORKDIR}/asm" 
 
  1. 更新 k8s-repo
cd $WORKDIR/k8s-repo
git pull
cd $WORKDIR
  1. 在两个操作集群上更新配送服务 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
 
  1. Fortio 负载生成器 Pod 复制到 Dev1 区域中的 GKE_1 集群中。这是我们将用于“行程”的客户端 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
 
  1. 提交更改。
cd $K8S_REPO 
git add . && git commit -am "Circuit Breaker: shippingservice"
git push
cd $ASM
 
  1. 等待 Cloud Build 完成。
  2. 返回 Cloud Shell,使用 fortio Pod 将 gRPC 流量发送到具有 1 个并发连接的 shippingservice - 共 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
  1. 现在再次运行 fortio,将并发连接数增加到 2,但保持请求总数不变。我们应该会看到,最多三分之二的请求会返回“overflow”错误,因为断路器已跳动:在我们定义的政策中,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
  1. 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
  1. 通过从两个区域移除断路器政策进行清理。
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 Service 创建 VirtualService,以引入 5 秒延迟
  • 使用 fortio 负载生成器测试延迟
  • 移除 VirtualService 中的延迟并验证

Fast Track 脚本实验室说明

Fast Track 脚本实验室即将推出!!

复制和粘贴方法实验室说明

向服务添加断路器政策是针对生产环境中的服务构建弹性的一种方式。然而,断路会导致故障,从而可能出现面向用户的错误,这并不理想。为了提前应对这些错误情况,并更好地预测在后端返回错误时下游服务可能会如何响应,您可以在预演环境中采用混淆测试。混淆测试是故意破坏服务,以分析系统中的弱点并提高容错能力的做法。您还可以使用混淆测试来确定在后端失败时减少面向用户的错误的方法,例如在前端显示缓存的结果。

使用 Istio 进行故障注入非常有用,因为您可以使用生产版本映像,并在网络层添加故障,而无需修改源代码。在生产环境中,除了在网络层之外,您还可以使用成熟的混淆测试工具在 Kubernetes/计算层测试弹性。

您可以使用 Istio 进行混淆测试,只需应用具有“故障”的 VirtualService 即可字段。Istio 支持两种故障:延迟故障(注入超时)和中止故障(注入 HTTP 错误)。在此示例中,我们将在推荐服务中注入一个 5 秒延迟故障。但这一次,不是使用断路器“快速失败”此挂起服务,我们将强制下游服务忍受全部超时。

  1. 导航到故障注入目录。
export K8S_REPO="${WORKDIR}/k8s-repo"
export ASM="${WORKDIR}/asm/" 
cd $ASM
 
  1. 打开 k8s_manifests/prod/istio-networking/app-recommendation-vs-fault.yaml 以检查其内容。请注意,Istio 提供了将故障注入一定比例的请求的选项。在这里,我们将在所有 Recommendationsservice 请求中引入超时。

输出(请勿复制)

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
  1. 将 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
 
  1. 推送更改
cd $K8S_REPO 
git add . && git commit -am "Fault Injection: recommendationservice"
git push
cd $ASM
 
  1. 等待 Cloud Build 完成。
  2. 执行到断路器部分中部署的 Fortio Pod,并将一些流量发送到 Recommendationsservice。
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
  1. 另一种查看我们实际注入的故障的方式是在网络浏览器中打开前端,然后点击任意产品。商品页面应额外需要 5 秒才能加载完毕,因为它会提取显示在页面底部的推荐内容。
  2. 通过从两个 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
 
  1. 推送更改:
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 信息中心,让运营人员能够直观呈现这些监控数据,并评估控制平面的运行状况和性能。

查看信息中心

  1. 对使用 Istio 安装的 Grafana 服务进行端口转发
kubectl --context ${OPS_GKE_1} -n istio-system port-forward svc/grafana 3000:3000 >> /dev/null
 
  1. 在浏览器中打开 Grafana
  2. 点击“网页预览”点击 Cloud Shell 窗口右上角的图标
  3. 点击端口 3000 上的“预览”(注意:如果端口不是 3000,请点击“更改端口”并选择端口 3000)
  4. 此操作会在浏览器中打开一个网址类似于“BASE_网址/?orgId=1&authuser=0&environment_id=default
  5. 查看可用的信息中心
  6. 将网址修改为“BASE_URL/dashboard&quot;
  7. 点击“istio”文件夹,用于查看可用的信息中心
  8. 点击其中任一信息中心即可查看该组件的效果。我们将在接下来的部分中介绍每个组件的重要指标。

监测飞行员

Pilot 是将网络和政策配置分布到数据平面(Envoy 代理)的控制平面组件。小规模测试往往会随工作负载和部署的数量而扩展,但不一定根据这些工作负载的流量量而扩展。健康状况不佳的飞行员可能会:

  • 会消耗不必要的资源(CPU 和/或 RAM)
  • 会导致在将更新后的配置信息推送到 Envoys 时出现延迟

注意:如果 Pilot 停止或出现延迟,您的工作负载仍会处理流量。

  1. 导航至“BASE_URL/dashboard/db/istio-pilot-dashboard&quot;在浏览器中查看试行计划指标。

重要的受监控指标

资源使用情况

如需了解可接受的用量数字,请参考“Istio 性能和可伸缩性”页面。如果您发现持续的资源使用量明显高于此值,请与 GCP 支持团队联系。

5f1969f8e2c8b137

测试推送信息

此部分会监控向 Envoy 代理推送配置的 Pilots。

  • 测试推送显示在任何给定时间发送的配置类型。
  • ADS 监控显示系统中虚拟服务、服务和连接的端点的数量。
  • 没有已知端点的集群会显示已配置但未运行任何实例的端点(这可能表示外部服务,例如 *.googleapis.com)。
  • 试点错误显示一段时间内遇到的错误数量。
  • 冲突数显示的是在监听器配置方面含糊不清的冲突数量。

如果您遇到错误或冲突,则表明您的一项或多项服务的配置错误或不一致。如需了解相关信息,请参阅“排查数据平面问题”。

Envoy 信息

本部分包含有关连接控制平面的 Envoy 代理的信息。如果您重复看到 XDS 连接失败,请与 GCP 支持团队联系。

监控混音器

Mixer 是一个将 Envoy 代理中的遥测数据传送到遥测后端(通常是 Prometheus、Stackdriver 等)的组件。在此容量中,它不在数据平面中。它部署为两个使用两个不同的服务名称(istio-telemetry 和 istio-policy)部署的 Kubernetes 作业(称为 Mixer)。

Mixer 还可用于与政策系统集成。在此容量中,Mixer 确实会影响数据平面,因为对 Mixer 进行的政策检查会阻碍对您服务的访问。

搅拌机往往会随流量的增长而扩缩。

  1. 导航至“BASE_URL/dashboard/db/istio-mixer-dashboard&quot;在浏览器中查看 Mixer 指标。

重要的受监控指标

资源使用情况

如需了解可接受的用量数字,请参考“Istio 性能和可伸缩性”页面。如果您发现持续的资源使用量明显高于此值,请与 GCP 支持团队联系。

87ed83238f9addd8

搅拌机概览

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

e07bdf5fde4bfe87.png

  • Adapter Dispatch Duration 表示混合器在调用适配器时所经历的延迟(通过它向遥测和日志记录系统发送信息)。高延迟时间绝对会影响网格上的性能。同样,第 90 百分位延迟时间应低于 10 毫秒。

1c2ee56202b32bd9

监控图库

Galley 是 Istio 的配置验证、注入、处理和分发组件。它将配置从 Kubernetes API 服务器传递给 Pilot。与 Pilot 一样,它往往会随着系统中服务和端点的数量而扩展。

  1. 导航至“BASE_URL/dashboard/db/istio-galley-dashboard&quot;在浏览器中查看 Galley 指标。

重要的受监控指标

资源验证

需要遵循的最重要指标,用于指示各种类型的资源的数量,例如目标规则、网关和服务条目,验证通过或失败。

已连接的客户端

表示连接到 Galley 的客户端数量;通常为 3(小规模测试、istio-遥测、istio-policy),并将随着这些组件的规模扩缩而扩展。

16. Istio 问题排查

数据平面问题排查

如果您的试运行信息中心显示存在配置问题,您应检查试运行日志或使用 istioctl 查找配置问题。

如需检查 Pilot 日志,请运行 kubectl -n istio-system logs istio-pilot-69db46c598-45m44 发现,将 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="
}

“Push Status”(推送状态)会指明尝试将配置推送到 Envoy 代理时发生的任何问题,在这种情况下,我们会看到多个“Duplicate cluster”(重复集群)消息,指明重复的上游目的地。

如需诊断问题方面的帮助,请联系 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 存储分区 - 在引导脚本中定义。
  1. 打开 Cloud Shell,在 Cloud Shell 中执行以下所有操作。请点击下面的链接。

Cloud Shell

  1. 确认您已使用预期的管理员用户登录 gcloud。
gcloud config list
 
  1. 找到 asm 文件夹。
cd ${WORKDIR}/asm
 
  1. 指定要删除的组织名称和研讨会 ID。
export ORGANIZATION_NAME=<ORGANIZATION NAME>
export ASM_WORKSHOP_ID=<WORKSHOP ID>
export ADMIN_STORAGE_BUCKET=<ADMIN CLOUD STORAGE BUCKET>
 
  1. 按如下方式运行清理脚本。
./scripts/cleanup_workshop.sh --workshop-id ${ASM_WORKSHOP_ID} --admin-gcs-bucket ${ADMIN_STORAGE_BUCKET} --org-name ${ORGANIZATION_NAME}