...

понедельник, 21 апреля 2014 г.

Автоматизация в веб-разработке с Vagrant и SaltStack

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

Первой идеей было создание виртуальной машины и копирование её при необходимости. Схожие конфигурации настраивать стало проще, но каждый раз когда что-то в конфигурации менялось, приходилось заходить на сервер и настраивать его. Хотелось большего.

Путем проб и ошибок я пришел к связке Vagrant + SaltStack, где Vagrant берет на себя изоляцию окружений, а SaltStack – управление конфигурацией.



Vagrant.




Vagrant – это менеджер виртуальных машин с настройкой через Vagrantfile, позволяющий в одной точке собрать конфигурацию машины готовую для запуска. Он умеет не только поднимать виртуальные машины, но и заниматься их "обеспечением". Обеспечение делегирует системам, которые для этого предназначены.

Формат пакета для разворачивания окружения в Vagrant.box. Есть сервис для обмена боксами – http://ift.tt/1dIF8F9. На данный момент он в бете, но, за исключением, "битых" ссылок на боксы, ошибок я не видел.

Vagrantfile




Создать Vagrantfile не составляет труда. Подробности есть в документации, я же перечислю то, что понадобится в примере.

Сервер будет работать на debian без предустановленых компонентов SaltStack. На http://ift.tt/1dIF8F9можно найти .box.

config.vm.box = "mokote/debian-7"



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

config.vm.network "private_network", ip: "192.168.56.107"



Настройки виртуальной машины:

config.vm.provider "virtualbox" do |v|
v.name = "demostand"
v.memory = 1024

v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
v.customize ["setextradata", :id, "--VBoxInternal2/SharedFoldersEnableSymlinksCreate/v-root", "1"]
end




Синхронизируем директории с настройками SaltStack и с проектом, который будет развернут на создаваемой машине. Для проекта я использовал nfs в качестве метода синхронизации. Он работает быстрее, чем VirtualBox shared folders, и настраивается всего одним параметром :nfs => true , но требует root доступ.

config.vm.synced_folder "salt/roots/", "/srv/"
config.vm.synced_folder "~/Development/web/demostand", "/var/www/demostand", id: "vagrant-root", :nfs => true




Осталось настроить обеспечение хоста конфигурациями SaltStack.

salt.minion_config – файл, с которого начинается конфигурация сервера.

salt.run_highstate = true – запускать ли обеспечение при старте машины.

salt.pillar – данные pillar-хранилища.

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

salt.pillar({
"database" => {
"withUser" => true,
"name" => "demostand",
"password" => "fm2QTqimWUrk"
}
})

salt.pillar({"projectName" => "demostand"})
end




Полностью Vagrantfile можно посмотреть тут: http://ift.tt/1r9hZkf.

SaltStack




SaltStack позволяет создавать связку master –> minion и инициировать мастером обеспечение minion свежими конфигами. У меня не было такой необходимости, поэтому обеспечение будет выполняться без участия master.

Описание конфигурации для SaltStack – это набор утверждений (состояний, в терминологии SaltStack), которые должны быть удовлетворены, чтобы minion считался сконфигурированным успешно.

Я опишу возможности SaltStack, которые мне пригодились.

salt/minion




Для начала найдем файл salt/minion, который указан в Vagrantfile. Это файл с которого начинается конфигурирование машины.

Содержимое его крайне лаконично: file_client: local. Тут утверждается, что конфигурация хранится локально на minion, по умолчанию, в директории /srv/salt, в которую мы настроили синхронизацию.

Состояния




Полный мануал по состояниям есть на сайте проекта: http://ift.tt/1mwlKRg.

Состояния хранятся в .sls файлах. Обычно .sls состоит из описания состояний в формате YAML.

apache: # ID
pkg: # состояние
- installed # функция




Вызов одной функции можно сокращать:

apache:
pkg.installed




Также, если ID не совпадает с именем объекта состояния – можно указать имя.

apache_pkg:
pkg:
- name: apache
- installed




pkg – это состояние пакетного менеджера. installed – одна из самых часто используемых функций этого состояния, подразумевающая, что пакет с таким именем должен быть установлен в системе.

service – состояние сервисов. При помощи него можно запускать или останавливать сервисы. Состояние останавливающее apache2:

apache2:
service.dead




file – состояние файловой системы.

Обычно для работы с ФС используется функция managed.

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

source – место, откуда берется содержимое файла. salt:// – указатель на /srv/salt, или относительно Vagrantfile: salt/roots/salt.

По-умолчанию, файлы не являются шаблонами jinja, поэтому использовать внутри них данные pillar нельзя. Чтобы сделать файл шаблоном, нужно указать template: jinja в параметрах. После этого, файл будет обработан шаблонизатором. jinja используется и в самих .sls файлах.

В SaltStack поддерживаются зависимости между состояниями.

watch_in указывает, в каких сервисах используется файл, чтобы при его изменении перезапустить их.

require поддерживается состоянием pkg и требует установки определенного пакета.

/etc/nginx/sites-available/default:
file.managed:
- source: salt://nginx/default
- template: jinja
- user: root
- group: root
- mode: 644
- watch_in:
- service: nginx


Данные




Для хранения данных в SaltStack сущестует две системы.

pillar – данные, которых не должно быть в файлах конфига. В Vagrantfile я положил в pillar 2 ключа: database – параметры БД и projectName – имя проекта.

grains – статическая информация, которая будет загружена на minion при его запуске.

grains я практически не использовал, поэтому не интересовался тонкостями этой системы, если нужно больше информации, она доступна на сайте SaltStack: http://ift.tt/1fEw3OG.

По умолчанию, любой .sls файл обрабатывается шаблонизатором, поэтому в нем можно использовать конструкции:

{{ }} – вывод.

{% %} – условия, или циклы.

{{ pillar['database']['name'] }}:
{% if (pillar['database']['withUser']) %}
mysql_user.present:
- host: localhost
- password: {{ pillar['database']['password'] }}
- require:
- service: mysql
- pkg: python-mysqldb
{% endif %}




В примере выше, из pillar берется значение [database][name], записанное в Vagrantfile, и назначается в качестве ID для состояния mysql_user.present.

Значение ['database']['password'] будет использовано в качестве пароля.

Top.sls




top.sls – файл, с которого SaltStack начнет считывать состояния.

Он содержит список подключаемых файлов .sls для данной конфигурации.

Готовая конфигурация




Готовая конфигурация Vagrant и SaltStack лежит на GitHub. Она позволяет развернуть сервер с PHP, nginx и mysql одной командой:

vagrant up --provision



При разворачивании нескольких образов одновременно нужно не забывать менять IP в приватной сети.

Вывод




Автоматизация позволяет сократить объем рутинной работы до небольших правок. Разворачивание обычных серверов сократилось до копипаста типовых настроек и запуска vagrant up. То, на что раньше могло уйти несколько часов, сейчас занимает минуты, большую часть которых сервер сам ставит пакеты.

This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий