Pull to refresh

Comments 81

я также укажу конкретную версию (такая педантичность когда-нибудь убережет вас от ошибок из-за обратной несовместимости новых версий некоторых гемов)


А разве Gemfile.lock не для этого придуман?
Может получиться так, что вы обновите сам гем (например, со второй до третьей версии) и попробуете выполнить старый сценарий с помощью нового гема.
Как правильно заметил farcaller, именно для этого и есть Gemfile.lock.
И нет, не может если:

1. в репозитории хранится как Gemfile, так и сгенерированный Gemfile.lock
2. и если выполняется все через bundle exec
Полагаю, вы правы. Ремарка дана под влиянием bootstrap-sass, обновившегося с 3.1 до 3.2 (в чем, казалось бы, ничего криминального) и сломавшего деплой. Сейчас поправлю в тексте, чтобы не смущать народ.
Возможно, у вас ассеты не перекомпилились.
Так и произошло, и по этой причине деплой не был выполнен — Capistrano зафиксировал ошибку компиляции.
Тут, кстати, не указано что будет при перезагрузке сервера, а будет печаль.
Эту часть я тоже хотел включить, но уже и так слишком много букв. Или нет?
Минималистичный конфиг того же monit'а не повредит. Ну и как минимум упоминание о том что этим стоит озаботиться.
Про него и Unicorn Worker Killer тоже думаю. Допишу — добавлю. Спасибо!
Для перезапуска и мониторинга CPU/ памяти рекомендую посмотреть на github.com/kostya/eye.
Для его интеграции в capistrano есть capistrano-eye. Очень простой gem которые автоматом добавляет таски по eye load config/ eye restart
В одном конфиге может быть несколько процессов (unicorn/ sidekiq/ etc), а так же приложение может быть разделено на несколько конфигов, что удобно если куски деплоятся отдельно, но хочется их перезапускать одновременно
Хороший пост, спасибо.
Добавлю буквально мелочь: при установке версии руби, имеет смысл сразу её[версию] ставить по дефолту.

rvm install 2.1.3
rvm --default use 2.1.3

Да, кстати! Спасибо, дособираю все замечания и внесу правки в текст.
Статья весьма неплохая вышла — неделю назад у самого были мысли написать о том же и примерно теми же словами, но лень-матушка не дала.

В некоторых моментах, правда самую малость перемудрили.

В наших проектах используем rbenv вместо rvm — результат получается более гибкий и адекватный, потому что rbenv не лезет куда не нужно — весь зоопарк версий ограничен уровнем директорий, что бывает очень полезно например если на одной и той же машинке в соседних папках живут приложения, работающие на разных версиях руби. Сам довольно долго пользовался RVM, но в итоге посчитал этот подход более удобным. Кроме того, достаточно сильно напрягает что RVM прописывается везде так что потом не выпилишь, подменяя стандартные команды шелла. И еще, если какой-то руби-скрипт (не рельсы, а например какой-нибудь парсер) запускаются по крону, с RVM я долго плясал почему окружение ведет себя как-то странно пока не прописал в этот же crontab состояние всего окружения с текущего пользователя. Как по мне — так топорный подход, это как для того чтобы завести будильник, ты должен был ему свои паспортные данные показывать. В этом плане rbenv работает значительно проще. Но и для стандартного rvm-подобного подхода никто не мешает задать глобальную версию руби, а также отдельную версию например для шелла (а также набор гемов чтобы не грузить лишнее для консольных утилит).

Что касается основного сабжа — для тех же людей на кого ориентирована статья стоит сказать о том что все это можно и нужно автоматизировать, потому что каждый раз при разворачивании контейнера проделывать весь ритуал из раза в раз надоест уже разе на втором.

Конечно, уже не в рамках этой статьи, но дальше заинтересовавшимся лучше посмотреть в сторону связки Vagrant / Docker чтобы деплой ограничивался вообще разворачиванием собственного заранее настроенного контейнера со всем окружением (тем более удобно если вся команда работает с копиями этого же контейнера локально и ни у кого ничего не отличается). Но это мня уже чуток занесло. Понедельник, простите.

