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. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Artifact Registry and Google Kubernetes Engine APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Artifact Registry and Google Kubernetes Engine APIs.

    Enable the APIs

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. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  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

次のステップ