Обновление кода на продакшене (или деплой) одна из рутинных операций которые приходится выполнять время от времени, и в зависимости от сложности архитектуры может превратиться или в просто, или в ужасно нудный процесс.
На то мы и программисты чтобы автоматизировать рутину, поэтому ниже речь пойдет о автоматизации процесса выгрузки обновлений в продакшен, при помощи подсмотренной в рубистов утилиты Capistrano.
Установка
Capistrano распространяется в виде ruby gem'a, поэтому для установки сначала ставим gems:
aptitude install gems
после чего с гемов устанавливаем Capistrano
gem install capistrano
Что нам стоит деплой процесс построить
Инструкции прописываются в файле Capfile, который обычно лежит в корне проекта и содержит шаги и разнообразные функции использующиеся при деплое (или для автоматизации еще каких-нибудь нудных задач).
Давайте сконфигурируем обновление проекта, содержащего PHP/Nodejs код, хранящийся в git, при том что на продакшене PHP и NodeJS бегают на разных серверах. Итак, для обновления всей системы необходимо:
Сервер 1:
обновить php код из git
Сервер 2:
1. Остановить старый NodeJS сервер
2. Обновить NodeJS из git
3. Запустить новый NodeJS сервер
Начнем с конфигурации серверов. Так как Capistrano мы "одолжили" в рубистов, то естественно и Capfile прийдется писать на руби, но ничего страшного в этом нет, для наших плотских задач высоких знаний не потребуется.
Пропишем параметры доступа к обеим серверам:
set :application, "DeployMe"
role :app_server, "myserver.com"
role :nodejs_server, "myserver2.com"
set :user, "nakko"
В первой строке указали название приложения, в строках 2, 3 хосты серверов, а в 4-ой имя пользователя которым будем авторизироваться. Пароли не указаны, потому что дурное дело хранить ssh пароли в конфигурационных файлах, поэтому будем использовать авторизацию по публичному ключу (настройка ssh public key авторизации).
Теперь создадим задачу для обновления php кода:
desc "Update appserver"
task :update_appserver, :roles => :app_server do
puts "Updating php sources"
run "cd /var/www/myproject && git pull"
puts "Done"
end
Задача "update_appserver" выполнит все входящие в нее команды на сервере (или серверах) заданных в app_server. Для обновления в нашем случае просто выполняется git pull в определенной папке (Capistrano умеет более "умно" работать с git, больше тут).
Очередь обновить NodeJS
desc "Update nodejs"
task :update_nodejs, :roles => :nodejs_server do
puts "Stoping old instance"
pid = capture("echo $(ps aux | grep '[s]erver.js' | awk '{print $2}' | head -n 1)").strip
run "kill #{pid}" if pid != ""
puts "Updating code"
run "cd /var/www/node && git pull"
puts "Starting new instance"
run "node /var/www/node/server.js &"
puts "Done"
end
Пройдемся по использованных командах:
puts - вывести строку (например для индикации текущего этапа деплоя)
run - выполнить команду на сервере
capture - выполнить команду и вернуть результат, мы использовали для получения идентификатора процесса nodejs сервера для последующей остановки.
И напоследок сделаем задачу которая будет выполнять полное обновление:
desc "Update all"
task :update do
update_appserver
update_nodejs
end
Тепер выполняем в консоли
cap update
и наслаждаемся процессом.
Как видите никаких высоких материй.
Но самое вкусное то, что в ролях которые мы задавали в самом начале можно указать не один, а несколько серверов, тоесть не только
role :app_server, "myserver.com"
но и
role :app_server, "myserver.com", "myserver10.com", "myserver11.com", "myserver12.com"
В таком случае команды будут выполнены параллельно на всех серверах.
Итак, никакой рутины, гибко и расширяемо, у нас опять получилось переложить на компьютер часть своей работы. Еще бы научить его кофе готовить и пиво открывать)
На самом деле Capistrano умеет намного больше чем перечисленные 3 команды, поэтому кого заинтересовало - вики проекта.
В тему:
Если пост понравился - нажмите на +1 - мне будет приятно.