Inmersión técnica profunda: GitLab Runners en Kubernetes, instalación del operador, valores de Helm, escalado automático y el modelo de costos FinOps. Para la versión corta, leeDeja de pagar por CI inactivo.
La mayoría de los equipos pagan por la integración continua como si cada noche y cada fin de semana fuera todavía lunes por la mañana. Los servidores permanecen calientes. El disco sigue asignado. Nadie está fusionando código — y la factura no se da cuenta. Esa frase no es un eslogan; es la forma predeterminada de una flota fija de runners.
Este artículo largo es el compañero técnico de una guía práctica deGitLab Server y GitLab Runner en Kubernetes: cómo el ejecutor Kubernetes convierte cada trabajo CI en un pod efímero, cómo eso habilita la provisión y desprovisión dinámica de capacidad, y cómo ese diseño desbloqueaenormes ahorros de costosal recuperar CPU, RAM y almacenamiento cuando la demanda colapsa de noche y los fines de semana.
Mira ambas sesiones primero, luego usa esta página como la arquitectura escrita y el modelo de costos.
1. Runners & pipelines— escalado automático de cargas de trabajo GitLab Runner usando Kubernetes.
Ver: GitLab Runners completos y CI/CD en Kubernetes· Versión en lenguaje sencillo:Deja de pagar por CI inactivo
2. GitLab Server en HA Kubernetes— implementa GitLab con el Operator en unos minutos.
Ver: Implementa GitLab en un cluster HA Kubernetes usando el Operator· Docs:Instalación del GitLab Operator
1. Tesis
GitLab en Kubernetes + el executor Kubernetescambia la unidad de capacidad de CI de "una máquina que poseemos todo el mes" a "pods (y nodos) que alquilamos para el trabajo". El gestor de runners se mantiene pequeño y siempre activo. Los pods de trabajo aparecen para una compilación y desaparecen después. Con el escalado automático del cluster, los nodos de trabajo siguen la misma curva. Así es como proteges el rendimiento de la mañana de lunes y dejas de pagar precios de la mañana de lunes para el martes a las 03:00 y para los sábados tranquilos.
En una línea — la misma línea que la guía para principiantes:provisiona para el pico, desprovisiona para el valle.
2. El hábito costoso, declarado como un olor a arquitectura
La CI tradicional suele parecer una flota permanente: un conjunto fijo de máquinas de compilación que permanecen encendidas «por si acaso». Eso funciona cuando el tráfico es estable. Gasta dinero cuando la demanda es irregular.
- Día:los desarrolladores empujan ramas, abren solicitudes de fusión y ejecutan pruebas — la demanda se dispara.
- Tardes y noches:la actividad disminuye; las máquinas siguen consumiendo CPU y RAM.
- Fin de semana:a menudo casi inactivo — sin embargo, los volúmenes de almacenamiento y los nodos de nube pueden seguir reservados y facturados.
No estás pagando por «compilaciones realizadas». Estás pagando por capacidad que existe, independientemente de que alguien la use o no. Las flotas fijas también acumulan estado pegajoso: «funciona en el runner 3», paquetes desviados, cachés que nunca expiran. Los pods elásticos no resuelven la disciplina por sí solos, pero hacen que la hoja en blanco sea la opción predeterminada.
3. Mapa del sistema
| Capa | Rol | Ubicación típica |
|---|---|---|
| Servidor GitLab | SCM, coordinación CI, registro, interfaz API | Kubernetes a través de GitLab Operator / gráfico Helm (por ejemplo, k3s lab) |
| Gestor de runners | Agente registrado que consulta trabajos | Lanzamiento Helm en un namespace dedicado (por ejemplo,gitlab-runner) |
| Pods de trabajos | Pasos reales de compilación / prueba / empaquetado | Creados por cada trabajo por el ejecutor Kubernetes, luego eliminados |
| Servicio DinD opcional | Compilaciones Docker dentro del trabajo | Contenedor de servicio con privilegios junto al trabajo |
| Autoscaler de clúster / nodo | Añadir/eliminar nodos de trabajo bajo presión de pods | ASG de nube, Cluster Autoscaler, Karpenter, o equivalente |
La analogía de la guía básica sigue siendo válida en esta capa: GitLab Runner es el trabajador; Kubernetes es el despachador que llama a los trabajadores solo cuando llegan los paquetes (trabajos), y luego los envía a casa.
4. Instalación de GitLab en el clúster (ruta del operador)
La ruta de formación Day 1 instala GitLab con el operador oficial, por lo que el servidor comparte la misma base Kubernetes que los runners. El vídeo complementarioDespliegue de GitLab en un clúster Kubernetes con alta disponibilidad usando el Operadorrecorre esa instalación en unos minutos. Requisitos previos: un clúster con ingress, Helm,kubectl, y cert-manager cuando el chart gestiona 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
Ejemplo de forma de CR (personaliza el dominio y el correo del emisor para tu entorno):
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
La primera instalación suele tardar entre 10 y 15 minutos mientras el webservice, Sidekiq, las bases de datos y los componentes relacionados se estabilizan. Recupera la contraseña raíz inicial desde el secret del clúster:
kubectl get secret gitlab-gitlab-initial-root-password -n gitlab-system \
-o jsonpath='{.data.password}' | base64 -d
Referencia:Instalación del Operador GitLab(pestaña Helm en esa página). Resumen del chart:docs.gitlab.com/charts· guía de instalación:instalación de charts.
5. GitLab Runner con el executor Kubernetes
Un GitLab Runner es la aplicación que colabora con GitLab CI/CD para ejecutar trabajos en una pipeline. Con elexecutor Kubernetes, el manager no compila en sí mismo. Para cada trabajo:
- Crea un pod (más contenedores de servicio/auxiliares según la configuración).
- Envía los registros de vuelta a GitLab.
- Recoge los artefactos y el estado de salida.
- Elimina el pod — devolviendo CPU y RAM al clúster.
Ese ciclo de crear/ejecutar/eliminar es el primer palanca de coste. El trabajo terminado no debe dejar una máquina caliente dedicada toda la noche.
5.1 Helm patrón de instalación
Los scripts de entrenamiento crean un namespace, pasan un token de registro y pueden instalar más de una versión (por ejemplo, runners basados en alpine y ubuntu) para que los trabajos puedan seleccionar diferentes entornos. Procedimiento oficial:Instalar GitLab Runner con el gráfico Helm; referencia de valores:Configurar el gráfico GitLab Runner Helm.
helm upgrade --install --namespace gitlab-runner gitlab-runner-alpine \
-f config-runner-alpine.yaml \
--set serviceAccount.create=true \
gitlab/gitlab-runner \
--create-namespace
Obtener tokens desde la interfaz de GitLab (ejecutores de instancia / grupo / proyecto) o desde secretos gestionados por el operador. Prefiera tokens de autenticación modernos de ejecutores; los tokens de registro están obsoletos hacia GitLab 18.Nunca comprometa tokens en vivo— los scripts de laboratorio a veces contienen marcadores de posición que deben reemplazarse localmente.
5.2 Valores que importan para la escala y el aislamiento
Desde las plantillas Workstation (gitlab-runner-values-template.yaml/ generadoconfig-runner-*.yaml):
| Configuración | Por qué importa |
|---|---|
concurrent | Máximo de trabajos que este gestor ejecuta simultáneamente. Aumentar para picos diurnos (las notas de entrenamiento mencionan decenas, por ejemplo 20–40, en laboratorios ocupados). Amortiguador suave antes de los límites del clúster. |
runners.privileged/ executorprivileged | A menudo necesario para Docker-en-Docker; endurecer si no necesitas DinD. |
[runners.kubernetes].namespace | Donde aterrizan los pods de trabajo — mantener separado de los componentes del sistema de GitLab. |
Por defectoimage/ imagen auxiliar | Fijar etiquetas para reproducibilidad entre pools alpine/ubuntu. |
[[runners.kubernetes.services]]DinD | Sidecardocker:dindpara la construcción de imágenes; configurar espejos de registro / registros inseguros solo según sea necesario. |
RBACclusterWideAccess | Solo si los trabajos deben gestionar recursos a nivel de clúster; preferir el mínimo privilegio en producción. |
| alias de host / configuración DNS | Conveniencia en laboratorio para nombres de host de GitLab y registro dentro del clúster. |
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
La concurrencia sin CPU solo alarga la cola. Combinarconcurrentcon margen real de nodos o escalado automático de nodos.
6. Autoscaling en dos niveles (realmente cuatro)
"Autoscaling GitLab Runners on Kubernetes" no es un solo interruptor. Apila estos controles:
- Elasticidad de pods de trabajo— integrada en el ejecutor Kubernetes. Cero trabajos → cero pods de trabajo. Solo esto elimina la mayor parte del desperdicio por trabajo en un clúster compartido.
- Runner
concurrenty múltiples Deployments de runners— separa alpine vs ubuntu (o CPU vs constructores más grandes) para que la capacidad especializada no se mantenga inactiva por una mezcla incorrecta. - Autoscaling de clúster/nodos— los pods pendientes añaden nodos; los nodos vacíos se retiran después del ajetreo nocturno.
- Política opcional con conciencia del horario— límites concurrentes más bajos o escalado de pools de nodos según el calendario para noches/fin de semana como medida de seguridad adicional sobre el colapso natural de la demanda.
El hyperscale cuenta la misma historia con una amplitud más aguda: expande para colas profundas y luego desprovisiona agresivamente para que la mitad tranquila de la semana no parezca la mitad ocupada en la factura.
6.1 Una nota sobre "inactivo" en el sentido de GitLab Runner
Algunos ejecutores mantienen un número pequeño de máquinas inactivas calientes para absorber el siguiente trabajo sin latencia de arranque en frío. En Kubernetes, el arranque en frío suele ser crear un pod (segundos), no arrancar una VM (minutos). Prefiere dejar que los pods lleguen a cero y aceptar un ligero retraso en la programación antes que mantener un turno nocturno de nodos vacíos "por si acaso". Si debes mantener un mínimo calientito, dimensiona ese mínimo según la realidad del guardia — no según la tormenta de fusiones del lunes.
6.2 Provisión y desprovisión dinámica de extremo a extremo
Rastrear un trabajo de pipeline:
- El desarrollador hace push; GitLab crea un trabajo en la cola pendiente.
- El gestor de runners reclama el trabajo y pide un pod a API.
- Si el clúster tiene escasez de CPU/RAM, el autoscaler añade un nodo (provisión).
- El pod ejecuta el script, sube los artefactos y sale.
- El pod se elimina; los recursos vuelven al pool (desprovisión a nivel de trabajo).
- Cuando muchos nodos permanecen vacíos más allá del umbral de reducción de escala — habitual tras la noche y todo el fin de semana — los nodos salen (desprovisión a nivel de infraestructura).
Ese bucle completo es lo que el vídeo significa con GitLab Runners a escala hiperscale para optimización de costes: no una sola bandera sofisticada, sino el ciclo de vida del trabajo y la elasticidad del clúster trabajando juntos.
7. Modelo de costes: dónde aparecen las grandes ahorros en dólares
Sé preciso. El escalado automático no hace que las compilaciones sean gratuitas. Evita que pagues tarifas de pico en horas fuera de pico. Los ahorros provienen de alinear el gasto con la demanda real — los cuatro puntos de la guía básica, ampliados para operadores.
7.1 Escalar solo cuando hay personas (o bots) trabajando
Cuando una mañana ocupada genera docenas de pipelines, Kubernetes programa muchos pods de trabajo en paralelo hasta los límites de concurrencia y del clúster. La throughput aparece cuando la presión de merge es real.
7.2 Escala a la baja con fuerza cuando desaparece la demanda
Cuando terminan los trabajos, los pods desaparecen. Con la escalada automática del clúster (o un grupo de nodos del tamaño adecuado), los nodos de nube no utilizados salen del grupo. Las noches y los fines de semana —generalmente las ventanas más tranquilas para los equipos de producto— son la primera capacidad por la que deberías dejar de pagar.
7.3 Deja de desperdiciar CPU, RAM y almacenamiento
| Recursos | VMs de runners siempre activos | Pods de trabajos Kubernetes + escalada automática de nodos |
|---|---|---|
| CPU | Núcleos reservados inactivos mientras la cola está vacía | Se liberan cuando salen los pods; los nodos pueden escalar hacia dentro |
| RAM | SO del agente + ejecutores inactivos residentes 24×7 | La memoria se devuelve con cada eliminación de pod |
| Almacenamiento | Discos calientes y capas de imágenes en cada VM | Scratch efímero por defecto; las cachés compartidas se convierten en una opción explícita y dimensionada |
Durante un mes, las horas tranquilas dominan el reloj. Recuperar las noches y los fines de semana es donde lasahorros en dólares se acumulan.
7.4 Paga por resultados, no por muebles
Sigues pagando por GitLab y por un plano de control delgado (gestor de runners + esenciales del clúster). Lo que dejas de pagar es un almacén de sillas vacías.
7.5 Intuición trabajada (no un benchmark fabricado)
Supongamos que el día necesita de forma sostenible lo equivalente a 20 slots de ejecutor ocupados, pero las noches y fines de semana necesitan 2. Una flota fija dimensionada para 20 paga por 20 las 24 horas. Un pool elástico paga por ~20 durante el día y ~2 (más el plano de control) cuando está tranquilo. Para muchos equipos de producto, las horas tranquilas son una fracción grande del mes — por lo que recuperarlas es cómo los ahorros se vuelvenenormessin inventar un porcentaje de marketing. Las finanzas multiplican los precios locales de nodo-hora; el trabajo de la arquitectura es hacer que las horas vacías sean realmente vacías en la cuenta de facturación.
Grandes ahorros de costos aparecen cuando el pico del lunes ya no dicta la factura de las 3 am del martes — y cuando el silencio del sábado finalmente se ve tranquilo en la factura también.
7.6 Lo que sigues pagando a propósito
- Componentes de GitLab Server — dimensionados para usuarios y coordinación de CI, no para la granja de compilación.
- Runner manager Deployment(s) — pequeños frente a granjas de trabajos.
- Cachés deliberados (proxy de dependencias, PVCs) — útiles, pero dimensionados; los cachés no son almacenamiento gratuito.
- DinD privilegiado — conveniente y más pesado; considera Kaniko/BuildKit cuando la densidad y el aislamiento importan más que la familiaridad.
8. CI/CD pipelines en la práctica
Con runners en línea,.gitlab-ci.ymldefine etapas y trabajos. GitLab agenda; el Kubernetes ejecutor materializa pods. Mantén las pipelines honestas sobre el coste:
- Falla rápido en lint/unidad antes de las pesadas construcciones de imágenes.
- Usa
rules/workflowpara que las ramas de borrador no expandan matrices completas. - Prefiere cachés compartidos con claves claras frente al crecimiento ilimitado del disco por VM.
- Etiqueta los trabajos al grupo de runners correcto (alpine vs ubuntu, constructores pequeños 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"
La idea económica es la misma que la de la plataforma: no agendes trabajo costoso cuando una verificación barata habría fallado, y no mantengas runners especializados calientes para trabajos que nunca llegan el sábado.
9. Notas de seguridad y tenencia
Los pods efímeros mejoran la higiene (menos estado pegajoso) pero DinD privilegiado y RBAC a nivel de clúster pueden ampliar el radio de explosión. Defaults prácticos para la mayoría de equipos:
- Ejecuta los pods de trabajo en un namespace dedicado con ResourceQuotas y LimitRanges.
- Prefiere construcciones no privilegiadas siempre que sea posible; aísla los runners DinD detrás de etiquetas específicas.
- Evita montar credenciales de nube de larga duración en cada trabajo; inyecta tokens de corta duración por pipeline.
- Trata los tokens de registro de runners como secretos — rotación cuando la gente se va o los laboratorios se comparten.
- Si varios equipos comparten un clúster, separa los gestores de runners (y opcionalmente los grupos de nodos) para que un vecino ruidoso no mantenga toda la granja caliente — y mantén la historia de costes atribuible por equipo.
10. Observabilidad que demuestra los ahorros
No puedes reclamar ahorros de noche y fines de semana sin mirar. Rastrea al menos:
| Señal | Lo que "bueno" se ve |
|---|---|
| Número de pods de trabajo por hora | Picos en horas laborales de semana; casi en el suelo por la noche y fines de semana |
| Pods pendientes | Picos solo brevemente en la cima; pendientes sostenidos significa concurrencia/nodos insuficientes |
| Nodo CPU / número de nodos | Rastrea la demanda de pods; los nodos vacíos no se quedan horas |
| Gestor de runners CPU/RAM | Plano y pequeño en relación con la granja de trabajos |
| Factura de la nube por hora de la semana | Los periodos tranquilos son visiblemente más baratos después del corte |
Si los conteos de pods bajan por la noche pero la factura de nodos no, la configuración de escala-down — no GitLab — es el siguiente control.
11. Máquinas virtuales fijas vs ejecutores Kubernetes (tabla de decisiones)
| Máquinas virtuales de runner fijas | Ejecutor Kubernetes + escalado automático | |
|---|---|---|
| Unidad de capacidad | Máquina completa, siempre asignada | Pod (y opcionalmente nodo) por trabajo |
| Picos de lunes | Cola o sobredimensionar VMs | Aumentar concurrentes + escalar nodos |
| Noches / fines de semana | Aún se factura si las VMs permanecen encendidas | Pods eliminados; los nodos pueden irse |
| Desperdicio de CPU / RAM / almacenamiento | Estructural cuando está inactivo | Recuperado por defecto |
| Deriva / "funciona en runner 3" | Común | Reducido (efímero por defecto) |
| Complejidad operativa | Menor inicialmente | Mayor (requiere habilidades de clúster) |
Elige máquinas virtuales fijas solo cuando realmente tengas una demanda plana 24×7 o restricciones que prohíban un clúster. Todos los demás con pipelines impulsados por humanos con picos están pagando el impuesto del mobiliario.
12. Lo que no estás perdiendo
El escalado automático no significa "sin control". Todavía puedes establecer la concurrencia, las imágenes permitidas, los privilegios DinD, la política de red y el alcance de registro. El punto es mantener esos controles mientras permites que la capacidad no utilizada se evapore — la misma tranquilidad que en el texto en lenguaje sencillo, ahora reforzada con RBAC, namespaces y lanzamientos de runners separados.
13. Lista de verificación operativa
- Versiones del operador/chart de pin; actualizar deliberadamente.
- Rotar tokens de runner; eliminar tokens de laboratorio de cualquier script antes de publicar.
- Nombres de espacio separados: GitLab sistema vs trabajos de runner.
- Vigilarpodspendientes — un aumento en los pendientes indica que la concurrencia o la capacidad del nodo es insuficiente en la punta.
- Vigilarhoras vacías del nodo— nodos que permanecen vacíos durante la noche indican retraso en la reducción de escala o necesidad de ajustar la política del grupo.
- Limitar runners con privilegios a trabajos que los necesiten.
- Realizar copias de seguridad de GitLab de forma independiente de la elasticidad del runner.
- Revisar la factura por hora de la semana una vez que el CI elástico esté en funcionamiento — las noches y fines de semana deberían disminuir visiblemente.
14. Para quién es esto
- Ingenieros de plataforma y SREs que implementan GitLab CI en Kubernetes.
- DevOps líderes que reemplazan máquinas virtuales de runner fijas con pods de ejecutor.
- Socios de ingeniería y finanzas que necesitan que el CI se comporte como una utilidad basada en el uso, no como mobiliario.
15. Documentación oficial de GitLab
Estas páginas son las referencias canónicas para las implementaciones Helm y el comportamiento de escalado descritos anteriormente. Prefíralas a los artículos de blog cuando cambien las versiones.
Servidor GitLab en Kubernetes
- Instalar el operador GitLab— ruta de instalación del operador + Helm utilizada en la guía de entrenamiento.
- Diagramas GitLab Helm— documentación del diagrama paraguas.
- Instalar GitLab con el diagrama Helm— cuando despliegas GitLab mediante diagramas en lugar del operador.
- subdiagrama gitlab-runner (diagrama GitLab)— runner incluido junto a GitLab en el diagrama principal (distinto del diagrama de runner independiente).
Diagrama GitLab Runner Helm
- Instalar GitLab Runner con el diagrama Helm—
helm repo add gitlab, instalar/actualizar, notas del diagrama OCI. - Configurar el diagrama GitLab Runner Helm—
concurrent, plantillas de configuración, RBAC, cachés, opciones de imagen. - diagrama gitlab-runner
values.yaml— valores predeterminados completos (incluidos HPA opcional).
Kubernetes executor y autoscaling
- Kubernetes executor— pods de trabajos, helpers, servicios (por ejemplo, DinD), solicitudes de recursos, verbos RBAC.
- Configurar autoscaling (Kubernetes executor / chart)— pausar pods,
[runners.kubernetes.autoscaler], políticas de período (inactivo por la noche/fin de semana). - Autoscaling de GitLab Runner— modelo general de autoscaling (también cubre caché distribuido).
- Planificar y gestionar una flota de GitLab Runner— escalado y operaciones a nivel de flota.
- Configuración avanzada (
config.toml)— secciones globalesconcurrenty de executor incrustadas en Helmrunners.config.
Trabajos CI, compilaciones y configuraciones de runner en GitLab
- Configurar runners en GitLab— registro, etiquetas, run-untagged, runners protegidos.
- Usar Docker para construir imágenes en CI— DinD y alternativas (relevante cuando
privileged/ servicio Docker está habilitado en los valores del runner).
Para el control de costes por la noche y los fines de semana, combinar: (1) pods de trabajos del Kubernetes executor que se reducen a cero, (2) políticas del chartconcurrenty autoscalerconfuera de horario puntaidle_count = 0, y (3) autoscaling de clúster/nodo para que los nodos vacíos abandonen el pool — como se describe en las secciones 6–7.
16. Volviendo al video y al repositorio
La sesión de YouTube —GitLab completo en ~20 minutos. Escalado automático de cargas de trabajo de GitLab Runner en Kubernetes— demuestra GitLab en Kubernetes, runners vía Helm, y la historia de costos a escala hiper: aprovisionar y desaprovisionar infraestructura dinámicamente para que no pagues tarifas de pico en noches y fines de semana inactivos. Usa el prompt de construcción del cursogitlab-runners-k3s-hyperscale-course.prompt.mden este repositorio, con la documentación oficial anterior como fuente de verdad versionada. Para el encuadre no técnico de las mismas ideas, consultaDeja de pagar por CI inactivo.
Cierre
Kubernetes no solo aloja GitLab Runners. Usado correctamente, cambia la economía del CI:aprovisiona bajo demanda, desaprovisiona en inactividad, recupera CPU/RAM/almacenamiento cuando los humanos se van a casa. Ese es el patrón de escala hiper — disponible para cualquier equipo dispuesto a intercambiar una flota permanente por una cola de pods.
Comienza con el video, levanta el operador + runner Helm en un laboratorio, activa el escalado automático de nodos y luego comprueba si el sábado finalmente se ve tranquilo en la factura.
Publicado porWorkstation.