Crea una canalización de IC/EC con Azure Pipelines y Google Kubernetes Engine

Last reviewed 2022-11-29 UTC

En este instructivo, se muestra cómo usar Azure Pipelines, Google Kubernetes Engine (GKE) y Container Registry de Google para crear una canalización de integración continua/implementación continua (CI/CD) para una aplicación web ASP.NET MVC. Para los fines de este instructivo, puedes seleccionar entre dos aplicaciones de ejemplo:

  • Una aplicación web de ASP.NET Core que usa .NET 6.0 y se ejecuta en Linux
  • Una aplicación web ASP.NET MVC que usa .NET Framework 4 y se ejecuta en Windows

La canalización de CI/CD usa dos clústeres de GKE independientes, uno para el desarrollo y otro para la producción, como se muestra en el siguiente diagrama.

Diagrama conceptual de la canalización de CI/CD en el que se muestra cómo los desarrolladores y los usuarios finales interactúan con la aplicación

Al comienzo de la canalización, los desarrolladores confirman cambios en la base de código de ejemplo. Esta acción activa la canalización para crear una nueva versión y para implementarla en el clúster de desarrollo. Un administrador de versiones puede promover la versión para que se implemente en el clúster de producción.

Este instructivo está dirigido a ingenieros DevOps y desarrolladores. Se supone que tienes conocimientos básicos de Microsoft .NET, Azure Pipelines y GKE. Para este instructivo también es necesario tener acceso de administrador a una cuenta de Azure DevOps.

Objetivos

  • Conectar Container Registry de Google con Azure Pipelines para publicar imágenes de Docker
  • Prepara una app de muestra de.NET para implementarla en GKE.
  • Autenticar de forma segura en GKE sin tener que utilizar la autenticación heredada
  • Utilizar la administración de versiones de Azure Pipelines para organizar las implementaciones de GKE

Fuera de alcance

En este instructivo, no se explica cómo conectar Azure Pipelines con un clúster privado de GKE ni cómo conectarse a redes privadas autorizadas.

Costos

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

Para obtener una estimación de costos en función del uso previsto, usa la calculadora de precios.

Es posible que los usuarios de Google Cloud nuevos cumplan con los requisitos para acceder a una prueba gratuita.

Cuando completes las tareas que se describen en este documento, podrás borrar los recursos que creaste para evitar que se te siga facturando. Para obtener más información, consulta Realiza una limpieza.

Consulta la página de precios de Azure DevOps para conocer las tarifas que podrían aplicarse por su uso.

Antes de comenzar

Por lo general, se recomienda usar proyectos diferentes para las cargas de trabajo de desarrollo y producción, a fin de que las funciones y los permisos de administración de identidades y accesos (IAM) se puedan otorgar de forma individual. Por cuestiones prácticas, en este instructivo se usa un solo proyecto para ambos clústeres de GKE, el de desarrollo y el de producción.

  1. 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

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

  3. Asegúrate de tener una cuenta de Azure DevOps y de contar con acceso de administrador. Si todavía no tienes una cuenta de Azure DevOps, puedes registrarte en su página principal.

Crea un proyecto de Azure DevOps

