GitHub Actions ワークフローを使用して .NET Framework アプリを Google Kubernetes Engine にデプロイする


このチュートリアルでは、GitHub Actions ワークフローを使用して、.NET Framework を使用する ASP.NET Model-View-Controller(MVC)ウェブ アプリケーションを Google Kubernetes Engine (GKE)にデプロイする方法について説明します。

このチュートリアルは、Microsoft .NET、GitHub Actions、GKE に関する基本的な知識があるデベロッパーと DevOps エンジニアを対象としています。このチュートリアルを実行するには、GitHub アカウントが必要です。

目標

.NET Framework 4 を使用し、Windows で実行されている ASP.NET MVC ウェブ アプリケーションを Google Kubernetes Engine にデプロイします。

次の図は、ASP.NET MVC ウェブ アプリケーションを Google Kubernetes Engine(GKE)にデプロイする GitHub Actions ワークフローを示しています。

GitHub Actions ワークフローの概念図

このチュートリアルでは、目的を達成するために次のタスクを行う方法について説明します。

  • GitHub リポジトリの作成
  • 認証を構成する
  • GKE クラスタと Artifact Registry リポジトリをデプロイする
  • GitHub Actions ワークフローを作成する

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. Artifact Registry and Google Kubernetes Engine API を有効にします。

    API を有効にする

  5. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  6. Google Cloud プロジェクトで課金が有効になっていることを確認します

  7. Artifact Registry and Google Kubernetes Engine API を有効にします。

    API を有効にする

GitHub リポジトリの作成

GitHub アカウントに dotnet-docs-samples リポジトリのフォークを作成します。GitHub Actions でビルドしているので、この手順が必要です。

  1. dotnet-docs-samples GitHub リポジトリに移動します。
  2. [Fork] をクリックします。
  3. [新しいフォークの作成] ページで、次のように設定します。

    • オーナー - GitHub アカウント
    • リポジトリ名 - dotnet-docs-samples
  4. [フォークの作成] をクリックします。

認証を構成する

GitHub Actions が Google Cloud プロジェクトのリソースを認証してアクセスできるように、Google Cloud プロジェクトを準備します。

Workload Identity 連携のプールとプロバイダを作成する

GitHub Actions が Google Cloud を認証して GKE にデプロイするのを許可するには、Workload Identity 連携を使用します。Workload Identity 連携を使用することで、GitHub Actions ワークロードのサービス アカウント キーを保存および管理する必要がなくなります。

Workload Identity 連携を使用するには、Workload Identity プールとプロバイダが必要です。専用のプロジェクトを使用して Workload Identity プールとプロバイダを管理することをおすすめします。このチュートリアルでは、わかりやすくするために、GKE クラスタと同じプロジェクトにプールとプロバイダを作成します。

  1. Google Cloud コンソールを開きます。

  2. Google Cloud コンソールで、「Cloud Shell をアクティブにする」をクリックします。

    Cloud Shell をアクティブにする

    Google Cloud コンソールの下部で Cloud Shell セッションが開始し、コマンドライン プロンプトが表示されます。Cloud Shell はシェル環境です。Google Cloud CLI がすでにインストールされており、現在のプロジェクトの値もすでに設定されています。セッションが初期化されるまで数秒かかることがあります。

  3. 新しい Workload Identity プールを作成します。

    gcloud iam workload-identity-pools create github-actions \
        --location="global" \
        --description="GitHub Actions tutorial" \
        --display-name="GitHub Actions"
    
  4. GitHub Actions を Workload Identity プールのプロバイダとして追加します。

    gcloud iam workload-identity-pools providers create-oidc github-actions-oidc \
        --location="global" \
        --workload-identity-pool=github-actions \
        --issuer-uri="https://token.actions.githubusercontent.com/" \
        --attribute-mapping="google.subject=assertion.sub"
    

