Creación de imágenes de máquina virtual personalizadas con Acciones de GitHub y Azure

Para empezar a trabajar con Acciones de GitHub, cree un flujo de trabajo para crear una imagen de máquina virtual.

Con las Acciones de GitHub, puede acelerar el proceso de CI/CD al crear imágenes de máquina virtual personalizadas con artefactos de sus flujos de trabajo. Puede crear imágenes y distribuirlas en una Shared Image Gallery.

Después, puede usar estas imágenes para crear máquinas virtuales y conjuntos de escalado de máquinas virtuales.

La acción para compilar la imagen de máquina virtual usa el servicio Azure Image Builder.

Requisitos previos

Información general sobre el archivo de flujo de trabajo

Un archivo YAML (.yml) define un flujo de trabajo en la ruta de acceso /.github/workflows/ de su repositorio. En esta definición se incluyen los diversos pasos y parámetros que componen el flujo de trabajo.

El archivo tiene tres secciones:

Sección Tareas
Autenticación 1. Agregue una identidad administrada por el usuario.
2. Configure una entidad de servicio o open ID Conectar.
3. Cree un secreto de GitHub.
Compilar 1. Configure el entorno.
2. Cree la aplicación.
Imagen 1. Cree una imagen de máquina virtual.
2. Cree una máquina virtual.

Creación de una identidad administrada por el usuario

Necesitará una identidad administrada por el usuario para que Azure Image Builder (AIB) distribuya las imágenes. La identidad administrada asignada por el usuario de Azure se usará durante la compilación de la imagen para leer y escribir las imágenes en una instancia de Shared Image Gallery.

  1. Cree una identidad administrada por el usuario con la CLI de Azure o Azure Portal. Anote el nombre de la identidad administrada.

  2. Personalice este código JSON. Reemplace los marcadores de posición de {subscriptionID} y {rgName} por el identificador de la suscripción y el nombre del grupo de recursos.

    {
    "properties": {
        "roleName": "Image Creation Role",
        "IsCustom": true,
        "description": "Azure Image Builder access to create resources for the image build",
        "assignableScopes": [
          "/subscriptions/{subscriptionID}/resourceGroups/{rgName}"
        ],
        "permissions": [
            {
                "actions": [
                    "Microsoft.Compute/galleries/read",
                    "Microsoft.Compute/galleries/images/read",
                    "Microsoft.Compute/galleries/images/versions/read",
                    "Microsoft.Compute/galleries/images/versions/write",
                    "Microsoft.Compute/images/write",
                    "Microsoft.Compute/images/read",
                    "Microsoft.Compute/images/delete"
                ],
                "notActions": [],
                "dataActions": [],
                "notDataActions": []
            }
        ]
        } 
    } 
    
  3. Use este código JSON para crear un nuevo rol personalizado con JSON.

  4. En Azure Portal, abra azure Compute Gallery y vaya a Control de acceso (IAM).

  5. Seleccione Agregar asignación de roles y asigne el rol de creación de imágenes a la identidad administrada por el usuario.

Genere las credenciales de implementación.

Cree una entidad de servicio mediante el comando az ad sp create-for-rbac de la CLI de Azure. Puede ejecutar este comando mediante Azure Cloud Shell en Azure Portal o haciendo clic en el botón Probar.

az ad sp create-for-rbac --name "myML" --role contributor \
                            --scopes /subscriptions/<subscription-id>/resourceGroups/<group-name> \
                            --json-auth

El parámetro --json-auth está disponible en las versiones de la CLI de Azure >= 2.51.0. Las versiones anteriores a esta usan --sdk-auth con una advertencia de desuso.

En este ejemplo, reemplace los marcadores de posición por su identificador de suscripción, el nombre del grupo de recursos y el nombre de la aplicación. La salida es un objeto JSON con las credenciales de asignación de roles que proporcionan acceso a la aplicación App Service similar al siguiente. Copie este objeto JSON para más adelante.

  {
    "clientId": "<GUID>",
    "clientSecret": "<GUID>",
    "subscriptionId": "<GUID>",
    "tenantId": "<GUID>",
    (...)
  }

