Déployer une application .NET Framework sur Google Kubernetes Engine à l'aide d'un workflow GitHub Actions

Ce tutoriel explique comment utiliser un workflow GitHub Actions, pour déployer une application Web ASP.NET Model-View-Controller (MVC) qui utilise .NET Framework sur Google Kubernetes Engine (GKE).

Ce tutoriel est destiné aux développeurs et aux ingénieurs DevOps qui possèdent des connaissances de base sur Microsoft .NET, GitHub Actions et GKE. Vous devez également disposer d'un compte GitHub pour suivre ce tutoriel.

Objectifs

Déployer une application Web ASP.NET MVC qui utilise .NET Framework 4 et s'exécute sous Windows sur Google Kubernetes Engine.

Le schéma suivant illustre le workflow GitHub Actions permettant de déployer une application Web ASP.NET MVC sur Google Kubernetes Engine (GKE).

Diagramme conceptuel du workflow GitHub Actions

Ce tutoriel vous explique comment effectuer les tâches suivantes, en vue d'atteindre votre objectif :

  • Créer un dépôt GitHub
  • Configurer l'authentification
  • Déployer un cluster GKE et un dépôt Artifact Registry
  • Créer un workflow GitHub Actions

Coûts

Dans ce tutoriel, vous utilisez les composants facturables de suivants Google Cloud:

Obtenez une estimation des coûts en fonction de votre utilisation prévue, utilisez le simulateur de coût.

Les nouveaux utilisateurs de peuvent bénéficier d'un essai sans frais. Google Cloud

Une fois que vous avez terminé les tâches décrites dans ce document, supprimez les ressources que vous avez créées pour éviter que des frais vous soient facturés. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  1. Connectez-vous à votre Google Cloud compte. Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $de crédits sans frais pour exécuter, tester et déployer des charges de travail.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

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

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

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

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

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

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the APIs

Créer un dépôt GitHub

Créez un fork du dépôt dotnet-docs-samples dans votre compte GitHub. Cette étape est nécessaire, car nous allons effectuer la compilation avec GitHub Actions.

  1. Accédez au dotnet-docs-samples dépôt GitHub.
  2. Cliquez sur Fork (Dupliquer).
  3. Sur la page Create a new fork (Créer un fork), définissez les éléments suivants :

    • Owner (Propriétaire) : votre compte GitHub
    • Repository name (Nom du dépôt) : dotnet-docs-samples
  4. Cliquez sur Create fork (Créer un fork).

Configurer l'authentification

Préparez votre Google Cloud projet afin que GitHub Actions puisse s'authentifier et accéder aux ressources du Google Cloud projet.

Créer un pool d'identité de charge de travail et un fournisseur

Pour autoriser GitHub Actions à s'authentifier Google Cloud et à effectuer un déploiement sur GKE, utilisez la fédération d'identité de charge de travail. L'utilisation de la fédération d'identité de charge de travail vous évite d'avoir à stocker et gérer des clés de compte de service pour votre charge de travail GitHub Actions.

L'utilisation de la fédération d'identité de charge de travail nécessite un pool d'identité de charge de travail et un fournisseur. Nous vous recommandons d'utiliser un projet dédié pour gérer les pools d'identité de charge de travail et les fournisseurs. Dans ce tutoriel, par souci de simplicité, créez le pool et le fournisseur dans le même projet que votre cluster GKE :

  1. Ouvrez la Google Cloud console.

  2. Dans la Google Cloud console, activez Cloud Shell.

    Activer Cloud Shell

    En bas de la fenêtre de la console, une session Cloud Shell démarre et affiche une invite de ligne de commande. Google Cloud Cloud Shell est un environnement shell dans lequel Google Cloud CLI est déjà installé, et dans lequel des valeurs sont déjà définies pour votre projet actuel. L'initialisation de la session peut prendre quelques secondes.

  3. Créez un pool d'identité de charge de travail :

    gcloud iam workload-identity-pools create github-actions \
        --location="global" \
        --description="GitHub Actions tutorial" \
        --display-name="GitHub Actions"
    
  4. Ajoutez GitHub Actions en tant que fournisseur de pool d'identité de charge de travail :

    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" \
        --attribute-condition="assertion.repository_owner=='ORGANIZATION'"
    

    Remplacez ORGANIZATION par le nom de votre organisation GitHub.

Créer un compte de service

  1. Dans Cloud Shell, créez un compte de service que GitHub Actions peut utiliser pour publier des images Docker et effectuer un déploiement sur GKE :

    SERVICE_ACCOUNT=$(gcloud iam service-accounts create github-actions-workflow \
      --display-name "GitHub Actions workflow" \
      --format "value(email)")
    
  2. Attribuez le rôle de rédacteur Artifact Registry (roles/artifactregistry.writer) au compte de service pour autoriser les actions GitHub à effectuer un push vers Artifact Registry :

    gcloud projects add-iam-policy-binding $(gcloud config get-value core/project) \
      --member serviceAccount:$SERVICE_ACCOUNT \
      --role roles/artifactregistry.writer
    
  3. Attribuez le rôle de développeur Google Kubernetes Engine (roles/container.developer) au compte de service pour autoriser les actions GitHub à effectuer un push vers Artifact Registry :

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

