通过创建用于生成虚拟机映像的工作流开始使用 GitHub Actions 。
使用 GitHub Actions,可以通过使用工作流中的构件创建自定义的虚拟机镜像来加速 CI/CD 过程。 可以生成映像并将其分发到 共享映像库。
生成虚拟机映像的操作使用 Azure 映像生成器服务。
先决条件
- 拥有有效订阅的 Azure 帐户。 免费创建帐户。
- 包含活动存储库的 GitHub 帐户。 如果你没有帐户,可免费注册一个。
- 此示例使用 Java Spring PetClinic 示例应用程序。
- 包含映像的 Azure 计算库。
工作流文件概述
工作流是由存储库中 /.github/workflows/ 路径中的 YAML (.yml) 文件定义的。 此定义包含组成工作流的各种步骤和参数。
该文件有三个部分:
| Section | Tasks |
|---|---|
| 身份验证 | 1. 添加用户管理的身份标识。 2.设置服务主体或打开 ID Connect。 3.创建 GitHub 机密。 |
| 构建 | 1.设置环境。 2.生成应用。 |
| 图像 | 1.创建 VM 映像。 2.创建虚拟机。 |
创建用户托管标识
需要 Azure 映像生成器(AIB)的用户托管标识才能分发映像。 映像生成期间将使用 Azure 用户分配的托管标识来读取和写入共享映像库。
自定义此 JSON 代码。 将占位符
{subscriptionID}{rgName}替换为订阅 ID 和资源组名称。{ "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": [] } ] } }使用此 JSON 代码通过 JSON 创建新的自定义角色 。
在 Azure 门户中,打开 Azure 计算库并转到访问控制(IAM)。
选择添加角色分配,并将图像创建角色分配给您的用户托管标识。
生成部署凭据
若要对 OIDC 使用 Azure 登录操作,需要在 Microsoft Entra 应用或用户分配的托管身份上配置联合身份凭证。
选项 1:Microsoft Entra 应用程序
- 在 Azure 门户、Azure CLI或 Azure PowerShell中创建具有服务主体的 Microsoft Entra 应用程序。
- 复制 客户端 ID、订阅 ID和 Directory(租户)ID 的值,以便在 GitHub Actions 工作流中稍后使用。
- 在 Azure 门户、Azure CLI或 Azure PowerShell中,为服务主体分配适当的角色。
- 在 Microsoft Entra 应用程序上配置联合标识凭据 来信任由 GitHub Actions 颁发的令牌,用于您的 GitHub 存储库。
选项 2:用户分配的托管标识
- 创建用户分配的托管标识。
- 复制 客户端 ID、订阅 ID和 Directory(租户)ID 的值,以便在 GitHub Actions 工作流中稍后使用。
- 为用户分配的托管标识分配适当的角色。
- 在用户分配的托管标识上配置联合标识凭据,以信任由 GitHub Actions 向你的 GitHub 仓库颁发的令牌。
创建 GitHub 机密
需要在登录操作中提供应用程序的 客户端 ID、目录(租户)ID和 订阅 ID。 这些值可直接在工作流中提供,或可存储在 GitHub 机密中并在工作流中引用。 将这些值保存为 GitHub 机密是更安全的选择。
在 GitHub 中,转到存储库。
选择“安全性”>“机密和变量”>“操作”。
选择“新建存储库机密”。
注释
若要增强公共存储库中的工作流安全性,请使用 环境机密 而不是存储库机密。 如果环境需要审批,在所需审阅者之一批准之前,作业无法访问环境机密。
为
AZURE_CLIENT_ID、AZURE_TENANT_ID和AZURE_SUBSCRIPTION_ID创建机密。 请从 Microsoft Entra 应用程序或用户分配的托管标识中复制这些值,以用于您的 GitHub 机密。GitHub 机密 Microsoft Entra 应用程序或用户分配的托管标识 AZURE_CLIENT_ID 客户 ID AZURE_SUBSCRIPTION_ID 订阅编号 AZURE_TENANT_ID (Azure租户ID) 目录(租户)ID 注释
出于安全原因,我们建议使用 GitHub 机密,而不是将值直接传递到工作流。
使用 Azure 登录操作
通过使用 Azure 登录操作 中的 GitHub 机密来对 Azure 进行身份验证。
对于 Open ID Connect,您将使用与 Active Directory 应用程序关联的联邦凭证。
有关在工作流文件中引用 GitHub 机密的详细信息,请参阅在 GitHub Docs 的工作流中使用加密机密 。
on: [push]
name: Create Custom VM Image
jobs:
build-image:
runs-on: ubuntu-latest
steps:
- name: Log in with Azure
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
配置 Java
使用 Java 设置 SDK 操作 设置 Java 环境。 在本示例中,你将设置环境,使用 Maven 生成,然后输出项目。
GitHub 工件 是在作业之间共享工作流中的文件的方法。 你将创建一个项目来保存 JAR 文件,然后将其添加到虚拟机映像。
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@v2
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
生成映像
使用 “生成 Azure 虚拟机映像”作 创建自定义虚拟机映像。
将占位符{subscriptionID}{rgName}{Identity}替换为订阅 ID、资源组名称和托管标识名称。 将{galleryName}替换为您的映像库名称,将{imageName}替换为您的映像名称。
注释
如果“创建应用程序烘焙镜像”操作失败并发生权限错误,请验证是否已将镜像创建角色分配给用户管理的标识。
- 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'
虚拟机操作参数
| Input | 必选 | Description |
|---|---|---|
resource-group-name |
是的 | 在构建过程中用于存储和保存工件的资源组。 |
image-builder-template-name |
否 | 使用的映像生成器模板资源的名称。 |
location |
是的 | Azure 映像生成器将运行的位置。 请参阅 支持的位置。 |
build-timeout-in-minutes |
否 | 时间达到后取消生成 默认值为 240。 |
vm-size |
可选 | 默认情况下, Standard_D1_v2 将使用。 请参阅 虚拟机大小。 |
managed-identity |
是的 | 之前创建的用户托管标识。 如果您的标识位于不同的资源组中,请使用完整标识符。 如果名称位于同一资源组中,请使用该名称。 |
source-os |
是的 | 基础映像的 OS 类型(Linux 或 Windows) |
source-image-type |
是的 | 将用于创建自定义映像的基本映像类型。 |
source-image |
是的 | 基础映像的资源标识符。 源映像应存在于位置的输入值中设置的同一 Azure 区域。 |
customizer-source |
否 | 可在其中保留需要添加到基础映像进行自定义的所有项目的目录。 默认情况下,该值为 ${{ GITHUB.WORKSPACE }}/workflow-artifacts. |
customizer-destination |
否 | 这是自定义映像中用于复制工件的目录。 |
customizer-windows-update |
否 | 仅适用于 Windows。 布尔值。 如果 true,映像生成器将在自定义项结束时运行 Windows 更新。 |
dist-location |
否 | 对于 SharedImageGallery,这是dist-type。 |
dist-image-tags |
否 | 这些标记是添加到创建的自定义映像的用户定义标记(示例: version:beta |
创建虚拟机
最后一步,从镜像创建虚拟机。
将占位符
{rgName}替换为资源组名称。使用虚拟机密码添加 GitHub 机密(
VM_PWD)。 请务必记下密码,因为无法再次看到密码。 用户名为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 }}"
完成 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@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- 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 }}"
后续步骤
- 了解如何 部署到 Azure。