使用 Istio 将 ASP.NET Core 应用部署到 Google Kubernetes Engine(第 2 部分)

1. 概览

在实验的第一部分中,您创建了一个 ASP.NET Core 应用,将其容器化并部署到 Google Kubernetes Engine (GKE),然后配置其流量以由 Istio 管理。

本实验的第二部分假设您已拥有 Kubernetes 集群,并且第一个实验中的应用正在运行。您将了解 Istio 如何通过最少的代码更改来帮助您管理、监控和保护服务。具体来说,您将探索 Istio 的各项功能,例如指标、跟踪、服务可视化、动态流量管理、故障注入等。

学习内容

  • 如何使用 Prometheus 查询指标。
  • 如何使用 Grafana 直观呈现指标。
  • 如何创建服务的新版本。
  • 如何将服务固定到特定版本。
  • 如何在不同版本之间拆分流量。
  • 如何在服务调用中注入故障。

所需条件

您打算如何使用本教程?

仅阅读教程内容 阅读并完成练习

您如何评价自己在 Google Cloud Platform 方面的经验水平?

新手水平 中等水平 熟练水平

2. 设置和要求

自定进度的环境设置

  1. 登录 Cloud 控制台,然后创建一个新项目或重复使用现有项目。 (如果您还没有 Gmail 或 G Suite 账号,则必须创建一个。)

H_hgylo4zxOllHaAbPKJ7VyqCKPDUnDhkr-BsBIFBsrB6TYSisg6LX-uqmMhh4sXUy_hoa2Qv87C2nFmkg-QAcCiZZp0qtpf6VPaNEEfP_iqt29KVLD-gklBWugQVeOWsFnJmNjHDw

dcCPqfBIwNO4R-0fNQLUC4aYXOOZhKhjUnakFLZJGeziw2ikOxGjGkCHDwN5x5kCbPFB8fiOzZnX-GfuzQ8Ox-UU15BwHirkVPR_0RJwl0oXrhqZmMIvZMa_uwHugBJIdx5-bZ6Z8Q

jgLzVCxk93d6E2bbonzATKA4jFZReoQ-fORxZZLEi5C3D-ubnv6nL-eP-iyh7qAsWyq_nyzzuEoPFD1wFOFZOe4FWhPBJjUDncnTxTImT3Ts9TM54f4nPpsAp52O0y3Cb19IceAEgQ

请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID

  1. 接下来,您需要在 Cloud 控制台中启用结算功能,才能使用 Google Cloud 资源。

运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。请务必按照“清理”部分中的所有说明操作,该部分介绍了如何关停资源,以免产生超出本教程范围的结算费用。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。

启动 Cloud Shell

虽然您可以通过笔记本电脑对 Google Cloud 进行远程操作,但在此 Codelab 中,您将使用 Google Cloud Shell,这是一个在 Google Cloud 中运行的命令行环境。

激活 Cloud Shell

  1. 在 Cloud Console 中,点击激活 Cloud ShelldnDTxS9j60RcXdTjea12HLB9paS9Gzf7PfFLE9RW8g0Qx1bz7nmCzyCu4rjluX3bOEwavOpDwioXEkzOf6xtZp6-ZbJa08jwJqtmeeW8jZ1tYfi2lyXqvW3WFHP0eAxDkQDfpO9Ljw

yzBQBp2RC1EFvSSLYVkMA2m6LHqGsp22O81rUS5tGb9Y1FqlVhoRj_ka8V_uEjtpcirZRULMy1IjNr848uYvb9mC9RcGGqeayaLcXFfRwUGeXWChZPtWkHzUshTcqx_wJHis0X8viA

如果您以前从未启动过 Cloud Shell,您将看到一个中间屏幕(非首屏),上面描述了它是什么。如果是这种情况,请点击继续(您将永远不会再看到它)。一次性屏幕如下所示:

VgsaqGbKPRiqK24CqAKjSXjepuJT96PmiDqQMcySmWKx8QyW5F3G2D8JH2d08ek-YM77wWKxPvggpOFER8Hbq3aaZipTDU2o0il7A0kS3FXY_NzuujjEqDF1nsbDKkNMThrqcdMGtQ

预配和连接到 Cloud Shell 只需花几分钟时间。

7RuYr-LCKzdiE1veTFmL_lYrVxsMZ6-xDoxAnfwPPc5uFA0utmFGejvu81jGmTdbqnqxrytW3KcHT6xrMIRc3bskctnDZC5nJdpqw-LRxu3r35hL4A0BSBTtbtirfh3PKv-eOKt8Rg

这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证。只需使用一个浏览器或 Google Chromebook 即可完成本 Codelab 中的大部分(甚至全部)工作。

在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID:

  1. 在 Cloud Shell 中运行以下命令以确认您已通过身份验证:
gcloud auth list

命令输出

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

命令输出

[core]
project = <PROJECT_ID>

如果不是上述结果,您可以使用以下命令进行设置:

gcloud config set project <PROJECT_ID>

命令输出

