Saltar al contenido principal

GitLab runners

warning

Esta documentación está obsoleta. Su nueva versión está en el K8s Project.

Introducción

Los anteriores servicios proporcionan los sistemas para gestionar, desplegar, monitorizar y almacenar los contenedores, pero necesitamos algo para convertir nuestro código fuente a contenedores y desplegarlos. Esto es el trabajo del CI/CD.

Actualmente las 2 grandes herramientas de repositorio de código son GitHub y GitLab, cada una de ellas tiene su propia herramienta para este proceso, y aunque existen otras herramientas que han liderado este trabajo durante años (como Jenkins), el potencial de estas nuevas herramientas es superior.

En mi caso dispongo de un GitLab propio, debido a que su versión Omnibus es gratuita y de fácil instalación, con lo que utilizará GitLab Runner. Este también puede utilizarse con GitLab cloud, ya que un Runner se asigna a nivel global (cualquier proyecto puede utilizarlo), a un grupo o a un proyecto, así que podemos utilizar nuestro propio Runner en vez de los genéricos de GitLab.

La principal ventaja de GitLab Runner sobre Jenkins es que funciona ejecutando contenedores, no requiere instalar plugins para cada idioma de programación, versión u otros necesarios, siempre dispones de cualquier contenedor que exista, y no es necesario hacer una petición para instalar un plugin que no esté disponible en ese momento.

Esta gran ventaja también significa que es muy mala idea desplegar un Runner en un servicio de producción, ya que cualquier persona podrá afectar directa o indirectamente a ese servidor, debido a ello, he separado esta sección del resto de servicios, ya que estará en un servidor propio y no utilizará Swarm, un Docker simple es la mejor idea.

Requisitos

GitLab permite configurar los Runners a nivel global, a un grupo o a un proyecto.

  • Global: El Runner es público. Se configura en Admin Area - Runner.
  • Grupo: El Runner está disponible para cualquier proyecto de ese grupo. En el grupo, Settings - CI/CD - Runners.
  • Proyecto: Solo ese proyecto puede utilizarlo. En el proyecto, Settings - CI/CD - Runners.

De estos debemos copiar la URL y el Token.

Pre instalación

Antes de empezar, se requiere un servidor únicamente para los Runners, este debería ser un clon del sistema de Swarm ya explicado para simplificar el mantenimiento, así que necesitaremos:

  1. Instalar un Ubuntu.
  2. Instalar Docker pero únicamente con el paso de instalación, sin iniciar clúster ni encriptar la red.
  3. Configurar el acceso a los repositorios privados creados en Nexus3 para poder subir y descargar contenedores

Portainer

Portainer es bastante práctico para monitorizar el sistema, pero no tiene HTTPS por defecto, así que desplegarlo podría ser un problema de seguridad. Hay opciones para solucionarlo, pero como estará en un servidor aparte no me preocuparé de ello.

Se despliega Portainer sin agente y publicado en el puerto 9000:

docker volume create portainer_data
docker run -d -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

Al acceder preguntará el usuario y contraseña, después el método que debe utilizar para acceder, en este caso es Docker, para ello le hemos asignado el volumen.

http://serverName.domain.intranet:9000/

Descarga

La información del despliegue también se encuentra en Git.

Despliegue

Cada Runner requiere de su configuración y una caché, ambos se asignarán a volúmenes.

Volúmenes

Para cada Runner, se genera sus volúmenes:

docker volume create runner1
docker volume create cache1

El de caché no será necesario si lo configuramos hacia un externo.

Si el GitLab tiene certificado autofirmado, debemos copiar el CA para que pueda acceder.

sudo mkdir -p /var/lib/docker/volumes/runner1/_data/certs
sudo mv cert-ca.crt /var/lib/docker/volumes/runner1/_data/certs/ca.crt

Configuración

La configuración se puede hacer manualmente o con el asistente, en este caso utilizaré el asistente.

docker run --rm -it -v runner1:/etc/gitlab-runner gitlab/gitlab-runner register

