Creare immagini di macchine virtuali personalizzate con GitHub Actions e Azure

Per iniziare a usare GitHub Actions , creare un flusso di lavoro per creare un'immagine di macchina virtuale.

Con GitHub Actions è possibile velocizzare il processo CI/CD creando immagini di macchine virtuali personalizzate con artefatti dai flussi di lavoro. È possibile creare immagini e distribuirle in un Raccolta immagini condivise.

È quindi possibile usare queste immagini per creare macchine virtuali e set di scalabilità di macchine virtuali.

L'azione di immagine della macchina virtuale di compilazione usa il servizio Image Builder di Azure.

Prerequisiti

Panoramica dei file del flusso di lavoro

Un flusso di lavoro viene definito da un file YAML (con estensione yml) nel percorso /.github/workflows/ del repository. Questa definizione contiene i vari passaggi e i parametri che costituiscono il flusso di lavoro.

Il file include tre sezioni:

Sezione Attività
Autenticazione 1. Aggiungere un'identità gestita dall'utente.
2. Configurare un'entità servizio o open ID Connessione.
3. Creare un segreto GitHub.
Build 1. Configurare l'ambiente.
2. Compilare l'app.
Image 1. Creare un'immagine di macchina virtuale.
2. Creare una macchina virtuale.

Creare un'identità gestita dall'utente

Per distribuire le immagini, è necessaria un'identità gestita dall'utente per Azure Image Builder (AIB). L'identità gestita assegnata dall'utente di Azure verrà usata durante la compilazione dell'immagine per leggere e scrivere immagini in un Raccolta immagini condivise.

  1. Creare un'identità gestita dall'utente con l'interfaccia della riga di comando di Azure o l'portale di Azure. Annotare il nome dell'identità gestita.

  2. Personalizzare questo codice JSON. Sostituire i segnaposto per {subscriptionID} e {rgName}con l'ID sottoscrizione e il nome del gruppo di risorse.

    {
    "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. Usare questo codice JSON per creare un nuovo ruolo personalizzato con JSON.

  4. In portale di Azure aprire la raccolta di calcolo di Azure e passare a Controllo di accesso (IAM).

  5. Selezionare Aggiungi assegnazione di ruolo e assegnare il ruolo di creazione dell'immagine all'identità gestita dall'utente.

Generare le credenziali per la distribuzione

Creare un'entità servizio con il comando az ad sp create-for-rbac nell'interfaccia della riga di comando di Azure. Eseguire questo comando con Azure Cloud Shell nel portale di Azure oppure selezionando il pulsante Prova.

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

Il parametro --json-auth è disponibile nelle versioni >dell'interfaccia della riga di comando di Azure = 2.51.0. Versioni precedenti a questo utilizzo --sdk-auth con un avviso di deprecazione.

Nell'esempio precedente sostituire i segnaposto con l'ID sottoscrizione, il nome del gruppo di risorse e il nome dell'app. L'output è un oggetto JSON con le credenziali di assegnazione di ruolo che forniscono l'accesso all'app del servizio app simile a questo esempio. Copiare l'oggetto JSON per un uso successivo.

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

Creare segreti di GitHub

  1. In GitHub passare al repository.

  2. Passare a Impostazioni nel menu di spostamento.

  3. Selezionare Segreti di sicurezza > e variabili > Azioni.

    Screenshot of adding a secret

  4. Selezionare Nuovo segreto repository.

  5. Incollare l'intero output JSON del comando dell'interfaccia della riga di comando di Azure nel campo del valore del segreto. Assegnare al segreto il nome AZURE_CREDENTIALS.

  6. Selezionare Aggiungi segreto.

Usare l'azione di accesso di Azure

Usare il segreto GitHub con l'azione di accesso di Azure per eseguire l'autenticazione in Azure.

In questo flusso di lavoro l'autenticazione viene eseguita usando l'azione di accesso di Azure con i dettagli dell'entità servizio archiviati in secrets.AZURE_CREDENTIALS. Quindi, eseguire un'azione dell'interfaccia della riga di comando di Azure. Per altre informazioni su come fare riferimento ai segreti di GitHub in un file del flusso di lavoro, vedere Uso di segreti crittografati in un flusso di lavoro nella documentazione di 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 }}'

Configurare Java

Configurare l'ambiente Java con l'azione Java Setup SDK. Per questo esempio si configurerà l'ambiente, si compilerà con Maven e quindi si restituirà un artefatto.

Gli artefatti di GitHub sono un modo per condividere i file in un flusso di lavoro tra processi. Si creerà un artefatto per contenere il file JAR e quindi aggiungerlo all'immagine della macchina virtuale.

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

Creare l'immagine

Usare l'azione Compila immagine macchina virtuale di Azure per creare un'immagine di macchina virtuale personalizzata.

Sostituire i segnaposto per {subscriptionID}{rgName}e {Identity} con l'ID sottoscrizione, il nome del gruppo di risorse e il nome dell'identità gestita. Sostituire i valori di e {imageName} con il nome della {galleryName} raccolta immagini e il nome dell'immagine.

Nota

Se l'azione Crea immagine con bake dell'app ha esito negativo con un errore di autorizzazione, verificare di aver assegnato il ruolo di creazione dell'immagine all'identità gestita dall'utente.

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

Argomenti dell'azione macchina virtuale

Input Richiesto Descrizione
resource-group-name Gruppo di risorse usato per l'archiviazione e il salvataggio degli artefatti durante il processo di compilazione.
image-builder-template-name No Nome della risorsa modello del generatore di immagini usata.
location Percorso in cui verrà eseguito Image Builder di Azure. Vedere i percorsi supportati.
build-timeout-in-minutes No Ora dopo la quale la compilazione viene annullata. Il valore predefinito è 240.
vm-size Facoltativo Verrà usata l'impostazione predefinita Standard_D1_v2. Vedere Dimensioni delle macchine virtuali.
managed-identity Identità gestita dall'utente creata in precedenza. Usare l'identificatore completo se l'identità si trova in un gruppo di risorse diverso. Usare il nome se si trova nello stesso gruppo di risorse.
source-os Tipo di sistema operativo dell'immagine di base (Linux o Windows)
source-image-type Tipo di immagine di base che verrà usato per la creazione dell'immagine personalizzata.
source-image Identificatore della risorsa per l'immagine di base. Un'immagine di origine deve essere presente nella stessa area di Azure impostata nel valore di input della posizione.
customizer-source No Directory in cui è possibile mantenere tutti gli artefatti che devono essere aggiunti all'immagine di base per la personalizzazione. Per impostazione predefinita, il valore è ${{ GITHUB.WORKSPACE }}/workflow-artifacts.
customizer-destination No Si tratta della directory nell'immagine personalizzata in cui vengono copiati gli artefatti.
customizer-windows-update No Solo per Windows. Valore booleano. Se true, il generatore di immagini eseguirà l'aggiornamento di Windows alla fine delle personalizzazioni.
dist-location No Per SharedImageGallery, si tratta di dist-type.
dist-image-tags No Si tratta di tag definiti dall'utente che vengono aggiunti all'immagine personalizzata creata (ad esempio: version:beta).

Creare la macchina virtuale

Come ultimo passaggio, creare una macchina virtuale dall'immagine.

  1. Sostituire i segnaposto per {rgName}con il nome del gruppo di risorse.

  2. Aggiungere un segreto GitHub con la password della macchina virtuale (VM_PWD). Assicurarsi di annotare la password perché non sarà possibile visualizzarla di nuovo. Il nome utente è 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 }}"              

Completare 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 }}"              

Passaggi successivi