Deep técnico: GitLab Runners no Kubernetes, instalação do Operator, valores do Helm, autoscaling e o modelo de custos FinOps. Para a versão resumida, leiaPare de pagar por CI ocioso.
A maioria das equipas paga pela integração contínua como se todas as noites e todos os fins de semana fossem ainda segunda-feira de manhã. Os servidores ficam quentes. O disco permanece alocado. Ninguém está a fundir código — e a fatura não nota. Essa frase não é um slogan; é a forma padrão de uma frota fixa de runners.
Este artigo longo é o complemento técnico de um guia prático deGitLab Server e GitLab Runner no Kubernetes: como o executor Kubernetes transforma cada job CI num pod efêmero, como isso permite provisionamento e desprovisionamento dinâmicos de capacidade, e como esse design libertaenormes poupançasao recuperar CPU, RAM e armazenamento quando a demanda colapsa à noite e aos fins de semana.
Assista a ambas as sessões primeiro, depois use esta página como a arquitetura escrita e o modelo de custos.
1. Runners & pipelines— autoscaling de workloads GitLab Runner usando Kubernetes.
Assistir: GitLab Runners completos e CI/CD no Kubernetes· Versão em linguagem simples:Pare de pagar por CI ocioso
2. GitLab Server em HA Kubernetes— implemente o GitLab com o Operator em poucos minutos.
Assista: Implemente o GitLab em cluster HA Kubernetes usando o Operator· Docs:Instalação do GitLab Operator
1. Tese
GitLab no Kubernetes + o executor Kubernetesmuda a unidade de capacidade de CI de "uma máquina que possuímos o mês todo" para "pods (e nós) que alugamos para o trabalho". O gerenciador de runners permanece pequeno e sempre ativo. Os pods de jobs aparecem para uma build e desaparecem depois. Com autoescalamento de cluster, os nós de trabalho seguem a mesma curva. É assim que você protege a produtividade da segunda-feira de manhã e para de pagar preços de segunda-feira de manhã para terça às 03:00 e para sábados calmos.
Em uma linha — a mesma linha do guia para leigos:provisione para o pico, desprovisione para o vale.
2. O hábito caro, declarado como um odor de arquitetura
O CI tradicional costuma parecer uma frota permanente: um conjunto fixo de máquinas de build que ficam ligadas "só por以防". Isso funciona quando o tráfego é estável. Gasta dinheiro quando a demanda é pontual.
- Dia:os desenvolvedores empurram branches, abrem merge requests, executam testes — a demanda dispara.
- Noites e madrugadas:a atividade cai; as máquinas continuam consumindo CPU e RAM.
- Finais de semana:frequentemente quase inativos — mas os volumes de armazenamento e nós de nuvem podem ainda estar reservados e cobrados.
Você não paga por "builds realizados". Você paga por capacidade que existe, independentemente de alguém usá-la ou não. Frota fixa também acumula estado colante: "funciona no runner 3", pacotes desviados, caches que nunca expiram. Pods elásticos não resolvem a disciplina por si sós, mas tornam o clean-slate o padrão.
3. Mapa do sistema
| Camada | Função | Posição típica |
|---|---|---|
| Servidor GitLab | SCM, coordenação CI, registro, UI/API | Kubernetes via GitLab Operator / Helm chart (por exemplo, k3s lab) |
| Gerenciador de Runner | Agente registrado que consulta por trabalhos | Helm lançado em um namespace dedicado (por exemplo,gitlab-runner) |
| Pods de trabalho | Etapas reais de build / teste / empacotamento | Criados por trabalho pelo executor Kubernetes, depois excluídos |
| Serviço DinD opcional | Builds Docker dentro do trabalho | Contêiner de serviço privilegiado ao lado do trabalho |
| Autoscaler de cluster/nó | Adicionar/remover nós de trabalho sob pressão de pod | Cloud ASG, Cluster Autoscaler, Karpenter, ou equivalente |
A analogia do guia básico ainda se aplica nesta camada: o GitLab Runner é o trabalhador; Kubernetes é o despachante que chama trabalhadores apenas quando os pacotes (trabalhos) chegam, depois os manda para casa.
4. Instalando o GitLab no cluster (caminho do operador)
O caminho de treinamento Day 1 instala o GitLab com o operador oficial, de modo que o servidor compartilhe a mesma base Kubernetes dos runners. O vídeo complementarDeploy GitLab in HA Kubernetes cluster using the Operatorpercorre essa instalação em poucos minutos. Pré-requisitos: um cluster com ingress, Helm,kubectl, e cert-manager quando o chart gerencia TLS.
helm repo add gitlab https://charts.gitlab.io
helm repo update
helm install gitlab-operator gitlab/gitlab-operator \
--create-namespace \
--namespace gitlab-system
kubectl -n gitlab-system get deployment gitlab-controller-manager
# Apply the GitLab custom resource (pin chart version in the manifest)
kubectl -n gitlab-system apply -f deploy_gitlab_server.yaml
Formato de exemplo de CR (personalize o domínio e o e-mail do emissor para o seu ambiente):
apiVersion: apps.gitlab.com/v1beta1
kind: GitLab
metadata:
name: gitlab
spec:
chart:
version: "9.2.2"
values:
global:
hosts:
domain: "example.com"
ingress:
configureCertmanager: true
certmanager-issuer:
email: you@example.com
A primeira instalação geralmente leva cerca de 10–15 minutos enquanto o webservice, Sidekiq, bancos de dados e componentes relacionados se estabilizam. Recupere a senha inicial de root do segredo do cluster:
kubectl get secret gitlab-gitlab-initial-root-password -n gitlab-system \
-o jsonpath='{.data.password}' | base64 -d
Referência:GitLab Operator installation(aba Helm nessa página). Visão geral do chart:docs.gitlab.com/charts· guia de instalação:charts installation.
5. GitLab Runner com o executor Kubernetes
Um GitLab Runner é a aplicação que trabalha com o GitLab CI/CD para executar jobs em um pipeline. Com oKubernetes executor, o manager não compila em si mesmo. Para cada job ele:
- Cria um pod (mais containers auxiliares/serviço conforme configurado).
- Transmite os logs de volta ao GitLab.
- Coleta artefatos e status de saída.
- Elimina o pod — devolvendo CPU e RAM ao cluster.
Esse ciclo de criar/executar/eliminar é a primeira alavanca de custo. O trabalho concluído não deve deixar uma máquina aquecida dedicada durante a noite.
5.1 Helm padrão de instalação
Scripts de treinamento criam um namespace, passam um token de registro e podem instalar mais de uma release (por exemplo, runners baseados em alpine e ubuntu) para que os jobs possam selecionar ambientes diferentes. Procedimento oficial:Instale o GitLab Runner com o gráfico Helm; referência de valores:Configure o gráfico Helm do GitLab Runner.
helm upgrade --install --namespace gitlab-runner gitlab-runner-alpine \
-f config-runner-alpine.yaml \
--set serviceAccount.create=true \
gitlab/gitlab-runner \
--create-namespace
Obtenha tokens da interface do GitLab (runners de instância / grupo / projeto) ou de segredos gerenciados pelo operador. Prefira tokens de autenticação modernos de runner; tokens de registro estão sendo depreciados em direção ao GitLab 18.Nunca cometa tokens em produção— scripts de laboratório às vezes contêm placeholders que devem ser substituídos localmente.
5.2 Valores que importam para escala e isolamento
A partir dos templates Workstation (gitlab-runner-values-template.yaml/ geradosconfig-runner-*.yaml):
| Configuração | Por que importa |
|---|---|
concurrent | Número máximo de jobs que este gerenciador executa simultaneamente. Aumente para picos diurnos (notas de treinamento mencionam dezenas, por exemplo, 20–40, em laboratórios ocupados). Throttle suave antes dos limites do cluster. |
runners.privileged/ executorprivileged | Frequentemente necessário para Docker-em-Docker; aperte se não precisa de DinD. |
[runners.kubernetes].namespace | Onde os pods dos jobs são implantados — mantenha separado dos componentes do sistema do GitLab. |
Padrãoimage/ imagem auxiliar | Fixe tags para reprodutibilidade entre pools alpine/ubuntu. |
[[runners.kubernetes.services]]DinD | Sidecardocker:dindpara construção de imagens; configure espelhos de registro / registros inseguros apenas quando necessário. |
RBACclusterWideAccess | Apenas se os jobs devem gerenciar recursos em nível de cluster; prefira menor privilégio em produção. |
| aliases de host / configuração DNS | Conveniência de laboratório para nomes de host do GitLab e do registro dentro do cluster. |
gitlabUrl: http://gitlab-webservice-default.gitlab-system.svc.cluster.local:8080/
concurrent: 2
rbac:
create: true
clusterWideAccess: true
runners:
privileged: true
config: |
[[runners]]
environment = ["GIT_SSL_NO_VERIFY=1"]
[runners.kubernetes]
namespace = "gitlab-runner"
image = "alpine/git:latest"
service_account = "gitlab-runner"
privileged = true
Concorrência sem CPU apenas alonga a fila. Combineconcurrentcom capacidade real dos nós ou autoescalamento de nós.
6. Autoscaling em dois (na verdade quatro) níveis
"Autoscaling GitLab Runners on Kubernetes" não é uma única alavanca. Encadene estas:
- Elasticidade de pods de job— integrada no executor Kubernetes. Zero jobs → zero pods de job. Apenas isso elimina a maior parte do desperdício por job em um cluster compartilhado.
- Runner
concurrente múltiplas Deployments de runner— separe alpine vs ubuntu (ou CPU vs builders maiores) para que capacidade especializada não fique ociosa para a mistura errada. - Autoscaling de cluster/nó— pods pendentes adicionam nós; nós vazios saem após o rush da noite.
- Política opcional consciente de agenda— limites concorrentes menores ou escalonamento de pools de nós em calendário para noites/weekends como reforço adicional sobre o colapso natural da demanda.
Hyperscale é a mesma história com amplitude mais acentuada: expanda para filas profundas e depois desprovisione agressivamente para que a metade tranquila da semana não se assemelhe à metade ocupada na fatura.
6.1 Uma nota sobre "idle" no sentido do GitLab Runner
Alguns executores mantêm um pequeno número de máquinas ociosas aquecidas para absorver o próximo job sem latência de cold-start. No Kubernetes, o cold-start é geralmente criar um pod (segundos), não iniciar uma VM (minutos). Prefira deixar os pods irem a zero e aceitar um atraso de agendamento curto em vez de manter uma turnista de nós vazios "apenas por precaução". Se você precisa aquecer um piso mínimo, dimensione esse piso para a realidade de on-call — não para a tempestade de merges de segunda-feira.
6.2 Provisão e desprovisão dinâmica de ponta a ponta
Rastrear um pipeline de trabalho:
- O desenvolvedor faz push; o GitLab cria um trabalho na fila pendente.
- O gerente de runners assume o trabalho e solicita um pod ao API.
- Se o cluster estiver com escassez de CPU/RAM, o autoscaler adiciona um nó (provisão).
- O pod executa o script, sobe os artefatos e sai.
- O pod é excluído; os recursos retornam ao pool (desprovisão no nível do trabalho).
- Quando muitos nós ficam vazios além do limite de redução de escala — típico após o fim de tarde e todo o fim de semana — os nós saem (desprovisão no nível de infraestrutura).
É esse ciclo completo que o vídeo significa ao falar de GitLab Runners em hiperscale para otimização de custos: não uma única bandeira sofisticada, mas o ciclo de vida do trabalho e a elasticidade do cluster trabalhando juntos.
7. Modelo de custos: onde aparecem grandes economias em dólares
Seja preciso. O autoscaling não torna as compilações gratuitas. Impede que você pague tarifas de pico em horários fora de pico. As economias vêm de alinhar o gasto à demanda real — os quatro pontos do guia simples, expandidos para operadores.
7.1 Escalar apenas quando pessoas (ou bots) estão trabalhando
Quando uma manhã movimentada gera dezenas de pipelines, o Kubernetes agenda muitos pods de trabalho em paralelo, até os limites de concorrência e do cluster. O throughput aparece quando a pressão de merge é real.
7.2 Reduza drasticamente quando a demanda desaparece
Quando os jobs terminam, os pods somem. Com autoescalabilidade de cluster (ou um pool de nós dimensionado corretamente), os nós de nuvem não utilizados saem do pool. Noites e fins de semana — tipicamente as janelas mais tranquilas para equipes de produto — são a primeira capacidade pela qual você deve parar de pagar.
7.3 Pare de desperdiçar CPU, RAM e armazenamento
| Recurso | VMs de runner sempre ativas | Kubernetes job pods + autoescalabilidade de nós |
|---|---|---|
| CPU | Núcleos reservados ociosos enquanto a fila está vazia | Liberados quando os pods saem; nós podem escalar para dentro |
| RAM | SO do agente + executores ociosos residentes 24×7 | Memória retorna com cada exclusão de pod |
| Armazenamento | Discos quentes e camadas de imagem em cada VM | Scratch efêmero por padrão; caches compartilhados tornam-se uma escolha explícita e dimensionada |
Ao longo de um mês, as horas tranquilas dominam o relógio. Recuperar noites e fins de semana é onde aseconomias em dólar se acumulam.
7.4 Pague por resultados, não por móveis
Você ainda paga pelo GitLab e por um plano de controle fino (gerenciador de runners + essenciais do cluster). O que você para de pagar é um armazém de cadeiras vazias.
7.5 Intuição trabalhada (não um benchmark fabricado)
Suponha que o dia útil precisa sustentavelmente de slots equivalentes a 20 executores ocupados, mas noites e fins de semana precisam de 2. Uma frota fixa dimensionada para 20 paga por 20 dia e noite. Um pool elástico paga por ~20 durante o dia e ~2 (mais o plano de controle) quando está calmo. Para muitas equipes de produto, as horas calmas representam uma grande fração do mês — então recuperá-las é como as economias se tornamenormessem inventar uma porcentagem de marketing. Financeiro multiplica preços locais de hora-nó; o trabalho da arquitetura é tornar as horas vazias realmente vazias na conta de faturamento.
Grandes economias de custo aparecem quando o pico da segunda-feira não dita mais a fatura da terça-feira às 3h — e quando o silêncio do sábado finalmente parece calmo na fatura também.
7.6 O que você ainda paga propositalmente
- Componentes do GitLab Server — dimensione para usuários e coordenação de CI, não para a fazenda de compilação.
- Gerenciador de Runner Deployment(s) — pequeno versus fazendas de jobs.
- Caches deliberados (proxy de dependências, PVCs) — úteis, mas dimensionados; caches não são armazenamento gratuito.
- DinD Privilegiado — conveniente e mais pesado; considere Kaniko/BuildKit quando densidade e isolamento importam mais que familiaridade.
8. CI/CD pipelines na prática
Com runners online,.gitlab-ci.ymldefine estágios e jobs. O GitLab agenda; o Kubernetes executor materializa pods. Mantenha os pipelines honestos sobre custo:
- Falhe rápido em lint/unit antes de builds de imagem pesados.
- Use
rules/workflowpara que branches de rascunho não expandam matrizes completas. - Prefira caches compartilhados com chaves claras ao crescimento ilimitado de disco por VM.
- Etiquete jobs para o pool de runner correto (alpine vs ubuntu, builders pequenos vs grandes).
stages: [lint, test, build]
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
lint:
stage: lint
image: alpine:3.19
script:
- echo "cheap checks first"
test:
stage: test
tags: [kubernetes, alpine]
script:
- echo "unit tests"
build:
stage: build
tags: [kubernetes, dind]
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
script:
- echo "heavy image build only on default branch"
A ideia econômica é a mesma da ideia de plataforma: não agende trabalho caro quando uma verificação barata teria falhado, e não mantenha runners especializados aquecidos para jobs que nunca chegam no sábado.
9. Notas de segurança e tenancy
Pods efêmeros melhoram a higiene (menos estado colado), mas DinD privilegiado e RBAC em nível de cluster podem ampliar o raio de explosão. Padrões práticos para a maioria das equipes:
- Execute pods de job em namespace dedicado com ResourceQuotas e LimitRanges.
- Prefira builds não-privilegiados sempre que possível; isole runners DinD atrás de tags específicas.
- Evite montar credenciais de nuvem de longa duração em cada job; injete tokens de curta duração por pipeline.
- Trate tokens de registro de runner como segredos — rote-os quando pessoas saírem ou labs forem compartilhados.
- Se múltiplas equipes compartilharem um cluster, separe gerentes de runner (e opcionalmente pools de nós) para que um vizinho barulhento não mantenha toda a fazenda quente — e mantenha a narrativa de custo atribuível por equipe.
10. Observabilidade que comprova as economias
Você não pode alegar economias de noite e fim de semana sem olhar. Acompanhe pelo menos:
| Sinal | O que "bom" significa |
|---|---|
| Contagem de pods por hora | Picos nas horas úteis de dias úteis; quase zero à noite e nos fins de semana |
| Pods pendentes | Picos apenas brevemente no pico; pendência sustentada indica concorrência/nós subdimensionados |
| Nó CPU / número de nós | Acompanha a demanda de pods; nós vazios não ficam ociosos por horas |
| Gerenciador de runners CPU/RAM | Plano e pequeno em relação ao fazenda de jobs |
| Fatura de nuvem por hora da semana | Períodos calmos visivelmente mais baratos após a migração |
Se a contagem de pods cai à noite mas a fatura de nós não, as configurações de scale-down — não o GitLab — são o próximo ajuste.
11. VMs fixos vs executores Kubernetes (tabela de decisão)
| VMs de runner fixas | Executor Kubernetes + autoescalabilidade | |
|---|---|---|
| Unidade de capacidade | Máquina inteira, sempre alocada | Pod (e opcionalmente nó) por job |
| Picos de segunda-feira | Filas ou compra excessiva de VMs | Aumentar concorrentes + escalar nós |
| Noites / fins de semana | Ainda cobrado se as VMs permanecerem ligadas | Pods removidos; nós podem sair |
| Desperdício de CPU / RAM / armazenamento | Estrutural quando ocioso | Recuperado por padrão |
| Deriva / "funciona no runner 3" | Comum | Reduzido (efêmero por padrão) |
| Complexidade operacional | Menor inicialmente | Maior (requer habilidades de cluster) |
Escolha VMs fixas apenas quando você realmente tem demanda plana 24×7 ou restrições que proíbem um cluster. Todos os outros com pipelines impulsionados por humanos com picos estão pagando o imposto de móveis.
12. O que você não está perdendo
Autoescalabilidade não significa "sem controle". Você ainda define concorrência, imagens permitidas, privilégios DinD, política de rede e escopo de registro. O ponto é manter esses controles enquanto permite que a capacidade não utilizada evapore — a mesma tranquilidade do texto em linguagem simples, agora reforçada com RBAC, namespaces e releases de runner separados.
13. Lista de verificação operacional
- Versões do operador/chart do pin; atualize deliberadamente.
- Rotacione tokens do runner; limpe tokens do laboratório de qualquer script antes de publicar.
- Namespaces separados: GitLab sistema vs jobs do runner.
- Monitorepodspendentes — se os pendentes aumentarem, significa que a concorrência ou a capacidade dos nós está insuficiente no pico.
- Monitorehoras de nó vazio— nós que permanecem ociosos durante a noite indicam atraso no redimensionamento ou necessidade de ajuste da política do pool.
- Limite runners privilegiados a jobs que os necessitem.
- Faça backup do GitLab independentemente da elasticidade do runner.
- Revise a fatura por hora da semana uma vez que o CI elástico esteja em operação — as noites e fins de semana devem diminuir visivelmente.
14. Para quem é isso
- Engenheiros de plataforma e SREs que implementam GitLab CI no Kubernetes.
- Líderes do DevOps que substituem VMs de runner fixas por pods de executor.
- Parceiros de engenharia e finanças que precisam que o CI se comporte como uma utilidade baseada no uso, não como mobília.
15. Documentação oficial do GitLab
Estas páginas são as referências canônicas para as implantações Helm e o comportamento de escalonamento descritos acima. Prefira-as a posts de blog quando as versões mudarem.
Servidor GitLab no Kubernetes
- Instale o Operador GitLab— caminho de instalação do Operador + Helm usado no walkthrough de treinamento.
- Gráficos GitLab Helm— documentação do gráfico guarda-chuva.
- Instale o GitLab com o gráfico Helm— quando você implanta o GitLab via gráficos em vez do Operador.
- subgráfico gitlab-runner (gráfico GitLab)— runner embutido ao lado do GitLab no gráfico principal (diferente do gráfico de runner independente).
Gráfico GitLab Runner Helm
- Instale o GitLab Runner com o gráfico Helm—
helm repo add gitlab, instalar/atualizar, notas do gráfico OCI. - Configure o GitLab Runner Helm—
concurrent, modelos de configuração, RBAC, caches, escolhas de imagem. - gráfico gitlab-runner
values.yaml— valores padrão completos (incluindo stubs opcionais de HPA).
Kubernetes executor e autoscaling
- Kubernetes executor— pods de jobs, helpers, serviços (por exemplo, DinD), solicitações de recursos, verbos RBAC.
- Configure autoscaling (Kubernetes executor / chart)— pause de pods,
[runners.kubernetes.autoscaler], políticas de período (inativo à noite/semana). - Autoscaling do GitLab Runner— modelo geral de autoscaling (também abrange cache distribuído).
- Planeje e gerencie uma frota de GitLab Runner— escalonamento e operações em nível de frota.
- Configuração avançada (
config.toml)— seções globaisconcurrente de executor incorporadas em Helmrunners.config.
Jobs CI, builds e configurações do runner no GitLab
- Configure runners no GitLab— registro, tags, run-untagged, runners protegidos.
- Use Docker para construir imagens no CI— DinD e alternativas (relevante quando
privileged/ serviço Docker está habilitado nos valores do runner).
Para controle de custos à noite e no fim de semana, combine: (1) pods de jobs do Kubernetes executor que vão a zero, (2) chartconcurrente políticas de autoscalercom off-peak, e (3) autoscaling de cluster/nó para que nós vazios saiam do pool — conforme descrito nas seções 6–7.
16. Mapeando de volta ao vídeo e ao repositório
A sessão do YouTube —GitLab completo em ~20 minutos. Escalonamento automático de workloads do GitLab Runner usando Kubernetes— demonstra o GitLab no Kubernetes, runners via Helm, e a narrativa de custos em escala hiper: provisionar e desprovisionar infraestrutura dinamicamente para que você não pague tarifas de pico em noites e fins de semana ociosos. Use o prompt de construção do cursogitlab-runners-k3s-hyperscale-course.prompt.mdneste repositório, com os documentos oficiais acima como a fonte da verdade versionada. Para a formulação não técnica das mesmas ideias, vejaPare de pagar por CI ocioso.
Encerramento
O Kubernetes não apenas hospeda runners do GitLab. Usado corretamente, ele muda a economia do CI:provisionar sob demanda, desprovisionar em ociosidade, recuperar CPU/RAM/armazenamento quando os humanos vão para casa. Esse é o padrão de escala hiper — disponível para qualquer equipe disposta a trocar uma frota permanente por uma fila de pods.
Comece com o vídeo, configure o operador + runner Helm em um laboratório, ative o escalonamento automático de nós e, em seguida, verifique se o sábado finalmente parece tranquilo na fatura.
Publicado porWorkstation.