Авторизоваться
Виталик Коростелёв 11.11.2020 Опубликована

Автодеплой через gilab.ci + pm2-ecosystem 

В какой-то момент перед нами встала проблема как сделать автодеплой, потому что деплоить надо было много и часто + это ускоряет процесс разработки т.к. я могу нажраться и валяться в под забором в канаве (: быть недоступен, а раскатать и посмотреть как оно хочется уже сейчас.Так как хотелось пойти в ногу со временем я начал исследования с kubernetes-кластера и сборки докер образов через jenkins. Эксперименты я ставил на своем роутере-сервере на e6750, где столкнулся с любопытным моментом: при сборке докер-образов сборка могла идти часами. После какого-то времени исследований я выяснил что проблема кроется в https-соединении, а точнее с шифрованием, хотя из под кубернетеса некоторые контейнеры крутились как надо… Вроде как пару раз наткнулся на багрепорты про это от весны 2017. В иттоге стали искать другие решения и решили съехать на гитлаб, о чем в общем-то не жалеем.

Итак к сути: катаемся мы через gitlab-ci и pm2, так как все крутится собственно им. Как это выглядит: при пуше срабатывает триггер, гитлаб запускает докер-контейнер, из которого рулит pm2-деплоем. А теперь более подробно

Как перестать катать обновления руками и начать спокойно бухать жить

Для начала надо завести репку, а в ней положить файлик .gitlab-ci.yml примерно следующего содержания:

image: keymetrics/pm2:8

stages:
  - deploy

deploy_stage:
  stage: deploy
  script:
    - echo "====== Deploy to stage server ======"
    - apk update && apk upgrade
    - apk add git openssh bash
    # Add target server`s secret key
    - mkdir ~/.ssh
    - echo -e "$DEPLOY_KEY" | base64 -d > ~/.ssh/id_rsa
    - chmod 700 ~/.ssh && chmod 600 ~/.ssh/*
    - echo "Test ssh connection"
    - ssh -o StrictHostKeyChecking=no -T "$TARGET_SERVER_USER@$TARGET_SERVER_HOST"
    # Deploy
    - echo "Setup tagget server directories"
    - pm2 deploy ecosystem.config.js production setup 2>&1 || true
    - echo "make deploy"
    - pm2 deploy ecosystem.config.js production
  environment:
    name: deploying
  only:
  - master

Итак. Что он делает:

image: keymetrics/pm2:8 - берем pm2-образ докера с официального репозитория keymetrics

stages: - описываем стадии деплоя, а нашем случае только deploy.

дальше уже любопытнее - собсвенно deploy_staging: - говорит нам что происходит, а именно деплой на staging. В нем описываем стадии, для удобства. script - это скрипт деплоя, как нетрудно догадаться.

    - echo "====== Deploy to stage server ======"
    - apk update && apk upgrade
    - apk add git openssh bash 

обновляем пакеты, я ясно выделяем стадию, а затем немного магии подключения к серверу:

    # Add target server`s secret key
    - mkdir ~/.ssh
    - echo -e "$DEPLOY_KEY" | base64 -d > ~/.ssh/id_rsa
    - chmod 700 ~/.ssh && chmod 600 ~/.ssh/*
    - echo "Test ssh connection"
    - ssh -o StrictHostKeyChecking=no -T "$TARGET_SERVER_USER@$TARGET_SERVER_HOST"

- echo -e "$DEPLOY_KEY" | base64 -d > ~/.ssh/id_rsa переменные лучше кодировать в base64 из-за того что они крайне плохо обрабатывают переносы строк.

    # Deploy
    - echo "Setup tagget server directories"
    - pm2 deploy ecosystem.config.js production setup 2>&1 || true
    - echo "make deploy"
    - pm2 deploy ecosystem.config.js production

а вот тут уже произошла маааагия (: мы озадачили pm2 собственно деплоем.

  environment:
    name: deploying
  only:
  - master

environment задает собственно env, из которого будут браться переменные, как я понял, если честно, с этим еще не разбирался.

only показывает какая ветка будет кататься. есть еще полезный ключ when: manual - он отвечает за то что сборка не будет начинаться автоматически, а только вручную. Например вам иногда надо катать другую ветку или вы вообще не хотите деплоить автоматом.

Теперь немного про pm2:

pm2 предоставляет возможность деплоя, для этого нам нужен файл ecosystem.config.js. Сгенерировать себе такой можно командой pm2 ecosystem. Ну а вот собственно как у нас примерно это выглядит:

 // Target server hostname or IP address
const TARGET_SERVER_HOST = process.env.TARGET_SERVER_HOST ? process.env.TARGET_SERVER_HOST.trim() : '';
// Target server username
const TARGET_SERVER_USER = process.env.TARGET_SERVER_USER ? process.env.TARGET_SERVER_USER.trim() : '';
// Target server application path
const TARGET_SERVER_APP_PATH = '/usr/necronomicon/SUPER-FLYING-SHEEP';
// Your repository
const REPO = 'git@gitlab.com:worms/SUPER-FLYING-SHEEP';

module.exports = {
  /**
   * Application configuration section
   * http://pm2.keymetrics.io/docs/usage/application-declaration/
   */
  apps : [

    // First application
    {
      name      : 'SUPER-FLYING-SHEEP',
      script    : 'terminator.js',
      watch     : 'true',
      env: {
        NODE_ENV: 'testing'
      },
    }
  ],
  /**
   * Deployment section
   * http://pm2.keymetrics.io/docs/usage/deployment/
   */
  deploy : {
    production : {
      user: TARGET_SERVER_USER,
      host: TARGET_SERVER_HOST,
      ref: 'origin/master',
      repo: REPO,
      ssh_options: 'StrictHostKeyChecking=no',
      path: TARGET_SERVER_APP_PATH,
      'pre-setup': "git reset --hard origin/master",
      'pre-deploy': "rm -rf node_modules && rm package-lock.json && sudo /etc/init.d/zabbix-server stop && npm install && npm run build",
      'post-deploy' : 'pm2 reload ecosystem.config.js --env production && sudo /etc/init.d/zabbix-server start',
    }
  }
};

Впринципе тоже ничего сложного. Есть стадии pre-setupsetuppre-deploydeploypost-deploy. Еще есть минимум две локальных стадии pre-deploy-local и post-deploy-local. Несколько версий назад git reset --hard origin/master исполнялся самим pm2, но недавно он стал плеваться ошибкой

○ full fetch
fatal: destination path '/usr/necronomicon/SUPER-FLYING-SHEEP/source' already exists and is not an empty directory.

  failed to clone

как выяснилось гит-резет выпилили из самого pm2, теперь надо его делать самому. вернут или нет я так и не понял, но раньше таких проблем не было.

Заббикс-сервер приходится тушить посколько на сборку ангуляры нехватало оперативки, пришлось костылить. Для этого в /etc/sudoers надо записать строчку django_chained ALL = (root:root) NOPASSWD: /etc/init.d/postgresql

Коментарии
Авторизоваться что-бы оставить комментарий
Присоединяйся в тусовку
Наш сайт использует файлы cookie для вашего максимального удобства. Пользуясь сайтом, вы даете свое согласие с условиями пользования cookie