Dominando a Otimização de Executores Jenkins para Builds Mais Rápidos
Otimize o desempenho da sua CI/CD dominando a configuração de executores Jenkins. Este guia especializado explica como calcular o número ideal de executores com base em restrições de CPU e E/S, reduzindo o tempo de fila de builds e maximizando a taxa de transferência dos agentes. Aprenda estratégias essenciais de configuração, incluindo o uso de paralelismo em Pipelines, gerenciamento de agentes estáticos vs. dinâmicos e identificação de gargalos usando métricas-chave como tamanho da fila e espera de E/S. Implemente estas etapas práticas para obter builds mais rápidos e um ambiente Jenkins mais eficiente.
Dominando a Otimização de Executores Jenkins para Builds Mais Rápidos
A otimização de executores Jenkins é, na verdade, planejamento de capacidade em pequenas peças. Um executor é um slot onde o Jenkins pode executar trabalho em um nó. Adicione poucos slots e os trabalhos esperam na fila. Adicione muitos e cada build disputa por CPU, memória, disco, rede e, às vezes, o mesmo cache de dependências.
O objetivo não é "mais executores". O objetivo é um tempo total de feedback mais curto, sem tornar os builds individuais instáveis.
Mantenha executores do controlador em zero
Para a maioria das instalações modernas do Jenkins, o controlador deve agendar trabalho, servir a interface do usuário, armazenar a configuração do trabalho e coordenar agentes. Ele não deve compilar código ou executar suítes de teste.
Defina os executores do controlador como 0, a menos que você tenha um trabalho administrativo pequeno e deliberado que deva ser executado lá. Um build ocupado no controlador pode prejudicar a interface do usuário, atrasar o agendamento da fila e tornar os problemas de plugins mais difíceis de diagnosticar. Se o controlador se tornar instável, todas as equipes que usam Jenkins sentirão o impacto.
Mova o trabalho de build para agentes com rótulos claros:
linux && docker
linux && maven
windows && visualstudio
large-memory
Os rótulos fazem parte da otimização de executores porque um trabalho aguardando linux && docker não se importa que você tenha executores Windows ociosos.
Comece pelo tipo de carga de trabalho, não por uma fórmula universal
Para builds com uso intensivo de CPU, comece próximo ao número de núcleos de CPU físicos ou virtuais. Uma VM de build de 8 núcleos executando compilação C++ ou grandes suítes de teste Java pode começar com 6 a 8 executores e depois ajustar para cima ou para baixo com base nas medições.
Para builds com uso intensivo de E/S, você pode executar mais executores do que núcleos de CPU porque os trabalhos passam tempo esperando por downloads de rede, uploads de artefatos ou serviços de teste. Um agente de 8 núcleos com muitas dependências pode lidar bem com 10 a 12 executores. Também pode colapsar com 6 se o disco for lento ou a memória for escassa.
A memória geralmente define o limite real. Se cada build pode usar 2 GB de RAM e o agente tem 16 GB, oito executores não deixam espaço para o SO, daemon Docker, runtimes de linguagem, testes de navegador ou cache do sistema de arquivos. Nesse caso, quatro ou cinco executores podem ser mais rápidos que oito porque a máquina evita a troca (swap).
Use uma planilha como esta:
RAM do agente: 32 GB
reserva para SO e daemons: 4 GB
utilizável para builds: 28 GB
pico típico do build: 3 GB
executores iniciais: 8 ou 9, depois valide sob carga
Os números não precisam ser perfeitos. Eles precisam ser explícitos o suficiente para que você possa ajustá-los após observar builds reais.
Observe os motivos da fila
A fila de builds do Jenkins informa por que o trabalho está esperando. "Aguardando o próximo executor disponível" é diferente de "Não há nós com o rótulo." O primeiro sugere pressão de capacidade. O segundo sugere problemas de provisionamento de rótulo ou agente.
Quando os desenvolvedores reclamam que o Jenkins está lento, verifique:
- Tamanho da fila por rótulo.
- Tempo médio de espera na fila.
- Rotatividade de agentes online/offline.
- Builds presos esperando por recursos bloqueados.
- Estágios de pipeline paralelos consumindo mais executores do que o esperado.
Um único pipeline com dez ramos paralelos pode consumir dez slots de executor. Isso pode ser exatamente o que você deseja para uma matriz de teste. Também pode prejudicar todos os outros trabalhos em uma instalação pequena do Jenkins.
Use um executor por agente descartável
Para agentes Kubernetes e muitos agentes criados em nuvem, um executor por pod ou instância geralmente é o modelo mais limpo. O pod é a unidade de isolamento. Se você precisar de mais concorrência, crie mais pods em vez de empacotar builds não relacionados no mesmo espaço de trabalho descartável.
Esse modelo torna as solicitações de recursos importantes:
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
memory: "6Gi"
Se as solicitações forem muito baixas, o Kubernetes pode empacotar muitos agentes Jenkins em um único nó. O Jenkins vê executores disponíveis, mas o nó do cluster está sobrecarregado. Se os limites forem muito restritos, os builds falham com erros de memória que parecem problemas de aplicação.
Para agentes VM estáticos, vários executores podem ser adequados. Apenas mantenha o layout do espaço de trabalho, diretórios de cache e instalações de ferramentas projetados para trabalhos simultâneos.
Limite os trabalhos ruidosos
Alguns trabalhos não devem executar tantas cópias quanto o Jenkins pode agendar. Testes de integração de banco de dados, testes de navegador, testes de carga e builds de imagem podem saturar rapidamente sistemas compartilhados.
Use limitação em nível de trabalho, recursos bloqueáveis ou controles de pipeline:
pipeline {
agent { label 'linux && docker' }
options {
disableConcurrentBuilds()
}
stages {
stage('Build Image') {
steps {
sh 'docker build -t app:${BUILD_NUMBER} .'
}
}
}
}
Para um banco de dados de staging compartilhado, um bloqueio é mais claro:
lock('staging-db') {
sh './run-integration-tests.sh'
}
Isso pode fazer com que um trabalho espere, mas evita que cinco trabalhos falhem juntos e desperdicem todo o tempo de seus executores.
Meça o agente, não apenas o Jenkins
O Jenkins pode informar sobre o tempo de fila e o uso do executor. O sistema operacional informa se a contagem de executores é razoável.
Em agentes Linux, verifique:
uptime
mpstat 1
iostat -xz 1
free -h
df -h
docker system df
CPU alta com baixa espera de E/S significa trabalho vinculado à CPU. Espera de E/S alta significa que adicionar executores provavelmente tornará os builds mais lentos. O uso de swap durante os builds é um forte sinal para reduzir executores ou aumentar a memória. Um disco quase cheio pode fazer com que checkout, arquivamento e builds Docker se arrastem.
Observe também a duração individual do build. Se o tempo de fila cair um minuto, mas cada build se tornar cinco minutos mais lento, a contagem maior de executores não é uma vitória.
Ajuste em pequenas mudanças
Altere as contagens de executores gradualmente. Mova um agente de 4 para 6, observe por alguns dias movimentados e depois decida. Grandes saltos escondem a causa das regressões.
Mantenha anotações:
2026-05-24: linux-build-03 executores 4 -> 6
Motivo: fila para linux && maven com média de 12 minutos
Observar: CPU, iowait, contenção de bloqueio de cache Maven, duração do build
Reverter: definir para 4 se a duração do build no p95 aumentar mais do que o esperado
Esse registro curto ajuda quando alguém pergunta por que o agente está lento duas semanas depois.
O alvo prático
Uma configuração saudável do Jenkins tem a maioria dos agentes ocupados durante os períodos de pico, filas curtas para rótulos comuns, sem swap, duração de build previsível e nenhum build no controlador. Também tem capacidade suficiente específica por rótulo para que a falta de um agente Docker não deixe trabalhos Maven não relacionados esperando.
A otimização de executores não é uma configuração única. Ela muda quando suas equipes adicionam estágios paralelos, migram para suítes de teste maiores, adotam builds Docker ou migram de VMs estáticas para agentes Kubernetes. Revise-a quando o tempo de fila se tornar visível, quando os agentes começarem a fazer swap ou quando a correção mais rápida que as pessoas sugerirem for "apenas adicione mais executores". Às vezes isso está correto. Frequentemente, a melhor correção é um novo pool de agentes, melhores rótulos ou menos cópias simultâneas do trabalho que prejudica todos os outros.
Estágios paralelos precisam de um orçamento
O paralelismo de Pipeline pode ser uma grande vantagem, mas gasta executores rapidamente. Um build de matriz em quatro versões Java e três sistemas operacionais pode criar doze ramos. Se cada ramo for executado em um agente separado, esse único build pode consumir doze executores antes mesmo de os estágios de implantação começarem.
Isso é aceitável quando a equipe planejou para isso. É doloroso quando uma única solicitação de pull prejudica os builds de lançamento. Coloque limites em torno de trabalhos com grande fan-out:
options {
parallelsAlwaysFailFast()
}
Use rótulos que enviem ramos caros para o pool certo e considere executar a matriz completa no branch principal enquanto executa uma matriz menor em solicitações de pull. O objetivo é feedback rápido onde importa, não concorrência máxima em todos os lugares.
Separe expectativas interativas e em lote
Nem todo trabalho Jenkins merece o mesmo alvo de fila. Um build de hotfix de produção, um trabalho de validação de solicitação de pull, uma varredura de segurança noturna e um trabalho de limpeza semanal podem ser executados no Jenkins, mas não devem competir igualmente.
Você pode separá-los com rótulos, períodos de silêncio, limitadores e janelas agendadas. Trabalhos noturnos pesados devem ser executados quando o tráfego de PR interativo é baixo. Testes de carga de longa duração devem ter seus próprios agentes. Trabalhos de lançamento podem merecer capacidade reservada ou um rótulo que trabalhos de branch comuns não podem usar.
Isso é menos sobre política e mais sobre confiabilidade. Se cada carga de trabalho compartilha um pool de executores, a carga de trabalho mais ruidosa define a experiência para todos.
O que documentar
Para cada pool de agentes, mantenha um pequeno registro:
rótulo: linux && docker
tipo de agente: VM estática
executores por agente: 4
cargas de trabalho principais: builds de imagem Docker, testes de integração
limites conhecidos: E/S de disco e crescimento de camadas Docker
limpeza: docker prune noturno, limpeza do espaço de trabalho após o build
proprietário: equipe de plataforma
Esse registro torna o ajuste futuro muito mais fácil. Quando o tempo de fila crescer, você pode decidir se adiciona mais agentes do mesmo tipo, divide uma carga de trabalho em um novo pool ou reduz a concorrência nos trabalhos que estão causando contenção.