Configurar GitLab Runner: dale vida a tu pipeline

«Subí las instrucciones, ¿por qué no responde?»

La última vez, lleno de entusiasmo, escribí el archivo .gitlab-ci.yml y lo envié con push. «Ahora el despliegue se hará automáticamente, ¿verdad?», pensé con expectación mientras hacía clic en el menú ‘CI/CD > Pipelines’ de GitLab.

Pero en lugar de la marca verde de éxito, lo único que apareció en pantalla fue una barra de carga girando sin parar y el mensaje de estado ‘Pending (en espera)’. Al hacer clic en el mensaje, vi esta advertencia:

This job is stuck because the project doesn't have any runners online assigned to it.

Traducido: «Llegó una tarea, pero el trabajador (Runner) que debe procesarla no se ha presentado en su puesto». Vaya, le había entregado las instrucciones al jefe de fábrica (el servidor GitLab), pero no había contratado al empleado (Runner) que realmente debía hacer el trabajo en la fábrica.

Por muy perfecto que sea el plano, sin un ‘obrero’ que lo ensamble, la fábrica no funciona.

GitLab Runner: las manos y los pies de la pipeline

GitLab se divide a grandes rasgos en dos componentes.

  1. GitLab Server (sede central/jefe de fábrica): almacena el código, gestiona el estado de la pipeline y da las órdenes.
  2. GitLab Runner (sucursal/operario de campo): se instala en el servidor real, recibe las órdenes de la sede central, descarga el código, hace el build y ejecuta los comandos de despliegue.

«¿Y por qué GitLab no se conecta sin más a mi servidor y hace el despliegue por mí?». Si lo piensas bien, sería una idea peligrosísima. Si una página web en internet (GitLab) pudiera, con solo pulsar un botón, entrar en el ordenador de tu habitación (el servidor) y ejecutar comandos a su antojo, eso sería un auténtico ‘hackeo’. Si alguien comprometiera tu cuenta de GitLab, podría convertir tu servidor en una máquina de minar Bitcoin.

Por eso GitLab no accede directamente a tu servidor. En su lugar, instala un ‘representante de confianza (Runner)’ que opera únicamente dentro de tu servidor, y solo a través de ese representante delega las tareas. El proceso, algo enrevesado, de instalación y registro que vamos a realizar es precisamente el ‘procedimiento de seguridad’ para autenticar a este representante.

Paso 1: consultar la oferta de empleo (obtener el token)

Antes de instalar el runner, primero hay que publicar en la sede central (GitLab) una ‘oferta de empleo’ que diga «nuestro proyecto necesita un trabajador» y obtener una ‘credencial (Token)’.

En las versiones más recientes de GitLab, la forma de consultar el token está algo oculta por motivos de seguridad.

  1. Entra en el proyecto de GitLab
  2. Menú de la izquierda: Settings > CI/CD
  3. En la sección Runners, haz clic en Expand
  4. En la esquina superior derecha de la sección Project runners, haz clic en el botón de tres puntos (⋮)

Al pulsar este botón se abre un menú emergente con la información que estamos buscando. Anota y copia la URL y el Registration token.

(Nota: puede aparecer una advertencia algo intimidante: ‘Support for registration tokens is deprecated’. Significa que este método pronto desaparecerá, pero por ahora se mantiene por compatibilidad. No te asustes y copia el token sin más.)

[Consejo] ¿Varios proyectos? (Group Runner) Si, como yo, tienes varios proyectos —frontend, backend, etc.— agrupados bajo un mismo grupo, registrar un runner para cada proyecto es ineficiente. En ese caso, en vez de registrar el runner desde la configuración del proyecto, hazlo en Group Settings > CI/CD. El ‘Group Runner’ creado de este modo puede gestionar él solo todas las tareas de todos los proyectos pertenecientes a ese grupo. (Como tengo muchos proyectos, opté por esta vía.)

Hay que abrir el menú oculto (⋮) para ver el token. Este token es la ‘llave secreta’ que conecta el runner con el servidor; jamás debes filtrarlo.

Paso 2: contratar al obrero (instalar el Runner)

Vamos a instalar el runner en un servidor Linux (o en tu PC). La forma más limpia, como era de esperar, es utilizar nuestro querido ‘Docker’.