P.S. собственно, кому интересна замена rvm, посмотрите: github.com/sstephenson/rbenv
Спасибо за такой развернутый комментарий, я во многих мануалах видел rbenv, но пока еще не разбирался с ним. А что касается деплоя контейнеров — уже и хостеры, вроде Digital Ocean, предлагают дроплеты с предустановленным окружением.
Не осилил rbenv и rvm (не смог их настроить так, чтобы оно устанавливалось в %homedir% при компиляции, а затем работало из /opt). Запилил свой скрипт, который на специальном build сервере (docker) скачивает сорцы ruby, компилирует их и устаналивает только нужные gem. Затем это упаковывается в rpm, который уже устанавливает ruby в /opt директорию. В результате мы можем установить рабочие ruby для приложения в docker без всяческих gcc, headers, -devel пакетов, только бинарники. Docker контейнеры подготавливаю как раз установкой этих rpm.
postmodern/ruby-install вам в помощь. Зачем RVM на сервере куда происходит деплой не понятно.
Вы тоже за rbenv? Поделитесь ссылкой на что-нибудь, что даст ясное понимание преимуществ?
Товарищ имел ввиду другой подход — github.com/postmodern/ruby-install

А насчет плюсов и минусов — это как разные дистрибутивы линукса сравнивать. Это чрезвычайно субъективно. Просто пакетные менеджеры (читай — способы приспособить среду под себя для выполнения в ней ruby-скриптов)

Очень кратко мое мнение:

RVM — наиболее популярен, встраивается в окружение, меняет под себя настройки шелла, хранит все версии в себе, больше подходит для практики «один контейнер — одно окружение — один проект» (ну или несколько проектов но с единым набором вводных данных для начала работы).

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

ruby-install — не совсем пакетный менеджер, скорее я бы назвал утилитой для установки любой версии руби в систему, больше подходит для задач «поставил и забыл», минимум настроек, версия по-умолчанию глобальна на контейнер.

-+-+-+-

Тем не менее, любой из инструментов справится со своей задачей — поставить нужную версию руби и настроить окружение. Любой можно использовать по своему усмотрению и у каждого свои плюшки. Первыми двумя я пользовался на реальных проектах, последний — разок ставил посмотреть нужно ли оно и счел для моих задач не нужным (читай — для моих задач не настолько нужным чтобы менять привычное на него).

Буду рад если кто аргументированно поправит.
Я за RVM. rbenv я терпеть не могу. Я не одобряю использование rvm'а и ему подобных на продакшен серверах.
Чрезвычайно интересно услышать подробное обоснование.
1. что не так с rbenv и как он мешает вашему подходу?
2. чем rvm лучше и почему вы за него?
3. почему не одобряете использование на продакшене?

Это не придирка, просто реально интересно обоснованное мнение, потому что кроме субъективного нравится / не нравится вообще в интернете мало что встречаю. В принципе не понимаю, как может нравиться или не нравиться консольная утилита или пакетный менеджер. Как минимум, интересны критерии оценки.
0. Зачем rbenv и rvm вообще? Так ли они часто нужны?
Это зависит от подхода в разработке и специфики версий.

Например, у нас частая задача — иметь несколько версий ruby для разных приложений дабы они не пересекались друг с другом. Это может быть полезно если несколько веб-приложений работают из одного контейнера, чаще всего это могут быть веб-сайты, которые могут быть написаны в разное время, и не факт что какие-то из них будут активно поддерживаться (клиенты оплатили работу, хостинг на год и все, на этом работа над сайтом закончилась), соответственно велик риск нарушить работоспособность сайта если обновить версию руби глобально. Решается как раз при помощи rbenv с привязкой отдельной версии руби и локом ее на проект.

Если вы работаете над большими приложениями или просто придерживаетесь подхода: один контейнер — одно приложение, то может вам ни rvm ни rbenv не нужны и вы ставите глобально версию руби в системе с которой работает конкретное приложение.

