Esegui il deployment di un'app .NET Framework in Google Kubernetes Engine utilizzando un flusso di lavoro GitHub Actions

Questo tutorial descrive come utilizzare un flusso di lavoro di GitHub Actions, per eseguire il deployment di un'applicazione web ASP.NET Model-View-Controller (MVC) che utilizza .NET Framework in Google Kubernetes Engine (GKE).

Questo tutorial è destinato a sviluppatori e ingegneri DevOps che hanno una conoscenza di base di Microsoft .NET, GitHub Actions e GKE. Per eseguire questo tutorial è necessario anche un account GitHub.

Obiettivi

Esegui il deployment di un'applicazione web ASP.NET MVC che utilizza .NET Framework 4 ed è in esecuzione su Windows in Google Kubernetes Engine.

Il seguente diagramma mostra il flusso di lavoro di GitHub Actions per eseguire il deployment di un'applicazione web ASP.NET MVC in Google Kubernetes Engine (GKE).

Diagramma concettuale del flusso di lavoro di GitHub Actions

Questo tutorial mostra come completare le seguenti attività per raggiungere il tuo obiettivo:

  • Crea un repository GitHub
  • Configura l'autenticazione
  • Esegui il deployment di un cluster GKE e di un repository Artifact Registry
  • Crea un flusso di lavoro di GitHub Actions

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

I nuovi Google Cloud utenti potrebbero avere diritto a una prova senza costi.

Al termine delle attività descritte in questo documento, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per saperne di più, consulta Liberare spazio.

Prima di iniziare

  1. Accedi al tuo Google Cloud account. Se non conosci Google Cloud, crea un account per valutare le prestazioni dei nostri prodotti in scenari reali. I nuovi clienti ricevono anche 300 $di crediti senza costi per l'esecuzione, il test e il deployment dei workload.
  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

Crea un repository GitHub

Crea un fork del repository dotnet-docs-samples nel tuo account GitHub. Questo passaggio è necessario perché stiamo creando con GitHub Actions.

  1. Vai al dotnet-docs-samples repository GitHub.
  2. Fai clic su Fork.
  3. Nella pagina Crea un nuovo fork, imposta quanto segue:

    • Proprietario : il tuo account GitHub
    • Nome repository - dotnet-docs-samples
  4. Fai clic su Crea fork.

Configura l'autenticazione

Preparail tuo Google Cloud progetto in modo che GitHub Actions possa autenticare e accedere alle risorse nel Google Cloud progetto.

Crea un pool e un provider di federazione delle identità per i carichi di lavoro

Per consentire a GitHub Actions di autenticare Google Cloud ed eseguire il deployment in GKE, utilizza la federazione delle identità per i workload. Utilizzando la federazione delle identità per i workload, puoi evitare di dover archiviare e gestire le chiavi degli account di servizio per il tuo workload di GitHub Actions.

L'utilizzo della federazione delle identità per i workload richiede un pool di identità del workload e un provider. Ti consigliamo di utilizzare un progetto dedicato per gestire i pool e i provider di identità per i carichi di lavoro. In questo tutorial, per semplicità, crea il pool e il provider nello stesso progetto del cluster GKE:

  1. Apri la Google Cloud console.

  2. Nella Google Cloud console, attiva Cloud Shell.

    Attiva Cloud Shell

    Nella parte inferiore della Google Cloud console viene avviata una sessione di Cloud Shell e viene visualizzato un prompt della riga di comando. Cloud Shell è un ambiente shell con Google Cloud CLI già inclusa e installata e con valori già impostati per il progetto corrente. L'inizializzazione della sessione può richiedere alcuni secondi.

  3. Crea un nuovo pool di identità del workload:

    gcloud iam workload-identity-pools create github-actions \
        --location="global" \
        --description="GitHub Actions tutorial" \
        --display-name="GitHub Actions"
    
  4. Aggiungi GitHub Actions come provider di pool di identità del workload:

    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'"
    

    Sostituisci ORGANIZATION con il nome della tua organizzazione GitHub.

Crea un account di servizio

  1. In Cloud Shell, crea un account di servizio che GitHub Actions può utilizzare per pubblicare immagini Docker ed eseguire il deployment in GKE:

    SERVICE_ACCOUNT=$(gcloud iam service-accounts create github-actions-workflow \
      --display-name "GitHub Actions workflow" \
      --format "value(email)")
    
  2. Concedi il ruolo Writer di Artifact Registry (roles/artifactregistry.writer) all'account di servizio per consentire a GitHub Actions di eseguire il push in Artifact Registry:

    gcloud projects add-iam-policy-binding $(gcloud config get-value core/project) \
      --member serviceAccount:$SERVICE_ACCOUNT \
      --role roles/artifactregistry.writer
    
  3. Concedi il ruolo Sviluppatore Google Kubernetes Engine (roles/container.developer) all'account di servizio per consentire a GitHub Actions di eseguire il push in Artifact Registry:

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

