На Хабре несколько раз писали о системах менеджмента конфигураций puppet и chef, но по какой-то причине первопроходец этой темы — cfengine, обделен вниманием, давайте воспоним этот пробел.
Первое, что надо отметить касательно cfengine — это декларативный фреймворк, а не императивный. Мы не описываем подробные последовательные шаги для достижения нужной нам конфигурации, мы описываем желаемое состояние системы. Например, «удостовериться, что все вебсерверы с именем web.* имели пакет nginx» или «удостовериться, что скрипт bckup.sh был запущена в 5-й час суток и * успешно* завершился». Cfengine оперирует понятием «обещание» (promice), кроме того cfengine будет пытаться «восстановить» (repair) его периодически, и даже после успешного восстановления будет проверять состояние (state) и восстанавливать опять и опять, что бы достичь конвергенции (convergent configuration). Плюс такого подхода заключается в том, что нет необходимости знать текущее состояние, что бы придти к желаемому. Это особенно важно если у вас часть нод не доступны на момент добавления новых политик (policy) или же наоборот, вы добавляете не сконфигурированные ноды.
Надеюсь, достаточно вводной информации, давайте рассмотрим примеры.
Установка проста и не требует много времени. Для Debian:
cd /tmp
wget http://cfengine.com/pub/gpg.key
apt-key add gpg.key
rm gpg.key
echo "deb http://cfengine.com/pub/apt squeeze main" >
/etc/apt/sources.list.d/cfengine-community.list
apt-get update
apt-get install cfengine-community
Теперь создадим файл содержащий один простой cfengine bundle и совсем
базовый body который импортирует стандартную библиотеку.
cat /var/cfengine/inputs/python_virtualenv.cf:
body common control
{
bundlesequence => { "python_virtualenv" };
inputs => {
"cfengine_stdlib.cf",
};
}
bundle agent python_virtualenv {
vars:
"package_list" slist => { "virtualenvwrapper", "python-pip" };
"environments" slist => { "s1.example.com", "s2.example.com" };
packages:
"${package_list}"
package_policy => "add",
package_method => generic;
classes:
"incorrect_$(environments)" not => fileexists("/tmp/$(environments)/bin/python") ;
reports:
linux::
"Virtual environment $(environments) is not installed correctly."
ifvarclass => canonify("incorrect_$(environments)");
commands:
linux::
"/usr/bin/virtualenv /tmp/$(environments) --no-site-packages"
ifvarclass => canonify("incorrect_$(environments)");
}
Мы декларируем бандл типа agent и с именем python_virtualenv, как можно догадаться, я хочу удостоверится что у меня установлено два независимых python virtualenv, для примера они будут созданы в /tmp/s1.example.com и /tmp/s2.example.com, предварительно «обещаем» переменные в slist. Очевидно, нам нужен python, что мы и декларируем в обещании типа packages. Заметьте, что cfengine автоматически итерирует по list, никаких циклов писать не надо — мы просто декларируем наше намерение. Далее, мы декларируем класс в зависимости от того есть определенный файл или нет. Надо сказать, классы не совсем удачное название, правильнее бы назвать контекстами, и вообще они практически boolean — класс в cfengine или есть или нет! Далее идет обещание типа report, в нем мы видим так называемый hard class linux, hard классы декларирует сам cfengine и они включают тип операционной системы, IP, версию дистрибутива и много еще что, их можно увидеть запустив /var/cfengine/bin/cf-agent -v. Обещания в reports и commands отработают только если установлен класс «incorrect_$(environments)» (вызывается опция canonify, потому-что класс может содержать запрещенные символы и проверка может провалиться). Пробуем запустить:
/var/cfengine/bin/cf-agent -K -f /var/cfengine/inputs/python_virtualenv.cf
Получаем:
Q: "...virtualenv /tmp": New python executable in /tmp/s1.example.com/bin/python
Q: "...virtualenv /tmp": Installing distribute.................................................................................................................................................................................done.
I: Last 2 quoted lines were generated by promiser "/usr/bin/virtualenv /tmp/s1.example.com --no-site-packages"
Q: "...virtualenv /tmp": New python executable in /tmp/s2.example.com/bin/python
Q: "...virtualenv /tmp": Installing distribute.................................................................................................................................................................................done.
I: Last 2 quoted lines were generated by promiser "/usr/bin/virtualenv /tmp/s2.example.com --no-site-packages"
R: Virtual environment s1.example.com is not installed correctly.
R: Virtual environment s2.example.com is not installed correctly
Смотрим в /tmp и убеждаемся что наши virtualenv созданы.
Удаляем rm -rf /tmp/s2.example.com!
И запускаем /var/cfengine/bin/cf-agent -K -f /var/cfengine/inputs/python_virtualenv.cf
Видим:
Q: "...virtualenv /tmp": New python executable in /tmp/s2.example.com/bin/python
Q: "...virtualenv /tmp": Installing distribute.................................................................................................................................................................................done.
I: Last 2 quoted lines were generated by promiser "/usr/bin/virtualenv /tmp/s2.example.com --no-site-packages"
R: Virtual environment s2.example.com is not installed correctly.
Cfengine пересоздал только удаленный virtualenv, что вообщем-то что и ожидалось.
Очевидно, cfengine может работать как standalone, так и с policy hub. Заинтригованы? Можно начать отсюда http://cfengine.com/manuals/cf3-quickstart
Автор: alex_www