Implementa una app de .NET en Google Kubernetes Engine mediante un flujo de trabajo de Acciones de GitHub


En este instructivo, se describe cómo usar una acción de GitHub, un flujo de trabajo para implementar una aplicación web de ASP.NET Model-View-Controller (MVC) que usa .NET en Google Kubernetes Engine (GKE).

Este instructivo está dirigido a desarrolladores y a ingenieros DevOps que tienen conocimientos básicos de Microsoft .NET, GitHub Actions y GKE. También necesitas una cuenta de GitHub para ejecutar este instructivo.

Objetivos

Implementa una aplicación web de ASP.NET Core que use .NET 6.0 y se ejecute en Linux en Google Kubernetes Engine.

En el siguiente diagrama, se muestra el flujo de trabajo de GitHub para implementar una aplicación web de ASP.NET MVC en Google Kubernetes Engine (GKE).

Diagrama conceptual del flujo de trabajo de Acciones de GitHub

En este instructivo, se muestra cómo completar las siguientes tareas para alcanzar tu objetivo:

  • Crea un repositorio de GitHub
  • Configura la autenticación
  • Implementa un clúster de GKE y un repositorio de Artifact Registry
  • Crea un flujo de trabajo de Acciones de GitHub

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.

Antes de comenzar

  1. Accede a tu cuenta de Google Cloud. Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  2. En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  4. Habilita las API de Artifact Registry and Google Kubernetes Engine.

    Habilita las API

  5. En la página del selector de proyectos de la consola de Google Cloud, selecciona o crea un proyecto de Google Cloud.

    Ir al selector de proyectos

  6. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  7. Habilita las API de Artifact Registry and Google Kubernetes Engine.

    Habilita las API

Crea un repositorio de GitHub

Crea una bifurcación del repositorio dotnet-docs-samples en tu cuenta de GitHub. Este paso es necesario porque compilamos con Acciones de GitHub.

  1. Ve al repositorio de GitHub dotnet-docs-samples.
  2. Haz clic en Fork.
  3. En la página Crear un tenedor nuevo, configura lo siguiente:

    • Propietario: Tu cuenta de GitHub
    • Nombre del repositorio: dotnet-docs-samples
  4. Haz clic en Crear bifurcación.

Configura la autenticación

Prepara tu proyecto de Google Cloud para que las acciones de GitHub puedan autenticarse y acceder a los recursos del proyecto de Google Cloud.

Crear un grupo y proveedor de federación de Workload Identity

Para permitir que las acciones de GitHub autentiquen Google Cloud y se implementen en GKE, usa la federación de Workload Identity. Si usas la federación de Workload Identity, puedes evitar la necesidad de almacenar y administrar claves de cuenta de servicio para tu carga de trabajo de GitHub Actions.

El uso de la federación de Workload Identity requiere un grupo y un proveedor de Workload Identity. Te recomendamos que uses un proyecto dedicado para administrar grupos y proveedores de Workload Identity. En este instructivo, por cuestiones de simplicidad, crea el grupo y el proveedor en el mismo proyecto que el clúster de GKE:

  1. Abre la consola de Google Cloud.

  2. En la consola de Google Cloud, activa Cloud Shell.

    Activar Cloud Shell

    En la parte inferior de la consola de Google Cloud, se inicia una sesión de Cloud Shell en la que se muestra una ventana de línea de comandos. Cloud Shell es un entorno de shell con Google Cloud CLI ya instalada y con valores ya establecidos para el proyecto actual. La sesión puede tardar unos segundos en inicializarse.

  3. Crea un nuevo grupo de identidades para cargas de trabajo:

    gcloud iam workload-identity-pools create github-actions \
        --location="global" \
        --description="GitHub Actions tutorial" \
        --display-name="GitHub Actions"
    
  4. Agrega acciones de GitHub como proveedor de grupos de 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"
    

Crea una cuenta de servicio

  1. En Cloud Shell, crea una cuenta de servicio que GitHub Actions pueda usar para publicar imágenes de Docker y, también, implementarlas en GKE:

    SERVICE_ACCOUNT=$(gcloud iam service-accounts create github-actions-workflow \
      --display-name "GitHub Actions workflow" \
      --format "value(email)")
    
  2. Otorga el rol de escritor de Artifact Registry (roles/artifactregistry.writer) a la cuenta de servicio para permitir que las acciones de GitHub envíen a Artifact Registry:

    gcloud projects add-iam-policy-binding $(gcloud config get-value core/project) \
      --member serviceAccount:$SERVICE_ACCOUNT \
      --role roles/artifactregistry.writer
    
  3. Otorga el rol de desarrollador de Google Kubernetes Engine (roles/container.developer) a la cuenta de servicio para permitir que las acciones de GitHub envíen a Artifact Registry:

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

Permitir que el flujo de trabajo de Acciones de GitHub use la cuenta de servicio

Permite que el flujo de trabajo de GitHub Actions actúe en nombre y use la cuenta de servicio:

  1. Inicializa una variable de entorno que contenga el asunto que usa el flujo de trabajo de GitHub Actions. Un sujeto es similar a un nombre de usuario que identifica de forma única el repositorio y la rama de GitHub:

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

    Reemplaza OWNER por tu nombre de usuario de GitHub.

  2. Otorga permiso al sujeto para actuar en nombre de la cuenta de servicio:

    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"
    