Updated property [core/project].

3. 测试应用

在开始本实验之前,请确保应用仍能正常运行(与上一个实验中一样)。提醒一下,您可以通过以下方式查看网关的外部 IP 和端口(列在 EXTERNAL-IP 下):

kubectl get svc istio-ingressgateway -n istio-system

如需查看应用,您可以打开浏览器并前往 http://<gatewayurl>

f579a9baedc108a9.png

如果您没有看到该应用,请返回上一个实验,确保您已按照所有步骤进行操作,并且应用和 Istio 都已正确安装并运行。

此时,您可能想知道“Istio 有什么好处?”通过让 Istio 管理应用的流量,您可以免费获得指标、跟踪、动态流量管理、服务可视化、故障注入等功能。

您将从下一步开始探索指标。

4. 使用 Grafana 和 Prometheus 查看指标

默认情况下,Istio 会生成一些指标。您可以使用插件查询和直观呈现这些默认指标。

Prometheus

Prometheus 是一种开源监控解决方案。您可以使用 Prometheus 查询 Istio 生成的指标,但需要先安装 Prometheus 插件。

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/prometheus.yaml

验证 Prometheus 是否正在运行:

kubectl get svc prometheus -n istio-system

NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
prometheus   ClusterIP   10.31.243.62   <none>        9090/TCP   1d

通过多次访问 http://<gatewayurl> 或运行 curl 命令,向应用发送一些流量。

为 Prometheus 界面设置端口转发:

kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=prometheus -o jsonpath='{.items[0].metadata.name}') 8080:9090

现在,您可以点击 Cloud Shell 右上角的“网页预览”按钮,然后点击在端口 8080 上预览,以执行查询:

772a5248aa493025.png

您将在新标签页中看到 Prometheus 界面:

272ee63c1fe0be16.png

如需详细了解 Prometheus,请参阅使用 Prometheus 查询指标

Grafana

Grafana 是另一种用于直观显示指标的插件。

安装 Grafana。将 istio-version 替换为当前 Istio 版本,例如 1.0.3-gke.3

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/grafana.yaml

验证 Grafana 是否正在运行:

kubectl get svc grafana -n istio-system

NAME      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
grafana   ClusterIP   10.31.248.230   <none>        3000/TCP   1d

通过多次访问 http://<gatewayurl> 或运行 curl 命令,向应用发送一些流量。

为 Grafana 界面设置端口转发:

kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 8080:3000

您可以通过访问网页预览版来查看 Grafana 信息中心:

806d696d85267a37.png

524cb9f6d66f8655.png

如需详细了解 Grafana,请参阅使用 Grafana 直观呈现指标

5. 创建应用的新版本

在某些情况下,您部署到生产环境的应用将需要进行问题修复或需要其他功能。下面我们来看看该流程。

首先,我们来修改应用。从 Cloud Shell 中打开代码编辑器。

mxrggIJ2Zz8E47ULCEo4NywjM-EpSkZF5c3TQgfGx4nODwP2obiQXrwQjEEaXuBhJDA2jJ5evR7TuHIy1gsqqDRFm0Wh3xhZUu9tn_xb1ygFlBm1HKJqLdfz_aK7WJS33u2IBDO2oQ

前往 HelloWorldAspNetCore > Views > Home 下的 Index.cshtml,然后更新其中一条轮播消息。

找到以下行:

Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core 

并将其更改为以下内容:

Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core on Google Cloud

保存更改,然后返回到 Cloud Shell。在 HelloWorldAspNetCore, 中构建 Docker 映像:

docker build -t gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v2 . 

并推送到 Container Registry:

docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v2 

推送容器映像后,您可以在下一步中部署新版本。

6. 创建新部署

如需部署新版本,您首先需要在 Kubernetes 中为其创建新的部署。在 aspnetcore.yaml 文件末尾添加以下内容:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aspnetcore-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aspnetcore
      version: v2
  template:
    metadata:
      labels:
        app: aspnetcore
        version: v2
    spec:
      containers:
      - name: aspnetcore
        image: gcr.io/YOUR-PROJECT-ID/hello-dotnet:v2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

使用 kubectl 将新版本部署到默认命名空间:

kubectl apply -f aspnetcore.yaml
service "aspnetcore" unchanged
deployment.extensions "aspnetcore-v1" unchanged
deployment.extensions "aspnetcore-v2" created

验证预期的 pod 是否正在运行:

kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
aspnetcore-v1-6cf64748-mddb   2/2       Running   0          34s
aspnetcore-v2-5d765db-l9xmg   2/2       Running   0          1m

现在,再次测试该应用。获取网关的外部 IP:

kubectl get svc istio-ingressgateway -n istio-system

它列在 EXTERNAL-IP 下。打开无痕式浏览器,然后访问 http://<replace-with-external-ip>

刷新时,有时您会看到消息“了解如何使用 ASP.NET Core 构建 Web 应用”:

11d528132dbb6cee.png

