Выкладка go pet проекта на VPS

от автора

Привет, Хабр! Я верю, что Golang прекрасен, но в мире еще много php и других проектов работающих на VPS,VDS. Можно поставить туда докер, но это (по мнению автора) переусложнение задачи. Можно компилировать файлик и загружать по FTP — не безопасно и не по феншую, SFTP — безопаснее, но снова не феншуй. Тогда давайте автоматизируем этот процесс через CircleCI. Мы будем по шагам писать файл конфигурации для CI, в конце соберем результат и запустим deploy.

Требования к реализации.

  1. Минимальные нововведения на сервере
  2. Deploy должен быть автоматизирован
  3. Входная точка для организации deploy — выставления тега для dev сборки и дополнительное ручное подтверждение для prod
  4. Сборка должна пройти автоматическое тестирование
  5. Механизм ручной откатки версии

Почему СircleCI?

На проекте с самого начала использовали приватный репозиторий bitbucket. (Сейчас приватные репозитории уже есть в гитхабе.) Не уходя из экосистемы Atlasian решили взять CircleCI (далее CI). Понравилось, что:

  • минимальная настройка
  • возможность debug по ssh
  • бесплатная версия, но с ограничениями
    • 2500 кредитов/в неделю (примерно 250 минут выполнения) #go собирается и деплоится быстро, нам хватит
    • однопоточное исполнение #у нас не так много pet project
    • только lunix и windows #нам нужен linux

Часть первая, workflow

Создадим папку .circle и в ней создадим файл config.yml и опишем там ожидаемый workflow ( порядок исполнения задач)

    workflows:       version: 2       tagged-build:         jobs:           - test           - dev_deploy:               requires:                 - test           - approve_master_deploy:               type: approval               requires:                 - test                 - dev_deploy           - prod_deploy:               requires:                 - dev_deploy                 - approve_master_deploy 

Вот результат:

image

Мы описали паттерн, по которому каждый комит будет сначала проверяться тестами, далее выкатываться на dev, затем при ручном подтверждение отправляться на боевой сервер. Для наведения лоска добавим фильтр, что бы задача срабатывала только по тегу.

- dev_deploy:     requires:       - test     filters:       branches:         ignore: /.*/       tags:         only: /.*/

Второй шаг, самый простой.

Начнем с запуска запуска тестов, тут будет минимум кода.

jobs:   test:     docker:       - image: circleci/golang:1.12     working_directory: ~/go-example/     steps:       - checkout       # тут будут linter'ы и тд       - run: go test -cover -v ./...

После того как наш код протестирован и прошел code style проверки, можно делать deploy на dev. Я предлагаю использоваться для запуска go сервиса supervisor (ver3.1.4 на момент написания статьи), логи будем собирать им же.
Добавим в папку .circleci файлик supervisor_ph.conf, в рамках CI PH_NAME будет меняться на имя проекта. И в такой же файл будем писать вывод логов.

[program:PH_NAME] stopasgroup=true user=deploy-user autostart=true autorestart=true stdout_logfile=/var/log/supervisor/PH_NAME.log stderr_logfile=/var/log/supervisor/PH_NAME.log redirect_stderr=true

Всё, что отличает наш проект от других:

Время Deploy

Для dev и prod изменяются только сервера и к названию приложения добавляется суффикс. Конфиг хранится в переменных окружения. (12 факторные приложения) Эту часть мы вынесем в environment, остальное продублируем.

prod_deploy:   environment:     TARGET_IP: 0.0.0.0     TARGET_DIR: /var/www/deploy-user/go-example     REMOTE_USER: deploy-user     SERVICE_NAME: go_example_prod   docker:     - image: circleci/golang:1.12   working_directory: ~/go-example/   steps:     - checkout     - add_ssh_keys #копируем добавленные в ci ключи, о них позже     - run: go build -ldflags "-X main.version=$CIRCLE_TAG" -o ./main ./src/main     - run: ssh -o "StrictHostKeyChecking=no" $REMOTE_USER@$TARGET_IP "mkdir $TARGET_DIR/v$CIRCLE_TAG" #создаем папку по номеру тега, где будут лежать исполняемые и вспомогательные файлы     - run: scp main $REMOTE_USER@$TARGET_IP:$TARGET_DIR/v$CIRCLE_TAG/ #загружаем исполняемый файл в директорию по тегу     - run: sed "s/PH_NAME/$SERVICE_NAME/g" .circleci/supervisor_ph.conf > .circleci/$SERVICE_NAME.conf     - run: echo command=$TARGET_DIR/v$CIRCLE_TAG/main >> .circleci/$SERVICE_NAME.conf     - run: scp .circleci/$SERVICE_NAME.conf $REMOTE_USER@$TARGET_IP:$TARGET_DIR/v$CIRCLE_TAG/     - run: ssh $REMOTE_USER@$TARGET_IP "ln -sf $TARGET_DIR/v$CIRCLE_TAG/$SERVICE_NAME.conf /etc/supervisord.d"     - run: ssh $REMOTE_USER@$TARGET_IP "supervisorctl  -c /etc/supervisord.conf reread && supervisorctl -c /etc/supervisord.conf update"     - run: curl "$TELEGRAM_SERVICE?msg=$SERVICE_NAME%20v$CIRCLE_TAG%20deployed&channel=go_deploy"

Для уведомлений мы будем используем собственного бота, который вызывается через curl. Команда `when: on_fail` срабатывает если что-то пошло не так, ее можно также использовать для отката изменений. Хотя у нас это телеграмм бот, но в целом можно обойтись без него и использовать стандартные нотификации: Slack,IRC. Плюс уведомления об ошибках уходят на email.
Переменную `$TELEGRAM_SERVICE` добавим через раздел BUILD SETTINGS→Environment Variables.

- run:     command: curl "$TELEGRAM_SERVICE?msg=$SERVICE_NAME%20v$CIRCLE_TAG%20failed&channel=go_deploy"     when: on_fail

Финишная прямая

Делаем push в github или в bitbucket. После идем в CircleCI в пункт Add project

Затем выбираем Start building. Финальным шагом будет добавления ssh ключа для авторизации на сервере под выбранным пользователем.

Всё можно делать deploy, ставим tag и начинаем радоваться жизни. Финальный вариант ./.circleci/config.yml — тут

ссылка на оригинал статьи https://habr.com/ru/post/485240/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *