教程:使用 Azure 容器应用作业部署自承载 CI/CD 运行程序和代理

GitHub Actions 和 Azure Pipelines 允许使用自承载运行器和代理运行 CI/CD 工作流。 可以使用事件驱动的 Azure 容器应用作业运行自承载运行器和代理。

需要运行的工作流需要访问云托管运行器无法使用的本地资源或工具时,自承载运行器非常有用。 例如,容器应用作业中的自承载运行器允许工作流访问作业虚拟网络中无法通过云托管运行器访问的资源。

通过将自承载运行器作为事件驱动作业运行,可以利用 Azure 容器应用程序的无服务器特性。 作业在触发工作流时自动执行,并在作业完成时退出。

只需为运行作业的时间付费。

本教程介绍如何将 GitHub Actions 运行器作为事件驱动的容器应用作业运行。

  • 创建容器应用环境以部署自承载运行器
  • 创建 GitHub 存储库以运行使用自托管运行器的工作流
  • 生成运行 GitHub Actions 运行器的容器映像
  • 将运行器作为作业部署到容器应用环境
  • 创建使用自承载运行器的工作流并验证其是否运行

重要

仅建议专用存储库使用自承载运行器。 将自承载运行器用于公共存储库可能会导致在自托管运行器上执行危险代码。 有关详细信息,请参阅自承载运行器安全

本教程介绍如何将 Azure Pipelines 代理作为事件驱动的容器应用作业运行。

  • 创建容器应用环境以部署自托管代理
  • 创建 Azure DevOps 组织和项目
  • 生成运行 Azure Pipelines 代理的容器映像
  • 使用手动作业在容器应用环境中创建占位符代理
  • 将代理作为作业部署到容器应用环境
  • 创建使用自托管代理的管道并验证其是否运行

重要

仅建议专用存储库使用自托管代理。 将自托管代理用于公共项目可能会导致在自托管代理上执行危险代码。 有关详细信息,请参阅自托管代理安全

注意

容器应用和作业不支持在容器中运行 Docker。 在容器应用作业中的自承载运行器或代理上运行时,使用 Docker 命令的工作流中的任何步骤都会失败。

先决条件

有关限制列表,请参阅作业限制

设置

若要从 CLI 登录到 Azure,请运行以下命令,然后按照提示完成身份验证过程。

az cloud set -n AzureChinaCloud
az login
# az cloud set -n AzureCloud   //means return to Public Azure.

为了确保运行最新版本的 CLI,请运行升级命令。

az upgrade

接下来,安装或更新适用于 CLI 的 Azure 容器应用扩展。

如果在 Azure CLI 中运行 az containerapp 命令,或在 Azure PowerShell 中运行 Az.App 模块中的 cmdlet 时收到有关缺少参数的错误,请确保已安装最新版本的 Azure 容器应用扩展。

az extension add --name containerapp --upgrade

注意

从 2024 年 5 月开始,Azure CLI 扩展不再默认启用预览功能。 要访问容器应用预览功能,请使用 --allow-preview true 安装容器应用扩展。

az extension add --name containerapp --upgrade --allow-preview true

现在已安装当前扩展或模块,接下来请注册 Microsoft.AppMicrosoft.OperationalInsights 命名空间。

注意

Azure 容器应用资源已从 Microsoft.Web 命名空间迁移到 Microsoft.App 命名空间。 如需更多详细信息,请参阅 2022 年 3 月的从 Azure.Web 到 Microsoft.App 的命名空间迁移

az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

创建环境变量

完成 Azure CLI 安装后,接下来可以定义要在本文中使用的环境变量。

RESOURCE_GROUP="jobs-sample"
LOCATION="chinanorth3"
ENVIRONMENT="env-jobs-sample"
JOB_NAME="github-actions-runner-job"
RESOURCE_GROUP="jobs-sample"
LOCATION="chinanorth3"
ENVIRONMENT="env-jobs-sample"
JOB_NAME="azure-pipelines-agent-job"
PLACEHOLDER_JOB_NAME="placeholder-agent-job"

创建容器应用环境