サービス アカウントを作成する

  1. Cloud Shell で、GitHub Actions が Docker イメージの公開と GKE へのデプロイに使用できるサービス アカウントを作成します。

    SERVICE_ACCOUNT=$(gcloud iam service-accounts create github-actions-workflow \
      --display-name "GitHub Actions workflow" \
      --format "value(email)")
    
  2. Artifact Registry 書き込みロールroles/artifactregistry.writer)をサービス アカウントに付与して、GitHub のアクションが Artifact Registry に push できるようにします。

    gcloud projects add-iam-policy-binding $(gcloud config get-value core/project) \
      --member serviceAccount:$SERVICE_ACCOUNT \
      --role roles/artifactregistry.writer
    
  3. Google Kubernetes Engine デベロッパーのロールroles/container.developer)をサービス アカウントに付与して、GitHub のアクションが Artifact Registry に push できるようにします。

    gcloud projects add-iam-policy-binding $(gcloud config get-value core/project) \
      --member serviceAccount:$SERVICE_ACCOUNT \
      --role roles/container.developer
    

GitHub Actions ワークフローにサービス アカウントの使用を許可する

GitHub Actions ワークフローにサービス アカウントの権限借用と使用を許可します。

  1. GitHub Actions ワークフローで使用されるサブジェクトを含む環境変数を初期化します。サブジェクトは、GitHub リポジトリとブランチを一意に識別するユーザー名に似ています。

    SUBJECT=repo:OWNER/dotnet-docs-samples:ref:refs/heads/main
    

    OWNER は GitHub ユーザー名で置き換えます。

  2. サービス アカウントの権限を借用する権限をサブジェクトに付与します。

    PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value core/project) --format='value(projectNumber)')
    
    gcloud iam service-accounts add-iam-policy-binding $SERVICE_ACCOUNT \
      --role=roles/iam.workloadIdentityUser \
      --member="principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/github-actions/subject/$SUBJECT"
    

GKE クラスタと Artifact Registry リポジトリをデプロイする

  1. Docker イメージ用のリポジトリを作成します。

    gcloud artifacts repositories create clouddemo \
      --repository-format=docker \
      --location=us-central1
    
  2. Compute Engine のデフォルトのサービス アカウントにリポジトリへのアクセスを許可します。

    gcloud projects add-iam-policy-binding $(gcloud config get-value core/project) \
      --member=serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
      --role=roles/artifactregistry.reader
    
  3. クラスタを作成します。

    gcloud container clusters create clouddemo-windows \
      --enable-ip-alias \
      --zone us-central1-a
    
    gcloud container node-pools create clouddemo-windows-pool \
      --cluster=clouddemo-windows \
      --image-type=WINDOWS_LTSC_CONTAINERD \
      --no-enable-autoupgrade \
      --machine-type=n1-standard-2 \
      --zone us-central1-a
    

    この手順は完了するまでに数分かかることがあります。

  4. クラスタのプロジェクト名とプロジェクト番号を取得します。

    echo "Project ID: $(gcloud config get-value core/project)"
    echo "Project Number: $(gcloud projects describe $(gcloud config get-value core/project) --format=value\(projectNumber\))"
    

    これらの値は後で必要になります。

GitHub Actions ワークフローを作成する

これで、GitHub Actions を使用して継続的インテグレーションを設定できるようになりました。commit によって Git リポジトリへの push を行うたびに、GitHub Actions ワークフローによってコードがビルドされ、そのビルドのアーティファクトが Docker コンテナにパッケージ化されます。そのコンテナは Artifact Registry に公開されます。

リポジトリには、すでに次の Dockerfile が含まれています。

#
# Copyright 2020 Google LLC
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

FROM mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
EXPOSE 80
SHELL ["powershell", "-command"]

#------------------------------------------------------------------------------
# Add LogMonitor so that IIS and Windows logs are emitted to STDOUT and can be
# picked up by Docker/Kubernetes.
#
# See https://github.com/microsoft/windows-container-tools/wiki/Authoring-a-Config-File
# for details.
#------------------------------------------------------------------------------

