透過 Istio 將 ASP.NET Core 應用程式部署至 Google Kubernetes Engine (第 1 部分)

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. 設定和需求

自修環境設定

  1. 登入 Cloud 控制台建立新專案,或是重複使用現有專案。如果您還沒有 Gmail 或 Google Workspace 帳戶,請先建立帳戶

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

提醒您,專案 ID 是所有 Google Cloud 專案的專屬名稱 (已經有人使用上述名稱,很抱歉對您不符!)。稍後在本程式碼研究室中會稱為 PROJECT_ID

  1. 接下來,您需要在 Cloud 控制台中啟用計費功能,才能使用 Google Cloud 資源。

執行這個程式碼研究室並不會產生任何費用,如果有的話。請務必依照「清除所用資源」一節指示本節將說明如何關閉資源,這樣您就不會產生本教學課程結束後產生的費用。Google Cloud 的新使用者符合 $300 美元免費試用計畫的資格。

啟動 Cloud Shell

雖然 Google Cloud 可以從筆記型電腦遠端操作,但在本程式碼研究室中,您將使用 Google Cloud Shell,這是一種在 Google Cloud 中執行的指令列環境。

啟用 Cloud Shell

  1. 在 Cloud 控制台中,按一下「啟用 Cloud Shell」圖示 4292cbf4971c9786.png

bce75f34b2c53987.png

如果您先前從未啟動 Cloud Shell,您會看見中繼畫面 (需捲動位置),說明螢幕內容。如果出現這種情況,請按一下「繼續」 (之後不會再顯示)。以下是單次畫面的外觀:

70f315d7b402b476.png

佈建並連線至 Cloud Shell 只需幾分鐘的時間。

fbe3a0674c982259.png

這個虛擬機器搭載您需要的所有開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。在本程式碼研究室中,您的大部分作業都可以透過瀏覽器或 Chromebook 完成。

連線至 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`
  1. 在 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 網頁應用程式基本架構。

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」。

Capture.PNG

您會看到預設的 ASP.NET Core 網頁:

f579a9baedc108a9.png

確認應用程式正在執行後,按下 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

也可以再次利用 CloudShell 的網頁預覽功能:

2015-11-03 17:20:22.png 的螢幕截圖

您應該會在新分頁中看到預設的 ASP.NET Core 網頁。

f579a9baedc108a9.png

確認應用程式在 Docker 容器中正常執行後,即可在 Ctrl-> C 前停止執行中的容器。

映像檔現已如預期運作,您可以將其推送至 Google Container Registry,這是 Docker 映像檔的私人存放區,可從每個 Google Cloud 專案存取 (但也可從 Google Cloud Platform 外部存取):

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

如果一切順利,一段時間後,您應該就能在 Container Registry 區段中看到容器映像檔。此時,您已取得適用於專案層級的 Docker 映像檔,請稍待幾分鐘,Kubernetes 可以用來存取及自動化調度管理。

73558f3a54ce1c0c.png

如果想瀏覽儲存在 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 區段中。

e46fd9c6ee82bcc4.png

在本程式碼研究室中,我們會從 istio.io 下載並安裝 Istio。您也可以採用其他安裝選項,包括 GKE 適用的 Istio 外掛程式Anthos 服務網格。完成上述步驟後的應用程式步驟將適用於所有安裝的 Istio。

首先,請下載 Istio 用戶端和範例。Istio 版本頁面提供多個 OS 的下載構件。在本範例中,我們可以使用便利的指令下載和擷取目前平台的最新版本:

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。

自動插入補充資訊

如要開始使用 Istio,您無須對應用程式進行任何變更。當您設定並執行服務時,系統會自動將 Envoy 補充資訊插入服務的各個 Pod。

為此,您必須針對微服務使用的命名空間 (「預設」) 啟用補充插入功能。您只要套用標籤即可:

kubectl label namespace default istio-injection=enabled

如要確認標籤是否已成功套用,請執行下列指令:

kubectl get namespace -L istio-injection

輸出結果會確認預設命名空間已啟用補充插入功能:

NAME              STATUS   AGE    ISTIO-INJECTION
default           Active   3m     enabled
istio-system      Active   63s    disabled
...

7. 驗證安裝

Istio 提供三種服務:istiod 控制層,以及輸入和輸出閘道 (可視為「網際網路其餘部分的邊車 Proxy」),分別命名為 istio-ingressgatewayistio-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 Gateway 屬於 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 控制層。處理 Proxy 補充資訊、服務探索、憑證發布和補充資訊插入的設定和程式設計
  • ingress gateway:處理來自叢集外部的傳入要求。
  • egress gateway:處理向叢集外端點發出的傳出要求。

8. 部署應用程式

您已確認已安裝並執行 Istio,現在可以部署 ASP.NET Core 應用程式。

部署和服務

首先,使用您慣用的編輯器 (vim, nano,emacs 或 Cloud Shell 的程式碼編輯器) 建立 aspnetcore.yaml 檔案,然後定義應用程式的 Kubernetes Deployment 和 Service:

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

Gateway 和 VirtualService

如要允許輸入流量進入網格,您必須建立 GatewayVirtualService

閘道會設定 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 和通訊埠。SDK 列在 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> 查看應用程式:

f579a9baedc108a9.png

10. 恭喜!

您剛剛將簡易的 ASP.NET Core 應用程式部署至在 Google Kubernetes Engine (GKE) 上執行的 Kubernetes,並設定為由 Istio 代管。

您可能會想「Istio 有哪些優點?」。好問題!到目前為止,由 Istio 管理這個應用程式沒有好處。在研究室的第二部分,我們會進一步探索 Istio 的功能,例如指標、追蹤、動態流量管理、服務視覺化和錯誤植入。

後續步驟

授權

這項內容採用的是創用 CC 姓名標示 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