# 1. Ejecutar el contenedor de GitLab Runner
docker run -d --name gitlab-runner --restart always \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v gitlab-runner-config:/etc/gitlab-runner \
  gitlab/gitlab-runner:latest

  • -v /var/run/docker.sock:/var/run/docker.sock: esto es importante. Como el runner tiene que levantar otro contenedor de Docker (para el build), le compartimos el socket de Docker del host. (Método Docker in Docker)

Paso 3: firmar el contrato laboral (registrar el Runner)

Instalar el runner no es suficiente. Hace falta que este runner se registre en el servidor de GitLab declarando: «Soy el trabajador del proyecto A».

Entremos en el contenedor del runner que acabamos de levantar y ejecutemos el comando de registro.

# Ejecutar el comando de registro dentro del contenedor del runner
docker exec -it gitlab-runner gitlab-runner register

Ahora la terminal te lanzará una serie de preguntas, como en un cuestionario. Solo tienes que introducir la información que obtuviste en el paso 1.

  1. Enter the GitLab instance URL:
    • https://gitlab.com/ (o la dirección de tu GitLab privado)
  2. Enter the registration token:
    • (Pega el token que copiaste antes)
  3. Enter a description for the runner:
    • my-runner-01 (el que quieras; un nombre fácil de reconocer)
  4. Enter tags for the runner:
    • (Puedes saltártelo pulsando Enter. Sirve para que el runner solo ejecute trabajos con determinadas etiquetas.)
  5. Enter an executor:
    • docker (vamos a hacer el build sobre Docker, así que escribimos docker.)
  6. Enter the default Docker image:
    • docker:latest (la imagen que se usará por defecto)

«Runner registered successfully.» ¡Si aparece este mensaje, la contratación está hecha! Si refrescas la pantalla de GitLab, verás el runner con la luz verde encendida, gritando «Listo (Online)».

Cuando la conexión es exitosa, el indicador de estado del runner en la pantalla de GitLab se vuelve verde.

Paso 4: ¡pipeline en marcha!

En el momento en que se registra el runner, la pipeline que estaba parada (Pending) empieza a moverse automáticamente. Running… y, poco después, ¡Passed!

Sin que yo hiciera nada, la máquina ejecutó las pruebas, hizo el build, creó la imagen y la subió al registro por sí sola. Al abrir la terminal y revisar los logs, vi que todo el proceso había terminado mucho más rápido y con mayor precisión que cuando lo hacía manualmente.

«Vaya… realmente funciona».

El despliegue manual de 10 minutos ahora se resuelve con un solo git push. Ya puedo lanzar un despliegue y salir tranquilamente a tomarme un café.

Consejo práctico: problema de permisos de Docker (Permission Denied)

Hay un error con el que te toparás casi con un 99 % de probabilidad la primera vez que configures el runner: dial unix /var/run/docker.sock: connect: permission denied

Es un problema que aparece porque el runner intenta ejecutar comandos de Docker pero no tiene permisos para hacerlo. En ese caso hay que abrir el archivo de configuración de gitlab-runner (config.toml) y activar la opción privileged = true.

# /etc/gitlab-runner/config.toml (archivo de config del runner)
[[runners]]
  name = "my-runner-01"
  executor = "docker"

[runners.docker]

privileged = true # Hay que poner esta opción en true para que Docker-in-Docker funcione bien. # …

Para terminar: ya puedo irme a casa

Por fin tengo mi propio ‘robot de despliegue’. Ahora solo tengo que centrarme en escribir código. Las tareas aburridas y repetitivas de validación y despliegue las hará por mí mi fiel robot (Runner).

Pero todavía falta ese 2 %. De momento, la pipeline se ejecuta sin condiciones cada vez que se hace push a la rama master. «¿Y si quiero desplegar automáticamente en el servidor de desarrollo (dev), pero solo desplegar en el de producción (prod) cuando yo pulse un ‘botón de aprobación’?».

La próxima vez veremos cómo controlar la pipeline de forma más inteligente, con ‘estrategias de despliegue por rama’ y ‘procedimientos de aprobación manual (Manual)’.

Deja un comentario