Como Criar um Self-Hosted Agent do Azure DevOps
Compartilho como criei um Self-Hosted Agent do Azure DevOps
Introdução
Em um cenário de desenvolvimento ágil e integração contínua, a flexibilidade é importante. É nesse contexto que os Self-Hosted Agents do Azure DevOps emergem como uma solução poderosa, oferecendo controle total sobre seu ambiente de build e deploy.
Neste artigo, exploraremos passo a passo como criar seu próprio Agent Auto Hospedado do Azure DevOps. Essa abordagem não apenas amplia a capacidade de personalização do seu pipeline, mas também proporciona maior eficiência ao permitir a execução de builds em um ambiente familiar e sob seu controle direto.
Tipos de Agents do Azure DevOps
O Azure DevOps oferece flexibilidade na execução de pipelines de CI/CD através de três tipos de Agents:
Microsoft-Hosted Agents
Self-Hosted Agents
Azure Virtual Machine Scale Set Agents
Microsoft-Hosted Agents
Servidores Gerenciados pela Microsoft: Os Microsoft-Hosted Agents são servidores de build e deploy totalmente gerenciados e atualizados pela Microsoft e estão pronto para uso sem qualquer configuração adicional.
Limite Gratuito de Minutos por Mês: no momento da criação deste artigo, existe um limite de 1.800 minutos gratuitos por mês para o uso, oferecendo uma opção econômica para projetos menores.
Solicitação de Liberação de Minutos: A Microsoft começou a exigir a solicitação através de um formulário para liberar os 1.800 minutos gratuitos para evitar abusos, se você não o fizer receberá um erro parecido com:
0Microsoft-Hosted
:Self-Hosted Agents
Controle Total: Você precisa hospedar ou gerenciar o servidor. O self-hosted oferece controle total ao permitir que você configure e mantenha seus próprios agentes de build.
Adaptabilidade ao Ambiente: Permite a execução de builds em um ambiente que você controla, com a flexibilidade de adaptar recursos conforme necessário.
Adequado para Projetos Complexos: Ideal para projetos maiores, equipes que requerem ambientes específicos ou aqueles que precisam integrar com recursos internos.
Cobrança: Você tem a cobrança do seu servidor, mas seus minutos são ilimitados e você não será cobrado pelo limite e preço do Azure DevOps.
Azure Virtual Machine Scale Set Agents
Elasticidade com Azure Virtual Machine Scale Set: Os Azure Virtual Machine Scale Set Agents oferecem elasticidade, permitindo a escala automática de máquinas virtuais conforme a demanda de build e deploy.
Integração com Azure DevOps: Projetados para integração direta com o Azure DevOps, esses agentes fornecem um ambiente escalável e gerenciável para pipelines de CI/CD.
Configuração Sob Demanda: Permitem a configuração sob demanda de máquinas virtuais, garantindo recursos adequados para lidar com a carga de trabalho, com a flexibilidade de ajustar conforme necessário.
Benefícios do Self-Hosted Agents
Configurações de build personalizadas: os agents permitem que você configure seu hardware para diferentes tipos de build. Por exemplo, se seu build tiver que consumir muitos recursos, usar hardware com mais memória pode melhorar o tempo de execução.
Acesse aplicativos ou bancos de dados internos: ao executar pipelines na infraestrutura do Azure DevOps com Microsoft-Hosted Agents, dificulta o trabalho para poder acessar sistemas internos como banco de dados por exemplo. Se você precisa executar testes de integração em seus bancos de dados ou aplicativos internos, você poderá fazer isso com agents auto hospedados na mesma rede fornecendo acesso necessário aos serviços internos.
Fluxos de trabalho híbridos: você pode otimizar seus recursos usando agents auto hospedados com configurações personalizadas para builds que exigem isso e usar a infraestrutura do Azure DevOps com Microsoft-Hosted Agents para outros trabalhos.
Tutorial Prático - Pré-Requisitos
Para a instalação de um Agent auto hospedado do Azure DevOps, como o nome sugere você precisará de uma máquina, isso pode ser desde seu próprio computador até qualquer VPS de sua preferência.
AWS EC2
, Google Compute Engine
, Digital Ocean
, Vultr
, Linode
, etc.Criando uma instância Lightsail
1- Acesse o console AWS → Lightsail → Create Instance
2- Escolha a região
Norte da Virgínia
e a Zona de Disponibilidade A
3- Escolha o sistema operacional
Ubuntu 22.04
que é a mais recente no momento da criação deste artigo4- Não adicione um script de inicialização
, não altere sua chave key-pair
e não habilite snapshots automáticos
, as opções padrões parecem boas aqui.
5- Escolha Dual Stack
, pois ainda há limitações para uso do IPv6
e precisamos que nossa instância tenha IPv4 também.
6- Selecione o tamanho da instância
small de USD 10 com 2GB de memória, 2 vCPU e 3TB de transferência de dados
.1GB de memória não chegam a funcionar corretamente
, e tenho usado instâncias acima de 4GB de memória em ambientes de produção
. Mas para efeitos de tutorial essa parece ser uma escolha boa.7- Defina um nome, opcionalmente você pode inserir tags e clique em criar instância
8- Aguarde até o status Pending
mudar para Running
Criando um IP Fixo
Se olharmos bem, a instância Lightsail recebeu um IPv4
e IPv6
público dinâmicos, isso aconteceu porque selecionamos a opção Dual Stack
quando criamos a instância. O dinâmico significa que quando desligarmos essa instância e ligarmos novamente, esses endereços IPs irão mudar, isso pode ser um pouco chato e frustrante de se lembrar, principalmente quando você está tentando se conectar a ela.
Então vamos resolver isso criando um IP Fixo.
1- No console AWS Lightsail → Networking
2- Clique em Create Static IP
3- Mantenha a mesma região e zona de disponibilidade da sua instância → escolha a instância recém criada
Em nosso exemplo Norte da Virgínia
e Zona de Disponibilidade A
4- Defina um nome → Create
Conectando via SSH na instância Lightsail
Se você não quiser usar um cliente SSH, pode fazer isso diretamente no console da AWS clicando nesse botão:
Se você estiver usando uma distribuição linux
, como por exemplo ubuntu
, poderia acessar também através do seu terminal com o comando:
ssh -i <LightsailDefaultKey.pem> <user>@<public-ip>
LightsailDefaultKey.pem
é sua chave de acesso baixada do console da AWS, então especifique certinho o caminho da pasta para onde você fez download em sua máquina, também lembre-se que usamos o ubuntu, então mude user
para ubuntu
e <public-ip>
para seu ip fixo criado.# Example
ssh -i LightsailDefaultKey.pem ubuntu@54.160.152.44
Porém como estou usando em meu computador o sistema operacional Windows, eu poderia fazer isso através do WSL2
com Prompt de Comando
, Powershell
ou Terminal do Windows
, o Putty
e muitas outras opções de clientes SSH disponíveis.
Mas prefiro usar o cliente gratuito chamado Termius
, você pode obtê-lo em sua página de download e talvez seja necessário criar uma conta gratuita, há planos pagos disponíveis, mas o gratuito aqui é suficiente.
Também há opções disponíveis para Mac e Linux no final da página;
Não importa qual ferramenta SSH você usará, vimos agora que há muitas opções, tudo que você precisa ter em mente aqui é que você precisa se conectar na instância de alguma forma para seguirmos o tutorial.
1- Acesse o console AWS Lightsail → Account → SSH Keys
2- Procure por Default Keys → download
Norte da Virgínia
, por isso faço download da chave padrão dessa região.3- Abra o cliente SSH (em nosso exemplo Termius) → clique no ícone de engrenagem
4- Defina um nome de sua preferência → mova o arquivo da sua chave keypair que baixou do console AWS
5- Clique em New Host
6- Preencha os campos com:
Address
: o IP da instânciaLabel
: nome de sua preferência
User
: ubuntuSelecione
Key
Clique em Connect
Clique em Continue
Instalando o Docker e Docker Compose
Uma vez conectado na instância, você precisará instalar o Docker
e o Docker Compose
, por favor copie o código de instalação que criamos em outro artigo disponível aqui:
Cole em seu terminal e pressione Enter
.
Aguarde a instalação e ao final você deverá ver algo parecido com:
docker
sejam atualizados.docker in doker (dind)
. Então certifique-se de concluir essa instalação antes de seguir aos próximos passos.Criando um Personal Access Token (PAT)
1- Faça login no console Azure DevOps → ícone de engrenagem → Personal Access Token
2- Clique em New Token
3- Defina:
Um nome de sua preferência, por exemplo
self-hosted-agent-token
Sua organização
Altere o tempo de expiração de acordo com sua preferência, por exemplo gosto de definir o tempo máximo de um ano através da seleção no calendário, mas totalmente opcional
Em
scope
, selecioneCustom definied
→Show all scopes
4- Em Agent Pools
→ selecione Read & manage
→ Create
5- Copie e salve seu token em um local seguro agora
Instalando o Self-Hosted Agent
1- Abra novamente seu terminal → crie o diretório chamado azp-agent-in-docker
com o comando:
mkdir ~/azp-agent-in-docker \
&& cd ~/azp-agent-in-docker
Dockerfile
e start.sh
nesta pasta nos próximos passos, certifique-se que ambos os arquivos estejam na mesma pasta.2- Crie o arquivo Dockerfile com o comando:
touch Dockerfile
3- Insira o seguinte conteúdo em seu Dockerfile:
VSCode
, vim
, nano
, etc. Para nosso exemplo estamos usando o nano
para editar o arquivo.sudo nano Dockerfile
# Use Ubuntu 22.04 as the base image
FROM ubuntu:22.04
# Update package information and upgrade installed packages
RUN apt update && \
apt upgrade -y
# Install dependencies and capabilities
RUN apt install -y \
curl \
git \
jq \
libicu70
# Set the target architecture (e.g., "linux-x64", "linux-arm", "linux-arm64")
ENV TARGETARCH="linux-x64"
# Set the working directory inside the container
WORKDIR /azp/
# Copy the start script to the working directory
COPY ./start.sh ./
# Make the start script executable
RUN chmod +x ./start.sh
# Create a user 'agent' and set ownership of the working directory
RUN useradd agent && \
chown agent ./
# Switch to the 'agent' user
USER agent
# Another option is to run the agent as root.
# ENV AGENT_ALLOW_RUNASROOT="true"
# Define the entry point for the container to execute the start script
ENTRYPOINT ./start.sh
Ctrl + X
+ Y
(para sim) + Enter
para salvarcat Dockerfile
4- Agora crio o arquivo chamado start.sh
com o comando:
touch start.sh
5- Insira o seguinte conteúdo em seu start.sh
:
VSCode
, vim
, nano
, etc. Para nosso exemplo estamos usando o nano
para editar o arquivo.sudo nano 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
cleanup() {
trap "" EXIT
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 "\n${lightcyan}$1${nocolor}\n"
}
# 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
trap "cleanup; exit 0" EXIT
trap "cleanup; exit 130" INT
trap "cleanup; exit 143" TERM
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..."
chmod +x ./run.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.sh "$@" & wait $!
Ctrl + X
+ Y
(para sim) + Enter
para salvarcat start.sh
Dockerfile
e start.sh
criados na mesma pasta azp-agent-in-docker
com o comando:ls -1
6- Agora construo a imagem com o comando:
docker build -t "azp-agent:linux" -f Dockerfile .
docker image ls --format "table {{.ID}}\t{{.Repository}}"
7- Agora vamos precisar de três informações para poder iniciar nosso container:
AZP_URL
:Você pode obtê-la olhando para a barra de endereço do seu navegador:
🔗dev.azure.com<your-organization>
AZP_POOL
:ℹVocê precisa criar um novo em Organization Settings → Agent Pools → Add PoolℹSelecionar o tipoSelf-Hosted
ℹDefinir um nome de sua preferência, por exemploAWS-Lightsail-Self-Hosted-Linux-Docker
→ manter a opçãoAuto-provision this agent pool in all projects
marcado →Create
AZP_TOKEN
:Este é o
Personal Access Token (PAT)
que criamos e copiamos para um local seguro antes.
8- Com essas três informações em mãos, vamos iniciar o container com o seguinte comando:
docker run \
-e AZP_URL="<Your Azure DevOps instance>" \
-e AZP_TOKEN="<Your Personal Access Token>" \
-e AZP_POOL="<Your Agent Pool Name>" \
-e AZP_AGENT_NAME="AWS Lightsail Docker Agent 1" \
--name "azp-agent-1" \
azp-agent:linux
capabilities
com as ferramentas úteis que foram listadas no Dockerfilerestart policy
deste container do agent9- Digite o comando abaixo para atualizar o restart policy
deste container:
<your-container-id>
para o ID de seu container obtido com o comando docker ps -a
por exemplodocker update --restart always <your-container-id>
10- Verifique a inspeção de container com o novo restart policy
definido:
docker inspect -f '{{ json .HostConfig.RestartPolicy }}' <your-container-id>
Usando o Self-Hosted Agent
Se você estiver usando o arquivo azure-pipelines.yml
você pode definir seu Self-Hosted Agent no trecho pool
, por exemplo:
trigger:
- main
pool:
# Name of your agent pool
name: 'AWS-Lightsail-Self-Hosted-Linux-Docker'
jobs:
- job: RunOnSelfHostedAgent
displayName: 'Run on AWS Lightsail Docker Agent'
steps:
- script: echo "Hi, I'm running on AWS Lightsail Docker Agent 1"
displayName: 'Print Message'
Initialize Job
o agente self-hosted agent que criamos sendo usado.docker ps --format "table {{.ID}}\t{{.Names}}" --all
Se você estiver usando o editor classic
, poderá fazer isso selecionando o pool
Bônus - Atualização dos Agents
A qualquer momento, você pode atualizar seus agents em Organization Settings → Agent Pools → More Options (três pontinhos) → Update Agent
Conclusão
Em meio ao dinâmico cenário da automação e integração contínua, o Self-Hosted Agent do Azure DevOps emerge como uma ferramenta poderosa para capacitar equipes de desenvolvimento. Neste artigo, exploramos os diferentes tipos de agents disponíveis, destacando a versatilidade e flexibilidade do Self-Hosted Agent.
Ao conduzir um passo a passo prático, mergulhamos na criação de um Self-Hosted Agent utilizando o Docker. Essa abordagem não apenas oferece controle total sobre o ambiente de execução, mas também demonstra a escalabilidade e eficiência proporcionadas pelo uso de containers.
Vimos que os passos são manuais e você pode repeti-los quantas vezes for necessário. Também pode ainda pensar em uma forma de automatizar e escalar a criação de seus Self-Hosted Agents, mas para a maioria das pessoas isso será o suficiente.
Ao concluir esta jornada, espero que você esteja equipado com os conhecimentos necessários para aproveitar ao máximo o potencial do Self-Hosted Agent no Azure DevOps. A capacidade de personalizar, escalar e integrar-se perfeitamente ao seu ambiente torna esse recurso essencial para otimizar seus fluxos de trabalho de CI/CD.