Как говорится — итс ап то ю.
А у ruby так много несовместимых версий, что Lock и всё? Сколько их сейчас актуальных? 2? 3?
Не так много, но например на реальном проекте когда ненароком обновили с 1.8.7 до 2.1.2 много чего отвалилось и проект упал, пролежав в дауне до тех пор пока не локализовали проблему. Да, это было всего пару часов от силы, но с тех пор взяли за практику лочить версии на проект. Опять же, это справедливо для нашего подхода который я описал, поэтому вам и кажется нелогичным потому что вы работаете иначе.
Логично. 1.8.7 это вообще другой язык. Частные применения мне понятны. Но это же совершенно специальные случаи. А тут прямо так мимоходом как само собой разумеющееся — «ставим rvm». В том же python все напропалую используют virtualenv. Но в python нет традиции bundler и там оно как раз его функции выполняет. А тут…

P.S. Понятно, что я на хостинге держу php 5.2, тут даже пришлось копать патч, который его к apache 2.4 клеит… Но это очень специфичная бизнес-проблема хостинга…
0) Если на одной машине надо несколько версий руби. Позволяет очень просто установить разные версии с разными патчами и легко между ними переключаться. К примеру, у меня есть скрипты которые написаны под jruby (нужны настоящие треды), есть приложение которое должно работать в 2.0.0, на каждый день я использую 2.1.x, а так же есть одно легакси под 1.9.3 которое нельзя взять и обновить не уделяя времени на это.

Делать Vagrant Box под каждый проект затратно. Впрочем у меня есть универстальная коробка под руби приложения, но это скорее чтобы не устаналивать 100500 зависимостей на рабочую машину.
1) rbenv это три шага назад если сранивать с rvm; (тоесть до уровня питона)
2) Я использую практически весь функционал rvm, которого в rbenv тупо нет
3) Потому, что на продакшене должна быть одна версия руби и ровно одно приложение; если на продакшене зоопарк версий и приложений то это шаред хостинг для php, а не продакшен сервер.

1. размыто, хочется конкретики
2. опять же как и по первому вопросу важна и интересна конкретика
3. Зависит от приложений, подхода и ситуации. Один из кейсов описал в комментарии выше. Задачи бывают разные, и под приложением каждый понимает что-то свое. Приложением прекрасно может являться и сайт на пару страничек, для которого отдельный контейнер брать — жирновато. Предвижу что вы скажете мол зачем тогда вообще ему руби или пишите статику и юзайте шаред-хостинги, но опять же, это дело подхода, и соответственно личное дело каждого. В идеальном мире конечно нужно только по фен-шую все делать, но мы живем в реальности, где иногда один чайный пакетик можно на две и более кружек заварить и никто от этого не умрет.
1-2) Вы же понимаете, что это один и тот же вопрос? Меня просто не устраивает функционал rbenv, и нравится функционал rvm. Я же не эвангелист rvm, чтобы склонять кого-то на ту или иную сторону. Я считаю, что от rbenv несет питоном. Кого-то устраивает rbenv, лично меня нет.

3) Используйте, я не против. Я просто этого не одобряю. Только потому не удивляйтесь когда у вас утечет база или, что-то в этом роде. Я помню как было весело проникат на один ресурс через соседний DLE. Впрочем, легковестные контейнеры существуют уже много лет: zones, jails. Теперь даже есть хипстерский docker.
1-2) я не пытаюсь кого-то достать или подколоть, мне реально интересна суть. Где если не на хабре могут развернуто и обоснованно рассказать об интересующей теме? Просто подход «нравится / не нравится» например попахивает не питоном а детским садом. Ценность ответа была бы намного выше если бы вы описали ту задачу которая решается без труда при помощи rvm но rbenv для нее не подходит — это была бы ценная и полезная информация, может быть побудившая кого-то написать отдельную статью. И нашлись бы люди кто рассказал как эту же задачу решают совершенно по-другому.