Implementa un clúster de GKE y un repositorio de Artifact Registry

  1. Crea un repositorio para las imágenes de Docker:

    gcloud artifacts repositories create clouddemo \
      --repository-format=docker \
      --location=us-central1
    
  2. Permite que la cuenta de servicio predeterminada de Compute Engine acceda al repositorio:

    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 el clúster:

    gcloud container clusters create clouddemo-linux \
      --enable-ip-alias \
      --zone us-central1-a
    

    Este comando puede tardar varios minutos en completarse.

  4. Obtén el nombre y el número del proyecto del clúster:

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

    Necesitará estos valores más adelante.

Crea un flujo de trabajo de Acciones de GitHub

Ahora puedes usar Acciones de GitHub para configurar la integración continua. Por cada confirmación que se envía al repositorio de Git, un flujo de trabajo de GitHub Actions compila el código y empaqueta los artefactos de la compilación en un contenedor de Docker. Luego, el contenedor se publica en Artifact Registry.

El repositorio ya contiene el siguiente 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/dotnet/aspnet:6.0
EXPOSE 8080

#------------------------------------------------------------------------------
# Copy publishing artifacts.
#------------------------------------------------------------------------------

WORKDIR /app
COPY CloudDemo.MvcCore/bin/Release/net6.0/publish/ /app/

ENV ASPNETCORE_URLS=http://0.0.0.0:8080

#------------------------------------------------------------------------------
# Run application in Kestrel.
#------------------------------------------------------------------------------

ENTRYPOINT ["dotnet", "CloudDemo.MvcCore.dll"]

El repositorio también contiene un manifiesto de 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-netcore
spec:
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: clouddemo-netcore
  type: NodePort

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

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: clouddemo-netcore
spec:
  replicas: 2
  selector:
    matchLabels:
      app: clouddemo-netcore
  template:
    metadata:
      labels:
        app: clouddemo-netcore
    spec:
      containers:
      - name: clouddemo-netcore
        image: CLOUDDEMO_IMAGE
        ports:
          - containerPort: 8080
        livenessProbe:      # Used by deployment controller
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        readinessProbe:     # Used by Ingress/GCLB
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 3
          periodSeconds: 5
        resources:
          limits:
            memory: 1024Mi
          requests:
            memory: 256Mi

Crea un flujo de trabajo de GitHub Actions que realice las siguientes acciones:

  • Autentícate en Google Cloud con la federación de Workload Identity y la cuenta de servicio que creaste antes.
  • Compila una imagen de Docker y, luego, impleméntala en Artifact Registry.
  • Implementar la imagen de Docker en GKE

Para crear el flujo de trabajo de Acciones de GitHub, haz lo siguiente:

  1. En GitHub, ve a la bifurcación del repositorio dotnet-docs-samples.
  2. Haga clic en Agregar archivo > Crear archivo nuevo.
  3. En el campo de texto Name your file, ingrese el siguiente nombre:

    .github/workflows/deploy-gke.yaml
    
  4. Copia el siguiente código en el archivo:

    name: Build and Deploy to GKE
    
    on:
      push:
        branches:
          - main
    
    env:
      PROJECT_ID: PROJECT_ID
      PROJECT_NUMBER: PROJECT_NUMBER
    
      CLUSTER: clouddemo-linux
      CLUSTER_ZONE: us-central1-a
    
      REPOSITORY: clouddemo
      REPOSITORY_REGION: us-central1
    
      IMAGE: clouddemo
    
    jobs:
      build:
        runs-on: ubuntu-latest
        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: Build solution
          run: |-
            dotnet publish applications/clouddemo/netcore/CloudDemo.MvcCore.sln \
                --configuration Release \
                --framework net6.0
    
        #
        # 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 }}:$GITHUB_SHA" >> $GITHUB_ENV
    
        - name: Lock image version in deployment.yaml
          run: sed -i 's|CLOUDDEMO_IMAGE|${{ env.IMAGE_TAG }}|g' applications/clouddemo/netcore/deployment.yaml
    
        - name: Build Docker image
          run: docker build --tag "${{ env.IMAGE_TAG }}" applications/clouddemo/netcore
    
        - 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/netcore/deployment.yaml
        

    Reemplaza los siguientes valores:

    • PROJECT_ID: Es el ID del proyecto que contiene el clúster de GKE.
    • PROJECT_NUMBER: Es el número del proyecto que contiene el clúster de GKE.
  5. En la sección Confirmar archivo nuevo, ingresa un mensaje de confirmación, por ejemplo, Add workflow, y haz clic en Confirmar archivo nuevo.

  6. En el menú, haz clic en Acciones y espera a que se complete el flujo de trabajo.

    El flujo de trabajo puede tardar varios minutos en completarse.

  7. En la consola de Google Cloud, actualiza la página Ingress y servicios.

    Ir a Ingress y Service

  8. Ve a la pestaña Entrada.

  9. Ubica el servicio Ingress para el clúster clouddemo y espera a que su estado cambie a Ok. Esto podría llevar varios minutos.

  10. Abre el vínculo en la columna Frontends de la misma fila. El balanceador de cargas tarda unos minutos en estar disponible, por lo que es posible que la app de CloudDemo no se cargue al principio. Cuando el balanceador de cargas esté listo, verás la app de CloudDemo con el título personalizado, que esta vez se ejecuta en el clúster de producción.

Limpia

Una vez que completes el instructivo, puedes limpiar los recursos que creaste para que dejen de usar la cuota y generar cargos. En las siguientes secciones, se describe cómo borrar o desactivar estos recursos.

Borra el repositorio de GitHub

Para borrar el repositorio de GitHub, consulta Borra un repositorio. Si borras el repositorio, se perderán todos los cambios del código fuente.

Borra el proyecto

La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.

    Borra un proyecto de Google Cloud:

    gcloud projects delete PROJECT_ID

¿Qué sigue?