Voy a implementar una aplicación Spring Boot simple usando el servidor GitLab CI. Mi .gitlab-ci.yml es el siguiente:

stages:
  - build_and_test
  - deploy

web_server_build_and_test:
  stage: build_and_test
  script:
    - mvn clean package

web_server_deploy:
  stage: deploy
  script:
    - mvn clean package -Pprod
    - service gitlab-runner-test stop
    - cp target/*.war /var/gitlab-runner-test/gitlab-runner-test.war
    - chmod +x /var/gitlab-runner-test/gitlab-runner-test.war
    - service gitlab-runner-test start

Y la etapa deploy produce el siguiente resultado:

$ service gitlab-runner-test stop
Stopped [13247]
$ cp target/*.war /var/gitlab-runner-test/gitlab-runner-test.war
$ chmod +x /var/gitlab-runner-test/gitlab-runner-test.war
$ service gitlab-runner-test start
Started [21177]

Sin embargo, no puedo cargar la aplicación ya que el servicio se detuvo una vez que el corredor termina la etapa:

$ service gitlab-runner-test status
Not running (process 21177 not found)

Mis scripts de servicio delegan el trabajo real al paquete war ensamblado:

#!/usr/bin/env bash

export JAVA_HOME=/usr/lib/jvm/java-8-oracle/jre/bin/java
export MODE=service
export APP_NAME=gitlab-runner-test
export PID_FOLDER=/var/run/gitlab-runner-test


/var/gitlab-runner-test/gitlab-runner-test.war $*

Además, cuando estoy iniciando el servicio manualmente (service gitlab-runner-test start), permanece en ejecución incluso después de que se ha cerrado la sesión del usuario.

No estoy seguro, ¿cuál es la raíz del problema: el script de inicio de Spring Boot, la configuración de GitLab, mis scripts de servicio o algo más?

Estoy ejecutando Ubuntu 14.04 con GitLab CI multi runner versión 0.5.0 (c38415a).

UPD:

Actualizar el corredor a la versión 1.0.1 (cffb5c7) no resuelve el problema.

8
awesoon 29 ene. 2016 a las 19:10

2 respuestas

La mejor respuesta

Por qué es una mala idea hacerlo ...

Como indica claramente su documentación, el GitLab Runner "ejecuta pruebas y envía los resultados a GitLab ".

Y como las pruebas deben comenzar y detenerse de manera oportuna, el corredor está diseñado para matar todos los procesos creados después de terminar cada compilación.

Así que no es un error que su servicio se elimine, es una característica . ;)


La documentación de GitLab CI recomienda usar dpl para la implementación .

Dpl es un proyecto que le permite implementar su aplicación en varios proveedores de PaaS, como Google App Engine, Heroku o Elastic Beanstalk.

Por lo tanto, envía algunas solicitudes a algunas API REST o envía otros datos a través de Internet y su proceso finaliza sin problemas.


Entonces, hacer lo que quiere hacer en realidad requiere algo de piratería, anulando el comportamiento predeterminado del corredor. Y no debe hacerlo como una solución a largo plazo porque puede dejar de funcionar con alguna actualización de runner / gitlab.

... pero si insistes, aquí está el cómo :)

En su caso, cuando desee implementar y ejecutar la aplicación en el propio host de su corredor, necesitamos usar dos trucos:

  • no use el ejecutor de ejecución predeterminado shell pero ssh y haga que el ejecutor sea ssh para sí mismo (inspirado en michael's solución a esta pregunta (¡vota también su respuesta si votas a favor de la mía!),
  • rechazar el proceso que está siendo ejecutado por el script de inicio (la solución de Joe a esta pregunta (de nuevo, ¡por favor, vote a favor!)

Ok, estas son las instrucciones:

  1. Asegúrese de que puede SSH desde su host de corredor a sí mismo con una clave privada SSH en /root/.ssh/id_rsa, sin contraseña, sin confirmar la huella digital. ssh localhost ejecutado por root debería funcionar de forma no interactiva.

  2. Edite el archivo de configuración de su gitlab-runner, /etc/gitlab-runner/config.toml para que se vea así:

    [[runners]]
      name = "your-runner-name"
      url = "https://<your_gitlab_instance_fqdn>/ci"
      token = "<your_project_CI_token>"
      tls-ca-file = ""
      executor = "ssh"
      [runners.ssh]
        user = "root"
        password = ""
        host = "localhost"
        port = "22"
        identity_file = "/root/.ssh/id_rsa"
    

(El corredor se recargará solo después de guardar el archivo de configuración)

  1. Edite su script de servicio para que el proceso que creará NO sea hijo del script de inicio y no abra stdin, stdout y stderr:

    #!/usr/bin/env bash
    
    export JAVA_HOME=/usr/lib/jvm/java-8-oracle/jre/bin/java
    export MODE=service
    export APP_NAME=gitlab-runner-test
    export PID_FOLDER=/var/run/gitlab-runner-test
    
    
    /var/gitlab-runner-test/gitlab-runner-test.war $* <&- >&- 2>&- & disown
    

Pruebe volviendo a intentar la última compilación o realizando una confirmación con el repositorio de su proyecto.


PD: probé mi solución con un script de inicio que se ve así:

#!/usr/bin/env bash

start() {
  # Completely disowned process, not a child
  # Credits: Joe at https://stackoverflow.com/a/26420299/2693875
  sleep 99999 <&- >&- 2>&- & disown
  exit 0
}

stop() {
  echo "doing nothing"
  exit 0
}

echo "running on $HOSTNAME..."

case "$1" in
  start)
    start
    ;;
  stop)
    stop
    ;;
  *)
    echo $"Use this options $0 {start|stop}"
    exit 1
esac

..en Ubuntu 14.04 con gitlab-multi-runner v. 1.02 y GitLab CE 8.5.0.

13
Greg Dubicki 4 ago. 2017 a las 23:33

Si bien la solución, publicada por @GregDubicki, funciona perfectamente y contiene explicaciones para cada paso, terminé con una solución con el servicio de monitoreo, que reinicia mi servicio después de cada compilación.

Este enfoque tiene las siguientes ventajas:

  1. No debes iniciar el corredor bajo root usuario
  2. No deberías preocuparte por los procesos, asesinados por el corredor
  3. (+ bonificación) ¡Ahora tienes un sistema de monitoreo!
-1
awesoon 5 feb. 2016 a las 17:16