Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Deploy с поддержкой Salt

Anna | 15.06.2014 | нет комментариев
До сих пор во многих компаниях deploy создает крупные задачи и может занимать дни, недели и в особенно запущенных случаях месяцы. Но обстановка не безвыходна. Существует много инструментов и практик, способных подмогнуть в этом нелегком деле. Вот только эти инструменты Почаще каждого за один-два дня не освоишь, а сроки горят.

Чего традиционно хочется:

  • Вероятность поднять план локально на машине разработчика. Каждый либо правда бы частями. Причем дюже хочется, Дабы Dev конфигурация отличалась от Prod в минимуме паратемров. Это дозволит избежать “work on my machine” багов. Да и вообще, когда один разработчик работает на OS X, иной на Windows, а продакшен на Debian, то ожидай беды, это не считая того, что всякий делает работу по настройке окружения.
  • Dev конфигурацию хочется разворачивать на всякий машине и ОС в пару команд в консоли. Это вновь же дозволит уменьшить фактор “work on my machine” багов. А еще дозволит привлекать других разработчиков в план за минимальное время (vagrant up и поехали).
  • Конфигурация должна быть внятна и программисту, и админу.

Каждого этого мы добьемся на связке Salt Vagrant на примере Django плана. Но множество техник будут пригодны разработчикам не только на Python, но на других языках.

Сразу дам ссылку на исходники: bitbucket.org/awnion/salt-django-deploy

Что же такое Salt?

Если вы знакомы с Salt, то можете пропустить данный раздел.

Salt — это довольно сильный инструмент для управления кластером (cluster orchestration), но на мой индивидуальный взор даже применение на одной машине абсолютно оправдано и не будет оверкилом (дерзко говоря если в вашей команде ровно 1 разработчик, то это не значит, что не нужно применять систему контроля версий).

Salt состояния — это YAML файлы с растяжением sls, которые описывают в каком состоянии должна быть машина. Скажем, вот данный вот файл должен лежать здесь, вот данный сервис должен быть запущен, вот данный юзер должен иметь такие права и так дальше. В Salt дозволено поддерживать состояние не только системных утилит (apt, rpm, cron, init скрипты и различные конфиги), но и, скажем, дозволено проверить существует ли такой-то пользователь в RabbitMQ, последней ли версии репозиторий git, все ли пакеты стоят в вашем virtualenv и так дальше. Полный список состояний дозволено обнаружить здесьdocs.saltstack.com/ref/states/all/, и на мой взор он крайне значительный.

Несколько фактов про Salt
  • В качестве темплейтного языка для конфигов и фалов состояний Salt использует Jinja. Это немыслимо комфортно и разрешает следовать DRY даже в конфигах.
  • Salt теснее применяют такие компании, как Apple, NASA, LinkedIn и многие другие.
  • Salt написан на Python, правда для его применения знать Python вообще не непременно.
  • Pdf документация для Salt около 1000 страниц, и написана она абсолютно качественно. Там вы обнаружите не только изложение API, но и практики применения и примеры.

Dev конфигурация

На мой взор трудно переоценить значимость отличной и комфортной среды разработки. Но на настройку “все под себя” может уйти пара дней, а то и неделя. Давайте сэкономим эти дни нашим коллегам в грядущем и сотворим конфигурацию, которая дозволит поднять нынешнюю версию плана в одну команду:

git clone <repo_url> && cd <repo_name> && vagrant up

Хорошо, это на самом деле это 3 команды, но если вы можете проще — жму вам руку.

Выходит, мы будем строить нашу dev конфигурацию на Vagrant (тем, кто не знаком с Vagrant, настойчиво рекомендую познакомиться):

mkdir my_app && cd my_app
git init
vagrant init

В нашей папке my_app возник git репозиторий и конфиг для Vagrant.

Дальше заменяем оглавление Vagrantfile на следующее:

Vagrant.configure("2") do |config|
  config.vm.box = "precise64"

  config.vm.hostname = "dev-my-app"
  config.vm.network :private_network, ip: '3.3.3.3'

  config.vm.synced_folder "salt/roots/salt", "/srv/salt/"
  config.vm.synced_folder "salt/roots/pillar", "/srv/pillar/"

  config.vm.provision :salt do |salt|
    salt.minion_config = "salt/minion"
    salt.run_highstate = true
  end
end

Данный конфиг дозволит сделать гостевую машину на Ubuntu, в конфиге мы задали имя хоста и IP, а так же определили, какие папки синхронизировать и указали, что для приведения нашей машинки к надобному состоянию мы будем применять salt (кстати, корень нашего плана будет по умолчанию синхронизован с папкой /vagrant гостевой машины).

Подробней о том, что здесь происходит, дозволено узнать здесь

Выходит, мы готовы начать описывать состояния. Сделаем файл salt/minion со дальнейшим оглавлением:

file_client: local

Реально мы говорим, что эта машина хранит свои состояния сама. По умолчанию salt настроен так, что он берет файлы состояний с master-сервера, а локально их только кэширует где-то в /var/cache/salt. Следственно если вы не хотите чего-то кастомного, то данный файл на prod машине скорее каждого вообще не потребуется.

Сейчас сотворим две папки:

mkdir -p salt/roots/pillar
mkdir -p salt/roots/salt

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

Сделаем файл salt/roots/salt/top.sls

base:
  'dev-my-app':
    - nginx
    - python
    - supervisor

Как дозволено было додуматься sls дюже схож на yaml. Но основным отличаем здесь будет то, что sls это еще и jinja темплейт со всеми вытекающими (дальше вы увидите, что это реально приносит пользу).

base — это наименование конфигурации состояний нашего воображаемого кластера. dev-my-app — это hostname нашей гостевой машины. Здесь применяется pattern matching, то есть мы могли бы указать ‘dev-*’, и все состояни ниже применились бы ко каждому машинам типа dev-alpha, dev-foobar и т.п. Дальше следует список состояний, которые нам нужно будет описать.

Сотворим заявленные состояния python, nginx и supervisor:

salt/roots/salt/python.sls

# это состояние легко проконтролирует, что пакеты python и python-virtualenv
# установлены, а если нет -- то поставит их с зависимостями
python:
  pkg:
    - installed
    - names:
      - python
      - python-virtualenv

salt/roots/salt/nginx.sls

# это состояние поставит nginx и запустит его как сервис, при этом require 
# показывает, что состояние service необходимо запустить позже состояния pkg
nginx:
  pkg:
    - installed
  service:
    - running
    - reload: True  # сервис поддерживает reload
    - require:
      - pkg: nginx

salt/roots/salt/supervisor.sls

supervisor:
  pkg:
    - installed
  service:
    - running
    - require:
      - pkg: supervisor

Выходит, дозволено теснее запустить “vagrant up”. Эта процедура скачает образ Ubuntu (если у вас его еще нет в кэше образов), установит туда salt и запустит синхронизацию состояния.
Сейчас у нас на нашей гостевой машине есть python, supervisor и nginx.
Можете проверить это зайдя на машину через vagrant ssh либо зайдя на 3.3.3.3

Пока как бы бы все легко. Продолжим:

Сотворим переменные pillar:

salt/roots/pillar/top.sls

base:
  'dev-my-app':
    - my-app

salt/roots/pillar/my-app.sls

my_app:
  gunicorn_bind: 127.0.0.1:8000
  dns_name: dev.my-app.com
  venv_dir: /home/vagrant/my_app_env
  work_dir: /vagrant

1-й файл говорит, что хосту dev-my-app назначены переменные из конфига my-app. 2-й файл — собственно сами переменные.

Сейчас сотворим папку для состояний конфигов нашего Django приложения:

mkdir -p salt/roots/salt/my_app

salt/roots/salt/my_app/init.sls

{% set my_app = pillar['my_app'] %}

my_app.venv:
  virtualenv.managed:
    - name: {{ my_app['venv_dir'] }}
    - system_site_packages: False
    - require:
      - pkg: python

my_app.pip:
  pip.installed:
    - bin_env: {{ my_app['venv_dir'] }}
    - names:
      - Django==1.6
      - gunicorn==18.0
    - require:
      - virtualenv: my_app.venv

my_app.nginx.conf:
  file.managed:
    - name: /etc/nginx/sites-enabled/my_app.conf
    - source: salt://my_app/nginx.my_app.conf
    - context: # помимо переменных как бы pillar, мы можем передать добавочный контекст для тепмлейта
        bind: {{ my_app['gunicorn_bind'] }}
        dns_name: {{ my_app['dns_name'] }}
    - template: jinja
    - makedirs: True
    - watch_in:
      - service: nginx

my_app.supervisor.conf:
  file.managed:
    - name: /etc/supervisor/conf.d/my_app.conf
    - source: salt://my_app/supervisor.my_app.conf
    - context:
        app_name: my_app
        bind: {{ my_app['gunicorn_bind'] }}
        gunicorn: {{ my_app['venv_dir'] }}/bin/gunicorn
        directory: {{ my_app['work_dir'] }}
        workers: {{ grains['num_cpus'] * 2   1 }}  # в академических целях выпендрился
    - template: jinja
    - makedirs: True

my_app.supervisor:
  supervisord.running:
    - name: my_app
    - watch:
      - file: my_app.supervisor.conf
    - require:
      - pip: my_app.pip
      - pkg: supervisor

Hint: при составлении зависимостей require, watch и пр. имейте в виду, что состояния будут проверяться в произвольном порядке. При составлении статьи я допустил такого рода ошибку, и пакеты django и gunicorn пытались устанавливаться в еще не сделанный virtualenv.

salt/roots/salt/my_app/nginx.my_app.conf

server {
    listen 80;
    server_name {{ dns_name }} _;
    location / {
        proxy_pass http://{{ bind }};
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

salt/roots/salt/my_app/supervisor.my_app.conf

[program:{{ app_name }}]
command={{ gunicorn }} {{ app_name }}.wsgi:application -b {{ bind }} -w {{ workers }}
directory={{ directory }}
user=nobody
autostart=true
autorestart=true
redirect_stderr=true

Добавляем только что сделанное состояние в salt/roots/salt/top.sls

base:
  ‘dev-my-app’:
    - nginx
    - python
    - supervisor
    - my_app  # <----

Мы примерно завершили. Но не хватает самого основного — кода нашего воображаемого Django приложения. Давайте сотворим пустой тестовый Django план дальнейшим образом:

vagrant provision

Данный процесс займет несколько минут (огромную часть времени будут ставиться django и gunicorn в virtualenv).

Когда provision отработает заходим на гостевую машину:

vagrant ssh

И внутри делает следующее:

/home/vagrant/my_app_env/bin/django-admin.py startproject my_app /vagrant
exit

И на хост машине вновь делаем vagrant provision, и Дабы проверить, что все работает в файле hosts пропишите временно:

dev.my-app.com 3.3.3.3

Переходим в браузере на dev.my-app.com, и если все отлично, то мы увидим It worked!

Dev конфигурация построена. Дозволено коммитить.

Сейчас если вы захотите отдать поиграться со своим планом другу, то ему необходимо будет сделать толькоgit clone и vagrant up. Причем данный мнимый друг получит не только исходники самого плана, но и будет иметь представление о том, как его будут деплоить.

Помимо каждого прочего по умолчанию наш план вертится независимо под управлением gunicorn supervisor. Но что если мы хотим удаленно подебажить либо мы хотим воротить наш любимый autoreload изменений кода? Не вопрос:

vagrant ssh
supervisorctl stop my_app
/home/vagrant/my_app_env/bin/python /vagrant/manage.py runserver

Сейчас мы можем спокойно редактировать код, и все метаморфозы будут подхватываться django сервером механически.
И если у нас все еще временно подправлен hosts, то на запросы dev.my-app.com/ будет отвечать все тот же django сервер.

Prod конфигурация

Вот мы и добрались до самого основного. Будем считать, что деплоиться мы будем на prod-my-app.

Дальше мы разглядим вариант деплоя в обстановки, когда у нас есть обособленный сервер для salt-master (дальше легко мастер).

Копируем на мастер конфиги, добавляем в /srv/salt/top.sls

  ‘prod-my-app’:
    - nginx
    - python
    - supervisor
    - my_app

Либо в нашем случае дозволено сделать вот так:

base:
  ‘*-my-app’:
    - nginx
    - python
    - supervisor
    - my_app

Дальше делаем то же самое с файлом /srv/pillar/top.sls

base:
  '*-my-app':
    - my-app

В /srv/pillar/my_app.sls меняем переменные согласно нашей карте раскладки.

На prod-my-app ставим salt-minion. Подключаем salt-minion к salt-master (как это сделать читай здесь).
Сейчас на мастере дозволено запустить использование конфигов:

sudo salt prod-my-app state.highstate
Что осталось:
Доставка конфигов на мастер

Здесь куча методов от rsync до git. Все зависит от вашей внутренней политики.

Доставка исходников плана на prod-my-app

Здесь вновь же куча вариантов. Лично я делаю так: при помощи salt поддерживаю на prod-my-app репозиторий git на определенном коммите, хэш которого хранится в pillar, и если он меняется, то salt в конце работы запускает скрипты деплоя.

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

Ссылки

www.saltstack.com/
www.vagrantup.com/
hynek.me/talks/python-deployments/ — крайне пригодная статья, которая содержит комплект принципов на тему деплоя python планов.

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

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB