Jump to content

Featured Replies

Posted

Introdução

 

 

Por padrão temos no Azure Devops a opção de escalar os agents por Azure Virtual machine scale sets vm-scale-set, porém, temos a opção de utilizar o KEDA para escalar os agents.

 

Já temos um artigo no blog da Microsoft sobre o KEDA, porém, mais a ideia desse artigo é mostrar como utilizar o KEDA para escalar os agents do Azure Devops no Kubernetes.

 

O código fonte desse artigo está disponível no github

 

 

 

Pré-requisitos

 

 

 

 

Configurando o Azure Devops

 

 

 

 

Criando um agent pool

 

 

Após a criação da organização no Azure Devops, vamos criar um agent pool, para isso, vamos em Organization settings -> Agent pools -> Add pool.

 

No Pool type selecione Self-hosted e no name digite o nome do pool, no meu caso keda-pool.

 

No Pipeline permissions deixe marcado Grant access permissions to all pipelines e clique no botão Create.

 

create-agent-pool

 

Após a criação do agent pool, será necessário pegar qual é o id do mesmo.

 

Temos algumas maneiras que como pegar o id do agent pool, uma delas é acessando a url do agent pool, no meu caso https://dev.azure.com/xxxx-sua-organizationn/_apis/distributedtask/pools?poolname=keda-pool, essa chamada vai retornar um json com o id do agent pool.

 

Abra o json em qualquer ferramenta como o http://jsonviewer.stack.hu/ e procure o id, no meu caso o id é 18 como mostra a imagem abaixo.

 

212674648-7f7168e5-1d6d-4f5c-890a-8ef5861857ac.png.e7ae6faef926473e510193fd6f4108d7.png

 

 

Criando um PAT no Azure Devops

 

 

Vamos precisar de um token do Azure Devops para que o agent consiga se registrar no Azure Devops.

 

Siga os passos para criar o PAT criando um PAT no Azure Devops

 

Após a criação do PAT, salve o token em algum lugar, pois vamos precisar dele mais a frente.

 

 

 

Criando uma imagem docker para o agent e publicando no container registry

 

 

 

 

Criando um Dockerfile

 

 

Para criar uma imagem, siga os passos abaixo.

 

Crie um arquivo Dockerfile com o conteúdo abaixo.

 

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" ]

 

 

Na mesma pasta que foi criado o Dockerfile, crie um arquivo chamado start.sh com o conteúdo abaixo.

 

#!/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..."

 

if ! grep -q "template" <<< "$AZP_AGENT_NAME"; then

echo "Cleanup Traps Enabled"

 

trap 'cleanup; exit 0' EXIT

trap 'cleanup; exit 130' INT

trap 'cleanup; exit 143' TERM

 

fi

 

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 "$@" --once & wait $!

 

O seu arquivo start.sh tem que ter o EOL do unix/linux , caso esteja no windows, você pode usar o dos2unix para converter o arquivo ou utilizar o notepad++ e configurar o EOL para unix/linux.

 

212674705-9d231f6e-04a9-47ae-930e-33d7b4e08746.png.4f37ca32b69425c5c1055505d8d0a8cb.png

 

 

Criando a imagem e publicando no ACR

 

 

Abra um terminal na pasta onde está o Dockerfile e o start.sh e execute o comandos abaixo.

 

# cria a imagem

docker build -t azure-devops-agent:latest .

# loga no seu ACR

docker login -u <user> -p <password> <seu acr name>

# cria a tag da imagem

docker tag azure-devops-agent:latest <seu acr name>/azure-devops-agent:latest

# envia a imagem para o ACR

docker push <seu acr name>/azure-devops-agent:latest

 

Criando os arquivos YML para o Kubernetes

 

 

 

 

Criando o deployment do Azure DevOps Agent

 

 

Pegue o PAT que foi gerado nos passos anteriores e vamos precisar converter o mesmo para base64.

 

Va no site https://base64.guru/converter e cole o PAT gerado e clique em encode e salve o valor gerado.

 

Crie um arquivo chamado deployment.yml com o conteúdo abaixo.

 

apiVersion: v1

kind: Secret

metadata:

name: azdevops

data:

AZP_TOKEN: 'seu pat gerado convertido para base64'

---

apiVersion: apps/v1

kind: Deployment

metadata:

name: azdevops-deployment

labels:

app: azdevops-agent

spec:

replicas: 1

selector:

matchLabels:

app: azdevops-agent

template:

metadata:

labels:

app: azdevops-agent

spec:

containers:

- name: azdevops-agent

#nome do seu ACR que foi criado

image: nomedoseuacr.azurecr.io/azure-devops-agent:latest

env:

- name: AZP_URL

value: "https://dev.azure.com/sua-organizacao" #url da sua organização

- name: AZP_POOL

value: "keda-pool"

- name: AZP_TOKEN

valueFrom:

secretKeyRef:

name: azdevops

key: AZP_TOKEN

 

Fazendo o deploy do deployment no Kubernetes

 

 

Primeiro vamos instalar Kubernetes CLI para o Azure, fazer o login no cluster e executar o deploy.

 

# instalando o Kubernetes CLI

