Los sistemas CI/CD (continuous integration y continuous delivery o continuous deployment) son cómodos para un desarrollo, cuando se realiza un commit en una rama determinada se activa un sistema automático que sincroniza el código en el servidor. Nos ahorra tiempo en comprobar errores y evitamos las monótonas acciones para mantener la web acorde al último cambio: las automatizaciones son buenas y una bendición. Por ello, en este tutorial he decidido enseñar como aplico el sistema Gitlab CI/CD para un proyecto Django. En cada commit, de una rama determinada, se lanzará un script que atravesará diferentes fases: compilación, test y despliegue. Además si existe algún problema nos avisará de inmediatamente abortando las acciones siguiente.
Requisitos
No se puede realizar esta técnica en cualquier hosting, es obligatorio disponer de:
- Repositorio Gitlab donde almacenará el código.
- VPS o servidor dedicado en el cual se ejecutará Django.
- Acceso SSH al servidor.
- Rama develop y master.
En caso contrario no será posible.
Ramas y despligues
Debemos diferenciar el desarrollo en 2 estados: no estable y para los usuarios. Cada uno dispondrá de una rama propia con un servidor separado. Con esto conseguimos un limbo seguro solo usado por el equipo para probar todo unificado, con la intención de descubrir problemas antes de que los usuarios, y otro muy estable para ser usado por los usuarios reales.
- develop: La rama donde serán integrados los cambios del equipo. Serán desplegados en un servidor privado llamado Staging. Suele utilizarse un dominio sencillo como beta.miweb.com.
- master: La rama principal. La que menos cambio recibe, y siempre después de limpiar cualquier fallo dentro de la rama Develop. Se le denomina Production y es el servidor que visitará los usuarios finales. Se asigna el dominio principal miweb.com.
Siguiendo esta arquitectura usaremos 2 servidores y 2 ramas.
Pasos
Dentro de Gitlab hay una pieza de software llamada Runner, es el encargado de realizar las tareas. Puede ejecutarse dentro de Gitlab o en el servidor donde se aloja el sitio. En el ejemplo seguiremos esta última estrategia.
1) Desactiva Shared Runners
En Settings → CI/CD desactiva Shared Runners para que no levante imágenes de Docker en paralelo cuando se active un Runner. De esa manera los procesos irán en cola, disponiendo de mayor rapidez y control.
También puedes reducir el numero de Git shallow clone a 0 para que no se haga ninguna sincronización con Git. Más adelante explicaremos su utilidad.
2) Configuración de repositorio.
Para configurar el Runner necesitaremos añadir un fichero con el nombre de .gitlab-ci.yml
en la raiz del repositorio.
Editalo con el siguiente ejemplo.
stages:
- prepare
- test
- deploy
before_staging:
stage: prepare
tags:
- staging
only:
- develop
script:
- cd /home/django/django_project
- git fetch
- git checkout develop
- git reset --hard
- git pull origin develop
before_production:
stage: prepare
tags:
- production
only:
- master
script:
- cd /home/django/django_project
- git fetch
- git checkout master
- git pull origin master
linter:
stage: test
tags:
- staging
script:
# Linter
- cd /home/django/django_project
- /home/django/venv/bin/black .
# Test
- /home/django/venv/bin/python3 manage.py test
after_staging:
stage: deploy
tags:
- staging
only:
- develop
script:
- cd /home/django/django_project
- /home/django/venv/bin/pip3 install -r requirements.txt
# DB sync
- /home/django/venv/bin/python3 manage.py migrate
# Static sync
- /home/django/venv/bin/python3 manage.py compilemessages
- /home/django/venv/bin/python3 manage.py collectstatic --no-input
# Restart web server
- sudo systemctl restart gunicorn
after_production:
stage: deploy
tags:
- production
only:
- master
script:
- cd /home/django/django_project
- /home/django/venv/bin/pip3 install -r requirements.txt
# DB sync
- /home/django/venv/bin/python3 manage.py migrate
# Static sync
- /home/django/venv/bin/python3 manage.py compilemessages
- /home/django/venv/bin/python3 manage.py collectstatic --no-input
# Restart web server
- sudo systemctl restart gunicorn
3) Configurar Runner
Descargamos binario de Runner y lo instalaremos en el servidor.
https://docs.gitlab.com/runner/install/
Para Ubuntu:
# Linux x86-64
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64
# Linux x86
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-386
# Linux arm
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm
# Linux arm64
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-arm64
# Linux s390x
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-s390
Damos permisos de escritura.
chmod +x /usr/local/bin/gitlab-runner
Creamos un usuario para Gitlab.
useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash
Y borramos su .bash_logout
para evitar conflictos en la conexión del runner.
rm /home/gitlab-runner/.bash_logout
Instalamos servicio y lo iniciamos.
gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
gitlab-runner start
Registramos el Runner.
gitlab-runner register
Le decimos donde esta nuestro servidor de CI, que es el propio Gitlab.
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com )
https://gitlab.com
Ahora nos pedirá el token, lo copiamos de Settings → CI/CD.
Le damos un nombre para identificarlo en el panel de Gitlab.
Please enter the gitlab-ci description for this runner
[hostname] my-runner
Le damos el tag que identifique el servidor, de ese modo podremos decidir que comandos ejecutará en cada uno. En el tutorial nos iniciaremos con el servidor staging.
Please enter the gitlab-ci tags for this runner (comma separated):
staging
Indicamos donde queremos ejecutar las ordenes, en este caso en el VPS/Servidor donde esta alojada la web (shell).
Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
shell
4) Configuramos VPS/Servidor para que sincronice el repositorio.
Nos convertimos en el usuario del runner.
su gitlab-runner
Creamos credenciales de SSH para que el repositio pueda hacer un pull de cada cambio.
ssh-keygen -t rsa
Damos todo a enter.
Copiamos el contenido de .ssh/id_rsa.pub
. Podemos ver el contenido con el siguiente comando.
less .ssh/id_rsa.pub
Lo añadimos en Gitlab, en la sección Settings → Deploy Keys.
Le damos un título cualquiera y pegamos en Key
lo anterior (el contenido de .ssh/id_rsa.pub
).
Ahora ya podemos crear un clone
o realizar un pull
del repositorio.
Para que gitlab-runner pueda ejecutar comandos en la carpeta de otro usuario, que será lo más habitual, tendremos que darle permisos. Le añadimos el grupo del usuario que vayamos a modificar sus archivos. Por ejemplo, si tengo un usuario que se llama django
y dentro de su carpeta home
debe estar mi proyecto de Django.
sudo usermod -a -G django gitlab-runner
Ahora buscamos la carpeta donde queramos clonar el proyecto, o trabajar, y le damos permisos de lectura, escritura y ejecución para los grupos.
sudo chmod -R g+rwx tu_proyecto
Para poder usar el comando sudo necesitaremos.
sudo usermod -a -G sudo gitlab-runner
A continuación.
visudo
Y modificamos la siguiente línea con NOPASSWD
.
%sudo ALL=(ALL:ALL) NOPASSWD:ALL
Ya podemos clonar.
git clone url-proyecto .
5) Comprueba.
Ya ha llegado el momento de subir un cambio a Develop y ver como se ejecuta en CI/CD -> Pipeline. Si todo se ha ejecutado correctamente lo marcará como Passed, sino te proporcionará un informe.
El último paso consiste en repetir los pasos del 3 en adelante para Production cambiando:
Please enter the gitlab-ci tags for this runner (comma separated):
production
Espero que os sea de utilidad.
{{ comments.length }} comentarios