3) проекты разного уровня требуют разных подходов и степеней защиты данных. По легковесным конейнерам в соседней теме на хабре обсуждали — это безусловно круто, но на это надо переходить, а перетаскивать over9000 проектов без надобности — выкидывать ценное время на реорганизацию того что уже работает и кушать не просит. Тем не менее думаем в этом направлении и ищем решения, пока не все прозрачно и удобно.
Собрать руби с правильными патчами. Создать 3 гемсета на основе того, что было собрано. Сделать обвертку для пары гемом — чтобы foo сразу использовать jruby, bar — использовать rbx. При этом все остальное было в 2.1.2. Каждый проект имеет свой гемсет который автоматически включается при заходе в директорию. Я так же хочу, что jruby всегда был доступен через обвертку. Технически rbenv даже не может установить руби.

У кого это over9000 проектов? Что за фабрика визиток? Секрет контейнеров в том, что они существовали уже давно. Но линукс в них не мог (И все еще не может)

За ruby-install спасибо, не знал. Вот так и изобретаются велосипеды.
Только мой костыль уже немного продвинутее.
была похожая задача — решить можно простым шелл-скриптом и символьными ссылками. Хотя ваш подход реально интереснее. Тоже нечто подобное обдумываем, но пока это на стадии «отложено на завтра», пока уровень потраченного свободного времени не соотносится с явной или неявной выгодой. Но с каждым подобным примером интерес-таки к экспериментам растет.
Оставлю это здесь: wiki.summercode.com/rails_deployment_step_by_step_to_ubuntu — пошаговое руководство по настройке деплоймента рельсо-приложения на один продакшн-сервер (там есть один нюанс в том, что статья основана на Capistrano 2.x, а не на 3-ем, у меня руки все никак не дойдут обновить)
Замечание к статье: у вас не zero-downtime деплоймент. Вы сначала гасите все юникорны, а потом поднимаете. Будет даунтайм. Чтобы не было даунтайма, нужно рестартовать юникорны через сигналы. В моей инструкции (см. выше) это учтено (так же как и автоматическое поднятие юникорнов после перезагрузки сервера через init.d-скрипты).
Да, это просчет :-( Мне от чего-то казалось, что апстрим nginx-а продержит соединение пока перезапускается Unicorn. Ваш мануал хорош, но там много кода и мало слов — для чайников будет сложновато разобраться.
Да, я с этим совершенно не буду спорить. Скорее писал его для себя, как памятку, и для того, чтобы скинуть кому-нибудь ссылку.

А что касается юникорна и zero-downtime деплойменту дело вот в чем: при запуске юникорн создает процесс-мастер, который читает config/unicorn.rb (обычно) и создает какое-то кол-во воркеров — своих форков; и мастер же обслуживает unix-сокет. При получении сигнала на рестарт, мастер-процесс перестает распределять новые запросы из unix-сокета (куда их отправляет nginx) между детьми, он как раз запускает новый мастер, и ждет, пока тот поднимет нужное кол-во воркеров, а воркеры текущего вернут результаты обработки запросов и тогда они тоже гасятся. Потом передает бразды правления сокетом новому мастеру и само-уничтожается.
Зачем же вы учите юзеру в sudoers указывать NOPASSWD:ALL =) Небезопасно, да и не за чем.
Ряд англоязычных гайдов по Капистрано рекомендует делать это именно таким образом; если очень страшно — предлагают nopasswd на исполнение ограниченного набора команд. Но если совсем страшно, то можно даже отказаться от выполнения блоков кода, требующих sudo; только линковать конфиги и перезапускать сервисы придется вручную.
Чтобы меня потом не обвиняли в голословности, вот ссылка, раздел Authorisation. Я добавлю в текст, но смысл таков: если требуется использование собственных сценариев (базовые функции Capistrano не требуют sudo), то необходимо иметь этот самый paswodless sudo. В контексте статьи и вашего комментария, строка в sudoers может выглядеть так:

demo ALL=NOPASSWD:/etc/init.d/mysqld, /etc/init.d/apache2
Так уже лучше. Мало ли кто-то напишет <%= `ls #{params[:dir]}` %>. Пример, конечно, совсем деревянный, но могут и другие дыры оказаться.
Вообще конфигурацию веб-сервера и субд, думаю, нелогично в капистрано запихивать. Если много серверов, для этого есть chef. Если один — можно вручную настроить.
Добавьте в Capfile:
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'

