В какой-то момент перед нами встала проблема как сделать автодеплой, потому что деплоить надо было много и часто + это ускоряет процесс разработки т.к. я могу нажраться и валяться в под забором в канаве (: быть недоступен, а раскатать и посмотреть как оно хочется уже сейчас.Так как хотелось пойти в ногу со временем я начал исследования с 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
Итак. Что он делает:
- берем pm2-образ докера с официального репозитория keymetricsimage: keymetrics/pm2:8
- описываем стадии деплоя, а нашем случае только deploy.stages:
дальше уже любопытнее - собсвенно
- говорит нам что происходит, а именно деплой на staging. В нем описываем стадии, для удобства. deploy_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"
переменные лучше кодировать в base64 из-за того что они крайне плохо обрабатывают переносы строк.- echo -e "$DEPLOY_KEY" | base64 -d > ~/.ssh/id_rsa
# 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
задает собственно env, из которого будут браться переменные, как я понял, если честно, с этим еще не разбирался.environment
показывает какая ветка будет кататься. есть еще полезный ключ 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-setup
, setup
, pre-deploy
, deploy
. Еще есть минимум две локальных стадии post-deploy
pre-deploy-local
и post-deploy-local
. Несколько версий назад
исполнялся самим pm2, но недавно он стал плеваться ошибкойgit reset --hard origin/master
○ 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