
Первой идеей было создание виртуальной машины и копирование её при необходимости. Схожие конфигурации настраивать стало проще, но каждый раз когда что-то в конфигурации менялось, приходилось заходить на сервер и настраивать его. Хотелось большего.
Путем проб и ошибок я пришел к связке
Vagrant
+ SaltStack
, где Vagrant
берет на себя изоляцию окружений, а SaltStack
– управление конфигурацией.Vagrant.
Vagrant
– это менеджер виртуальных машин с настройкой через Vagrantfile
, позволяющий в одной точке собрать конфигурацию машины готовую для запуска. Он умеет не только поднимать виртуальные машины, но и заниматься их "обеспечением". Обеспечение делегирует системам, которые для этого предназначены.Формат пакета для разворачивания окружения в
Vagrant
– .box
. Есть сервис для обмена боксами – https://vagrantcloud.com/. На данный момент он в бете, но, за исключением, "битых" ссылок на боксы, ошибок я не видел.Vagrantfile
Создать
Vagrantfile
не составляет труда. Подробности есть в документации, я же перечислю то, что понадобится в примере.Сервер будет работать на
debian
без предустановленых компонентов SaltStack
. На https://vagrantcloud.com/можно найти .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
можно посмотреть тут: https://github.com/ligser/salt-vagrant-demostand/blob/master/Vagrantfile.SaltStack
SaltStack
позволяет создавать связку master
–> minion
и инициировать мастером обеспечение minion
свежими конфигами. У меня не было такой необходимости, поэтому обеспечение будет выполняться без участия master
.Описание конфигурации для
SaltStack
– это набор утверждений (состояний, в терминологии SaltStack
), которые должны быть удовлетворены, чтобы minion
считался сконфигурированным успешно. Я опишу возможности
SaltStack
, которые мне пригодились.salt/minion
Для начала найдем файл
salt/minion
, который указан в Vagrantfile
. Это файл с которого начинается конфигурирование машины.Содержимое его крайне лаконично:
file_client: local
. Тут утверждается, что конфигурация хранится локально на minion
, по умолчанию, в директории /srv/salt
, в которую мы настроили синхронизацию.Состояния
Полный мануал по состояниям есть на сайте проекта: http://docs.saltstack.com/en/latest/topics/tutorials/index.html#states.
Состояния хранятся в
.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://docs.saltstack.com/en/latest/topics/targeting/grains.html.По умолчанию, любой
.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
. То, на что раньше могло уйти несколько часов, сейчас занимает минуты, большую часть которых сервер сам ставит пакеты.