使用 Azure 文件创建用于在 Azure Kubernetes 服务(AKS)上部署高度可用的 GitHub Actions 的基础结构

在本文中,你将使用 Azure 文件存储和 Helm 来创建在 AKS 上部署高可用性操作运行器控制器 (ARC) 基础结构所需的基础结构。

在您开始之前

设置环境变量。

设置以下环境变量以在本指南中使用:

export AKS_AND_STORAGE_ACCOUNT_RG="aks-files-actions"
export AKS_CLUSTER_NAME="aks-actions"
export STORAGE_ACCOUNT_NAME=""
export AKS_STORAGE_ACCOUNT_LOCATION="chinanorth3"
export GITHUB_CONFIG_URL="azure-files-samples/Workloads/azurefiles-actions-aks at master · Azure-Samples/azure-files-samples"

# Optional. Changes might require additional changes on ./install/*.yaml files.

export NAMESPACE_ARC_CONTROLLER="arc-systems"
export ARC_CONTROLLER_NAME="arc-controller"
export NAMESPACE_ARC_RUNNERS="arc-runners"
export ARC_RUNNER_SCALESET_NAME="arc-runner-set"
export ARC_RUNNER_GITHUB_SECRET_NAME=""

请确保替换以下 必需 变量的值:

  • AKS_AND_STORAGE_ACCOUNT_RG 使用存储帐户和 AKS 群集使用的资源组名称。
  • AKS_CLUSTER_NAME 使用 AKS 群集的名称。
  • STORAGE_ACCOUNT_NAME 使用存储帐户的名称。
  • AKS_STORAGE_ACCOUNT_LOCATION 包含要在其中创建资源的区域的名称。 在此示例中,我们将部署在 AKS 群集所在的同一区域中,以促进性能和成本管理。
  • GITHUB_CONFIG_URL 包含 GitHub 组织或存储库的 URL。

如果可能,请将以下 可选 变量保留为默认值:

  • NAMESPACE_ARC_CONTROLLER:运行 ARC 运行程序规模集控制器的 Kubernetes 命名空间的名称。
  • ARC_CONTROLLER_NAME:ARC 运行程序规模集控制器的名称。
  • NAMESPACE_ARC_RUNNERS:用于运行 ARC 自承载运行程序的 Kubernetes 命名空间的名称。
  • ARC_RUNNER_SCALESET_NAME:ARC 运行程序规模集的名称。
  • ARC_RUNNER_GITHUB_SECRET_NAME:GitHub 密钥的名称。

安装所需的扩展

aks-preview、k8s-extension 和 amg 扩展提供了更多功能来管理 Kubernetes 群集和查询 Azure 资源。 使用以下 az extension add 命令安装这些扩展:

az extension add --upgrade --name aks-preview --yes --allow-preview true 
az extension add --upgrade --name k8s-extension --yes --allow-preview false 
az extension add --upgrade --name amg --yes --allow-preview false

创建资源组

使用 az group create 命令创建资源组。 此资源组将保存 AKS 群集和 Azure 文件存储存储帐户。

az group create \ 
    --name $AKS_AND_STORAGE_ACCOUNT_RG \ 
    --location $AKS_STORAGE_ACCOUNT_LOCATION

创建 AKS 群集

使用 az aks create 命令创建 AKS 群集。

az aks create --resource-group "${AKS_AND_STORAGE_ACCOUNT_RG}" --name "${AKS_CLUSTER_NAME}" \ 
    --os-sku AzureLinux \ 
    --node-count 1 \ 
    --enable-cluster-autoscaler \ 
    --min-count 1 \ 
    --max-count 3 \ 
    --node-vm-size standard_d4s_v5 \ 
    --max-pods=100 \ 
    --network-plugin azure \ 
    --network-plugin-mode overlay \ 
    --generate-ssh-keys

连接到 AKS 群集

