1. 概览
ASP.NET Core 是一款开源的跨平台框架,可用于使用 C# 编程语言构建基于云的现代应用和联网应用。
Kubernetes 是一个开源系统,用于自动部署、扩缩和管理容器化应用。Istio 是一个开放式框架,用于连接、保护、管理和监控服务。
在本实验的第一部分中,您将一个简单的 ASP.NET Core 应用部署到 Google Kubernetes Engine (GKE) 上运行的 Kubernetes,并将其配置为由 Istio 管理。
在本实验的第二部分中,您将进一步探索 Istio 的功能,例如指标、跟踪、动态流量管理、故障注入等。
学习内容
- 如何在 Docker 容器中创建和封装简单的 ASP.NET Core 应用。
- 如何使用 Google Kubernetes Engine (GKE) 创建 Kubernetes 集群。
- 如何在 GKE 上的 Kubernetes 集群上安装 Istio。
- 如何部署 ASP.NET Core 应用并配置其流量以由 Istio 管理。
所需条件
您打算如何使用本教程?
您如何评价自己在 Google Cloud Platform 方面的经验水平?
2. 设置和要求
自定进度的环境设置



请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID。
- 接下来,您需要在 Cloud 控制台中启用结算功能,才能使用 Google Cloud 资源。
运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。请务必按照“清理”部分中的所有说明操作,该部分介绍了如何关停资源,以免产生超出本教程范围的结算费用。Google Cloud 的新用户符合参与 $300 USD 免费试用计划的条件。
启动 Cloud Shell
虽然您可以通过笔记本电脑对 Google Cloud 进行远程操作,但在此 Codelab 中,您将使用 Google Cloud Shell,这是一个在 Google Cloud 中运行的命令行环境。
激活 Cloud Shell
- 在 Cloud Console 中,点击激活 Cloud Shell
。

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

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