Autoriser le workflow GitHub Actions à utiliser le compte de service

Autorisez le workflow GitHub Actions à emprunter l'identité du compte de service et à l'utiliser :

  1. Initialisez une variable d'environnement contenant le sujet utilisé par le workflow GitHub Actions. Un sujet est semblable à un nom d'utilisateur qui identifie de manière unique le dépôt et la branche GitHub :

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

    Remplacez OWNER par votre nom d'utilisateur GitHub.

  2. Accordez au sujet l'autorisation d'emprunter l'identité du compte de service :

    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"
    

Déployer un cluster GKE et un dépôt Artifact Registry

  1. Créez un dépôt pour les images Docker :

    gcloud artifacts repositories create clouddemo \
      --repository-format=docker \
      --location=us-central1
    
  2. Autorisez le compte de service Compute Engine par défaut à accéder au dépôt :

    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. Créez le cluster :

    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
    

    Cette commande peut prendre plusieurs minutes.

  4. Obtenez le nom et le numéro du projet du cluster :

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

    Vous aurez besoin de ces valeurs ultérieurement.

Créer un workflow GitHub Actions

Vous pouvez maintenant utiliser GitHub Actions pour configurer une intégration continue. Pour chaque commit envoyé dans le dépôt Git, un workflow GitHub Actions compile le code et crée un package des artefacts de la compilation dans un conteneur Docker. Le conteneur est ensuite publié dans Artifact Registry.

Le dépôt contient déjà le fichier Dockerfile suivant :

#
# 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"]

Le dépôt contient également un fichier manifeste 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

Créez un workflow GitHub Actions qui effectue les opérations suivantes :

  • Authentifiez-vous à l'aide de la fédération d'identité de charge de travail et du compte de service que vous avez créé précédemment. Google Cloud
  • Compilez une image Docker et déployez-la sur Artifact Registry.
  • Déployez l'image Docker sur GKE.

Pour créer le workflow GitHub Actions, procédez comme suit :

  1. Sur GitHub, accédez à votre fork du dotnet-docs-samples dépôt.
  2. Cliquez sur Add file (Ajouter un fichier) > Create new file (Créer un fichier).
  3. Dans le champ de texte Name your file (Nommer votre fichier), saisissez le nom suivant :

    .github/workflows/deploy-gke.yaml
    
  4. Copiez le code suivant dans le fichier :

    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
    

    Remplacez les valeurs suivantes :

    • PROJECT_ID : ID de projet du projet contenant le cluster GKE.
    • PROJECT_NUMBER : numéro de projet du projet contenant le cluster GKE.
  5. Dans la section Commit new file (Valider le nouveau fichier), saisissez un message de commit, par exemple Add workflow, puis cliquez sur Commit new file (Valider le nouveau fichier).

  6. Dans le menu, cliquez sur Actions et attendez la fin du workflow.

    Le workflow peut prendre plusieurs minutes.

  7. Dans la Google Cloud console, actualisez la page Services & Ingress.

    Accéder à la page Services et entrées

  8. Accédez à l'onglet Ingress (Entrée).

  9. Recherchez le service d'Ingress pour le cluster clouddemo et attendez que son état bascule sur Ok. Cela peut prendre quelques minutes.

  10. Ouvrez le lien dans la colonne Frontends (Interfaces) de la même ligne. L'équilibreur de charge a besoin de quelques minutes pour devenir disponible. Il est donc possible que l'application CloudDemo ne se charge pas au début. Lorsque l'équilibreur de charge est prêt, l'application CloudDemo s'affiche avec le titre personnalisé, qui s'exécute cette fois-ci dans le cluster de production.

Effectuer un nettoyage

Une fois le tutoriel terminé, vous pouvez procéder au nettoyage des ressources que vous avez créées afin qu'elles ne soient plus comptabilisées dans votre quota et qu'elles ne vous soient plus facturées. Dans les sections suivantes, nous allons voir comment supprimer ou désactiver ces ressources.

Supprimer le dépôt GitHub

Pour supprimer le dépôt GitHub, consultez Supprimer un dépôt. La suppression du dépôt entraîne la perte de toutes les modifications du code source.

Supprimer le projet

Le moyen le plus simple d’éliminer la facturation consiste à supprimer le projet que vous avez créé pour ce tutoriel.

    Supprimer un Google Cloud projet :

    gcloud projects delete PROJECT_ID

Étape suivante