ごった煮

色々な事を書いてます

Azure Container Apps で Azure Pipeline の Self Hosted Agents を構築する - その1

CI/CD のツールとして Azure Pipeline を使うのですが、Microsoft-Hosted Agent の場合、Parallel Job の制限がきつく、 どうしても順番待ちが発生しがちでした

Self Hosted Agent の場合、Visual Studioサブスクリプションがあると、Parallel Job の枠が増える為、 手っ取り早く Self Hosted Agent を増やして、有効活用したいということで、Container Apps を使った Self Hosted Agents を構築しました

今回は、その時の備忘録です。

その1 で行う事

  • Azure Container Registry (ACR) を作成する
  • Self Hosted Agent のイメージを ACR へ登録する

前提条件

  • Azure のサブスクリプションを持っている
  • Azure CLI が手元の環境にインストールされている
  • Docker が手元の環境にインストールされている

環境

  • Azure CLI : v.2.39.0
  • Docker : v.20.10

Azure Container Registry (ACR) を作成する

今回は、サクッと Bicep で構築します

リソースグループを作成する

まず今回作るものを格納するリソースグループを作成します

  • bicep
targetScope = 'subscription'

resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
  name: 'rg-devops-agent'
  location: deployment().location
}
  • コマンド
az deployment sub create \
--location japaneast \
--template-file {bicep ファイル名}

ACR を作成する

次に、ACR を作成します。

  • bicep
param location string = resourceGroup().location

// Create Azure Container Registry

param acrName string

module acr 'modules/containerRegistry.bicep' = {
  name: acrName
  params: {
    acrName: acrName
    adminUserEnabled: true
    location: location
    sku: 'Basic'
  }
}
  • コマンド
az deployment group create \
--resource-group rg-devops-agent \
--template-file {bicep ファイル名} \
--parameters acrName={ACR 名}

Self Hosted Agent のイメージを ACR へ登録する

Dockerfile をビルドする

公式でベースになる Dockerfile が提供されているので、次のものを保存します

FROM ubuntu:20.04
RUN DEBIAN_FRONTEND=noninteractive apt-get update
RUN DEBIAN_FRONTEND=noninteractive apt-get upgrade -y

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends \
    apt-transport-https \
    apt-utils \
    ca-certificates \
    curl \
    git \
    iputils-ping \
    jq \
    lsb-release \
    software-properties-common

RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash

# Can be 'linux-x64', 'linux-arm64', 'linux-arm', 'rhel.6-x64'.
ENV TARGETARCH=linux-x64

WORKDIR /azp

COPY ./start.sh .
RUN chmod +x start.sh

ENTRYPOINT [ "./start.sh" ]

次に、コンテナの ENTRYPOINT で実行するスクリプトを Dockerfile と同じ場所に start.sh として保存します。

#!/bin/bash
set -e

if [ -z "$AZP_URL" ]; then
  echo 1>&2 "error: missing AZP_URL environment variable"
  exit 1
fi

if [ -z "$AZP_TOKEN_FILE" ]; then
  if [ -z "$AZP_TOKEN" ]; then
    echo 1>&2 "error: missing AZP_TOKEN environment variable"
    exit 1
  fi

  AZP_TOKEN_FILE=/azp/.token
  echo -n $AZP_TOKEN > "$AZP_TOKEN_FILE"
fi

unset AZP_TOKEN

if [ -n "$AZP_WORK" ]; then
  mkdir -p "$AZP_WORK"
fi

export AGENT_ALLOW_RUNASROOT="1"

cleanup() {
  if [ -e config.sh ]; then
    print_header "Cleanup. Removing Azure Pipelines agent..."

    # If the agent has some running jobs, the configuration removal process will fail.
    # So, give it some time to finish the job.
    while true; do
      ./config.sh remove --unattended --auth PAT --token $(cat "$AZP_TOKEN_FILE") && break

      echo "Retrying in 30 seconds..."
      sleep 30
    done
  fi
}

print_header() {
  lightcyan='\033[1;36m'
  nocolor='\033[0m'
  echo -e "${lightcyan}$1${nocolor}"
}

# Let the agent ignore the token env variables
export VSO_AGENT_IGNORE=AZP_TOKEN,AZP_TOKEN_FILE

print_header "1. Determining matching Azure Pipelines agent..."

AZP_AGENT_PACKAGES=$(curl -LsS \
    -u user:$(cat "$AZP_TOKEN_FILE") \
    -H 'Accept:application/json;' \
    "$AZP_URL/_apis/distributedtask/packages/agent?platform=$TARGETARCH&top=1")

AZP_AGENT_PACKAGE_LATEST_URL=$(echo "$AZP_AGENT_PACKAGES" | jq -r '.value[0].downloadUrl')

if [ -z "$AZP_AGENT_PACKAGE_LATEST_URL" -o "$AZP_AGENT_PACKAGE_LATEST_URL" == "null" ]; then
  echo 1>&2 "error: could not determine a matching Azure Pipelines agent"
  echo 1>&2 "check that account '$AZP_URL' is correct and the token is valid for that account"
  exit 1
fi

print_header "2. Downloading and extracting Azure Pipelines agent..."

curl -LsS $AZP_AGENT_PACKAGE_LATEST_URL | tar -xz & wait $!

source ./env.sh

print_header "3. Configuring Azure Pipelines agent..."

./config.sh --unattended \
  --agent "${AZP_AGENT_NAME:-$(hostname)}" \
  --url "$AZP_URL" \
  --auth PAT \
  --token $(cat "$AZP_TOKEN_FILE") \
  --pool "${AZP_POOL:-Default}" \
  --work "${AZP_WORK:-_work}" \
  --replace \
  --acceptTeeEula & wait $!

print_header "4. Running Azure Pipelines agent..."

trap 'cleanup; exit 0' EXIT
trap 'cleanup; exit 130' INT
trap 'cleanup; exit 143' TERM

chmod +x ./run-docker.sh

# To be aware of TERM and INT signals call run.sh
# Running it with the --once flag at the end will shut down the agent after the build is executed
./run-docker.sh "$@" & wait $!
  • コマンド

後で使うので、分かりやすいタグも付けておきます

docker build . -t devops-agent

エラーが出なければ、イメージの作成完了です

ACR へイメージを登録する

まず ACR へログインします

az acr login --name {ACR 名}

次にプッシュしたいイメージにタグと明示的なイメージ名を設定します

イメージ名は、ACR のサーバ名/イメージ名:タグ名 とします

docker tag devops-agent {ACR 名}.azurecr.io/devops-agent:latest

最後に ACR に push します

docker push {ACR 名}.azurecr.io/devops-agent:latest

まとめ

ここまでで、Azure Container Registry に Self Hosted Agent のイメージを登録できました。

次回は、このイメージを基に Container Apps へ Self Hosted Agent を展開していこうと思います。