Azure 容器应用环境充当容器应用和作业周围的安全边界,因此容器应用和作业可以共享同一网络并相互通信。

注意

若要创建与现有虚拟网络集成的容器应用环境,请参阅为内部 Azure 容器应用环境提供虚拟网络

  1. 使用以下命令创建资源组。

    az group create \
        --name "$RESOURCE_GROUP" \
        --location "$LOCATION"
    
  2. 使用以下命令创建容器应用环境。

    az containerapp env create \
        --name "$ENVIRONMENT" \
        --resource-group "$RESOURCE_GROUP" \
        --location "$LOCATION"
    

创建用于运行工作流的 GitHub 存储库

若要执行工作流,需要创建包含工作流定义的 GitHub 存储库。

  1. 导航到 GitHub 并登录。

  2. 通过输入以下值创建新的存储库。

    设置 “值”
    所有者 选择 GitHub 用户名。
    存储库名称 为存储库输入名称。
    能见度 选择“专用”
    初始化此存储库 选择“添加 README 文件”。

    将其余值保留为默认选择。

  3. 选择“创建存储库”。

  4. 在新存储库中,选择“操作”

  5. 搜索“简单工作流”模板,然后选择“配置”

  6. 选择“提交更改”,将此工作流添加到存储库

工作流在 ubuntu-latest GitHub 托管的运行器上运行,并将消息输出到控制台。 稍后,将 GitHub 托管的运行器替换为自承载运行器。

获取 GitHub 个人访问令牌

若要运行自承载运行器,需要在 GitHub 中创建个人访问令牌 (PAT)。 每次启动运行器时,PAT 都会生成一个令牌,以便在 GitHub 上注册运行器。 GitHub Actions 运行器缩放规则还使用 PAT 来监视存储库的工作流队列并根据需要启动运行器。

注意

个人访问令牌 (PAT) 设置了过期日期。 请定期轮换令牌,以确保它们持续有效(不会过期),使服务不会中断。

  1. 在 GitHub 中,选择右上角的个人资料图片,然后选择“设置”

  2. 选择“开发人员设置”。

  3. 在“个人访问令牌”下,选择“细粒度令牌”

  4. 选择“生成新令牌”

  5. 在“新的细粒度个人访问令牌”屏幕中,输入以下值

    设置
    令牌名称 输入令牌的名称。
    到期日期 选择“30 天”
    存储库访问 选择“仅选择存储库”,然后选择已创建的存储库

    为“存储库权限”输入以下值

    设置 “值”
    操作 选择“只读”
    管理 选择“读取和写入”
    元数据 选择“只读”
  6. 选择“生成令牌”。

  7. 复制令牌值。

  8. 定义稍后用于配置运行器和缩放规则的变量。

    GITHUB_PAT="<GITHUB_PAT>"
    REPO_OWNER="<REPO_OWNER>"
    REPO_NAME="<REPO_NAME>"
    

    将占位符替换为以下值:

    占位符
    <GITHUB_PAT> 生成的 GitHub PAT。
    <REPO_OWNER> 之前创建的存储库的所有者。 此值通常是 GitHub 用户名。
    <REPO_NAME> 之前创建的存储库的名称。 此值与在“存储库名称”字段中输入的名称相同

生成 GitHub Actions 运行器容器映像

若要创建自承载运行器,需要生成执行运行器的容器映像。 在本节中,将生成容器映像并将其推送到容器注册表。

注意

本教程中生成的映像包含一个适合作为容器应用作业运行的基本自承载运行器。 可以对其进行自定义,以包含工作流所需的其他工具或依赖项。

  1. 定义容器映像和注册表的名称。

    CONTAINER_IMAGE_NAME="github-actions-runner:1.0"
    CONTAINER_REGISTRY_NAME="<CONTAINER_REGISTRY_NAME>"
    

    <CONTAINER_REGISTRY_NAME> 替换为用于创建容器注册表的唯一名称。 容器注册表名称在 Azure 中必须唯一,长度为 5 到 50 个字符,仅包含数字和小写字母

  2. 创建容器注册表。

    az acr create \
        --name "$CONTAINER_REGISTRY_NAME" \
        --resource-group "$RESOURCE_GROUP" \
        --location "$LOCATION" \
        --sku Basic \
        --admin-enabled true
    
  3. 用于创建运行器映像的 Dockerfile 在 GitHub 上提供。 运行以下命令,使用 az acr build 命令克隆存储库并在云中生成容器映像。

    az acr build \
        --registry "$CONTAINER_REGISTRY_NAME" \
        --image "$CONTAINER_IMAGE_NAME" \
        --file "Dockerfile.github" \
        "https://github.com/Azure-Samples/container-apps-ci-cd-runner-tutorial.git"
    

    映像现已在容器注册表中提供。