Azure DevOps se usa con el fin de administrar el código fuente, ejecutar compilaciones y pruebas, y organizar la implementación en GKE. Para comenzar, crea un proyecto en la cuenta de Azure DevOps.

  1. Ve a la página principal de Azure DevOps (https://dev.azure.com/YOUR_AZURE_DEVOPS_ACCOUNT_NAME).
  2. Haz clic en Nuevo proyecto.
  3. Ingresa un nombre para el proyecto, como CloudDemo.
  4. Configura la Visibilidad como Privada y, luego, haz clic en Crear.
  5. Después de crear el proyecto, haz clic en Repos en el menú de la izquierda.
  6. Haz clic en Importar para bifurcar el repositorio de dotnet-docs-samples desde GitHub y, luego, establece los siguientes valores:
    • Tipo de repositorio: Git
    • URL de clonación: https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git
  7. Haga clic en Import.

    Una vez completado el proceso de importación, verás el código fuente del repositorio de dotnet-docs-samples.

Conecta Azure Pipelines a Google Container Registry

Antes de configurar la integración continua para la app de CloudDemo, debes conectar Azure Pipelines a Container Registry. Esta conexión permite que Azure Pipelines publique imágenes de contenedor en Container Registry.

Configura una cuenta de servicio para publicar imágenes

Crea una cuenta de servicio deGoogle Cloud en tu proyecto:

  1. Abre la consola de Google Cloud .

  2. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  3. Para ahorrar tiempo cuando escribes el ID del proyecto y las opciones de la zona de Compute Engine, establece los valores de configuración predeterminados; para ello, ejecuta los siguientes comandos:

    gcloud config set project PROJECT_ID
    gcloud config set compute/zone us-central1-a
    

    Reemplaza PROJECT_ID por el ID de tu proyecto:

  4. Habilita la API de Container Registry en el proyecto

    gcloud services enable containerregistry.googleapis.com
    
  5. Crea una cuenta de servicio que Azure Pipelines use para publicar imágenes de Docker:

    gcloud iam service-accounts create azure-pipelines-publisher \
        --display-name="Azure Pipelines Publisher"
    
  6. Otorga la función de IAM de administrador de almacenamiento (roles/storage.admin) a la cuenta de servicio para permitir que Azure Pipelines se envíe a Container Registry:

    AZURE_PIPELINES_PUBLISHER=azure-pipelines-publisher@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
    
    gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
        --member serviceAccount:$AZURE_PIPELINES_PUBLISHER \
        --role roles/storage.admin
    
  7. Genera una clave de cuenta de servicio:

    gcloud iam service-accounts keys create azure-pipelines-publisher.json \
        --iam-account $AZURE_PIPELINES_PUBLISHER
    
    tr -d '\n' < azure-pipelines-publisher.json > azure-pipelines-publisher-oneline.json
    
  8. Visualiza el contenido del archivo de claves de la cuenta de servicio:

    echo $(<azure-pipelines-publisher-oneline.json)
    

    Necesitas la clave de la cuenta de servicio en uno de los siguientes pasos.

  9. Crea una conexión de servicio para Container Registry de Google

    En Azure Pipelines, crea una conexión de servicio nueva para Container Registry:

    1. En el menú de Azure DevOps, selecciona Configuración del proyecto y, luego, selecciona Canalizaciones > Conexiones de servicio.
    2. Haz clic en Crear conexión de servicio.
    3. En la lista, selecciona Registro de Docker y, luego, haz clic en Siguiente.
    4. En el diálogo, ingresa valores para los siguientes campos:
      • Tipo de registro: Otros
      • Registro de Docker: https://gcr.io/PROJECT_ID, y reemplaza PROJECT_ID por el nombre de tu proyecto (por ejemplo, https://gcr.io/azure-pipelines-test-project-12345)
      • ID de Docker: _json_key
      • Contraseña: Pega el contenido de azure-pipelines-publisher-oneline.json
      • Nombre de conexión del servicio: gcr-tutorial
    5. Haz clic en Guardar para crear la conexión.

    Compila de forma continua

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

    El repositorio ya contiene el siguiente Dockerfile:

    .NET/Linux

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

    .NET Framework/Windows

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

    Ahora, debes crear una canalización nueva que use la sintaxis YAML:

    1. Mediante Visual Studio o un cliente git de línea de comandos, clona el repositorio de Git nuevo y revisa la rama main.
    2. En la raíz del repositorio, crea un archivo llamado azure-pipelines.yml.
    3. Copia el siguiente código en el archivo:

      .NET/Linux

      resources:
      - repo: self
        fetchDepth: 1
      pool:
        vmImage: ubuntu-20.04
      trigger:
      - main
      variables:
        TargetFramework: 'net6.0'
        BuildConfiguration: 'Release'
        DockerImageName: 'PROJECT_ID/clouddemo'
      steps:
      - task: DotNetCoreCLI@2
        displayName: Publish
        inputs:
          projects: 'applications/clouddemo/netcore/CloudDemo.MvcCore.sln'
          publishWebProjects: false
          command: publish
          arguments: '--configuration $(BuildConfiguration) --framework=$(TargetFramework)'
          zipAfterPublish: false
          modifyOutputPath: false
      - task: CmdLine@1
        displayName: 'Lock image version in deployment.yaml'
        inputs:
          filename: /bin/bash
          arguments: '-c "awk ''{gsub(\"CLOUDDEMO_IMAGE\", \"gcr.io/$(DockerImageName):$(Build.BuildId)\", $0); print}'' applications/clouddemo/netcore/deployment.yaml > $(build.artifactstagingdirectory)/deployment.yaml"'
      - task: PublishBuildArtifacts@1
        displayName: 'Publish Artifact'
        inputs:
          PathtoPublish: '$(build.artifactstagingdirectory)'
      - task: Docker@2
        displayName: 'Login to Container Registry'
        inputs:
          command: login
          containerRegistry: 'gcr-tutorial'
      - task: Docker@2
        displayName: 'Build and push image'
        inputs:
          Dockerfile: 'applications/clouddemo/netcore/Dockerfile'
          command: buildAndPush
          repository: '$(DockerImageName)'

      .NET Framework/Windows

      resources:
      - repo: self
        fetchDepth: 1
      pool:
        vmImage: windows-2019     # Matches WINDOWS_LTSC in GKE
        demands:
        - msbuild
        - visualstudio
      trigger:
      - master
      variables:
        Solution: 'applications/clouddemo/net4/CloudDemo.Mvc.sln'
        BuildPlatform: 'Any CPU'
        BuildConfiguration: 'Release'
        DockerImageName: 'PROJECT_ID/clouddemo'
      steps:
      - task: NuGetCommand@2
        displayName: 'NuGet restore'
        inputs:
          restoreSolution: '$(Solution)'
      - task: VSBuild@1
        displayName: 'Build solution'
        inputs:
          solution: '$(Solution)'
          msbuildArgs: '/p:DeployOnBuild=true /p:PublishProfile=FolderProfile'
          platform: '$(BuildPlatform)'
          configuration: '$(BuildConfiguration)'
      - task: PowerShell@2
        displayName: 'Lock image version in deployment.yaml'
        inputs:
          targetType: 'inline'
          script: '(Get-Content applications\clouddemo\net4\deployment.yaml) -replace "CLOUDDEMO_IMAGE","gcr.io/$(DockerImageName):$(Build.BuildId)" | Out-File -Encoding ASCII $(build.artifactstagingdirectory)\deployment.yaml'
      - task: PublishBuildArtifacts@1
        displayName: 'Publish Artifact'
        inputs:
          PathtoPublish: '$(build.artifactstagingdirectory)'
      - task: Docker@2
        displayName: 'Login to Container Registry'
        inputs:
          command: login
          containerRegistry: 'gcr-tutorial'
      - task: Docker@2
        displayName: 'Build and push image'
        inputs:
          Dockerfile: 'applications/clouddemo/net4/Dockerfile'
          command: buildAndPush
          repository: '$(DockerImageName)'

      Reemplaza PROJECT_ID por el nombre del proyecto y, luego, guarda el archivo.

    4. Confirma los cambios y envíalos a Azure Pipelines.

      Visual Studio

      1. Abre Team Explorer y haz clic en el ícono de página principal.
      2. Haz clic en Cambios.
      3. Ingresa un mensaje de confirmación, como Add pipeline definition.
      4. Haz clic en Confirmar todo y enviar.

      Línea de comandos

      1. Almacena en etapa intermedia todos los archivos modificados:

        git add -A
        
      2. Confirma los cambios en el repositorio local:

        git commit -m "Add pipeline definition"
        
      3. Envía los cambios a Azure DevOps:

        git push
        
    5. En el menú de Azure DevOps, selecciona Canalizaciones y, luego, haz clic en Crear canalización.

    6. Selecciona Azure Repos Git.

    7. Selecciona tu repositorio.

    8. En la página Revisar la canalización de YAML, haz clic en Ejecutar.

      Se activará una compilación nueva. Es posible que la compilación tarde alrededor de 6 minutos en completarse.

    9. Para verificar que la imagen se publicó en Container Registry, cambia a tu proyecto en la Google Cloud consola, selecciona Container Registry > Imágenes y, luego, haz clic en clouddemo.

      Se muestra una sola imagen y su etiqueta. La etiqueta corresponde al ID numérico de la compilación que se ejecutó en Azure Pipelines.

    Implementa de forma continua

    Debido a que Azure Pipelines compila el código de forma automática y publica las imágenes de Docker de cada confirmación, ahora puedes enfocarte en la implementación.

    A diferencia de otros sistemas de integración continua, Azure Pipelines distingue entre la implementación y la compilación, y ofrece un conjunto especializado de herramientas etiquetadas como Administración de versiones para todas las tareas relacionadas con la implementación.

    La Administración de versiones de Azure Pipelines se basa en los siguientes conceptos:

    • El término versión hace referencia a un conjunto de artefactos que conforman una versión específica de la app y que, por lo general, son el resultado de un proceso de compilación.
    • La implementación se refiere al proceso de tomar una actualización e implementarla en un entorno específico.
    • Una implementación realiza un conjunto de tareas, que se pueden agrupar en trabajos.
    • Las etapas te permiten segmentar la canalización y se pueden usar para organizar implementaciones en varios entornos, por ejemplo, entornos de desarrollo y prueba.

    El artefacto principal que produce el proceso de compilación de CloudDemo es la imagen de Docker. Sin embargo, debido a que la imagen de Docker se publica en Container Registry, la imagen está fuera del alcance de Azure Pipelines. Por ende, la imagen no funciona bien como definición de una versión.

    Para implementar en Kubernetes, también necesitas un manifiesto, que se parece a una factura de materiales. El manifiesto no solamente define los recursos que se supone que Kubernetes creará y administrará, sino que, además, especifica la versión exacta de la imagen de Docker que se utilizará. El manifiesto de Kubernetes es adecuado para funcionar como el artefacto que define la versión en la Administración de versiones de Azure Pipelines.

    Configura la implementación de Kubernetes

    Para ejecutar CloudDemo en Kubernetes, necesitarás los siguientes recursos:

    • Una implementación que defina un solo pod que ejecute la imagen de Docker producida por la compilación
    • Un servicio NodePort que vuelve al pod accesible para el balanceador de cargas
    • Un Ingress que exponga la aplicación a la Internet pública mediante un balanceador de cargas de HTTP(S) de Cloud

    El repositorio ya contiene el siguiente manifiesto de Kubernetes que define estos recursos:

    .NET/Linux

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

    .NET Framework/Windows

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

    Configura los entornos de desarrollo y producción

    Antes de volver a la Administración de versiones de Azure Pipelines, deberás crear el clúster de GKE.

    Crea clústeres de GKE

    1. Regresa a tu instancia de Cloud Shell.

    2. Habilita la API de GKE para tu proyecto:

      gcloud services enable container.googleapis.com
    3. Crea el clúster de desarrollo; para ello, utiliza el siguiente comando. Ten en cuenta que puede tardar unos minutos en completarse:

      .NET/Linux

      gcloud container clusters create azure-pipelines-cicd-dev --enable-ip-alias
      

      .NET Framework/Windows

      gcloud container clusters create azure-pipelines-cicd-dev --enable-ip-alias
      
      gcloud container node-pools create azure-pipelines-cicd-dev-win \
          --cluster=azure-pipelines-cicd-dev \
          --image-type=WINDOWS_LTSC \
          --no-enable-autoupgrade \
          --machine-type=n1-standard-2
      
    4. Crea el clúster de producción mediante el siguiente comando. Ten en cuenta que puede tomar unos minutos en completarse:

      .NET/Linux

      gcloud container clusters create azure-pipelines-cicd-prod --enable-ip-alias
      

      .NET Framework/Windows

      gcloud container clusters create azure-pipelines-cicd-prod --enable-ip-alias
      
      gcloud container node-pools create azure-pipelines-cicd-prod-win \
          --cluster=azure-pipelines-cicd-prod \
          --image-type=WINDOWS_LTSC \
          --no-enable-autoupgrade \
          --machine-type=n1-standard-2
      

    Conecta Azure Pipelines al clúster de desarrollo

    Así como puedes usar Azure Pipelines para conectarte a un registro externo de Docker, como Container Registry, Azure Pipelines admite la integración de clústeres de Kubernetes externos.

    Es posible autenticarse en Container Registry con una cuenta de servicioGoogle Cloud , pero Azure Pipelines no admite el uso de cuentas de servicio Google Cloud para la autenticación con GKE. En su lugar, debes usar una cuenta de servicio de Kubernetes.

    Por lo tanto, para conectar Azure Pipelines al clúster de desarrollo, primero debes crear una cuenta de servicio de Kubernetes.

    1. En Cloud Shell, conéctate al clúster de desarrollo:

      gcloud container clusters get-credentials azure-pipelines-cicd-dev
    2. Crea una cuenta de servicio de Kubernetes para Azure Pipelines:

      kubectl create serviceaccount azure-pipelines-deploy
    3. Crea un Secret de Kubernetes que contenga una credencial de token para Azure Pipelines:

      kubectl create secret generic azure-pipelines-deploy-token --type=kubernetes.io/service-account-token --dry-run -o yaml \
        | kubectl annotate --local -o yaml -f - kubernetes.io/service-account.name=azure-pipelines-deploy \
        | kubectl apply -f -
      
    4. Asigna la función cluster-admin a la cuenta de servicio mediante la creación de una vinculación de función de clúster:

      kubectl create clusterrolebinding azure-pipelines-deploy --clusterrole=cluster-admin --serviceaccount=default:azure-pipelines-deploy
    5. Define la dirección IP del clúster:

      gcloud container clusters describe azure-pipelines-cicd-dev --format=value\(endpoint\)
      

      Necesitarás esta dirección en un momento.

    6. En el menú de Azure DevOps, selecciona Configuración del proyecto y, luego, Canalizaciones > Conexiones de servicio.

    7. Haz clic en Nueva conexión de servicio.

    8. Selecciona Kubernetes y haz clic en Siguiente.

    9. Establece la siguiente configuración:

      • Método de autenticación: Cuenta de servicio
      • URL del servidor: https://PRIMARY_IP. Reemplaza PRIMARY_IP por la dirección IP que definiste antes.
      • Secret: El Secret de Kubernetes que creaste antes. Para obtener el Secret, ejecuta el siguiente comando, copia el Secret y, luego, cópialo en la página de Azure.
        kubectl get secret azure-pipelines-deploy-token -o yaml
      • Nombre de la conexión de servicio: azure-pipelines-cicd-dev
    10. Haz clic en Guardar.

    Conecta Azure Pipelines al clúster de producción

    Para conectar Azure Pipelines al clúster de producción, puedes seguir el mismo enfoque.

    1. En Cloud Shell, conéctate al clúster de producción:

      gcloud container clusters get-credentials azure-pipelines-cicd-prod
    2. Crea una cuenta de servicio de Kubernetes para Azure Pipelines:

      kubectl create serviceaccount azure-pipelines-deploy
    3. Asigna la función cluster-admin a la cuenta de servicio mediante la creación de una vinculación de función de clúster:

      kubectl create clusterrolebinding azure-pipelines-deploy --clusterrole=cluster-admin --serviceaccount=default:azure-pipelines-deploy
    4. Define la dirección IP del clúster:

      gcloud container clusters describe azure-pipelines-cicd-prod --format=value\(endpoint\)
      

      Necesitarás esta dirección en un momento.

    5. En el menú de Azure DevOps, selecciona Configuración del proyecto y, luego, Canalizaciones > Conexiones de servicio.

    6. Haz clic en Nueva conexión de servicio.

    7. Selecciona Kubernetes y haz clic en Siguiente.

    8. Establece la siguiente configuración:

      • Método de autenticación: Cuenta de servicio
      • URL del servidor: https://PRIMARY_IP. Reemplaza PRIMARY_IP por la dirección IP que definiste antes.
      • Secret: Ejecuta el siguiente comando en Cloud Shell y copia el resultado:
        kubectl get secret $(kubectl get serviceaccounts azure-pipelines-deploy -o custom-columns=":secrets[0].name") -o yaml
      • Nombre de la conexión de servicio: azure-pipelines-cicd-prod.
    9. Haz clic en Guardar.

    Configura la canalización de la versión

    Después de configurar la infraestructura de GKE, vuelve a Azure Pipelines para automatizar la implementación, lo que incluye las siguientes acciones:

    • Implementar en el entorno de desarrollo
    • Solicitar aprobación manual antes de iniciar una implementación en el entorno de producción
    • Implementar en el entorno de producción

    Crea una definición de la versión

    Como primer paso, crea una nueva definición de la versión.

    1. En el menú de Azure DevOps, selecciona Canalizaciones > Versiones.
    2. Haz clic en Nueva canalización.
    3. En la lista de plantillas, selecciona Trabajo vacío.
    4. Cuando se te solicite un nombre para la etapa, ingresa Development.
    5. En la parte superior de la pantalla, nombra la versión CloudDemo-KubernetesEngine.
    6. En el diagrama de la canalización, junto a Artifacts (Artefactos), haz clic en Add (Agregar).
    7. Selecciona Compilar y agrega la siguiente configuración:

      • Tipo de origen: Compilación
      • Origen (canalización de compilación): Selecciona la definición de compilación (solo debe haber una opción)
      • Versión predeterminada: Latest
      • Alias de origen: manifest
    8. Haz clic en Agregar.

    9. En el cuadro Artefacto, haz clic en el ícono del rayo Desencadenador de implementación continua para agregar un desencadenador de implementación.

    10. En Desencadenador de implementación continua, establece la opción como Habilitado.

    11. Haz clic en Guardar.

    12. Si lo deseas, ingresa un comentario y, luego, haz clic en Aceptar para confirmar.

      La canalización se muestra de la siguiente manera.

      Captura de pantalla de la canalización actualizada en Azure Pipelines

    Implementa en el clúster de desarrollo

    Una vez que creaste la definición de la versión, puedes configurar la implementación en el clúster de desarrollo de GKE.

    1. En el menú, cambia a la pestaña Tareas.
    2. Haz clic en Trabajo de agente y establece la siguiente configuración:

      • Grupo de agentes: Azure Pipelines
      • Especificación del agente: ubuntu-18.04
    3. Junto a Trabajo de agente, haz clic en Add a task to agent job para agregar un paso a la fase.

    4. Selecciona la tarea Implementar en Kubernetes y haz clic en Agregar.

    5. Haz clic en la tarea recién agregada y establece la siguiente configuración:

      • Nombre visible: Deploy
      • Acción: implementar
      • Conexión de servicio de Kubernetes: azure-pipelines-cicd-dev
      • Espacio de nombres: default
      • Estrategia: ninguna
      • Manifiestos: manifest/drop/deployment.yaml
    6. Haz clic en Guardar.

    7. Si lo deseas, ingresa un comentario y, luego, haz clic en Aceptar para confirmar.

    Implementa en el clúster de producción

    Por último, configura la implementación en el clúster de producción de GKE.

    1. En el menú, pasa a la pestaña Canalización.
    2. En la casilla Etapas, selecciona Agregar > Nueva etapa.
    3. En la lista de plantillas, selecciona Trabajo vacío.
    4. Cuando se te solicite un nombre para la etapa, ingresa Production.
    5. Haz clic en el ícono del rayo de la etapa recién creada.
    6. Establece la siguiente configuración:

      • Seleccionar activador: After stage
      • Etapas: Dev
      • Aprobaciones previas a la implementación: (habilitadas)
      • Aprobadores: Selecciona tu nombre de usuario.

      La canalización ahora se ve de la siguiente manera:

      Captura de pantalla de la canalización actualizada en Azure Pipelines

    7. Pasa a la pestaña Tareas.

    8. Mantén el mouse sobre la pestaña Tareas y selecciona Tareas > Producción

    9. Haz clic en Trabajo de agente y establece la siguiente configuración:

      • Grupo de agentes: Azure Pipelines
      • Especificación del agente: ubuntu-18.04
    10. Haz clic en Add a task to agent job para agregar un paso a la fase.

    11. Selecciona la tarea Implementar en Kubernetes y haz clic en Agregar.

    12. Haz clic en la tarea recién agregada y establece la siguiente configuración:

      • Nombre visible: Deploy
      • Acción: implementar
      • Conexión de servicio de Kubernetes: azure-pipelines-cicd-prod
      • Espacio de nombres: default
      • Estrategia: ninguna
      • Manifiestos: manifest/drop/deployment.yaml
    13. Haz clic en Guardar.

    14. Si lo deseas, ingresa un comentario y, luego, haz clic en Aceptar para confirmar.

    Ejecuta la canalización

    Ahora que configuraste toda la canalización, realiza un cambio en el código fuente para probarla:

    1. En tu computadora local, abre el archivo Index.cshtml desde el repositorio de Git que clonaste antes:

      .NET/Linux

      El archivo se encuentra en applications\clouddemo\netcore\CloudDemo.MvcCore\Views\Home\

      .NET Framework/Windows

      El archivo se encuentra en applications\clouddemo\net4\CloudDemo.Mvc\Views\Home\

    2. En la línea 26, cambia el valor de ViewBag.Title de Home Page a This app runs on GKE.

    3. Confirma tus cambios y envíalos a Azure Pipelines.

      Visual Studio

      1. Abre Team Explorer y haz clic en el ícono de página principal.
      2. Haz clic en Cambios.
      3. Ingresa un mensaje de confirmación, como Change site title.
      4. Haz clic en Confirmar todo y enviar.

      Línea de comandos

      1. Almacena en etapa intermedia todos los archivos modificados:

        git add -A
        
      2. Confirma los cambios en el repositorio local:

        git commit -m "Change site title"
        
      3. Envía los cambios a Azure Pipelines:

        git push
        
    4. En el menú de Azure DevOps, selecciona Canalizaciones. Se activará una compilación.

    5. Cuando se complete la compilación, selecciona Canalizaciones > Versiones. Se iniciará un proceso de actualización.

    6. Haz clic en Release-1 para abrir la página de detalles y espera a que el estado de la etapa de Desarrollo cambie a Correcto.

    7. En la consola, selecciona Kubernetes Engine > Ingress y servicios > Ingress. Google Cloud

    8. Ubica el servicio de Ingress del clúster azure-pipelines-cicd-dev y espera a que su estado cambie a Correcto. Esto podría llevar varios minutos.

    9. Abre el vínculo en la columna Frontends de la misma fila. Es posible que al principio te encuentres con un error debido a que el balanceador de cargas tarda unos minutos en estar disponible. Cuando esté listo, verás que CloudDemo se implementó y usa el título personalizado.

    10. En Azure Pipelines, haz clic en el botón Aprobar (Approve) ubicado en la etapa de Producción (Prod) para promover la implementación en el entorno de producción.

      Si no ves el botón, es posible que primero debas aprobar o rechazar una versión anterior.

    11. Si lo deseas, ingresa un comentario y, luego, haz clic en Aprobar (Approve) para confirmarlo.

    12. Espera a que el estado del entorno Prod cambie a Succeeded (Correcto). Es posible que tengas que actualizar de forma manual la página en tu navegador.

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

    14. Ubica el servicio de Ingress del clúster azure-pipelines-cicd-prod y espera a que su estado cambie a Correcto. Esto podría llevar varios minutos.

    15. Abre el vínculo en la columna Frontends de la misma fila. De nuevo, es posible que al principio te encuentres con un error, debido a que el balanceador de cargas tarda unos minutos en estar disponible. Cuando esté listo, verás la aplicación de CloudDemo con el título personalizado, pero esta vez se estará ejecutando en el clúster de producción.

Limpia

Para evitar que se generen más costos después de completar este instructivo, borra las entidades que creaste.

Borra el proyecto de Azure Pipelines

Para borrar el proyecto de Azure Pipelines, consulta la documentación de servicios de Azure DevOps. Si borras el proyecto de Azure Pipelines, se perderán todos los cambios del código fuente.

Borra el Google Cloud desarrollo y los proyectos

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

¿Qué sigue?