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.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.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-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 であるため、インターネットからアクセスできます。他の 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

上り(内向き)トラフィックがメッシュに到達できるようにするには、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. 完了

シンプルな ASP.NET Core アプリを Google Kubernetes Engine(GKE)で実行されている Kubernetes にデプロイし、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