ADD https://github.com/microsoft/windows-container-tools/releases/download/v1.1/LogMonitor.exe LogMonitor/
ADD LogMonitorConfig.json LogMonitor/

#------------------------------------------------------------------------------
# Copy publishing artifacts to webroot.
#------------------------------------------------------------------------------

ADD CloudDemo.Mvc/bin/Release/PublishOutput/ c:/inetpub/wwwroot/

#------------------------------------------------------------------------------
# Configure IIS using the helper functions from deployment.ps1.
#------------------------------------------------------------------------------

ADD deployment.ps1 /
RUN . /deployment.ps1; \
	Install-Iis; \
	Register-WebApplication -AppName "CloudDemo"; \
	Remove-Item /deployment.ps1

#------------------------------------------------------------------------------
# Run IIS, wrapped by LogMonitor.
#------------------------------------------------------------------------------

ENTRYPOINT ["C:\\LogMonitor\\LogMonitor.exe", "C:\\ServiceMonitor.exe", "w3svc"]

リポジトリには Kubernetes マニフェストも含まれています。

#
# Copyright 2020 Google LLC
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#

apiVersion: v1
kind: Service
metadata:
  name: clouddemo-net4
  annotations:
    cloud.google.com/neg: '{"ingress": false}' # Disable NEG

spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
    name: http
  selector:
    app: clouddemo-net4
  type: NodePort

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: clouddemo-net4
spec:
  defaultBackend:
    service:
      name: clouddemo-net4
      port:
        number: 80

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: clouddemo-net4
spec:
  replicas: 2
  selector:
    matchLabels:
      app: clouddemo-net4
  template:
    metadata:
      labels:
        app: clouddemo-net4
    spec:
      nodeSelector:
        kubernetes.io/os: windows
      containers:
      - name: clouddemo-net4
        image: CLOUDDEMO_IMAGE
        ports:
          - containerPort: 80
        livenessProbe:      # Used by deployment controller
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 120
          periodSeconds: 5
        readinessProbe:     # Used by Ingress/GCLB
          httpGet:
            path: /health
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 5
        resources:
          limits:
            memory: 1024Mi
          requests:
            memory: 256Mi

次の処理を行う GitHub Actions ワークフローを作成します。

  • Workload Identity 連携と前の手順で作成したサービス アカウントを使用して、Google Cloud に対する認証を行います。
  • Docker イメージをビルドして、Artifact Registry にデプロイします。
  • Docker イメージを GKE にデプロイします。

