Разберем ситуацию, ставшую достаточно распространенной в наше время. Есть распределенная команда, допустим в двух городах (А и Б), которая работает над одним крупным проектом. Сборка проекта происходит на Jenkins’е в городе А и длится, например 3 минут. Скачать готовый продукт из города А в город Б можно в среднем за 30 минут (в зависимости от времени суток, загрузки канала, фазы луны и т.д.). Итого: команде из города Б нужно ждать час(60 минут) чтобы запустить/протестировать свежий билд. Очевидно, это достаточно много. Нужно ускорять.

Рассматривать вопросы вынесения этого всего (CI) в облако и прочее я не буду по двум причинам:

 

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

 

Также я пропущу вопросы синхронизации репозиториев с исходниками и прочие инфраструктурные вещи, не относящиеся к данной теме.

Решать данную проблему буду так: в обоих офисах настраивается Jenkins-нода, на которой можно собирать свежий билд. Главная задача - 2 одновременных билда одного проекта в разных офисах.

Делается это, примерно, так:

 

  1. Заходим на наш Jenkins и устанавливаем нужные плагины (Jenkins => Manage Jenkins =>  Manage Plugins => Available). Нам нужен “Throttle Concurrent Builds Plugin” (https://wiki.jenkins-ci.org/display/JENKINS/Throttle+Concurrent+Builds+Plugin) и NodeLabel Parameter Plugin (https://wiki.jenkins-ci.org/display/JENKINS/NodeLabel+Parameter+Plugin).
  2. Настраиваем Slave node. Документация лежит тут: https://wiki.jenkins-ci.org/display/JENKINS/Step+by+step+guide+to+set+up+master+and+slave+machines.
  3. Настраиваем нашу Job’у для параллельного выполнения на двух нодах. Я для примера создал Fake-long-job, которая выполняет простой bash-скрипт “sleep 20;”.
    • Отмечаем флаг “This build is parameterized”
    • Добавляем параметр Node

    • Выбираем на каких нодах можно выполнять билд

    • Настраиваем одновременные билды. В моем случае их может быть 2, по одному на каждой ноде

      .
    • Нажимаем кнопку Save.
  4. Проверяем, что все работает, запустив два билда на разных нодах.

 

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


Или мне так не везет, или для всех это совершенно очевидные вещи, но я, при выполнении простой fabric task'и копирования содержимого директорий, столкнулся на ряд проблем, которые хоть и казались простыми и распростаренными, но были описаны в найденных мной блогах и мануалах в плной мере.

Проблема #1 - неправильный пользователь

Не всегда бывает что имя локального пользователя совпадает с удаленным. Ситуация распространенная и описанная всеми, кому не лень. Решение простое - указывем нужного пользователя в переменной env.user:

from fabric.api import *
env.user = 'e0ne'

Проблема #2 - аутентификация

Самый простой способ аутентификации по SSH - имя пользователя и пароль. Самая распространенная проблема - нужно как-то безопасно хранить пароль. А так, как я предпочитаю все скрипты для развертывания хранить в VCS (читать как в git’е), то возникает проблема: нехорошо хранить пароль в репозитории, особенно в открытом на GitHub’е. Решение простое - использование пары public/private RSA ключей. Процесс генерации и настройки (ключевые слова: ssh-keygen, ~/.ssh/known_hosts) описывать сейчас не буду, только то, что касается Jenkins’а.

В моем случае, Jenkins был установлен на Ubuntu server 13.04 командой  “apt-get install jenkins”, поэтому пользователь jenkins в системе создался таким образом, что без подоплнительной настройки под ним не залогинишься. Поэтому использем sudo и генерируем ключи для подключения по SSH, примерно, так:

$ sudo -u jenkins -i ssh-keyget -t rsa

После чего в домашнем каталоге jenkins’а будет лежать пара ключей, публичный из которых нужно положить на наш сервер, на который fabric будет копировать файлы. Достатьid_rsa.pub можно так:

$ sudo -u jenkins -i cat ~/.ssh/id_rsa.pub

И положить этот ключ на сервер, в моем случае в файл /home/e0ne/.ssh/known_hosts.

Этот способ так же решает проблему того, что не нужно передавать в fabric путь к ключу, он будет браться из пути по умолчанию.

Проблема # 3 - не загружаются файлы

Ошибка тут у меня была совсем непонятной (привет paramiko и протоколу ssh), откатывать настройки или делать это с другим сервером сейчас нет возможности. Да и точно не помню как я пришел к решению. Наверное, после медитации на вывод команды “ls -al”. Задача jenkins job’ы была в том, что нужно было апдейтить простое веб-приложение, а у пользователя, под которым jenkins/fabric подключался к серверу не было прав на запись в нужную директорию. Решилось добавлением пользователя в группу www-data, в которой у меня находится пользователь nginx’а.

Пока все. Эти три проблемы были при попытке “простого копирования” файлов. Дальше будет должно быть интереснее. Или проще. Как повезет:).