Creación de secretos de GitHub

  1. En GitHub, vaya al repositorio.

  2. Vaya a Configuración en el menú de navegación.

  3. Seleccione Seguridad > Secretos y variables > Acciones.

    Screenshot of adding a secret

  4. Seleccione New repository secret (Nuevo secreto del repositorio).

  5. Pegue la salida JSON completa del comando de la CLI de Azure en el campo de valor del secreto. Asigne al secreto el nombre AZURE_CREDENTIALS.

  6. Seleccione Add secret (Agregar secreto).

Uso de la acción Azure Login

Use el secreto de GitHub con la acción Inicio de sesión de Azure para autenticarse en Azure.

En este flujo de trabajo, la autenticación se realiza mediante la acción Azure Login con los detalles de la entidad de servicio almacenados en secrets.AZURE_CREDENTIALS. A continuación, ejecute una acción de la CLI de Azure. Para más información sobre cómo hacer referencia a secretos de GitHub en un archivo de flujo de trabajo, consulte Uso de secretos cifrados en un flujo de trabajo en la documentación de GitHub.

on: [push]

name: Create Custom VM Image

jobs:
  build-image:
    runs-on: ubuntu-latest
    steps:
      - name: Log in with Azure
        uses: azure/login@v1
        with:
          creds: '${{ secrets.AZURE_CREDENTIALS }}'

Configuración de Java

Configure el entorno de Java con la acción Java Setup SDK. En este ejemplo, configurará el entorno, compilará con Maven y, a continuación, generará un artefacto.

Los artefactos de GitHub son una forma de compartir archivos en un flujo entre trabajos. Creará un artefacto para contener el archivo JAR y, a continuación, lo agregará a la imagen de máquina virtual.

on: [push]

name: Create Custom VM Image

