Как запустить службу с помощью GitLab runner и предотвратить ее остановку?

Я собираюсь развернуть простое приложение Spring Boot с помощью сервера GitLab CI. Мой .gitlab-ci.yml выглядит следующим образом:

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

И этап deploy дает следующий результат:

$ 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]

Однако я не могу загрузить приложение, так как служба была остановлена ​​после того, как бегун завершил этап:

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

Мои служебные скрипты делегируют реальную работу собранному пакету war:

#!/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 $*

Более того, когда я запускаю сервис вручную (service gitlab-runner-test start), он продолжает работать даже после закрытия пользовательского сеанса.

Я не уверен, в чем корень проблемы - сценарий запуска Spring Boot, конфигурация GitLab, мои служебные сценарии или что-то еще?

Я запускаю Ubuntu 14.04 с многопользовательской версией GitLab CI 0.5.0 (c38415a).

UPD:

Обновление раннера до версии 1.0.1 (cffb5c7) проблему не решает.


person awesoon    schedule 29.01.2016    source источник
comment
О, я понимаю, в чем проблема. Используйте nohup, чтобы запустить процесс, не завершая его при выходе из родительского объекта. Итак, - nohup service gitlab-runner-test start или nohup /var/gitlab-runner-test/gitlab-runner-test.war $*.   -  person Chloe    schedule 21.12.2018


Ответы (2)


Почему это плохая идея ...

Как четко указано в документации, GitLab Runner "запускает тесты и отправляет результаты в GitLab ".

И поскольку тесты должны запускаться и останавливаться своевременно, раннер предназначен для уничтожения всех созданных процессов после завершения каждой сборки.

Так что прекращение работы службы не является ошибкой, это функция. ;)


В документации GitLab CI рекомендуется использовать dpl для развертывания .

dpl - это проект, который позволяет вам развертывать ваше приложение у различных поставщиков PaaS, таких как Google App Engine, Heroku или Elastic Beanstalk.

Таким образом, он запускает некоторые запросы к некоторым REST API или проталкивает некоторые другие данные через Интернет, и его процесс красиво завершается.


Таким образом, выполнение того, что вы хотите, на самом деле требует некоторого взлома - переопределения поведения бегуна по умолчанию. И вы не должны делать это как долгосрочное решение, потому что оно может перестать работать с некоторым обновлением runner / gitlab.

... но если вы настаиваете, то вот как это сделать :)

В вашем случае, когда вы действительно хотите развернуть и запустить приложение на самом хосте вашего бегуна, нам нужно использовать два взлома:

  • не используйте shell исполнитель runner по умолчанию, а ssh и сделайте исполнителя ssh самому себе (на основе решения Майкла на этот вопрос (пожалуйста, проголосуйте за его ответ, если вы проголосуете за мой!),
  • отказаться от процесса, который запускается сценарием инициализации (решение Джо на этот вопрос (снова - пожалуйста, проголосуйте за него!)

Итак, вот инструкции:

  1. Убедитесь, что вы можете использовать SSH с вашего хоста runner к самому себе с закрытым ключом SSH в /root/.ssh/id_rsa, без парольной фразы, без подтверждения отпечатка пальца. ssh localhost, запущенный root, должен работать в неинтерактивном режиме.

  2. Отредактируйте файл конфигурации вашего gitlab-runner, /etc/gitlab-runner/config.toml, чтобы он выглядел так:

    [[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"
    

(Бегун перезагрузится после сохранения файла конфигурации)

  1. Отредактируйте сценарий службы, чтобы создаваемый им процесс НЕ был дочерним по отношению к сценарию инициализации и не открывал stdin, stdout и 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
    

Протестируйте, повторив последнюю сборку или сделав фиксацию в репозитории вашего проекта.


PS Я протестировал свое решение с помощью сценария инициализации, который выглядит следующим образом:

#!/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

..на Ubuntu 14.04 с gitlab-multi-runner v. 1.02 и GitLab CE 8.5.0.

person Greg Dubicki    schedule 04.02.2016
comment
Спасибо! Я проверю ваше решение, как только приду на работу. Обязательно ли запускать раннер с правами root? - person awesoon; 05.02.2016
comment
Итак, если развертывание GitLab CI - плохая идея, не следует ли мне вместо этого написать собственный провайдер для dpl? - person awesoon; 05.02.2016
comment
Почему кто-то должен использовать dpl вместо eb deploy для Elastic Beanstalk? - person Chloe; 21.12.2018
comment
Вероятно потому, что dpl предоставляет унифицированные интерфейсы для многих бэкендов, не только AWS, но и GCP, Azure, Heroku и т. Д., @Chloe. - person Greg Dubicki; 22.12.2018

Хотя решение, опубликованное @GregDubicki, работает отлично и содержит объяснения для каждого шага, я получил решение со службой мониторинга, которая перезапускает мою службу после каждой сборки.

Такой подход имеет следующие преимущества:

  1. Вы не должны запускать runner под root пользователем
  2. Вы не должны заботиться о процессах, убитых раннером
  3. (+ бонус) Теперь у вас есть система мониторинга!
person awesoon    schedule 05.02.2016
comment
Мне интересна созданная вами служба мониторинга. Это на гитхабе? Вы нигде не встречали ничего подобного? Похоже, запуск приложения был бы важным шагом в CICD, который, похоже, не особо освещен. - person Ali; 17.04.2019
comment
Что ж, это было около 3 лет назад, с тех пор многое изменилось, в настоящее время я не работаю над этим проектом, поэтому я не могу вспомнить точные детали эволюции процесса CI / CD. Хотя я помню, какую систему мониторинга я использовал, это была mmonit - работала нормально и решила проблему с перезапуском службы (все, что вам нужно, это развернуть новые файлы и остановить службу - система мониторинга перезапустит ее за вас). Однако через некоторое время я изменил сценарий, чтобы использовать подход, похожий на dpl. Это было не совсем dpl, потому что ... - person awesoon; 17.04.2019
comment
... Это было не совсем dpl, потому что мы не использовали облачные серверы, поэтому наше индивидуальное решение работало нормально. Конвейер был очень прост: построить войну, scp ее передать на сервер и запустить deploy.sh сценарий на этом сервере поверх ssh. deploy.sh был способен создавать новые службы при необходимости (скажем, если мы развертываем тестовую ветвь, нам нужно создать новую службу, а затем уничтожить ее), подготавливать конфигурацию приложения (база данных, хост, порт и т. Д.) И так далее. Я разговаривал с разработчиком из этой компании несколько месяцев назад, и теперь они планируют перейти на Docker + k8s (или аналогичную платформу развертывания). - person awesoon; 17.04.2019
comment
В настоящее время я использую k8s для своих новых проектов, однако, если вы не используете Docker, я предлагаю вам использовать отдельный сервер для сборок CI и развертывать свои приложения (даже среды разработки и промежуточные среды) на отдельном сервере с подходом, подобным dpl. Хотя, если ваша компания небольшая и у вас еще нет отдельного сервера для приложений, вы можете использовать инструмент мониторинга для перезапуска приложений, но это не идеальное решение. - person awesoon; 17.04.2019