将自承载运行器部署为作业

现在可以创建用于使用容器映像的作业。 在本节中,将创建一个作业,此作业使用之前生成的 PAT 执行自承载运行器并使用 GitHub 进行身份验证。 作业使用 github-runner 缩放规则根据挂起的工作流运行数创建作业执行。

  1. 在容器应用环境中创建作业。

    az containerapp job create -n "$JOB_NAME" -g "$RESOURCE_GROUP" --environment "$ENVIRONMENT" \
        --trigger-type Event \
        --replica-timeout 1800 \
        --replica-retry-limit 0 \
        --replica-completion-count 1 \
        --parallelism 1 \
        --image "$CONTAINER_REGISTRY_NAME.azurecr.cn/$CONTAINER_IMAGE_NAME" \
        --min-executions 0 \
        --max-executions 10 \
        --polling-interval 30 \
        --scale-rule-name "github-runner" \
        --scale-rule-type "github-runner" \
        --scale-rule-metadata "githubAPIURL=https://api.github.com" "owner=$REPO_OWNER" "runnerScope=repo" "repos=$REPO_NAME" "targetWorkflowQueueLength=1" \
        --scale-rule-auth "personalAccessToken=personal-access-token" \
        --cpu "2.0" \
        --memory "4Gi" \
        --secrets "personal-access-token=$GITHUB_PAT" \
        --env-vars "GITHUB_PAT=secretref:personal-access-token" "GH_URL=https://github.com/$REPO_OWNER/$REPO_NAME" "REGISTRATION_TOKEN_API_URL=https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/actions/runners/registration-token" \
        --registry-server "$CONTAINER_REGISTRY_NAME.azurecr.cn"
    

    下表描述了命令中使用的关键参数。

    参数 说明
    --replica-timeout 副本可以执行的最大持续时间。
    --replica-retry-limit 重试失败副本的次数。
    --replica-completion-count 在作业执行成功之前要成功完成的副本数。
    --parallelism 每个作业执行要启动的副本数。
    --min-executions 每个轮询间隔运行的最小作业执行数。
    --max-executions 每个轮询间隔运行的最大作业执行数。
    --polling-interval 评估缩放规则的轮询间隔。
    --scale-rule-name 缩放规则的名称。
    --scale-rule-type 要使用的缩放规则的类型。 若要了解有关 GitHub 运行器缩放器的详细信息,请参阅 KEDA 文档
    --scale-rule-metadata 缩放规则的元数据。 如果你使用 GitHub Enterprise,请使用其 API URL 更新 githubAPIURL
    --scale-rule-auth 缩放规则的身份验证。
    --secrets 作业要使用的机密。
    --env-vars 作业要使用的环境变量。
    --registry-server 作业要使用的容器注册表服务器。 对于 Azure 容器注册表,此命令会自动配置身份验证。

    缩放规则配置定义要监视的事件源。 它会在每个轮询间隔上进行评估,并确定要触发的作业执行数。 若要了解详细信息,请参阅设置缩放规则

事件驱动作业现已在容器应用环境中创建。

运行工作流并验证作业

作业配置为每隔 30 秒评估一次缩放规则。 在每次评估期间,作业会检查需要自承载运行器的挂起工作流运行的数量,并为挂起工作流启动新的作业执行,最多可配置 10 次执行。

若要验证作业是否已正确配置,可以修改工作流以使用自承载运行器并触发工作流运行。 然后,可以查看作业执行日志以查看工作流运行。

  1. 在 GitHub 存储库中,导航到之前生成的工作流。 它是 .github/workflows 目录中的 YAML 文件。

  2. 选择“就地编辑”

  3. 将属性 runs-on 更新为 self-hosted

    runs-on: self-hosted
    
  4. 选择“提交更改...”。

  5. 选择“提交更改”。

  6. 导航到“操作”选项卡

    新的工作流现已排队。 30 秒内,作业执行将启动,工作流将很快完成。

    等待操作完成,然后再执行下一步。

  7. 列出作业的执行,以确认作业执行已创建并成功完成。

    az containerapp job execution list \
        --name "$JOB_NAME" \
        --resource-group "$RESOURCE_GROUP" \
        --output table \
        --query '[].{Status: properties.status, Name: name, StartTime: properties.startTime}'
    

创建 Azure DevOps 项目和存储库

若要执行管道,需要一个 Azure DevOps 项目和存储库。

  1. 导航到 Azure DevOps 并登录到帐户。

  2. 选择现有组织或创建新组织。

  3. 在组织概述页中,选择“新建项目”并输入以下值

    设置
    项目名称 输入项目的名称。
    可见性 选择“专用”
  4. 选择创建

  5. 从左侧导航中,选择“存储库”

  6. 在“使用自述文件或 .gitignore 初始化主分支”下,选择“添加自述文件”

  7. 将其余值保留为默认值,然后选择“初始化”

创建新代理池

创建新的代理池以运行自承载运行器。

  1. 在 Azure DevOps 项目中,展开左侧导航栏并选择“项目设置”

    Azure DevOps 项目设置按钮的屏幕截图。

  2. 在“项目设置”导航菜单的“管道”部分下,选择“代理池”

    Azure DevOps 代理池按钮的屏幕截图。

  3. 选择“添加池”,然后输入以下值

    设置 “值”
    要链接的池 选择“新建”。
    池类型 选择“自承载”
    Name 输入“container-apps”
    向所有管道授予访问权限 选中此复选框。
  4. 选择创建

获取 Azure DevOps 个人访问令牌

若要运行自承载运行器,需要在 Azure DevOps 中创建个人访问令牌 (PAT)。 PAT 用于通过 Azure DevOps 对运行器进行身份验证。 缩放规则还使用它来确定挂起的管道运行数并触发新的作业执行。

[!NOTE]

个人访问令牌 (PAT) 设置了过期日期。 请定期轮换令牌,以确保它们持续有效(不会过期),使服务不会中断。

  1. 在 Azure DevOps 中,选择右上角个人资料图片旁的“用户设置”

  2. 选择“个人访问令牌”。

  3. 在“个人访问令牌”页中,选择“新建令牌”并输入以下值

    设置
    Name 输入令牌的名称。
    组织 选择之前选择或创建的组织。
    作用域 选择“自定义”
    显示所有范围 选择“显示所有范围”
    代理池(读取和管理) 选择“代理池(读取和管理)”

    将所有其他范围保留为未选中状态。

  4. 选择创建

  5. 将令牌值复制到安全位置。

    离开此页后,将无法检索令牌。

  6. 定义稍后用于配置容器应用作业的变量。

    AZP_TOKEN="<AZP_TOKEN>"
    ORGANIZATION_URL="<ORGANIZATION_URL>"
    AZP_POOL="container-apps"
    REGISTRATION_TOKEN_API_URL="<YOUR_REGISTRATION_TOKEN_API_URL>"
    

    将占位符替换为以下值:

    占位符 注释
    <AZP_TOKEN> 生成的 Azure DevOps PAT。
    <ORGANIZATION_URL> Azure DevOps 组织的 URL。 请确保 URL 末尾没有尾随 / 例如,https://dev.azure.com/myorghttps://myorg.visualstudio.com
    <YOUR_REGISTRATION_TOKEN_API_URL> entrypoint.sh 文件中的注册令牌 API URL 例如“https://myapi.example.com/get-token”

生成 Azure Pipelines 代理容器映像