Este es un ejemplo de valores para configurarlo con Docker y predefinir el contenedor docker:stable, el contenedor se descargará de la URL de Nexus3 para acelerar el proceso:

Enter the GitLab instance URL (for example, https://gitlab.com/):
https://git.domain.intranet/
Enter the registration token:
token_code
Enter a description for the runner:
[39a6b33c4ded]: Runner1
Enter tags for the runner (comma-separated):
runner1,docker
Registering runner... succeeded runner=aaaaaaaa
Enter an executor: kubernetes, docker, shell, docker+machine, docker-ssh+machine, virtualbox, custom, docker-ssh, parallels, ssh:
docker
Enter the default Docker image (for example, ruby:2.6):
docker-public.domain.intranet/docker:stable
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Requiere algunas configuraciones extras para funcionar.

sudo vi /var/lib/docker/volumes/runner1/_data/config.toml

Es preferible añadir más instancias del mismo Runner y también reconfigurarlo para darle acceso al Docker y que así pueda construir los nuevos contenedores.

concurrent = 5
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]

Configuración de Runner global

En caso de utilizar un Runner global, es posible configurarlo para que todos los proyectos lo puedan utilizar, y no solo aquellos asignados por tag.

En GitLab, ir a:

  1. Admin Area
  2. Runners
  3. Editar el Runner
  4. Seleccionar Indicates whether this runner can pick jobs without tags

Guardar los cambios.

Desplegar el Runner

Solo queda iniciar el Runner.

docker run -d --name runner1 --restart always \
-v runner1:/etc/gitlab-runner \
-v cache1:/mnt/cache \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest

Caché

Cada proceso de CI/CD puede definir la caché, esta se almacena acorde a la configuración del Runner, pudiendo guardarla localmente o en un servidor externo.

Por defecto los Runners guardan su caché en el disco local, y por ello se han sacado a volumen, así que diferentes Runners podrían utilizar el mismo volumen para compartir los datos.

Otra forma es definir el servidor externo, pero el Runner solo utiliza los sistemas de storage de AWS, GCS o Azure, aunque podemos utilizar a MinIO para simular S3.

Estos se definen en el mismo fichero de configuración que ya hemos modificado previamente.

sudo vi /var/lib/docker/volumes/runner1/_data/config.toml

Este es un ejemplo con MinIO haciendo de S3:

/var/lib/docker/volumes/runner1/_data/config.toml
[runners.cache]
Type = "s3"
Shared = true
[runners.cache.s3]
ServerAddress = "minio.domain.intranet"
AccessKey = "access key"
SecretKey = "secret key"
BucketName = "bucket name"
Insecure = true
[runners.cache.gcs]
[runners.cache.azure]

Caché con SSL

Si el servicio de caché tiene un SSL válido no es necesario hacer nada más, pero en caso de tener un certificado autofirmado, los problemas son enormes.

GitLab Runner tiene una carpeta donde se almacenan los certificados para que él pueda acceder a GitLab, pero esta no es la que utiliza para conectar a la caché u otros, utiliza un contenedor especial gitlab/gitlab-runner-helper, así que se debe crear una modificación de este contenedor con el CA añadido y subir este contenedor al repositorio para que pueda descargarlo.

Para crear el contenedor, hay que construir el Dockerfile con los siguientes valores:

FROM gitlab/gitlab-runner-helper:x86_64-latest
RUN apk add --no-cache ca-certificates
COPY ca.crt /usr/local/share/ca-certificates/ca.crt
RUN update-ca-certificates
RUN rm /usr/local/share/ca-certificates/ca.crt

Construimos el contenedor y lo subimos al repositorio, en este ejemplo únicamente indico su construcción:

docker build -t internal/gitlab-runner-helper:x86_64-latest .

Con el contenedor creado, hay que añadirlo a la configuración.

/var/lib/docker/volumes/runner1/_data/config.toml
[[runners]]
...
[runners.docker]
helper_image = "docker-public.domain.intranet/internal/gitlab-runner-helper:x86_64-latest"
...

Al utilizar el runner veremos que va utilizando este contenedor para todos los procesos de Git y caché.