Istio を使用して ASP.NET Core アプリを Google Kubernetes Engine にデプロイする(パート 1)

1. 概要

ASP.NET Core はインターネットに接続された最新のクラウドベースのアプリケーションを C# プログラミング言語を使用して構築するための、オープンソースのクロス プラットフォーム フレームワークです。

Kubernetes は、コンテナ化アプリケーションのデプロイ、スケーリング、管理を自動化するオープンソース システムです。Istio は、サービスを接続、保護、管理、モニタリングするためのオープン フレームワークです。

このラボの最初のパートでは、Google Kubernetes Engine(GKE)で実行されている Kubernetes にシンプルな ASP.NET Core アプリをデプロイし、Istio で管理されるように構成します。

ラボの後半では、指標、トレース、動的トラフィック管理、フォールト インジェクションなど、Istio の機能について詳しく説明します。

学習内容

  • Docker コンテナにシンプルな ASP.NET Core アプリを作成してパッケージ化する方法。
  • Google Kubernetes Engine(GKE)を使用して Kubernetes クラスタを作成する。
  • GKE 上の Kubernetes クラスタに Istio をインストールする方法。
  • ASP.NET Core アプリをデプロイし、Istio で管理されるようにトラフィックを構成する方法。

必要なもの

このチュートリアルの利用方法をお選びください。

通読するのみ 内容を読んで演習を完了する

Google Cloud Platform のご利用経験について、いずれに該当されますか?

<ph type="x-smartling-placeholder"></ph> 初心者 中級 上達 をご覧ください。

2. 設定と要件

セルフペース型の環境設定

  1. Cloud コンソールにログインして、新しいプロジェクトを作成するか、既存のプロジェクトを再利用しますGmail アカウントも Google Workspace アカウントもまだお持ちでない場合は、アカウントを作成してください。

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

プロジェクト ID を忘れないようにしてください。プロジェクト ID はすべての Google Cloud プロジェクトを通じて一意の名前にする必要があります(上記の名前はすでに使用されているので使用できません)。以降、このコードラボでは PROJECT_ID と呼びます。

  1. 次に、Google Cloud リソースを使用するために、Cloud Console で課金を有効にする必要があります。

このコードラボを実行しても、費用はほとんどかからないはずです。このチュートリアル以外で請求が発生しないように、リソースのシャットダウン方法を説明する「クリーンアップ」セクションの手順に従うようにしてください。Google Cloud の新規ユーザーは、$300 USD 分の無料トライアル プログラムをご利用いただけます。

Cloud Shell の起動

Google Cloud はノートパソコンからリモートで操作できますが、この Codelab では、Google Cloud 上で動作するコマンドライン環境である Google Cloud Shell を使用します。

Cloud Shell をアクティブにする

  1. Cloud Console で、[Cloud Shell をアクティブにする] 4292cbf4971c9786.png をクリックします。

bce75f34b2c53987.png

Cloud Shell を初めて起動する場合は、その内容を説明する中間画面(スクロールしなければ見えない範囲)が表示されます。その場合は、[続行] をクリックします(今後表示されなくなります)。この中間画面は次のようになります。

70f315d7b402b476.png

Cloud Shell のプロビジョニングと接続に少し時間がかかる程度です。

fbe3a0674c982259.png

この仮想マシンには、必要な開発ツールがすべて含まれています。仮想マシンは Google Cloud で稼働し、永続的なホーム ディレクトリが 5 GB 用意されているため、ネットワークのパフォーマンスと認証が大幅に向上しています。このコードラボでの作業のほとんどは、ブラウザまたは 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)があります。そのためには、ASP.NET Core アプリがリッスンするポートを決定する際に使用する環境変数 ASPNETCORE_URLS を設定します。

この Dockerfile を保存します。次に、イメージをビルドします。

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

完了すると(すべてのダウンロードと抽出に時間がかかります)、イメージがビルドされてローカルに保存されます。

docker images

REPOSITORY                             TAG   
gcr.io/yourproject-XXXX/hello-dotnet   v1            

次のコマンドを使用して、イメージをローカルでテストします。これにより、新しく作成したコンテナ イメージから Docker コンテナがポート 8080 でローカルに実行されます。

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 を使用して、実行中のコンテナを停止できます。

イメージが意図どおりに機能することを確認したので、これを Docker イメージ用の非公開リポジトリである Google Container Registry に push します。このリポジトリにはすべての Google Cloud プロジェクトからアクセスできるだけでなく、Google Cloud Platform の外部からもアクセスできます。

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

すべてが正常に完了すると、しばらくすると [Container Registry] セクションにコンテナ イメージが表示されます。この時点で、プロジェクト全体の Docker イメージが使用可能になりました。このイメージは、後ほど説明するように、Kubernetes がアクセスしてオーケストレートできます。

73558f3a54ce1c0c.png

興味がある場合は、https://console.cloud.google.com/storage/browser/ から、Google Cloud Storage に保存されているコンテナ イメージを確認できます(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

この Codelab では、istio.io から Istio をダウンロードしてインストールします。GKE 用 Istio アドオンAnthos Service Mesh など、他のインストール オプションもあります。この後のアプリケーションの手順は、どの 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 の使用を開始するために、アプリケーションを変更する必要はありません。Service を構成して実行すると、Envoy サイドカーが Service の各 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 コントロール プレーンと、上り(内向き)ゲートウェイと下り(外向き)ゲートウェイ(インターネットの他の部分に対するサイドカー プロキシと考えることができます)という 3 つのサービス(それぞれ 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 ゲートウェイのタイプは 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 アプリをデプロイできます。

デプロイとサービス

まず、任意のエディタ(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 を使用して、サービスをデフォルトの Namespace にデプロイします。

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 を作成する必要があります。

Gateway は、HTTP/TCP トラフィック用のロードバランサを構成します。アプリケーションの上り(内向き)トラフィックを有効にするために、通常はメッシュのエッジで動作します。VirtualService は、Istio サービス メッシュ内でのサービスのリクエストのルーティング方法を制御するルールを定義します。

aspnetcore-gateway.yaml ファイルを作成して Gateway を定義します。

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 コマンドを実行して、次のコマンドで Gateway をデプロイします。

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> に移動してアプリを表示することもできます。

f579a9baedc108a9.png

10. 完了

Google Kubernetes Engine(GKE)で実行されている Kubernetes にシンプルな ASP.NET Core アプリをデプロイし、Istio で管理するように構成しました。

「Istio のメリットは何ですか?」と疑問に思われるかもしれません。ありがとうございます。ここまでのところ、Istio にこのアプリを管理する利点はありません。ラボの後半では、指標、トレース、動的トラフィック管理、サービスの可視化、フォールト インジェクションなど、Istio の機能について詳しく見ていきます。

次のステップ

ライセンス

この作業はクリエイティブ・コモンズの表示 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