若要创建自托管代理,需要生成运行代理的容器映像。 在本节中,将生成容器映像并将其推送到容器注册表。

注意

本教程中生成的映像包含一个适合作为容器应用作业运行的基本自托管代理。 可以对其进行自定义,以包含管道所需的其他工具或依赖项。

  1. 返回终端,定义容器映像和注册表的名称。

    CONTAINER_IMAGE_NAME="azure-pipelines-agent:1.0"
    CONTAINER_REGISTRY_NAME="<CONTAINER_REGISTRY_NAME>"
    

    <CONTAINER_REGISTRY_NAME> 替换为用于创建容器注册表的唯一名称。

    容器注册表名称在 Azure 中必须唯一,长度为 5 到 50 个字符,仅包含数字和小写字母

  2. 创建容器注册表。

    az acr create \
        --name "$CONTAINER_REGISTRY_NAME" \
        --resource-group "$RESOURCE_GROUP" \
        --location "$LOCATION" \
        --sku Basic \
        --admin-enabled true
    
  3. 用于创建运行器映像的 Dockerfile 在 GitHub 上提供。 运行以下命令,使用 az acr build 命令克隆存储库并在云中生成容器映像。

    az acr build \
        --registry "$CONTAINER_REGISTRY_NAME" \
        --image "$CONTAINER_IMAGE_NAME" \
        --file "Dockerfile.azure-pipelines" \
        "https://github.com/Azure-Samples/container-apps-ci-cd-runner-tutorial.git"
    

    映像现已在容器注册表中提供。

创建占位符自托管代理

在新的代理池中运行自托管代理之前,需要创建占位符代理。 占位符代理可确保代理池可用。 当没有占位符代理时,使用代理池的管道会失败。

可以运行手动作业来注册脱机占位符代理。 此作业运行一次,可以删除。 占位符代理不使用 Azure 容器应用或 Azure DevOps 中的任何资源。

  1. 在容器应用环境中创建创建占位符代理的手动作业。

    az containerapp job create -n "$PLACEHOLDER_JOB_NAME" -g "$RESOURCE_GROUP" --environment "$ENVIRONMENT" \
        --trigger-type Manual \
        --replica-timeout 300 \
        --replica-retry-limit 0 \
        --replica-completion-count 1 \
        --parallelism 1 \
        --image "$CONTAINER_REGISTRY_NAME.azurecr.cn/$CONTAINER_IMAGE_NAME" \
        --cpu "2.0" \
        --memory "4Gi" \
        --secrets "personal-access-token=$AZP_TOKEN" "organization-url=$ORGANIZATION_URL" \
        --env-vars "AZP_TOKEN=secretref:personal-access-token" "AZP_URL=secretref:organization-url" "AZP_POOL=$AZP_POOL" "AZP_PLACEHOLDER=1" "AZP_AGENT_NAME=placeholder-agent" \
        --registry-server "$CONTAINER_REGISTRY_NAME.azurecr.cn"
    

    下表描述了命令中使用的关键参数。

    参数 说明
    --replica-timeout 副本可以执行的最大持续时间。
    --replica-retry-limit 重试失败副本的次数。
    --replica-completion-count 在作业执行成功之前要成功完成的副本数。
    --parallelism 每个作业执行要启动的副本数。
    --secrets 作业要使用的机密。
    --env-vars 作业要使用的环境变量。
    --registry-server 作业要使用的容器注册表服务器。 对于 Azure 容器注册表,此命令会自动配置身份验证。

    设置 AZP_PLACEHOLDER 环境变量会将代理容器配置为在不运行作业的情况下注册为脱机占位符代理。

  2. 执行手动作业以创建占位符代理。

    az containerapp job start -n "$PLACEHOLDER_JOB_NAME" -g "$RESOURCE_GROUP"
    
  3. 列出作业的执行,以确认作业执行已创建并成功完成。

    az containerapp job execution list \
        --name "$PLACEHOLDER_JOB_NAME" \
        --resource-group "$RESOURCE_GROUP" \
        --output table \
        --query '[].{Status: properties.status, Name: name, StartTime: properties.startTime}'
    
  4. 验证占位符代理是否已在 Azure DevOps 中创建。

    1. 在 Azure DevOps 中,导航到你的项目。
    2. 选择“项目设置”>“代理池”>“container-apps”>“代理”
    3. 确认列出名为 placeholder-agent 的占位符代理,其状态为脱机。
  5. 不需要再次执行作业。 可以删除该帐户。

    az containerapp job delete -n "$PLACEHOLDER_JOB_NAME" -g "$RESOURCE_GROUP"
    