GitHub Actions ワークフローを作成するには、次のようにします。

  1. GitHub で、dotnet-docs-samples リポジトリのフォークに移動します。
  2. [ファイルを追加] > [新しいファイルを作成] をクリックします。
  3. [Name your file] テキスト フィールドに次の名前を入力します。

    .github/workflows/deploy-gke.yaml
    
  4. 次のコードをファイルにコピーします。

    name: Build and Deploy to GKE
    
    on:
      push:
        branches:
          - main
    
    env:
      PROJECT_ID: PROJECT_ID
      PROJECT_NUMBER: PROJECT_NUMBER
    
      CLUSTER: clouddemo-windows
      CLUSTER_ZONE: us-central1-a
    
      REPOSITORY: clouddemo
      REPOSITORY_REGION: us-central1
    
      IMAGE: clouddemo
    
    jobs:
      build:
        runs-on: windows-2019  # Matches WINDOWS_LTSC in GKE
        permissions:
          id-token: write
          contents: read
    
        steps:
        - name: Checkout
          uses: actions/checkout@v3
    
        #
        # Authenticate to Google Cloud using workload identity federation
        #
        - id: 'auth'
          name: 'Obtain access token by using workload identity federation'
          uses: 'google-github-actions/auth@v0'
          with:
            create_credentials_file: true
            token_format: access_token
            workload_identity_provider: projects/${{ env.PROJECT_NUMBER }}/locations/global/workloadIdentityPools/github-actions/providers/github-actions-oidc
            service_account: github-actions-workflow@${{ env.PROJECT_ID }}.iam.gserviceaccount.com
    
        - name: Connect to Artifact Registry
          run: |-
            echo ${{ steps.auth.outputs.access_token }} | docker login -u oauth2accesstoken --password-stdin https://${{ env.REPOSITORY_REGION }}-docker.pkg.dev
    
        - name: Connect to GKE
          uses: google-github-actions/get-gke-credentials@v0
          with:
            cluster_name: ${{ env.CLUSTER }}
            location: ${{ env.CLUSTER_ZONE }}
    
        #
        # Build the .NET code
        #
        - name: Setup MSBuild
          uses: microsoft/setup-msbuild@v1
    
        - name: Setup NuGet
          uses: NuGet/setup-nuget@v1
    
        - name: Restore NuGet packages
          run: nuget restore applications/clouddemo/net4/CloudDemo.Mvc.sln
    
        - name: Build solution
          run: msbuild /t:Rebuild /p:Configuration=Release /p:DeployOnBuild=true /p:PublishProfile=FolderProfile /nologo applications/clouddemo/net4/CloudDemo.Mvc.sln
    
        #
        # Build the Docker image and push it to Artifact Registry
        #
        - name: Create image tag
          run: echo "IMAGE_TAG=${{ env.REPOSITORY_REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/${{ env.IMAGE }}:$env:GITHUB_SHA" >> $env:GITHUB_ENV
    
        - name: Lock image version in deployment.yaml
          shell: pwsh
          run: (Get-Content applications\clouddemo\net4\deployment.yaml) -replace "CLOUDDEMO_IMAGE","${{ env.IMAGE_TAG }}" | Out-File -Encoding ASCII applications\clouddemo\net4\deployment.yaml
    
        - name: Build Docker image
          run: docker build --tag "${{ env.IMAGE_TAG }}" applications/clouddemo/net4
    
        - name: Publish Docker image to Google Artifact Registry
          run: docker push "${{ env.IMAGE_TAG }"
    
        #
        # Deploy to GKE
        #
        - name: Deploy to GKE
          run: kubectl apply -f applications/clouddemo/net4/deployment.yaml
    

    次の値を置き換えます。

    • PROJECT_ID: GKE クラスタを含むプロジェクトのプロジェクト ID。
    • PROJECT_NUMBER: GKE クラスタを含むプロジェクトのプロジェクト番号。
  5. [Commit new file] セクションで commit メッセージ(Add workflow など)を入力し、[Commit new file] をクリックします。

  6. メニューで [Actions] をクリックし、ワークフローの完了を待ちます。

    ワークフローの完了には数分かかることがあります。

  7. Google Cloud コンソールで、[Services と Ingress] ページを更新します。

    [Service と Ingress] に移動

  8. [Ingress] タブに移動します。

  9. clouddemo クラスタの Ingress サービスを確認して、そのステータスが [OK] に切り替わるのを待ちます。これには数分かかることがあります。

  10. 同じ行の [フロントエンド] 列にあるリンクを開きます。ロードバランサが利用可能になるまで数分かかるため、最初は CloudDemo アプリが読み込まれない場合があります。ロードバランサの準備が整うと、カスタム タイトルが付いた CloudDemo アプリが表示されます。ただし、今回は本番環境クラスタで実行されます。

クリーンアップ

チュートリアルが終了したら、作成したリソースをクリーンアップして、割り当ての使用を停止し、課金されないようにできます。以下のセクションで、リソースを削除または無効にする方法を説明します。

GitHub リポジトリの削除

GitHub リポジトリを削除するには、リポジトリの削除をご覧ください。リポジトリを削除すると、すべてのソースコードの変更が失われます。

プロジェクトの削除

課金を停止する最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

    Delete a Google Cloud project:

    gcloud projects delete PROJECT_ID

次のステップ