这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证。只需使用一个浏览器或 Google Chromebook 即可完成本 Codelab 中的大部分(甚至全部)工作。
在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的项目 ID:
- 在 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`
- 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目:
gcloud config list project
命令输出
[core] project = <PROJECT_ID>
如果不是上述结果,您可以使用以下命令进行设置:
gcloud config set project <PROJECT_ID>
命令输出
Updated property [core/project].
3. 在 Cloud Shell 中创建 ASP.NET Core 应用
在 Cloud Shell 提示符处,您可以通过检查 dotnet 命令行工具的版本来验证该工具是否已安装。此命令应会输出已安装的 dotnet 命令行工具的版本:
dotnet --version
接下来,创建一个新的 ASP.NET Core Web 应用。
dotnet new mvc -o HelloWorldAspNetCore
系统会创建一个项目并恢复其依赖项。您应该会看到如下所示的消息:
Restore completed in 11.44 sec for HelloWorldAspNetCore.csproj.
Restore succeeded.
4. 运行 ASP.NET Core 应用
我们的应用很快就可以运行了。前往应用文件夹。
cd HelloWorldAspNetCore
最后,运行应用。
dotnet run --urls=http://localhost:8080
该应用随即便开始监听端口 8080。
Hosting environment: Production
Content root path: /home/atameldev/HelloWorldAspNetCore
Now listening on: http://[::]:8080
Application started. Press Ctrl+C to shut down.
如要验证该应用是否正在运行,请点击右上角的网页预览按钮,然后选择“在端口 8080 上预览”。

您将看到默认的 ASP.NET Core 网页:

验证应用正在运行后,按 Ctrl+C 关闭应用。
5. 将 ASP.NET Core 应用封装到 Docker 容器中
接下来,准备好应用以作为容器运行。第一步是定义容器及其内容。
在应用的基础目录中,创建一个 Dockerfile 来定义 Docker 映像。
touch Dockerfile
使用您惯用的编辑器(vim,、nano,emacs 或 Cloud Shell 的代码编辑器)将以下内容添加到 Dockerfile。
# Use Microsoft's official build .NET image. # https://hub.docker.com/_/microsoft-dotnet-core-sdk/ FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build WORKDIR /app # Install production dependencies. # Copy csproj and restore as distinct layers. COPY *.csproj ./ RUN dotnet restore # Copy local code to the container image. COPY . ./ WORKDIR /app # Build a release artifact. RUN dotnet publish -c Release -o out # Use Microsoft's official runtime .NET image. # https://hub.docker.com/_/microsoft-dotnet-core-aspnet/ FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine AS runtime WORKDIR /app COPY --from=build /app/out ./ # Make sure the app binds to port 8080 ENV ASPNETCORE_URLS http://*:8080 # Run the web service on container startup. ENTRYPOINT ["dotnet", "HelloWorldAspNetCore.dll"]
您的 Dockerfile 中包含的一项重要配置是应用监听传入流量的端口 (8080)。为此,您可以设置 ASPNETCORE_URLS 环境变量,ASP.NET Core 应用会使用该变量来确定要监听的端口。
保存此 Dockerfile。现在,我们来构建映像:
docker build -t gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1 .
完成后(需要一些时间下载和解压缩所有内容),您会看到映像已构建并保存在本地:
docker images REPOSITORY TAG gcr.io/yourproject-XXXX/hello-dotnet v1
使用以下命令在本地测试映像,该命令将从新创建的容器映像在本地端口 8080 上运行 Docker 容器:
docker run -p 8080:8080 gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1
再次利用 Cloud Shell 的网页预览功能:

您应该会在新标签页中看到默认的 ASP.NET Core 网页。

确认应用正在 Docker 容器中本地正常运行后,您可以按 Ctrl-> C 停止正在运行的容器。
现在,映像已按预期运行,您可以将其推送到 Google Container Registry,这是一个私有代码库,用于存储您的 Docker 映像,可从每个 Google 云项目(也可从 Google Cloud Platform 外部)访问:
docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1
如果一切顺利,过一会儿,您应该就能在 Container Registry 部分中看到列出的容器映像。现在,您拥有一个适用于整个项目的 Docker 映像,Kubernetes 可对其进行访问和编排(几分钟后您便会看到)。

如果您有兴趣,可以点击以下链接,浏览存储在 Google Cloud Storage 中的容器映像:https://console.cloud.google.com/storage/browser/(最终链接应采用以下完整形式:https://console.cloud.google.com/project/PROJECT_ID/storage/browser/)。
6. 创建包含 Istio 的 Kubernetes/GKE 集群
首先,确保您已启用 Kubernetes Engine API:
gcloud services enable container.googleapis.com
创建 Kubernetes 集群。如果您愿意,可以将地区更改为离您较近的地区:
gcloud container clusters create hello-istio \ --cluster-version=latest \ --machine-type=n1-standard-2 \ --num-nodes=4 \ --region europe-west1
请稍等片刻,系统正在为您设置集群。它将显示在 Google Cloud Platform 控制台的 Kubernetes Engine 部分中。

在此 Codelab 中,我们将从 istio.io 下载并安装 Istio。还有其他安装选项,包括 GKE 的 Istio 插件和 Anthos Service Mesh。此步骤之后的应用步骤适用于任何 Istio 安装。
我们先下载 Istio 客户端和示例。Istio 发布页面提供了适用于多种操作系统的下载制品。在我们的示例中,我们可以使用一个便捷的命令来下载并提取当前平台的最新版本:
curl -L https://istio.io/downloadIstio | sh -
脚本会告知您已下载的 Istio 版本:
Istio has been successfully downloaded into the istio-1.8.1 folder on your system.
安装目录包含示例应用和 istioctl 客户端二进制文件。切换到该目录:
cd istio-1.8.1
复制并粘贴提供的命令,将 bin 目录添加到 PATH,以便您可以使用 istioctl:
export PATH="$PATH:/home/<YOURHOMEID>/istio-1.8.1/bin"
通过检查集群是否已为 Istio 做好准备,验证 istioctl 是否可用:
istioctl x precheck
您应该会看到一条消息,显示 Install Pre-Check passed! The cluster is ready for Istio installation.
使用演示配置文件安装 Istio:
istioctl install --set profile=demo
Istio 现已安装到您的集群中。
自动 Sidecar 注入
您无需对应用进行任何更改,即可开始使用 Istio。配置并运行服务时,系统会自动将 Envoy 边车注入到服务的每个 pod 中。
为此,您需要为用于微服务的命名空间(“default”)启用边车注入。为此,请应用标签:
kubectl label namespace default istio-injection=enabled
如需验证标签是否已成功应用,请运行以下命令:
kubectl get namespace -L istio-injection
输出确认已为默认命名空间启用 Sidecar 注入:
NAME STATUS AGE ISTIO-INJECTION default Active 3m enabled istio-system Active 63s disabled ...
7. 验证安装
Istio 随附三项服务:istiod 控制平面、入站网关和出站网关(您可以将其视为“面向互联网其余部分的边车代理”),分别命名为 istio-ingressgateway 和 istio-egressgateway。
kubectl get svc -n istio-system
输出的内容应如下所示:
NAME TYPE CLUSTER-IP EXTERNAL-IP AGE istio-egressgateway ClusterIP 10.55.252.182 <none> istio-ingressgateway LoadBalancer 10.55.250.185 35.233.118.42 istiod ClusterIP 10.55.253.217 <none>
Ingress 网关的类型为 LoadBalancer,因此可从互联网访问;其他网关只需从集群内访问即可。
接下来,确保已部署相应的 Kubernetes pod,并且所有容器均正常运行:
kubectl get pods -n istio-system
当所有 pod 都处于运行状态时,您可以继续操作。
NAME READY STATUS istio-egressgateway-674988f895-m6tk4 1/1 Running istio-ingressgateway-6996f7dcc8-7lvm2 1/1 Running istiod-6bf5fc8b64-j79hj 1/1 Running
istiod:Istio 控制平面。处理代理边车的配置和编程、服务发现、证书分发和边车注入ingress gateway:处理来自集群外部的入站请求。egress gateway:处理向集群外部端点发出的出站请求。
8. 部署应用
现在,您已验证 Istio 已安装并正在运行,接下来可以部署 ASP.NET Core 应用了。
Deployment 和 Service
首先,使用您惯用的编辑器(vim, nano,emacs 或 Cloud Shell 的代码编辑器)创建一个 aspnetcore.yaml 文件,并为应用定义 Kubernetes 部署和服务:
apiVersion: v1
kind: Service
metadata:
name: aspnetcore-service
labels:
app: aspnetcore
spec:
ports:
- port: 8080
name: http
selector:
app: aspnetcore
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: aspnetcore-v1
spec:
replicas: 1
selector:
matchLabels:
app: aspnetcore
version: v1
template:
metadata:
labels:
app: aspnetcore
version: v1
spec:
containers:
- name: aspnetcore
image: gcr.io/YOUR-PROJECT-ID/hello-dotnet:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
该文件的内容是用于部署应用的 Deployment 和 Service 标准,不包含任何特定于 Istio 的内容。
使用 kubectl 将服务部署到默认命名空间:
kubectl apply -f aspnetcore.yaml
service "aspnetcore-service" created deployment.extensions "aspnetcore-v1" created
验证 pod 是否正在运行:
kubectl get pods
NAME READY STATUS RESTARTS AGE aspnetcore-v1-6cf64748-mddb 2/2 Running 0 34s
网关和 VirtualService
如需允许入站流量到达网格,您需要创建 Gateway 和 VirtualService。
网关用于为 HTTP/TCP 流量配置负载平衡器,通常在网格边缘运行,以实现应用的入站流量。VirtualService 定义了用于控制服务请求在 Istio 服务网格中的路由方式的规则。
创建一个 aspnetcore-gateway.yaml 文件来定义网关:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: aspnetcore-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
创建 aspnetcore-virtualservice.yaml 文件以定义 VirtualService:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: aspnetcore-virtualservice
spec:
hosts:
- "*"
gateways:
- aspnetcore-gateway
http:
- route:
- destination:
host: aspnetcore-service
运行 kubectl 命令以部署网关,并执行以下操作:
kubectl apply -f aspnetcore-gateway.yaml
该命令会生成以下输出:
gateway.networking.istio.io "aspnetcore-gateway" created
接下来,运行以下命令以部署 VirtualService:
kubectl apply -f aspnetcore-virtualservice.yaml
该命令会生成以下输出:
virtualservice.networking.istio.io "aspnetcore-virtualservice" created
验证一切是否都在运行:
kubectl get gateway
NAME AGE aspnetcore-gateway 28s
kubectl get virtualservice
NAME AGE aspnetcore-virtualservice 33s
恭喜!您刚刚部署了一个已启用 Istio 的应用。接下来,您将看到应用的使用情况。
9. 测试应用
您终于可以看到应用的实际效果了。您需要获取网关的外部 IP 和端口。它列在 EXTERNAL-IP 下:
kubectl get svc istio-ingressgateway -n istio-system
将外部 IP 和端口导出到 GATEWAY_URL 变量:
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
使用 curl 测试应用。服务应以 200 的响应代码进行响应:
curl -o /dev/null -s -w "%{http_code}\n" http://${GATEWAY_URL}/
或者,您也可以打开浏览器,前往 http://<gatewayurl> 查看应用:

10. 恭喜!
您刚刚在 Google Kubernetes Engine (GKE) 上运行的 Kubernetes 中部署了一个简单的 ASP.NET Core 应用,并将其配置为由 Istio 管理。
您可能想知道“Istio 有什么好处?”。问得好。到目前为止,让 Istio 管理此应用没有任何优势。在实验的第二部分,我们将进一步探索 Istio 的功能,例如指标、跟踪、动态流量管理、服务可视化和故障注入。
后续步骤
- 使用 Istio 将 ASP.NET Core 应用部署到 GKE(第 2 部分)。
- 详细了解 Istio。
- 详细了解 Kubernetes。
- 详细了解 Google Kubernetes Engine。
- 详细了解 Google Cloud Platform 上的 .NET。
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。
11. 清理
如果您不继续进行实验的第二部分,可以删除应用并卸载 Istio,也可以直接删除 Kubernetes 集群。
删除应用
如需删除应用,请执行以下操作:
kubectl delete -f aspnetcore-gateway.yaml Kubectl delete -f aspnetcore-virtualservice.yaml kubectl delete -f aspnetcore.yaml
如需确认应用是否已删除,请执行以下操作:
kubectl get gateway kubectl get virtualservices 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-istio