创建自托管代理作为事件驱动的作业

拥有占位符代理后,可以创建自托管代理。 在本节中,将创建一个事件驱动的作业,当触发管道时此作业运行自托管代理。

az containerapp job create -n "$JOB_NAME" -g "$RESOURCE_GROUP" --environment "$ENVIRONMENT" \
    --trigger-type Event \
    --replica-timeout 1800 \
    --replica-retry-limit 0 \
    --replica-completion-count 1 \
    --parallelism 1 \
    --image "$CONTAINER_REGISTRY_NAME.azurecr.cn/$CONTAINER_IMAGE_NAME" \
    --min-executions 0 \
    --max-executions 10 \
    --polling-interval 30 \
    --scale-rule-name "azure-pipelines" \
    --scale-rule-type "azure-pipelines" \
    --scale-rule-metadata "poolName=$AZP_POOL" "targetPipelinesQueueLength=1" \
    --scale-rule-auth "personalAccessToken=personal-access-token" "organizationURL=organization-url" \
    --cpu "2.0" \
    --memory "4Gi" \
    --secrets "personal-access-token=$AZP_TOKEN" "organization-url=$ORGANIZATION_URL" \
    --env-vars "AZP_TOKEN=secretref:personal-access-token" "AZP_URL=secretref:organization-url" "AZP_POOL=$AZP_POOL" \
    --registry-server "$CONTAINER_REGISTRY_NAME.azurecr.cn"

下表描述了命令中使用的缩放规则参数。

参数 说明
--min-executions 每个轮询间隔运行的最小作业执行数。
--max-executions 每个轮询间隔运行的最大作业执行数。
--polling-interval 评估缩放规则的轮询间隔。
--scale-rule-name 缩放规则的名称。
--scale-rule-type 要使用的缩放规则的类型。 若要了解有关 Azure Pipelines 缩放器的详细信息,请参阅 KEDA 文档
--scale-rule-metadata 缩放规则的元数据。
--scale-rule-auth 缩放规则的身份验证。

缩放规则配置定义要监视的事件源。 它会在每个轮询间隔上进行评估,并确定要触发的作业执行数。 若要了解详细信息,请参阅设置缩放规则

事件驱动作业现已在容器应用环境中创建。

运行管道并验证作业

现在你已配置自托管代理作业,可以运行管道并验证它是否正常工作。

  1. 在 Azure DevOps 项目的左侧导航中,导航到“Pipelines”

  2. 选择“创建管道”。

  3. 选择“Azure Repos Git”作为代码的位置。

  4. 选择之前创建的存储库。

  5. 选择“初学者管道”。

  6. 在管道 YAML 中,将 poolvmImage: ubuntu-latest 更改为 name: container-apps

    pool:
      name: container-apps
    
  7. 选择“保存并运行”。

    管道运行并使用在容器应用环境中创建的自托管代理作业。

  8. 列出作业的执行,以确认作业执行已创建并成功完成。

    az containerapp job execution list \
        --name "$JOB_NAME" \
        --resource-group "$RESOURCE_GROUP" \
        --output table \
        --query '[].{Status: properties.status, Name: name, StartTime: properties.startTime}'
    

提示

遇到问题? 在 Azure 容器应用存储库中提交问题,告知我们有关 GitHub 的信息。

清理资源

完成后,运行以下命令以删除包含容器应用资源的资源组。

注意

以下命令删除指定的资源组及其包含的所有资源。 如果指定的资源组中存在本教程范围外的资源,这些资源也会被删除。

az group delete \
    --resource-group $RESOURCE_GROUP

若要删除 GitHub 存储库,请参阅删除存储库

后续步骤