Consenti al flusso di lavoro di GitHub Actions di utilizzare l'account di servizio

Consenti al flusso di lavoro di GitHub Actions di simulare l'identità e utilizzare l'account di servizio:

  1. Inizializza una variabile di ambiente che contiene il soggetto utilizzato dal flusso di lavoro di GitHub Actions. Un soggetto è simile a un nome utente che identifica in modo univoco il repository e il ramo GitHub:

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

    Sostituisci OWNER con il tuo nome utente GitHub.

  2. Concedi al soggetto l'autorizzazione a simulare l'identità dell'account di servizio:

    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"
    

Esegui il deployment di un cluster GKE e di un repository Artifact Registry

  1. Crea un repository per le immagini Docker:

    gcloud artifacts repositories create clouddemo \
      --repository-format=docker \
      --location=us-central1
    
  2. Consenti all'account di servizio predefinito Compute Engine di accedere al repository:

    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. Crea il 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
    

    Il completamento di questo comando potrebbe richiedere diversi minuti.

  4. Recupera il nome e il numero del progetto del 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\))"
    

    Avrai bisogno di questi valori in un secondo momento.

Crea un flusso di lavoro di GitHub Actions

Ora puoi utilizzare GitHub Actions per configurare l'integrazione continua. Per ogni commit di cui viene eseguito il push nel repository Git, un flusso di lavoro di GitHub Actions crea il codice e impacchetta gli artefatti di build in un container Docker. Il container viene quindi pubblicato in Artifact Registry.

Il repository contiene già il seguente 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"]

Il repository contiene anche un manifest 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

Crea un flusso di lavoro di GitHub Actions che:

  • Autentica utilizzando la federazione delle identità per i workload e l'account di servizio che hai creato in precedenza. Google Cloud
  • Crea un'immagine Docker ed eseguine il deployment in Artifact Registry.
  • Esegui il deployment dell'immagine Docker in GKE.

Per creare il flusso di lavoro di GitHub Actions, procedi come segue:

  1. Su GitHub, vai al fork del dotnet-docs-samples repository.
  2. Fai clic su Aggiungi file > Crea nuovo file.
  3. Nel campo di testo Assegna un nome al file, inserisci il seguente nome:

    .github/workflows/deploy-gke.yaml
    
  4. Incolla il seguente codice nel file:

    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
    

    Sostituisci i seguenti valori:

    • PROJECT_ID: l'ID progetto del progetto che contiene il cluster GKE.
    • PROJECT_NUMBER: il numero del progetto che contiene il cluster GKE.
  5. Nella sezione Esegui il commit del nuovo file , inserisci un messaggio di commit, ad esempio Add workflow e fai clic su Esegui il commit del nuovo file.

  6. Nel menu, fai clic su Azioni e attendi il completamento del workflow.

    Il completamento del workflow potrebbe richiedere diversi minuti.

  7. Nella Google Cloud console, aggiorna la pagina Servizi e Ingress.

    Vai a Servizi e Ingress

  8. Vai alla scheda Ingress.

  9. Individua il servizio Ingress per il cluster clouddemo e attendi che il suo stato passi a Ok. Questa operazione potrebbe richiedere diversi minuti.

  10. Apri il link nella colonna Frontend della stessa riga. Il bilanciatore del carico impiega alcuni minuti per diventare disponibile, quindi l'app CloudDemo potrebbe non essere caricata all'inizio. Quando il bilanciatore del carico è pronto, vedrai l'app CloudDemo con il titolo personalizzato, questa volta in esecuzione nel cluster di produzione.

Libera spazio

Al termine del tutorial, puoi eliminare le risorse che hai creato in modo che non utilizzino più la quota generando addebiti. Le seguenti sezioni descrivono come eliminare o disattivare queste risorse.

Elimina il repository GitHub

Per eliminare il repository GitHub, consulta Eliminare un repository. L'eliminazione del repository comporta la perdita di tutte le modifiche del codice sorgente.

Elimina il progetto

Il modo più semplice per eliminare la fatturazione è quello di eliminare il progetto creato per il tutorial.

    Elimina un Google Cloud progetto:

    gcloud projects delete PROJECT_ID

Passaggi successivi