Objetivo
Se busca configurar la funcionalidad de CI/CD de una instancia de gitlab community edition (self-managed).
Para ello debe agregarse por lo menos un runner que es una aplicación utilizada por gitlab CI/CD para ejecutar las tareas en un pipeline.
Al registrar un runner en gitlab se debe elegir un executor el cual determina el ambiente en el que cada trabajo es ejecutado.
Actualmente estoy utilizando el shell executor el cual tiene como ventajas la facilidad de configuración, pero como contra que los trabajos tienen acceso al servidor en que está instalado el runner el cual está compartido con otros servicios.
Se descartó utilizar el docker executor ya que requiere tener instalado docker y no funciona con podman (el cual está instalado en el equipo al cual se agregará el servicio de runner).
De las alternativas restantes, se intentará utilizar el executor virtualbox por la característica de proveer un entorno limpio para cada build y no tener problemas de que las tareas que se ejecuten accedan a los datos del servidor.
Una vez elegido virtualbox, hay que elegir la imagen a utilizar y la forma de configurarla. Ya que los proyectos que desean agregarse al pipeline de CI/CD deben generar imagenes de contenedores utilizando archivos con formato Dockerfile y teniendo en cuenta que podman, mediante su subcomando machine utiliza por defecto la distribución Fedora CoreOS se intentará utilizar esta.
Respecto a Fedora CoreOS o FCOS, parte de su filosofía radica en distribuir una imagen genérica mínima la cual deberá aprovisionarse en el primer inicio (first boot) utilizando ignition. ignition utiliza un archivo en formato json para realizar el aprovisionamiento durante la etapa de initramfs. Hay que notar que la forma recomendada de generar un archivo para ignition es usando butane, el cual requiere que se escriba la configuración en formato yaml que luego es validada por butane y convertida a json. Por otro lado, ya que utilizaremos virtualbox como virtualizador se aprevechará que ignition permite utilizar las virtualbox guest properties para cargar la información de aprovisionamiento. Como ejemplo conviene seguir la guía de aprovisionamiento en virtualbox. Por defecto FCOS contiene git y podman, que son las herramientas que utilizamos para generar los build y ssh para que gitlab-runner se conecte, por lo cual la imagen cumple con los requerimientos de gitlab-runner.
Por último, se configurará gitlab-runner para usar la imágen de virtualbox basada en FCOS.
NOTA: gitlab-runner es ejecutado con root por defecto y el executor virtualbox utiliza el usuario root para ejecutar virtualbox, por lo que el usuario en el cual se instala la máquina virtual debe ser root
Setup de proyecto de prueba
Antes de instalar gitlab-runner y configurar el executor (lo que implica crear y configurar una máquina virtual) hay que crear un proyecto (repositorio git en la instancia de gitlab) al cual se le registrará el runner.
A continuación se describe el contenido de un proyecto sencillo y representativo que se puede utilizar para probar el runner. Esperamos que el proyecto:
- utilice podman para generar un contenedor (que luego será descartado)
- descargue un contenedor de dockerhub (para verificar conectividad)
Para probar lo anterior utilizaremos solo dos archivos:
-
.gitlab-ci.yml de contenido:
stages: - build build-job: stage: build script: - echo "Compiling the code..." - podman build -t test-runner-config:latest . - echo "Compilation complete."
-
Dockerfile de contenido:
FROM docker.io/library/busybox:1.34.1-musl@sha256:0eddf32dbd528c2a46b97498a6f79d1fc14dbf59c5e2d7e9759e7a026b529c03 RUN date > /creation-date
Para registrar un runner (obtener el token para registrarlo) se debe ir a Settings (del proyecto) > CI/CD, expandir la sección Runners y extraer los datos bajo Specific runners: la url de la instancia de gitlab y el token para registrarse. Estos valores se utilizarán más adelante.
Instalar gitlab-runner
Para instalar el runner se siguen las indicaciones dadas en Install GitLab Runner using the official GitLab repositories
Preparación de imágen basada en FCOS
Creación de configuración de FCOS
Se escribe la configuración en butane con las siguientes características:
-
Se agregará el usuario
gitlab-runner
con directorio HOME/var/lib/gitlab-runner
que será utilizado por el runner para ejecutar los trabajos y el cual utilizará una contraseña aleatoria.Hay que notar que el password es solo para uso en la consola, ya que por defecto FCOS no permite el uso de passwords por ssh. Para solucionar esto se debe habilitar el uso de passwords con ssh.
-
Se configurará el usuario privilegiado por defecto
core
para conectarse al sistema en caso de que se requiera inspeccionar en busca de errores que surjan a futuro. -
Se agrega un segundo disco que será formateado con una única partición ext4 que será montada en el directorio
/var/lib/gitlab-runner
donde podrá ser utilizado por el usuariogitlab-runner
.Hay que tener en cuenta que en nuestro caso de uso de virtualbox el segundo disco es referenciado como
/dev/sdb
. -
Se crea el archivo
/etc/hostname
para dar nombre al SO en la vm.
Para realizar lo anterior se utiliza el script gen-ignition.sh que además:
- genera un password aleatorio para el usuario github-runner
- genera un certificado ssh para conectarse con el usuario core
- valida la configuración elegida mediante butane y genera el archivo json a utilizar con ignition
Nota: para un correcto funcionamiento del script hay que tener instalado el
paquete pwgen
(doas apt-get install -Vy pwgen
)
y el ejecutable de butane
(wget -O butane 'https://github.com/coreos/butane/releases/download/v0.15.0/butane-x86_64-unknown-linux-gnu' && doas install butane /usr/local/bin
).
La ejecución se realiza utilizando el comando:
$ doas ./gen-ignition.sh gitlab-runner
ignition config file: /root/VirtualBox Vms/gitlab-runner/gitlab-runner.ign
file with pass for user github-runner: /root/VirtualBox Vms/gitlab-runner/user_gitlabrunner.pass
file to connect with core user: /root/VirtualBox Vms/gitlab-runner/user_core.cert
Done
Creación de la VM
Se comienza descargando la imagen estable para virtualbox en el directorio
/tmp
:
$ wget -P /tmp https://builds.coreos.fedoraproject.org/prod/streams/stable/builds/36.20220806.3.0/x86_64/fedora-coreos-36.20220806.3.0-virtualbox.x86_64.ova
Para crear la vm se utiliza el script prepare-vm.sh. Este script, aparte de importar la vm realiza las siguientes tareas:
- crea un segundo disco y lo agrega a la vm
- se carga la configuración de ignition creada previamente por el script gen-ignition.sh como una property de la vm
- se agrega un port forward para conectarse a la vm por el puerto 2222 del host
- se configura un puerto serial para tener acceso a la salida de la consola en un archivo
$ doas ./prepare-vm.sh gitlab-runner
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Interpreting /tmp/fedora-coreos-36.20220806.3.0-virtualbox.x86_64.ova...
OK.
Disks:
vmdisk1 10737418240 816268288 http://www.vmware.com/interfaces/specifications/vmdk.html#streamOptimized disk.vmdk 816268288 -1
Virtual system 0:
0: Suggested OS type: "Fedora_64"
(change with "--vsys 0 --ostype <type>"; use "list ostypes" to list all possible values)
1: VM name specified with --vmname: "gitlab-runner"
2: Suggested VM group "/"
(change with "--vsys 0 --group <group>")
3: Suggested VM settings file name "/root/VirtualBox Vms/Fedora CoreOS stable/Fedora CoreOS stable.vbox"
(change with "--vsys 0 --settingsfile <filename>")
4: Suggested VM base folder "/root/VirtualBox Vms"
(change with "--vsys 0 --basefolder <path>")
5: Product (ignored): fedora-coreos Fedora CoreOS stable
6: Vendor (ignored): fedora-coreos
7: Version (ignored): 36.20220806.3.0
8: Number of CPUs: 2
(change with "--vsys 0 --cpus <n>")
9: Guest memory: 4096 MB
(change with "--vsys 0 --memory <MB>")
10: USB controller
(disable with "--vsys 0 --unit 10 --ignore")
11: Network adapter: orig NAT, config 6, extra slot=0;type=NAT
12: SATA controller, type AHCI
(disable with "--vsys 0 --unit 12 --ignore")
13: Hard disk image: source image=disk.vmdk, target path=disk.vmdk, controller=12;port=0
(change target path with "--vsys 0 --unit 13 --disk path";
change controller with "--vsys 0 --unit 13 --controller <index>";
change controller port with "--vsys 0 --unit 13 --port <n>";
disable with "--vsys 0 --unit 13 --ignore")
0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
Successfully imported the appliance.
Paso seguido se inicia la vm para que aplique la configuración:
$ doas vboxmanage startvm gitlab-runner --type headless
Waiting for VM "gitlab-runner" to power on...
VM "gitlab-runner" has been successfully started.
Podemos verificar el estado de la configuración y si esta terminó inspeccionando la salida de la consola que se configuró previamente:
$ doas tail -f "/root/VirtualBox Vms/gitlab-runner/gitlab-runner.log"
Para loguearnos con el usuario core utilizamos el certificado:
$ doas ssh -i "/root/VirtualBox Vms/gitlab-runner/user_core.cert" -p 2222 core@localhost
The authenticity of host '[localhost]:2222 ([127.0.0.1]:2222)' can't be established.
ED25519 key fingerprint is SHA256:Qunkm7ADQbMOixsKPLwbZeATETdfr9+jSgz4Fk8OUhg.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[localhost]:2222' (ED25519) to the list of known hosts.
Fedora CoreOS 36.20220806.3.0
Tracker: https://github.com/coreos/fedora-coreos-tracker
Discuss: https://discussion.fedoraproject.org/tag/coreos
[core@gitlab-runner-vm ~]$
Y paso seguido apagamos la vm:
[core@gitlab-runner-vm ~]$ sudo shutdown -h now
Connection to localhost closed by remote host.
Connection to localhost closed.
Para verificar que apagó correctamente utilizamos:
$ doas vboxmanage showvminfo gitlab-runner | grep -i state
State: powered off (since 2022-09-27T17:01:30.000000000)
Configuración y pruebas de gitlab-runner
Para registrar el runner se siguen las indicaciones de Non-interactive registration.
$ export CI_SERVER_URL='https://url/to/my/instance'
$ export REGISTRATION_TOKEN='my-registration-token'
$ export SSH_PASSWORD='ohphei3op+oh5NuDophei&W4zooDahquaiNgohr9gah=b3eini#k,ai6wei/weij'
$ doas gitlab-runner register --non-interactive --url "$CI_SERVER_URL" --registration-token "$REGISTRATION_TOKEN" --executor virtualbox --virtualbox-base-name gitlab-runner --ssh-user gitlab-runner --ssh-password "$SSH_PASSWORD"
Runtime platform arch=amd64 os=linux pid=1154947 revision=bbcb5aba version=15.3.0
Running in system-mode.
Registering runner... succeeded runner=XXXXXXXX
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
Configuration (with the authentication token) was saved in "/etc/gitlab-runner/config.toml"
Nota: Sobre las variables de entorno: aquí se utilizan para que no quede en
la linea de comandos información sensible y son las variables utilizadas por
gitlab-runner en la opción de linea de comando correspondiente. Como se está
utilizando doas y este “limpia” las variables de entorno (alcanza para probar
hacer doas printenv
) es que se reintroducen utilizando parámetros.
Conclusiones
- Configurar gitlab-runner con executor shell es sencillo y rápido, pero tiene problemas de seguridad.
- La documentación para configurar el executor virtualbox no está clara en
varios puntos. El que más tiempo me llevó fué darme cuenta que virtualbox se
ejecuta con
root
en lugar de con el usuariogitlab-runner
que es el usuario que se crea al instalar el paquetegitlab-runner
y el utilizado por el executor shell. - Lo que más valió la pena fué el familiarizarme con fedora coreos y la introducción de ignition vía butane para configuración del sistema que parece ser una solución más sencilla y de menor alcance que cloud-init, el cual era usado en las imágenes de Generic Cloud de centos7.
Apendice - Cambiar directorio ~/VirtualBox VMs
Sin tener máquinas virtuales creadas o con todas las máquinas virtuales apagadas
$ vboxmanage setproperty machinefolder $HOME/virtualbox-vms
Para verificar el cambio utilizar
$ vboxmanage list systemproperties | grep folder
Fuente: https://askubuntu.com/questions/800824/how-to-change-virtualbox-default-vm-location-in-command-line