Como criar um Self-Hosted Runner do Bitbucket

SimplesCloudSimplesCloud
14 min read

Introdução

Em um cenário de desenvolvimento ágil e integração contínua, a flexibilidade é importante. É nesse contexto que os Self-Hosted Runners do Bitbucket 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 Bitbucket Runner Auto Hospedado. 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 Runners do Bitbucket

O Bitbucket oferece flexibilidade na execução de pipelines de CI/CD através de dois tipos de Runners:

  • Shared

  • Self-Hosted

Shared Runner:

  • Gerenciado pela Nuvem: Você não precisa hospedar ou gerenciar nenhum servidor. O runner compartilhado é gerenciado e hospedado pelo Bitbucket na nuvem.

  • Pronto para Uso: É uma opção pronta para uso, eliminando a necessidade de configurações adicionais.

  • Ideal para Projetos Menores: Adequado para projetos menores e equipes que buscam uma solução rápida e eficiente sem a necessidade de manutenção direta.

  • Cobrança: Oferece um limite de minutos de execução no plano gratuito com possibilidade de realizar upgrades.

Self-Hosted Runner:

  • Controle Total: Você precisa hospedar ou gerenciar o servidor. O runner 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 Bitbucket.


Neste artigo, nos concentraremos no Self-Hosted Runner, ainda há vários tipos de instalação como por exemplo em Windows, Linux e Docker, nos concentraremos também na instalação em Docker para proporcionar maior isolamento e portabilidade.

Nível do Workspace

Se você for um administrador do espaço de trabalho, poderá configurar e gerenciar vários runners para toda a sua conta para que possam ser usados ​​em pipelines em qualquer repositório no espaço de trabalho. Isso torna mais fácil e economiza tempo na criação e gerenciamento de seus runners quando você tem muitos repositórios em seu espaço de trabalho.


Nível do Repositório

Você opcionalmente pode configurar e gerenciar runners para determinados repositórios, limitando seu uso em toda a organização, porém isso pode demandar mais tempo de administração sua.

Prefiro configurar em nível do workspace, isso torna o runner disponível para todos os repositórios e ajuda na administração, manutenção e gerenciamento. Para nosso tutorial prático, configuraremos um runner a nível de workspace.

Benefícios do Self-Hosted Runner

  • Configurações de build personalizadas: os runners 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 Bitbucket com shared runners, 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 runners auto hospedados na mesma rede fornecendo acesso necessário aos serviços internos.

  • Fluxos de trabalho híbridos: você pode otimizar seus recursos usando runners auto hospedados com configurações personalizadas para builds que exigem isso e usar a infraestrutura do Bitbucket com shared runners para outros trabalhos.


Todo esse contexto é interessante, mas talvez seu principal motivo seja resolver esse aviso em sua conta Bitbucket:

Your account has run out of build minutes. View plan details.

Se você atingir o limite mensal do plano gratuito, receberá esse aviso e ficará incapaz de continuar usando os shared runners até o próximo mês, você pode resolver isso realizando um upgrade de conta ou usando seu próprio runner, e sim, se você usar seu próprio runner você também terá os custos relacionados a isso, mas considerando que você pode cria-lo no seu mesmo ambiente e que pode obter minutos ilimitados (pois ele é seu), talvez faça sentido considerar esse custo ao invés do custo de upgrade de conta no Bitbucket, você deve colocar na balança o melhor custo-benefício e decidir pela melhor escolha no seu cenário.


Tutorial Prático - Pré-Requisitos

Para a instalação de um Runner auto hospedado do Bitbucket, 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.

Para o tutorial deste artigo, usaremos uma instância do AWS Lightsail, pois seu pacote de instância + tráfego de rede é ofertado a um preço mais acessível. Mas novamente você pode escolher de acordo com sua preferência como AWS EC2, Google Compute Engine, Digital Ocean, Vultr, Linode, etc.
💡
Se você já é mais experiente, ou se não deseja usar o Lightsail, você pode ignorar as etapas abaixo de criação de instância, criação de IP fixo e conexão SSH, não importa qual VPS você criou. Você pode pular diretamente para etapa de configuração dentro da instância e encurtar seu caminho deste artigo, mas se você é mais iniciante ou se está um pouco confuso nesse momento, recomendo seguir todos os passos.

Criando uma instância Lightsail

1- Acesse o console AWS → Lightsail → Create Instance

2- Escolha a região

Em nosso exemplo escolhi a região Norte da Virgínia e a Zona de Disponibilidade A

3- Escolha o sistema operacional

Nem todos os sistemas operacionais são suportados, então escolhi a opção Ubuntu 22.04 que é a mais recente no momento da criação deste artigo

4- 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

Lembre-se que essa decisão é muito importante, quanto menor a instância você escolher, mais lentidão e problemas seu pipeline pode ter por conta de falta de memória ou cpu. Para nosso artigo escolhi a opção small de USD 10 com 2GB de memória, 2 vCPU e 3TB de transferência de dados.
Em minhas experiências, as instâncias abaixo de 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

Pronto! Nesse momento, você já tem uma instância criada com sucesso.

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

Pronto! Agora já temos um IP Fixo anexado a nossa instância Lightsail

Conectando via SSH na instância Lightsail

Você pode fazer isso de muitas formas, com qualquer cliente SSH de sua preferência.

Se você não quiser usar um cliente SSH, pode fazer isso diretamente no console da AWS clicando nesse botão:

E isso irá abrir uma nova janela com seu acesso com sucesso:

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>
Lembre-se que 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.
💡
Para nosso exemplo isso seria:
# Example
ssh -i LightsailDefaultKey.pem ubuntu@44.198.68.63

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.

Importante ressaltar que a escolha do seu cliente SSH é totalmente opcional.

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.


Como acabamos de ver, vou utilizar o cliente SSH Termius, então nossos prints irão se basear nisso, mas uma vez que você estiver conectado, os comandos serão todos iguais independente de qual ferramenta usou.

1- Acesse o console AWS Lightsail → Account → SSH Keys

2- Procure por Default Keys → download

Lembre-se que estou usando 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ância

  • Label: nome de sua preferência

  • User: ubuntu

  • Selecione Key

Clique em Connect

Clique em Continue

Pronto! Você está conectado.

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:

Agora feche e abra seu terminal novamente para que os comandos docker sejam atualizados.
Essa instalação é muito importante, pois precisaremos dela mais a frente para a instalação do self-hosted, além disso muito provavelmente seu runner precisará do docker para baixar e construir imagens em seu pipeline através do docker in doker (dind). Então certifique-se de concluir essa instalação antes de seguir aos próximos passos.
Pronto! Você está com todos os pré-requisitos deste tutorial concluídos.

Adicionando um Self-Hosted Runner do Bitbucket

1- Acesse sua conta Bitbucket → ícone de engrenagem → Workspace Settings

Lembre-se que comentamos que criaremos o runner a nível do workspace para disponibilizar para todos os repositórios. Mas se você preferir criar somente para o repositório você precisa entrar nas configurações do repositório e em runner, após isso todos os passos são exatamente iguais.

2- Clique em Workspace runners → Add runner

3- Escolha Linux Docker (x86_64)

Há várias opções disponíveis, mas vamos nos concentrar em Linux Docker, isso nos dará mais liberdade e flexibilidade para executar qualquer coisa nele.

4- Defina um nome de sua preferência → crie um label

O label que você criar, é o que será usado de fato no arquivo bitbucket-pipelines.yml . Observe que para nosso tutorial prático o label foi definido como lightsail1

💡
Você pode definir quantos labels quiser de sua preferência

5- Clique em Next → e ele fornecerá uma saída de comando como a seguinte

Algumas informações foram omitidas por questões de segurança
docker container run -it \
-v /tmp:/tmp -v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/docker/containers:/var/lib/docker/containers:ro \
-e ACCOUNT_UUID={xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} \
-e REPOSITORY_UUID={xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} \
-e RUNNER_UUID={xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} \
-e RUNTIME_PREREQUISITES_ENABLED=true \
-e OAUTH_CLIENT_ID=xxxxxxxxxxxxxxxx \
-e OAUTH_CLIENT_SECRET=xxxxxxxxxxxxxxxxxx \
-e WORKING_DIRECTORY=/tmp --name runner-xxxxxxxxxxxxxxxxxx docker-public.packages.atlassian.com/sox/atlassian/bitbucket-pipelines-runner:1
Copie o código gerado

6- Cole em seu terminal SSH → Enter

Ao final você verá algo parecido com:

7- Feche seu terminal SSH → retorne para sua conta Bitbucket

8- Abra novamente seu terminal → obtenha o ID do container do seu runner com o comando:

docker ps --format 'table {{.ID}}\t{{.Names}}\t{{.Status}}'

