GKE で .NET Core アプリを実行してみた
この記事は Google Cloud Japan Customer Engineer Advent Calendar 2019 の 15日目の記事です。
TL;DR
.NET Core の特徴の一つはクロスプラットフォームであり、Windows 以外に Linux でも実行できるランタイムです。.NET Core のアプリケーションをコンテナ化し、Google Kubernetes Engine (GKE) を実行環境として選ぶと Google Cloud Platform (GCP)のサービスを利用できるメリットがありますので、簡単な Web アプリを GKE と GCP が提供している HTTP(S) Load Balancer の特徴を活かした設定を紹介します。
.NET Core の簡単なアプリケーションを作成しコンテナ化
.NET Core は現時点で 3.1 になっており、3.0 以降にコンテナ化として使うためにいくつかのパフォーマンス改善がありました。
Web アプリもしくは Web API を利用するには、.NET Core でもいいですが、ASP .NET Core は Web アプリケーションを作成するためのライブラリーを集めたフレームワークになりますので、ASP .NET Core を使ったほうが早いです。
この記事では以下の構成で簡単な ASP .NET Core アプリケーションを GKE にホスティングします。
まずは .NET Core をインストールします。インストールされたら Version が 3.0 以降かを確認します。
dotnet --version
簡単な Web アプリケーションを作成します。
dotnet new webapp
※ API を作成するには :dotnet new webapi
上のコマンドでテンプレートからアプリケーションが作成され、好みの IDE でコーディング・デバッグし、ローカルで実行します。
dotnet run — urls=http://localhost:8080
Docker Container として作成したアプリをパッケージするための Dockerfile を作成します。
例として Dockerfile は以下のようになります。
# Use official image from Microsoft
FROM mcr.microsoft.com/dotnet/core/sdk:3.0 AS build-env
WORKDIR /app# Copy csproj and restore as distinct layers
COPY *.csproj ./
RUN dotnet restore# Copy everything else and build
COPY . ./
RUN dotnet publish -c Release -o out# Build runtime image
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0
WORKDIR /app
COPY --from=build-env /app/out .# App binds to port 8080
ENV ASPNETCORE_URLS http://*:8080
ENTRYPOINT ["dotnet", "dotnetwebapp.dll"]
Dockerfile には環境変数である ASPNETCORE_URLS
を利用してポートを指定します。
次は Docker でビルドしたイメージを GCP が提供しているコンテナレジストリサービス GCR にプッシュします。
ProjectID を変数として取得
export PROJECT_ID=$(gcloud config get-value core/project)
Docker イメージをビルド
docker build -t gcr.io/${PROJECT_ID}/dotnet-app:v1 .
ここでローカル環境でコンテナが問題なく稼働できるかを確認
docker run -p 8080:8080 gcr.io/${PROJECT_ID}/dotnet-app:v1
curl localhost:8080
もしくはウェブブラウザに http://localhost:8080 にアクセスすると
GCR にプッシュ
docker push gcr.io/${PROJECT_ID}/dotnet-app:v1
これで GKE に Deployment を作成するために準備完了!
GKE クラスタを作成し、Deployment と Service を作成
GKE の詳細な作成方法はここに書きませんが、既存の GKE に対し Deployment や Service を作成するには Credentials が必要なので、取得します。
gcloud container clusters get-credentials <GKEクラスタ名>
そして Deployment と Service の作成はここに記載した同じ方法でできます。
今回は GKE Ingress と NodePort を使って外部にサービスを公開しますGKE では Ingress を作成すると HTTP(S) Load Balancer を作成してくれます。
例えば今回のサンプルで web という Service を NodePort タイプとして作成されているとします。Service が実行しているかを確認します。
kubectl get service web
Ingress リソースを以下の Ingress.yaml でデプロイします。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: basic-ingress
spec:
backend:
serviceName: web
servicePort: 8080
デプロイはこれで行います。
kubectl apply -f ingress.yaml
作成するには少し時間がかかりますが、作成されますと IP アドレスで作成した Web App にアクセスできます。
TLS 通信を行うために Load Balancer に SSL 証明書を設定
ここまでは HTTP 通信を HTTP(S) Load Balancer で実施しました。GCP で HTTPS を対応するのはとても簡単で、Load Balancer に SSL 証明書をアップロードするだけです。
所有しているドメインに対し DNS の設定が必要ですが、Google-managed SSL Certificate (現時点でベータ) で持っているドメインに対し証明書を発行できます。
gcloud beta compute ssl-certificates create mouradecert --domains mourade.com
証明書を Load Balancer にアタッチするには Ingress に Annotation として追加
networking.gke.io/managed-certificates: "mouradecert"
更新された Ingress をデプロイ
kubectl apply -f ingress.yaml
これで登録されているドメインで HTTPS 通信が可能になります。
まとめ
Webアプリケーションや API を .NET Core で作成するときホスティングサービスとして利用できるプラットフォームが多く提供されていますが、コンテナでパッケージし Kubernetes で提供するとスケーラビリティーを簡単に実現できます。GKE はマネージドサービスとして利用するメリットの他、GCP で提供されている HTTP(S) Load Balancer の特徴も活かせるので、TLS 通信を Load Balancer レベルでオフロードできるメリットがあります。