Иначе придётся при каждом деплое вручную накатывать миграции и компилировать ассетсы.
А мы реквайрим же полный стек capistrano/rails — и миграции, и ассеты компилируются в таком виде.
извините, не заметил. Никогда не приходило в голову реквайрить полностью весть capistrano rails, посмотрел gem, это по сути то же самое.
для сборки ассетов
Rails по-дефолту хочет работающий ExecJS для компиляции coffee -> js. Можно не ставить.
Chef это слишком тяжеловесно, мне кажется Ansible тут в самый раз будет. Заодно можно и функции Capistrano заменить.
Если кому будет интересно, то могу написать playbook и сделать обзорную статью здесь на эту тему.
Не можно, а нужно. И вот я бы даже попросил меня известить :)
Я такую штуку уже делал для клиента. Лежит на гитхабе https://github.com/redde/ansible-rails-stack. К сожалению, доки нет и основная работа идет в сабмодулях.
Вот, отлично!

Из improvements я бы дописал еще две роли (RVM + source), то есть выбор способа установки нужной версии Ruby(не все апологеты rbenv). Ну и в головном плейбуке файл Readme бы дописать. Раз уж вы в гэлэкси это закинули, то описание минимальное надо.
+ сервер бы, Unicorn/PUMA
В галакси не закидывал, пока только дописал файлы метадаты да и то не для всего.
Добавление rvm потребует написания кучи кода. Также, как и использование mysql.
Для шеф рецептов я игрался с пумой, однако в продакшене использую только unicorn. Гитлаб ушел обратно на unicorn с пумы, ну и я не знаю ни одного проекта на пуме.

Я не до конца разобрался с переменными в ansible, поэтому в коде есть не очень красивые куски.

Если хотите — присоединяйтесь к разработке.
Конечно, коллега.
В свободное время помогу Вам с развитием плейбуков.
Поправьте — редактировать sudoers следует ТОЛЬКО командой visudo. Она вызывет /etc/alternatives/editor который вы можете настроить в т.ч. и на nano. Но самое главное — visudo выполняет проверку синтаксиса /etc/sudoers, а также проверяет не редактирует ли этот файл кто-то вместе с вами.
добавлю, что если вам нужно запустить visudo под конкретным редактором на один раз, то можно перед запуском в переменной окружения EDITOR указать желаемый редактор:
$ sudo EDITOR=nano visudo
Nginx в Ubuntu стоит ставить не сысоевский, а собранный ребятами из команды поддержки nginx в Ubuntu из соотв. PPA ppa:nginx/stable launchpad.net/~nginx/+archive/ubuntu/stable
Сразу за оба комментария спасибо! — Сейчас поправлю.
Ничего не говорит за VPS. VPS всегда медленее шареда. Просто надо шаред искать нормальный.

Я не совсем понял, зачем в этой статье RVM. Это какая-то прослойка типа болонки для сдачи спектакля комиссии? Понятно зачем он нужен, но что он даёт в контексте статьи. Я бы например сделал упор на установку bundler и gem в домашний каталог, или вот bundle standalone. Об этом многие не знают и начинается тыкание rvm во все дыры.