💡
Por padrão, se desligarmos a instância por qualquer motivo, o container do runner não será iniciado automaticamente, então vamos garantir que o runner sempre esteja up mesmo que você reinicie sua instância.

9- Digite o comando abaixo para atualizar o restart policy deste container:

Lembre-se de alterar <your-container-id> para o ID de seu container obtido no passo acima
docker 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>

Pronto! Seu runner auto hospedado já está online e pronto para uso.

Use o Self-Hosted Runner do Bitbucket

Para usar seu Self-Hosted Runner criado, você deve definir o seguinte trecho em seu arquivo bitbucket-pipelines.yml:

runs-on:
  - "lightsail1"
Lembrando que "lightsail1" foi o nosso label que definimos em nosso tutorial, ajuste isso para seu valor real que está usando.

Vamos para um exemplo:

1- Crie um arquivo bitbucket-pipelines.yml na raíz do seu repositório, por exemplo:

definitions:

  hello_my_self_hosted_runner: &hello_my_self_hosted_runner
    name: Hi
    image: atlassian/default-image:4
    services:
      - docker
    runs-on:
      - "lightsail1"
    script:
      - echo "Hello, I'm running on Bitbucket's Self-Hosted Runner"

pipelines:

  branches:

    main:
      - stage:
          name: Production
          deployment: production
          steps:
            - step: *hello_my_self_hosted_runner
Observe o trecho runs-on

É aqui que estamos definindo para rodar somente no nosso runner criado com este label.
E então podemos verificar sua saída com sucesso

Pronto! Você agora tem um runner próprio executando seu pipeline.

Bônus - Segurança

Se você utilizar uma conexão entre Bitbucket e AWS com OpenID Connect, descrevemos o passo a passo de como fazer isso aqui:

Você pode aumentar ainda mais a sua segurança limitando o acesso apenas a este Self-Hosted Runner com o trecho SourceIp da seguinte forma:

{
  "Effect": "Allow",
  "Principal": {
    "Federated": "arn:aws:iam::{AWS_ACCOUNT_NUMBER}:oidc-provider/api.bitbucket.org/2.0/workspaces/{WORKSPACE}/pipelines-config/identity/oidc"
  },
  "Action": "sts:AssumeRoleWithWebIdentity",
  "Condition": {
    "StringLike": {
      "api.bitbucket.org/2.0/workspaces/{WORKSPACE}/pipelines-config/identity/oidc:sub": "{REPO_UUID}:*"
    },
    "IpAddress": {
      "aws:SourceIp": [
        "<your-runner-ip>"
      ]
    }
  }
}

Highlights editing your role trust relationship to limit tokens with IP ranges sub claim

Desta forma, somente seu runner é capaz de acessar, aumentando ainda mais sua segurança.

Limites de Uso

O Self-Hosted Runner tem os seguintes limites de uso:

  • Máximo de memória disponível: você pode configurar até 32 GB (8x) de memória

  • Número total de runners: você pode configurar até 100 runners por workspace e 100 runners por repositório

  • Tempo de fila dos steps: os steps podem ficar na fila por no máximo 2,5 horas


Conclusão

Em resumo, a escolha entre um Shared Runner e um Self-Hosted Runner no Bitbucket Pipelines depende das necessidades específicas do seu projeto. O Shared Runner oferece praticidade para projetos menores, enquanto o Self-Hosted Runner proporciona controle total, personalização e eficiência em ambientes mais complexos.

Vimos em um tutorial prático o passo a passo de como criar um Self-Hosted Runner hospedado na AWS. Também vimos que é possível limitar a segurança para um IP específico para que você tenha certeza de estar usando somente seu runner.

Se você observar bem, todo o processo ainda é manual e você pode repeti-lo quantas vezes precisar. Você ainda pode pensar em uma solução automática para lançar seus runners e escalar eles, mas para a grande maioria esse procedimento manual será suficiente.

Ao entender os benefícios do Self-Hosted Runner, como controle total do ambiente, personalização flexível e integração com recursos internos, você pode tomar decisões mais informadas para otimizar seus processos de CI/CD. Escolha o tipo de Runner que se alinha melhor com os requisitos únicos do seu projeto, garantindo uma implementação eficaz e adaptada ao seu ambiente de desenvolvimento.

Lembre-se de excluir todos os recursos ao final para não obter cobranças indesejadas e manter sua conta AWS limpa e organizada.
Espero que as informações tenham sido úteis para você!
0
Subscribe to my newsletter

Read articles from SimplesCloud directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

SimplesCloud
SimplesCloud