若要管理 Kubernetes 群集,请使用 Kubernetes 命令行客户端 kubectl。 若要在本地安装 kubectl,请使用 az aks install-cli 命令。

  1. 配置 kubectl 以使用 az aks get-credentials command 来连接到你的 Kubernetes 群集。 此命令将下载凭据,并将 Kubernetes CLI 配置为使用这些凭据。

    az aks get-credentials --resource-group "${AKS_AND_STORAGE_ACCOUNT_RG}" --name "${AKS_CLUSTER_NAME}"
    
  2. 使用 kubectl get nodes 命令验证与群集之间的连接。 此命令返回 AKS 群集中的节点列表。

    kubectl get nodes
    

创建 Azure 文件共享

在将 Azure 文件存储的文件共享用作 Kubernetes 卷之前,你需要先创建 Azure 存储帐户和文件共享。 本指南使用 Azure 文件共享高级 SMB 来支持元数据缓存。 对于创建的每个共享,最小值为 100 Gb 。

  1. 使用命令 az storage account create 创建存储帐户。 以下命令使用 Premium_LRS SKU 创建存储帐户。

    az storage account create --name "${STORAGE_ACCOUNT_NAME}" --resource-group "${AKS_AND_STORAGE_ACCOUNT_RG}" \
        --location "${AKS_STORAGE_ACCOUNT_LOCATION}" \
        --sku Premium_LRS \
        --kind FileStorage
    
  2. 使用 az storage account show-connection-string 命令将连接字符串导出为环境变量,然后用于创建文件共享。

    export AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string --name "${STORAGE_ACCOUNT_NAME}" --resource-group "${AKS_AND_STORAGE_ACCOUNT_RG}" --query connectionString -o tsv)
    
  3. 使用 az storage share create 命令创建 100 Gb 高级文件共享。 在此示例中,我们使用 元数据缓存 作为共享名称。 如果更改此名称,则还必须更改 arc-runners-set-pv.yaml 文件以反映此更改。

    az storage share create --name metadatacaching --quota 100 --connection-string "${AZURE_STORAGE_CONNECTION_STRING}"
    

安装 ARC 运行程序规模集控制器

使用下文的 helm install 命令安装 ARC 运行程序规模集控制器。

helm install "${ARC_CONTROLLER_NAME}" \ 
    --namespace "${NAMESPACE_ARC_CONTROLLER}" \ 
    --create-namespace \
    oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller

创建 Kubernetes 机密

Azure 文件共享存储密钥机密

Azure 文件要求您在 AKS 上使用存储密钥创建一个机密,该密钥用于从 AKS Pod 容器连接 Azure 文件共享。

  1. 使用 az storage account keys list 命令将存储帐户密钥导出为环境变量。

    STORAGE_KEY=$(az storage account keys list --resource-group ${AKS_AND_STORAGE_ACCOUNT_RG} --account-name ${STORAGE_ACCOUNT_NAME} --query "[0].value" -o tsv) 
    
  2. 创建 Kubernetes 命名空间,以使用 kubectl create namespace 命令运行 ARC 自承载运行程序。

    kubectl create namespace "${NAMESPACE_ARC_RUNNERS}" 
    
  3. 使用 kubectl create secret generic 命令创建用于存储 Azure 文件共享存储密钥的 Kubernetes Secret。

    kubectl create secret generic azure-storage-secret \ 
       --namespace "${NAMESPACE_ARC_RUNNERS}" \ 
       --from-literal=azurestorageaccountname=${STORAGE_ACCOUNT_NAME} \ 
       --from-literal=azurestorageaccountkey=${STORAGE_KEY}
    

