Runners en Kubernetes
Runners en Kubernetes
Por que Kubernetes
- Autoscaling: Cada job crea un Pod, se destruye al terminar
- Aislamiento: Jobs en Pods separados, sin estado compartido
- Recursos: Limites de CPU/memoria por job
- Cero mantenimiento: No hay runner “sucio” despues de muchos jobs
Instalacion con Helm
Agregar repositorio
helm repo add gitlab https://charts.gitlab.io
helm repo update
Crear namespace
kubectl create namespace gitlab-runner
Valores de configuracion
# values.yaml
gitlabUrl: https://gitlab.com/
runnerToken: "glrt-xxxxxxxxxxxx"
runners:
config: |
[[runners]]
[runners.kubernetes]
namespace = "gitlab-runner"
image = "alpine:latest"
cpu_request = "250m"
cpu_limit = "1"
memory_request = "256Mi"
memory_limit = "1Gi"
service_cpu_request = "100m"
service_memory_request = "128Mi"
[runners.kubernetes.pod_labels]
app = "gitlab-ci"
[runners.kubernetes.pod_annotations]
"prometheus.io/scrape" = "true"
concurrent: 10
checkInterval: 5
rbac:
create: true
clusterWideAccess: false
serviceAccount:
create: true
name: "gitlab-runner"
Instalar
helm install gitlab-runner gitlab/gitlab-runner \
-n gitlab-runner \
-f values.yaml
Verificar
kubectl get pods -n gitlab-runner
kubectl logs -f deployment/gitlab-runner -n gitlab-runner
Configuracion de recursos por job
En .gitlab-ci.yml puedes sobreescribir limites:
heavy_build:
tags:
- kubernetes
variables:
KUBERNETES_CPU_REQUEST: "2"
KUBERNETES_CPU_LIMIT: "4"
KUBERNETES_MEMORY_REQUEST: "2Gi"
KUBERNETES_MEMORY_LIMIT: "4Gi"
script:
- make build
Volumenes
EmptyDir (temporal por job)
# values.yaml
runners:
config: |
[[runners]]
[runners.kubernetes]
[[runners.kubernetes.volumes.empty_dir]]
name = "build-cache"
mount_path = "/cache"
PVC (persistente entre jobs)
runners:
config: |
[[runners]]
[runners.kubernetes]
[[runners.kubernetes.volumes.pvc]]
name = "ci-cache"
mount_path = "/cache"
Docker-in-Docker en Kubernetes
Opcion 1: DinD con sidecar
build_image:
image: docker:24
services:
- docker:24-dind
variables:
DOCKER_HOST: tcp://localhost:2376
DOCKER_TLS_CERTDIR: "/certs"
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
Requiere privileged = true en el runner (riesgo de seguridad).
Opcion 2: Kaniko (sin privilegios)
build_image:
image:
name: gcr.io/kaniko-project/executor:latest
entrypoint: [""]
script:
- /kaniko/executor
--context $CI_PROJECT_DIR
--dockerfile Dockerfile
--destination $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
Kaniko no necesita Docker daemon ni modo privilegiado. Es la opcion recomendada.
Troubleshooting
Pod no inicia
kubectl describe pod <pod-name> -n gitlab-runner
kubectl get events -n gitlab-runner --sort-by='.lastTimestamp'
Errores comunes
| Error | Causa | Solucion |
|---|---|---|
ImagePullBackOff | Imagen no existe o sin permisos | Verificar nombre de imagen y pull secrets |
OOMKilled | Job excede memoria | Aumentar memory_limit |
Evicted | Nodo sin recursos | Ajustar requests o agregar nodos |
CrashLoopBackOff | Runner no conecta a GitLab | Verificar URL y token |
Actualizar runner
helm upgrade gitlab-runner gitlab/gitlab-runner \
-n gitlab-runner \
-f values.yaml
Siguiente: Capitulo 11: Monitoreo, Troubleshooting y Buenas Practicas →