在其他情况下,您会看到“了解如何使用 ASP.NET Core 在 Google Cloud 上构建 Web 应用”消息:

3eb0d5be1b4cb40b.png

这是因为 v1v2 部署都通过同一 Kubernetes 服务 (aspnetcore-service) 公开,并且您在上一个实验中创建的 VirtualService (aspnetcore-virtualservice) 使用该服务作为主机。

在下一步中,您将使用 DestinationRule 将服务固定到 v2 部署。

7. 将服务固定到新版本

在此步骤中,您将固定服务以使用 v2 部署,您可以使用 DestinationRule 来实现此目的。DestinationRule 用于配置在 VirtualService 路由操作发生后要应用于请求的政策集。

DestinationRule 还定义了相应目标主机的可寻址子集(即命名版本)。在将流量发送到服务的特定版本时,这些子集会用于 VirtualService 路由规范中。

创建一个名为 aspnetcore-destinationrule.yaml 的新文件:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: aspnetcore-destinationrule
spec:
  host: aspnetcore-service
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

接下来,创建 DestinationRule。这会创建两个子集(v1 和 v2),您可以在 VirtualService 中使用这两个子集:

kubectl apply -f aspnetcore-destinationrule.yaml
destinationrule.networking.istio.io "aspnetcore-destionationrule" created

现在,返回 aspnetcore-virtualservice.yaml 文件以更新 VirtualService,使其使用 v2 子集:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - route:
    - destination:
        host: aspnetcore-service
        subset: v2

更新 VirtualService:

kubectl apply -f aspnetcore-virtualservice.yaml

打开浏览器并访问 http://<replace-with-external-ip>. 即使多次刷新,您也应该会看到“了解如何在 Google Cloud 上使用 ASP.NET Core 构建 Web 应用”消息:

3eb0d5be1b4cb40b.png

8. 在版本之间拆分流量

有时,您可能希望在不同版本之间拆分流量以进行测试。例如,您可能希望将 75% 的流量发送到服务的 v1 版本,并将 25% 的流量发送到服务的 v2 版本。借助 Istio,您可以轻松实现此目的。创建一个新的 aspnetcore-virtualservice-weights.yaml 文件,以引用具有不同权重的两个子集:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - route:
    - destination:
        host: aspnetcore-service
        subset: v1
      weight: 75
    - destination:
        host: aspnetcore-service
        subset: v2
      weight: 25

更新 VirtualService:

kubectl apply -f aspnetcore-virtualservice-weights.yaml

现在,当您刷新浏览器时,应该会看到 v1 和 v2 版本以大约 3:1 的比例提供。

如需了解详情,请参阅 Istio 中的流量拆分

9. 注入故障

另一项有用的开发任务是,在流量中注入故障或延迟,并查看服务在响应时的行为。

例如,您可能希望针对发送到 v1 版本的 50% 的流量返回错误请求 (HTTP 400) 响应。创建 aspnetcore-virtualservice-fault-abort.yaml 文件,使其与以下内容一致:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - fault:
      abort:
        percentage:
          value: 50
        httpStatus: 400
    route:
    - destination:
        host: aspnetcore-service
        subset: v1

更新 VirtualService:

kubectl apply -f aspnetcore-virtualservice-fault-abort.yaml

现在,当您刷新浏览器时,您应该会看到,有一半的时间,v1 服务会返回 HTTP 400s 响应代码。

或者,您可能想为请求添加 5 秒的延迟。创建 aspnetcore-virtualservice-fault-delay.yaml 文件,使其与以下内容一致:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - fault:
      delay:
        fixedDelay: 5s
        percentage:
          value: 100
    route:
    - destination:
        host: aspnetcore-service
        subset: v1

更新 VirtualService:

kubectl apply -f aspnetcore-virtualservice-fault-delay.yaml

现在,当您刷新浏览器时,应该会看到请求延迟了 5 秒。

如需详细了解 Istio 功能(例如超时、重试、条件规则、断路器等),请参阅流量管理功能

10. 恭喜!

希望本实验让您大致了解了 Istio 可以为您的服务提供哪些开箱即用的功能。详细了解 Istio 和 GKE。

后续步骤

许可

此作品已获得 Creative Commons Attribution 2.0 通用许可授权。

11. 清理

您可以删除应用并卸载 Istio,也可以直接删除 Kubernetes 集群。

删除应用

如需删除应用,请执行以下操作:

kubectl delete -f aspnetcore-gateway.yaml
kubectl delete -f aspnetcore-virtualservice.yaml
kubectl delete -f aspnetcore-destinationrule.yaml
kubectl delete -f aspnetcore.yaml

如需确认应用已消失,请执行以下操作:

kubectl get gateway 
kubectl get virtualservices
kubectl get destinationrule
kubectl get pods

卸载 Istio

如需删除 Istio,请执行以下操作:

kubectl delete -f install/kubernetes/istio-demo-auth.yaml

确认 Istio 已消失:

kubectl get pods -n istio-system

删除 Kubernetes 集群

gcloud container clusters delete hello-dotnet-cluster