P.S. А вообще любая статья про деплой — это круто :)
Гм, что-то и правда много ругаются на RVM, придется переписать этот кусочек. А по поводу хостинга ты, Щорс, предвзят :-) А если нет, то предлагай, про выбор хостинга там много свободного места осталось.
Я не предвзят. Я же дауншифтингом занимаюсь. VPS — это боль. Да, иногда он нужен, не спорю. Но для размещения приложения на рельсах вполне сойдёт например мой шаред. И вот да — вопрос развёртывания приложения он важен.
RVM он на самом деле тоже нужен. Но он тут портит всё своей лишнестью. Или тогда надо как-то привязать, где он тут к месту
До меня просто не совсем доходит что же в нем такого страшного, как по мне — он примерно Brew в Mac OS X. Пишут, что подменяет собой кучу пакетов, гадит по разным директориям. Я может чего-то не понял, но всегда думал, что использует только ~/.rvm и выпилить его можно удалив эту директорию и пару строчек из ~/.bash_profile?
А зачем? В чём смысл? В ruby в отличии даже от того же Python есть bundler, который 99% задач с разными пакетами решает.
Настраивал сервера, используя конфиги вот отсюда: gist.github.com/mikhailov/3052776
Может быть там мало комментариев и подробностей, зато неплохо прокачал скилл в процессе настройки.
Чем хуже ruby + nginx + passenger? Можно посмотреть бенчмарки?
Есть бенч 2009 года, но там а) не все так однозначно б) прошло пять лет. Есть свежий взгляд у Ярда, но выводы несколько иные.

Я писал про Unicorn потому что это не худший вариант. Кроме того, он позволяет чуть полнее понять принцип работы всей связки и возможности настройки. Плюс я не знаю как у пассажира с выносом за пределы одного сервера. Поделитесь своим опытом?

Но в целом-то вопрос из серии modphp или phpfpm, нет?
Мне показалось, что nginx + passenger гораздо проще в настройке. Если нет разницы в производительности, то и нет смысла «платить больше», как по мне.
Дико извиняюсь, если мои вопросы уже были раскрыты в комментах, но лень-матушка переборола над поиском во всех комментариях.

1. Зачем на production-сервере использовать Ubuntu. Ведь намного удобнее CentOS, или тот же самый Debian?

2. Насчет Vagrant. Если использовали, то в чем профит после поднятия сервера? То есть, вы же не дропаете сервер каждое утро и не поднимаете его с нуля.

3. Лично вас, устраивает RVM на сервере? Просто я не заметил особых недостатков в его использовании не на машине для локал-девелопмента.
Мне лично прекрасно подходит Убунта. Я не слышал ни о каких побочных эффектах, противопоказаниях и проблем за последние три года не испытывал.

Против RVM в комментариях выше уже высказывались; я, ради чистоты эксперимента, проделал все описанное в тексте, но с RBENV (плюс подменить одну строку импорта в Capfile). Апдейт к статье пишется (также и про мониторинг), скоро приаттачу отдельную ссылку (ибо редактор хабра — мука).

Про Вагрант совсем не понял вопроса %)
Интересно, а чем Debian удобнее Ubuntu?)
Времена, когда Ubuntu «могла быть» хуже Debian давно прошли и Вам настало время забросить этот топор войны.
А то получается, война закончилась, а Вы все поезда под откос пускаете.
Используем 200+ виртуальных и хостовых машин на Ubuntu(10,12,14 lts) и Debian и не находим каких-либо принципиальных отличий, чтобы пересесть только на Debian.
Как раз сам хотел написать на днях подобную инструкцию, но вы справились отлично.

В принципе, мы в работе используем тоже самое, только связка nginx + passenger и вместо RVM используем rbenv, но в общем ничего не отличается практически.
В комментариях за RVM я уже получил тумаков, скоро приложу ссылку на апдейт с Rbenv. Но есть вакантный слот с хорошим тестом производительности серверов приложений. Вы вот почему passenger выбрали?
Ну есть и на Unicorn проекты, но все актуальные проекты на passenger.

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

В принципе, это как и в вопросе rbenv/rvm — чистой воды вкусовщина. По той же производительности смотря как мерить. Разные приложения имеют разный принцип работы, и где-то пассажир показывает лучшие результаты в определенных условиях, а где-то единорог.

Ключевой аспект выбора именно то что используем парадигму нескольких проектов на одной VPS. Хотя планируем в не столь отдаленном будущем переходить на какое-то решение наподобие Docker'а, и концепцию «одно приложение — одно окружение», но пока в этом направлении еще маловато опыта и перестраивать воркфлоу на ровном месте с того к чему привыкли — не самый лучший фен-шуй.
Sign up to leave a comment.

Articles