GitHub 应用机密

  1. 创建一个 GitHub 应用,以允许自托管运行器按照注册 GitHub 应用指南访问您的 GitHub 组织或存储库。 GitHub 创建过程提供以下参数:

    • GITHUB_APP_ID:GitHub 应用的 ID。
    • GITHUB_APP_INSTALLATION_ID:GitHub 应用的安装 ID。
    • github_app_private_key:GitHub 应用的私钥。 需要将 -----BEGIN RSA 私钥----- 部分替换为您的私钥。
  2. 使用kubectl create secret generic命令创建 Kubernetes 机密来存储 GitHub 应用凭据。 请确保将占位符替换为从 GitHub 应用创建过程获取的实际值。

    GITHUB_APP_ID="app-id-placeholder"
    GITHUB_APP_INSTALLATION_ID="installation-id-placeholder"
    
    kubectl create secret generic ${ARC_RUNNER_GITHUB_SECRET_NAME} \ 
        --namespace=${NAMESPACE_ARC_RUNNERS} \
        --from-literal=github_app_id=${GITHUB_APP_ID} \
        --from-literal=github_app_installation_id=${GITHUB_APP_INSTALLATION_ID} \
        --from-literal=github_app_private_key=' <Private Key read here>'
    

Azure 文件共享配置

你可以使用 AccessMode: ReadWriteMany 在多个 Pod 中装载 Azure 文件存储的文件共享,同时在 ARC Kubernetes 副本集创建的所有 Pod 中装载相同的文件共享。 我们以如下方式使用 Azure 文件共享:

  • 作为 持久 SMB 文件共享 ,用于缓存 .NET 示例应用程序使用的 NuGet 包。 arc-runners-set-pv-pvc.yaml 文件能创建规定的 PV 和 PVC,以在 ARC 运行程序规模集 Pod 中装载 Azure 文件存储的文件共享。 对于此第一个选项,建议使用 Azure 文件高级版。 按照下文示例所示,自定义 PV 和 PVC 清单上的 volumeAttributes 和所有命名空间参数:

    volumeAttributes: 
      resourceGroup: metadata-agroves  # Optional. Only set this when the storage account isn't in the same resource group as node. 
      shareName: metadatacaching
    nodeStageSecretRef:
      name: azure-storage-secret
      namespace: arc-runners
    
  • 作为 GitHub 运行程序工作文件夹的“临时卷”。 我们还创建了两个存储类:Azure 文件标准版(github-azurefile)和 Azure 文件高级版(github-azurefile-premium)。 这些类可以按需创建和删除卷。 运行 GitHub 作业时,会在 Kubernetes 上创建新的运行程序 Pod,并创建并装载新的 Azure 文件存储的文件共享。 卷仅存在在作业运行期间。 标准版本允许任何存储卷大小,高级版本允许至少 100 Gb 存储卷。 你可以选择任何你喜欢的课程。 请记住,Premium 为你提供更好的性能。 可以自定义 arc-runners-storage-class-files.yaml 文件,但这不是必需的。

创建永久性卷和永久性卷声明

  1. 使用 kubectl apply 命令创建永久性卷和永久性卷声明。

    kubectl apply -f ./install/arc-runners-set-pv-pvc.yaml --namespace "${NAMESPACE_ARC_RUNNERS}" --wait 
    
  2. 使用 kubectl apply 命令为 Azure 文件应用存储类。

    kubectl apply -f ./install/arc-runners-storage-class-files.yaml --wait 
    

安装 ARC 运行程序规模集

以下代码片段来自安装文件夹中的 arc-runners-set-values.yaml 文件,你可以在安装运行程序集 Helm 图表之前对其进行自定义。

containerMode: 
  type: "kubernetes" # Type can be set to dind or kubernetes 
  ## The following is required when containerMode.type=kubernetes 
  kubernetesModeWorkVolumeClaim: 
    accessModes: ["ReadWriteMany"] 
    storageClassName: "github-azurefile-premium" # or "github-azurefile" for Standard_LRS 
    resources: 
      requests: 
        storage: 100Gi # 100Gi minimum to premium or any size when using Standard_LRS "github-azurefile" storage class 
template: 
  spec: 
  securityContext: 
    fsGroup: 123 # Group used by GitHub default agent image 
  containers: 
  - name: runner 
    image: ghcr.io/actions/actions-runner:latest 
    command: ["/home/runner/run.sh"] 
    env: 
      - name: ACTIONS_RUNNER_REQUIRE_JOB_CONTAINER 
        value: "false" 
      - name: ACTIONS_RUNNER_CONTAINER_HOOK_TEMPLATE 
        value: "/home/runner/container-config/container-podspec.yaml" 
    volumeMounts: 
      - name: "container-podspec-volume" 
        mountPath: "/home/runner/container-config" 
      - name: azurefile 
        mountPath: /home/runner/.nuget/              
  volumes: 
    - name: "container-podspec-volume" 
      configMap: 
        name: hook-extension 
    - name: azurefile 
      persistentVolumeClaim: 
        claimName: azurefile 

在此示例中,我们使用 Kubernetes containerMode 的自定义版本将 Azure 文件存储的文件共享卷装载到 NuGet 包和临时_工作文件夹卷中。

以下参数不需要更改:

  • storageClassName:在“github-azurefile-premium”和“github-azurefile”之间进行选择。
  • storage:选择存储的大小。 高级版最低为 100 Gb。

使用选项在 helm install 选项在 --set 命令上设置其他 Helm 参数。

为了与 GitHub 工作流容器功能兼容以便在管道中运行容器,我们在使用容器功能运行工作流时,为 ARC 创建的工作流 Pod 装载有 pod 规范的 container-podspec-volume。 此 Pod 规格是从安装文件夹中的 arc-runners-set-container-pod-spec.yaml 文件创建的 ConfigMap 装载的。 不需要进行任何更改。

kubectl apply -f ./install/arc-runners-set-container-pod-spec.yaml 

ARC 运行程序规模集 Helm 图表参数

ARC 运行程序规模集 Helm 图表提供了几个参数。 在 AKS 上安装具有 Azure 文件共享卷装载的规模集时,以下参数是最重要的:

  • githubConfigUrl:GitHub 组织或存储库。
  • githubConfigSecret:用于从自托管运行器访问 GitHub 的 GitHub 应用程序密钥。
  • minRunners:规模集中等待 GitHub 新作业的最小运行程序数。
  • maxRunners:正在运行作业或等待 GitHub 新作业的最大运行程序数。
  • runnerGroup:ARC 运行器集使用的 GitHub 运行器组。

下载 ARC 运行程序规模集 Helm 图表。

在 AKS 上安装 Helm 图表

使用 helm install 命令在 AKS 上安装 ARC 运行程序规模集 Helm 图表。

helm install "${ARC_RUNNER_SCALESET_NAME}" \ 
    --namespace "${NAMESPACE_ARC_RUNNERS}" \ 
    --create-namespace \ 
    --values ./install/arc-runners-set-values.yaml \ 
    --set githubConfigUrl="${GITHUB_CONFIG_URL}" \ 
    --set githubConfigSecret="${ARC_RUNNER_GITHUB_SECRET_NAME}" \ 
    --set minRunners=1 \ 
    --set maxRunners=3 \ 
    --set runnerGroup=default \ 
    oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set

升级运行程序规模集安装

如果想要升级 ARC 运行程序规模集上的任何配置,你可以 helm upgrade --install 命令,其参数与安装规模集的相同。 例如,如果要将 minRunners 参数从 1 更改为 2,可以运行以下命令:

helm upgrade --install "${ARC_RUNNER_SCALESET_NAME}" \
    --namespace "${NAMESPACE_ARC_RUNNERS}" \
    --create-namespace \
    --values ./install/arc-runners-set-values.yaml \
    --set githubConfigUrl="${GITHUB_CONFIG_URL}" \
    --set githubConfigSecret="${ARC_RUNNER_GITHUB_SECRET_NAME}" \
    --set minRunners=2 \
    --set maxRunners=3 \
    --set runnerGroup=default \
    oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set

后续步骤

供稿人

Microsoft维护本文。 以下贡献者最初撰写了这篇文章:

  • 豪尔赫·阿尔特里奥 | 高级云倡导者
  • Jeff Patterson | 首席产品经理
  • Rena Shah |高级产品经理
  • 谢哈尔·辛格·索罗特 |Product Manager 2
  • Erin Schaffer | 内容开发人员 2