jobs:
  build-image:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        java: [ '17' ]

    steps:
    - name: Checkout
      uses: actions/checkout@v3    

    - name: Login via Az module
      uses: azure/login@v1
      with:
        creds: ${{secrets.AZURE_CREDENTIALS}}

    - name: Set up JDK ${{matrix.java}}
      uses: actions/setup-java@v2
      with:
        java-version: ${{matrix.java}}
        distribution: 'adopt'
        cache: maven
    - name: Build with Maven Wrapper
      run: ./mvnw -B package
        
    - name: Build Java
      run: mvn --batch-mode --update-snapshots verify

    - run: mkdir staging && cp target/*.jar staging
    - uses: actions/upload-artifact@v2
      with:
        name: Package
        path: staging

Compilación de la imagen

Use la acción Build Azure Virtual Machine Image para crear una imagen de máquina virtual personalizada.

Reemplace los marcadores de posición de {subscriptionID}, {rgName} y {Identity} por el identificador de la suscripción, el nombre del grupo de recursos y el nombre de la identidad administrada. Reemplace los valores de {galleryName} y {imageName} por el nombre de la galería de imágenes y el nombre de la imagen.

Nota:

Si se produce un error en la acción Crear imagen horneada de aplicación con un error de permiso, compruebe que ha asignado el rol de creación de imágenes a la identidad administrada por el usuario.

    - name: Create App Baked Image
      id: imageBuilder
      uses: azure/build-vm-image@v0
      with:
        location: 'eastus2'
        resource-group-name: '{rgName}'
        managed-identity: '{Identity}' # Managed identity
        source-os-type: 'windows'
        source-image-type: 'platformImage'
        source-image: MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest #unique identifier of source image
        dist-type: 'SharedImageGallery'
        dist-resource-id: '/subscriptions/{subscriptionID}/resourceGroups/{rgName}/providers/Microsoft.Compute/galleries/{galleryName}/images/{imageName}/versions/0.1.${{ GITHUB.RUN_ID }}' #Replace with the resource id of your shared image  gallery's image definition
        dist-location: 'eastus2'

Argumentos de la acción de máquina virtual

Entrada Obligatorio Descripción
resource-group-name Grupo de recursos que se usa para almacenar y guardar artefactos durante el proceso de compilación.
image-builder-template-name No Nombre del recurso de plantilla de Image Builder utilizado.
location Ubicación en la que se ejecutará Image Builder. Consulte las ubicaciones admitidas.
build-timeout-in-minutes No Hora a partir de la cual se cancela la compilación. El valor predeterminado es 240.
vm-size Opcionales De forma predeterminada, se usará Standard_D1_v2. Consulte los tamaños de máquina virtual.
managed-identity Identidad administrada por el usuario que creó anteriormente. Use el identificador completo si la identidad está en un grupo de recursos diferente. Use el nombre si se encuentra en el mismo grupo de recursos.
source-os Tipo de sistema operativo de la imagen base (Linux o Windows).
source-image-type Tipo de imagen base que se utilizará para crear la imagen personalizada.
source-image Identificador de recurso de la imagen base. Debe haber presente una imagen de origen en la misma región de Azure que se configuró en el valor de entrada de la ubicación.
customizer-source No Directorio en el que puede mantener todos los artefactos que se deben agregar a la imagen base para la personalización. De manera predeterminada, el valor es ${{ GITHUB.WORKSPACE }}/workflow-artifacts..
customizer-destination No Este es el directorio de la imagen personalizada en la que se copiarán los artefactos.
customizer-windows-update No Solo para Windows. . Si es true, Image Builder ejecutará Windows Update al final de las personalizaciones.
dist-location No Para SharedImageGallery, este es el dist-type.
dist-image-tags No Se trata de etiquetas definidas por el usuario que se agregan a la imagen personalizada que se creó (por ejemplo: version:beta).

Creación de la máquina virtual

Como último paso, cree una máquina virtual a partir de la imagen.

  1. Reemplace los marcadores de posición de {rgName} por el nombre del grupo de recursos.

  2. Agregue un secreto de GitHub con la contraseña de la máquina virtual (VM_PWD). Asegúrese de anotar la contraseña, porque no podrá verla de nuevo. El nombre de usuario es myuser.

    - name: CREATE VM
      uses: azure/CLI@v1
      with:
        azcliversion: 2.0.72
        inlineScript: |
        az vm create --resource-group ghactions-vMimage  --name "app-vm-${{ GITHUB.RUN_NUMBER }}"  --admin-username myuser --admin-password "${{ secrets.VM_PWD }}" --location  eastus2 \
            --image "${{ steps.imageBuilder.outputs.custom-image-uri }}"              

Finalización del archivo YAML

  on: [push]

  name: Create Custom VM Image

  jobs:
    build-image:
      runs-on: ubuntu-latest    
      steps:
      - name: Checkout
        uses: actions/checkout@v2    

      - name: Login via Az module
        uses: azure/login@v1
        with:
          creds: ${{secrets.AZURE_CREDENTIALS}}

      - name: Setup Java 1.8.x
        uses: actions/setup-java@v1
        with:
          java-version: '1.8.x'
          
      - name: Build Java
        run: mvn --batch-mode --update-snapshots verify

      - run: mkdir staging && cp target/*.jar staging
      - uses: actions/upload-artifact@v2
        with:
          name: Package
          path: staging

      - name: Create App Baked Image
        id: imageBuilder
        uses: azure/build-vm-image@v0
        with:
          location: 'eastus2'
          resource-group-name: '{rgName}'
          managed-identity: '{Identity}' # Managed identity
          source-os-type: 'windows'
          source-image-type: 'platformImage'
          source-image: MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest #unique identifier of source image
          dist-type: 'SharedImageGallery'
          dist-resource-id: '/subscriptions/{subscriptionID}/resourceGroups/{rgName}/providers/Microsoft.Compute/galleries/{galleryName}/images/{imageName}/versions/0.1.${{ GITHUB.RUN_ID }}' #Replace with the resource id of your shared image  gallery's image definition
          dist-location: 'eastus2'

      - name: CREATE VM
        uses: azure/CLI@v1
        with:
          azcliversion: 2.0.72
          inlineScript: |
          az vm create --resource-group ghactions-vMimage  --name "app-vm-${{ GITHUB.RUN_NUMBER }}"  --admin-username myuser --admin-password "${{ secrets.VM_PWD }}" --location  eastus2 \
              --image "${{ steps.imageBuilder.outputs.custom-image-uri }}"              

Pasos siguientes