使用 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 使用体验?

<ph type="x-smartling-placeholder"></ph> 新手 中级 熟练

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-ZbJa08jwJqtmeeW8jZ1

yzBQBp2RC1EFvSSLYVkMA2m6LHqGsp22O81rUS5tGb9Y1FqlVhoRj_ka8V_uEjtpcirZRULMy1IjNr848uYvb9mC9RcGGqeayaLcXFfRwUGeXWChZPtWkHzUshTcqx_wJHis0X8viA

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

VgsaqGbKPRiqK24CqAKjSXjepuJT96PmiDqQMcySmWKx8QyW5F3G2D8JH2d08ek-YM77wWKxPvggpOFER8Hbq3aaZipTDU2o0il7A0kS3FXjY_kDzuud

预配和连接到 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. 测试应用

在开始此实验之前,请确保在上一个实验中,您的应用仍可正常运行。请注意,以下是 EXTERNAL-IP 下列出的网关外部 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

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

272ee63c1fe0be16

如需详细了解 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

524cb9f6d66f8655

如需详细了解 Granfana,请参阅使用 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

其他时间,您会看到“Learn about building Web apps with ASP.NET Core on Google Cloud”(了解如何在 Google Cloud 上使用 ASP.NET Core 构建 Web 应用)消息:

3eb0d5be1b4cb40b

这是因为 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

8. 在版本之间拆分流量

有时,您可能希望在版本之间拆分流量以进行测试。例如,您可能希望向 v1 服务发送 75% 的流量,向服务的 v2 版本发送 25% 的流量。您可以使用 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