az aks install-cli

# logando no seu cluster

az aks get-credentials --resource-group myResourceGroup --name myAKSCluster

# criando um namespace para o seu deployment

kubectl create namespace azdevops

# fazendo o deploy do deployment

kubectl apply -f deployment.yml -n azdevops

# verificando se o pod foi criado

kubectl get pods -n azdevops

# vai ter uma resposta parecido com essa

NAME READY STATUS RESTARTS AGE

azdevops-deployment-86b9c58cbd-nm45l 1/1 Running 0 13s

 

 

 

Agora vá no seu Azure Devops no pool que criamos no passo anterior e verifique se o agente foi adicionado e verifique se ele está online.

 

212674742-2597ea00-7b4e-4e54-bddb-1006d91c39d6.png.ebecb7ca356dcfc462cfa5c103e91781.png

 

Criando um pipeline

 

 

Crie um projeto default na sua organização do Azure DevOps. Clique aqui para saber como criar um projeto

 

Após a criação do projeto, vamos criar um pipeline. Clique aqui para saber como criar um pipeline

 

Quando aparecer a opção do review do seu pipeline, mude o pool para o que criamos, no meu caso foi o keda-pool e clique save and run.

 

212674775-f7af5f5f-965d-4c4a-854b-2ea152873c74.png.9d28c27bb9fb29ac731bfe7f003e13ab.png

 

Vá no seu pool e verifique se o agente está rodando a build.

 

212674819-794271b2-17ce-48fb-95b4-74c577924966.png.6c0ecc7be4c01d15ae96705eb1f8f738.png

 

Criando o Scale Object do KEDA

 

 

Crie um arquivo chamado scale-object.yml com o conteúdo abaixo.

 

Esse padrão de arquivo do KEDA, vai fazer o scaling por deployment, ao executar seus agentes como deployment, você não tem controle sobre qual pod é killed ao reduzir o scaling.

 

apiVersion: v1

kind: Secret

metadata:

name: pipeline-auth

data:

personalAccessToken: 'seu pat gerado convertido para base64'

---

apiVersion: keda.sh/v1alpha1

kind: TriggerAuthentication

metadata:

name: pipeline-trigger-auth

spec:

secretTargetRef:

- parameter: personalAccessToken

name: pipeline-auth

key: personalAccessToken

---

apiVersion: keda.sh/v1alpha1

kind: ScaledObject

metadata:

name: azure-pipelines-scaledobject

spec:

scaleTargetRef:

name: azdevops-deployment

minReplicaCount: 1

maxReplicaCount: 5 #número máximo de replicas

triggers:

- type: azure-pipelines

metadata:

poolID: "18" #seu id do pool

organizationURLFromEnv: "AZP_URL"

authenticationRef:

name: pipeline-trigger-auth

 

Vamos fazer o deploy do arquivo scale-object.yml, rode os comandos abaixo.

 

# cria os arquivo necessários para o KEDA

kubectl apply -f scale-object.yml -n azdevops

# verifica se o scaled object foi criado

kubectl get scaledobject -n azdevops

# vai ter uma resposta parecido com essa

NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK AGE

azure-pipelines-scaledobject apps/v1.Deployment azdevops-deployment 1 5 azure-pipelines pipeline-trigger-auth True False False 73s

 

 

 

Após o deploy dos manifestos do KEDA, vamos executar o mesmo pipeline várias vezes para ver o scaling acontecer.

 

212674849-7bbc2b00-6680-46c9-8b68-eb54ba96121c.png.0d81fb19b686e00e7de347fc117b2f4a.png Como podemos ver na imagem acima, o agent foi escalado para 4, pois temos 4 pipelines rodando. Caso tenha um pipeline que rode 4 jobs em paralelo o agent também será escalado para 4.

 

Conclusão

 

 

Como visto com o KEDA temos mais uma opção para escalar os agents de uma maneira simples e eficiente, lembrando que qualquer outra tools necessária para o seu processo de build/deploy tem que ser instalada junto no seu Dockerfile.

 

O KEDA também suporta mais alguns parâmetros para trigger, como podemos ver abaixo.

 

triggers:

- type: azure-pipelines

metadata:

# Optional: Name of the pool in Azure DevOps

poolName: "{agentPoolName}"

# Optional: Learn more in 'How to determine your pool ID'

poolID: "{agentPoolId}"

# Optional: Azure DevOps organization URL, can use TriggerAuthentication as well

organizationURLFromEnv: "AZP_URL"

# Optional: Azure DevOps Personal Access Token, can use TriggerAuthentication as well

personalAccessTokenFromEnv: "AZP_TOKEN"

# Optional: Target queue length

targetPipelinesQueueLength: "1" # Default 1

activationTargetPipelinesQueueLength: "5" # Default 0

# Optional: Parent template to read demands from

parent: "{parent ADO agent name}"

# Optional: Demands string to read demands from ScaledObject

demands: "{demands}"

authenticationRef:

name: pipeline-trigger-auth

Referências

 

  1. Example for ScaledObject
  2. Azure Pipelines scaler
  3. Docker Agents in Azure Devops

 

Continue reading...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...