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

1. 概要

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

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

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

ラボの第 2 部では、指標、トレース、動的トラフィック管理、障害の挿入など、Istio の機能をさらに詳しく調べます。

学習内容

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

必要なもの

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

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

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

初心者 中級者 上級者

2. 設定と要件

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

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

96a9c957bc475304.pngb9a10ebdf5b5a448.pnga1e3c01a38fa61c2.png

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

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

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

Cloud Shell の起動

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

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 コンテナにパッケージ化する

次に、アプリをコンテナとして実行するための準備を行います。最初のステップとして、コンテナとその内容を定義します。

アプリのベース ディレクトリに、Docker イメージを定義する Dockerfile を作成します。

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            

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

docker run -p 8080:8080 gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1

ここでも Cloud Shell のウェブ プレビュー機能を利用します。

Screenshot from 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 の使用を開始するために、アプリケーションを変更する必要はありません。サービスを構成して実行すると、Envoy サイドカーがサービスの各 Pod に自動的に挿入されます。

これを行うには、マイクロサービスに使用する名前空間(「default」)のサイドカー インジェクションを有効にする必要があります。これを行うには、ラベルを適用します。

kubectl label namespace default istio-injection=enabled

ラベルが正常に適用されたことを確認するには、次のコマンドを実行します。

kubectl get namespace -L istio-injection

出力は、デフォルトの Namespace でサイドカー インジェクションが有効になっていることを確認します。

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

7. インストールを確認する

Istio には、istiod コントロール プレーン、Ingress ゲートウェイ、Egress ゲートウェイ(「インターネットの残りの部分のサイドカー プロキシ」と考えることができます)の 3 つのサービスが付属しています。それぞれ 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 Gateway のタイプは LoadBalancer であるため、インターネットからアクセスできます。他の Gateway はクラスタ内からのみアクセスできれば十分です。

次に、対応する 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 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

上り(内向き)トラフィックがメッシュに到達できるようにするには、Gateway と VirtualService を作成する必要があります。

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. クリーンアップ

ラボの第 2 部に進まない場合は、アプリを削除して 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