?

Log in

No account? Create an account

Previous Entry | Next Entry

По следам USENIX CMS 2010

Удалось тут прочитать http://www.verticalsysadmin.com/config2010/ про Bcfg2, Cfengine, Chef, Puppet.

Вспоминается собственный опыт. В Netli (2002+) мы сделали свою систему менеджмента конфигурации. Под конец она управляла парой десятков кластеров с сотнями машин и десятком типов кастомного софта на каждой. Это немного не то, что сисадминские системы управления конфигурацией, рассмотренные в USENIX CMS. Ведь мы в основном занимались управлением конфигурации нашего собственного софта, а не механизмом администрирования хостов с опенсорснутым софтом. Но сравнивать на высоком уровне их можно.

Зачем нужно было конфигурировать софт? Ну для того, например, чтобы определить IP и порт, на котором софт должен висеть и слушать HTTP. Определить, какие расширения нужно префетчить, какие можно гзиповать. Выставить различные таймауты. В общем, представьте себе нечто вроде конфига Апача, который наши приложения должны были читать.


Сначала, в прототипе CDN/ADN сервиса, конфигурация софта выражалась четырьмя текстовыми tab-separated-values файлами, которые указывали на то, что с чем связано (какие ноды с какими), и с какой целью. Так как компания на тот момент работала на $500k посевных инвестиций, конфиг был последним делом, на которое обращали внимание — надо было запустить прототип софта. До восьми боксов этого было достаточно, затем, конечно, начали путаться в назначениях полей, а файлы начали рассинхронизироваться.

Поняв, что система конфигурирования без возможности хранения метаинформации и с аргументами, семантика которых определяется их позицией — это невыгодно, решили описать семантику конфигурируемых сущностей в каком-то языке. И это было сделано: на yacc был набросан язык, напрямую выражающий конфигурируемые сущности. Что-то типа такого:
box "p1" {
  process "proxy1" {
    service {
        port 8080;
        ip-address 1.2.3.4;
    }
    service {
        port 443;
        ip-address 1.2.3.4;
        use-ssl "yes";
    }
  }
}

И уже из конфигурации, написанной на этом языке генерировались tab-separated-values файлы, которые читались софтом.

Быстро стало понятно, что в этой конфигурации огорчает отсутствие средств для шаблонизации: абстракции, переиспользования, подстановки переменных, etc. Поэтому сверху неё был накручен Perl-шаблонизатор, который компенсировал недостатки языка. Главной особенностью этого шаблонизатора было то, что все конструкции, которые нужно было порождать по многу раз с небольшими вариациями, делались во вложенных циклах `for` прямо в шаблонах.

И это сразу стало давать свои плоды. Как известно, если у вас есть проблема, и вы думаете решать её в императивном стиле, то у вас появится две проблемы. Оказалось, что люди, конфигурирующие что-либо через Perl, очень любили то здесь, то там скосить углы. И внедряли в Perl-шаблоны какую-то неверную муть, типа глобальных переменных (и зависящих от них вариаций параметров циклов!). Порождаемые шаблонизатором конфигурации софта отличались забавностью и недетерминированностью: до того, чтобы генерировать разные конфигурации в разных проходах шаблонизатора не доходило, но вот например поменять местами два бокса в кластере было уже опасно.

В общем, очень скоро стало ясно, что на тюринг-полном языке делать шаблоны — это значит получить живую, шевелящуюся лапшу. Императив в шаблонах очень вредит и порождает недетерминированность.

Поэтому следующим этапом была разработка чисто декларативного языка, но который можно было легко шаблонизировать в нём же самом. Особенности языка:
1. Отделение языка от семантики сервисов. Например, "box" или "service" в упомянутом выше примере — это были конструкции языка, записанные в качестве таковых прямо в yacc'овском BNF. А в новом языке — это просто наборы букв, интерпретирующиеся только внутри самого конфигурируемого процесса, который умеет сам понимать, что значит "service" для него. В этом плане мы могли бы использовать и разметку XML, и JSON с похожим успехом.
2. Добавление в язык конструкции "inherit", которая служила главным механизмом обеспечения reuse.
3. Добавление в язык value assignments.
4. Раз язык становился декларативным и независимым от семантики, появилась лёгкая возможность обеспечения смены конфигурации на лету. Библиотека поддержки языка предоставляла возможность регистрировать коллбеки и навешивать их на произвольные узлы синтаксического дерева. Затем, при перезагрузке конфигурации, те синтаксические конструкции, внутри которых были детектированы какие-то изменения, вызывали ассоциированные с ними коллбеки.
5. Раз язык становился декларативным и независимым от семантики, появилась возможность сделать такой же независимый от семантики валидатор этой самой семантики. Например, можно было выразить такое правило, как "каждый бокс должен иметь как минимум один процесс, а каждый процесс — как минимум два сервиса".
6. Раз язык становился декларативным и независимым от семантики, появилась возможность делать отдельные тулзы типа pssh, которые управлялись конфигурацией, даже не полностью понимая её.

Конфигурация с "inherit" могла выглядеть, например, так:
process-defaults "proxy-std" {
    _validator-entity       "process-defaults";
    _validator-entity       "process-defaults:proxy";
    process-type    "proxy";
    pidfile                 "/var/run/proxy.pid";
    logging-data = standard-disk-logging; // Value assignment
    max-shutdown-time       "12";

    /*
     * Settings for the ladmin.
     */
    ladmin-settings "ladmin-settings" {
        cmdline "/bin/cpproxy -C /etc/ncnf.conf -S $sysid -H $heartbeat_pipe_fd";
        inherit ladmin-settings "hb-ladmin-settings"; // inheritance
        heartbeat-timeout "25";
        sleep-before-kill       "16";
        max-ru-idrss            "255000";
    }
}


Конфигурация, описывающая все сервисы в системе, занимала несколько мегабайт на диске, и около 65 мегабайт в памяти. Для того, чтобы её генерировать, редактировать руками единый конфигурационный файл было бы убийством. Поэтому файл распилили на несколько частей и завернули сборку этих частей в единый файл через M4. M4 — это тьюринг-полный шаблонизатор, использующийся, в частности, для конфигурирования sendmail'а. В этом историческом качестве он обладал удивительнейшим свойством, исключительно полезным для наших целей: его никто не хотел трогать, менять его макры. То есть, декларативная система, обёрнутая в сборку на M4, оставалась в целом декларативной. В отличие от шаблонизатора на перле, никто в M4 шаловливыми ручками не лез и лапшу из него не делал.

Возвращаясь к нашим баранам (Cfengine, Chef, Puppet, Bcfg2), хочется предложить несколько критериев, при которых конфигурация живой системы, подверженной изменениям, будет оставаться стабильной дольшее время:
1. Язык описания конфигурации должен быть декларативным. Конфигурация на Руби, например, этому условию может не удовлетворять — она требует слишком большой дисциплины от исполнителей.
2. Язык должен быть быть как можно более независим от семантики контролируемых сущностей. Это разделение на уровни (синтаксис-семантика) позволит добавлять в экосистему новые тулзы, работающие на соответствующем уровне. Тут, пожалуй, можно вспомнить XML. И закопать подальше.
3. Язык должен содержать как можно меньше конструкций. Это полезно для человека (меньше возможностей менять систему = большее единообразие = легче передавать опыт), это полезно для машины — парсинга, преобразований, etc.
4. К такому декларативному способу задания конфигурации, который на нижнем своём уровне (синтаксис языка) не соответствует какой-то конкретной семантике тех сущностей, которые он конфигурирует, должен прилагаться валидатор. Валидатор должен проверять семантическую валидность того, что получилось. Он всё, конечно, не проверит, но наиболее злостные ошибки должен иметь возможность отловить. Без автоматического валидатора рулить чем-то, кроме несколько боксов, может потребовать нечеловеческой дисциплины. Автоматический валидатор должен тоже конфигурироваться: правила валидации должны задаваться человеком.

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

Tags:

Comments

( 53 comments — Leave a comment )
brainslugs.blogspot.com
Dec. 30th, 2010 07:34 pm (UTC)
да вас, выходцев из этого Netli, я гляжу, целая секта
lionet
Dec. 30th, 2010 07:38 pm (UTC)
А кто ещё тут, кроме kika и squadette, и wadcom и is39 и dk379 и ...

Ок, ок, всё понял, вопрос закрыт.
(no subject) - brainslugs.blogspot.com - Dec. 30th, 2010 07:49 pm (UTC) - Expand
(no subject) - dk379 - Dec. 30th, 2010 08:46 pm (UTC) - Expand
(no subject) - squadette - Dec. 30th, 2010 11:11 pm (UTC) - Expand
(no subject) - lionet - Dec. 30th, 2010 11:14 pm (UTC) - Expand
yakov_sirotkin
Dec. 30th, 2010 07:42 pm (UTC)
А чем XML/XSLT - то не угодил?
lionet
Dec. 30th, 2010 07:44 pm (UTC)
1. Требование было чтобы это не было бинарным форматом. Для того, чтобы девелоперы могли его части руками писать.
2. Надо сказать, что никто для system configuration из вышеперечисленных систем не использовал XML. То есть, все считают, что бинарные форматы — зло.
(no subject) - yakov_sirotkin - Dec. 30th, 2010 07:51 pm (UTC) - Expand
(no subject) - lionet - Dec. 30th, 2010 07:56 pm (UTC) - Expand
(no subject) - metaclass - Dec. 30th, 2010 08:17 pm (UTC) - Expand
(no subject) - usovalx - Dec. 30th, 2010 07:54 pm (UTC) - Expand
(no subject) - usovalx - Dec. 30th, 2010 07:55 pm (UTC) - Expand
(no subject) - ex_chrobin - Dec. 30th, 2010 11:06 pm (UTC) - Expand
(no subject) - lionet - Dec. 30th, 2010 11:11 pm (UTC) - Expand
(no subject) - ex_chrobin - Dec. 30th, 2010 11:32 pm (UTC) - Expand
(no subject) - wizzard0 - Dec. 31st, 2010 06:19 pm (UTC) - Expand
(no subject) - lionet - Jan. 1st, 2011 09:37 am (UTC) - Expand
usovalx
Dec. 30th, 2010 07:57 pm (UTC)
А что особенного было в самом M4? Вроде я когда-то краем глаза его доки смотрел, и ничего особенно жуткого в нём небыло. Мне казалось что свою дурную славу он заслужил из-за sendmail, а не из-за своих собстреввных особенностей.
lionet
Dec. 30th, 2010 08:00 pm (UTC)
> Мне казалось что свою дурную славу он заслужил из-за sendmail

А я разве как-то по-другому выразился?
В этом историческом качестве он обладал удивительнейшим свойством, исключительно полезным для наших целей: его никто не хотел трогать, менять его макры.
(no subject) - usovalx - Dec. 30th, 2010 08:03 pm (UTC) - Expand
(no subject) - lionet - Dec. 30th, 2010 08:09 pm (UTC) - Expand
(no subject) - usovalx - Dec. 30th, 2010 08:25 pm (UTC) - Expand
9000
Dec. 30th, 2010 08:09 pm (UTC)
Хорошо написано. "Шевелящаяся лапша" и "удивительнейшее свойство" отдельно доставили :)
tzirechnoy
Dec. 30th, 2010 08:36 pm (UTC)
>В этом историческом качестве он обладал удивительнейшим
> свойством, исключительно полезным для наших целей: его никто не хотел >трогать, менять его макры.

Великолепно!

Но и статья в цэлом -- очень ёмкая. Полезнее многих мегабайтов разномастного кода.

>Скорее всего этот опыт и привёл меня в итоге к функциональным языкам.

А разве ваш стартап не на эрланге изначально?
lionet
Dec. 30th, 2010 09:44 pm (UTC)
Это про пред-предыдущий стартап, Netli, я в нём работал между 2001 и 2005 годом. Там всё на C было.

В текущем стартапе почти всё на эрланге, конечно, но далеко не изначально:
http://lionet.info/pdf/2010-lev-walkin-erlang-experience.pdf
norian
Dec. 31st, 2010 07:06 am (UTC)
> process-type "proxy";
> pidfile "/var/run/proxy.pid";

то есть фактически просто двустрочный мэп "именованная сучность - значение"
из которого заинтересованные софтины выпарсивают нужные ключи, а валидатор проверяет значения по шаблонам

ключи можно искать по дереву или хэш-функции плюс наложить сверху любое количество иерархий, хде ключ сам становицца значением
http://apps.breds.ru/k.pierre.k
Dec. 31st, 2010 01:34 pm (UTC)
Кажется, nix (http://nixos.org/) это почти то же самое. Оно кроме средства конфигурации еще и package manager чисто функциональный. И inherit там есть такой, и много что еще.

пример конфигурации компьютера: https://svn.nixos.org/websvn/nix/configurations/trunk/misc/viric/vicerveza.nix

для кластеров тоже что-то есть: http://nixos.org/disnix/
lionet
Dec. 31st, 2010 03:17 pm (UTC)
Посмотрел.

nix синтаксис — гораздо менее регулярный, чем «ncnf», который я описываю. И в этом отношении близок к синтаксису в моём первом примере. Обрати внимание на отсутствие кавычек вокруг IP-адресов, например.

Избранные места из nix, которые идеологически вредны и путают синтаксис и семантику:
// булевый тип. плохо. можно обойтись строковым
enableSplashScreen = false;
// о фак, ещё один тип. а вместо "none" что можно писать?
ddns-update-style none;
// понятие о списке элементов. плохо. можно просто несколько раз задать extraModule = { ... }
extraModules = [
        { name = "php5"; path = "${pkgs.php}/modules/libphp5.so"; }
        { name = "python"; path = "${pkgs.mod_python}/modules/mod_python.so"; }
];
// то же самое. можно обойтись interface "lo"; interface "eth0", etc
interfaces = [ "lo" "eth0" "wlan0" ];
// работа с файловой системой делается из конфига. плохо: конфиг не самодостаточный,
// просто так не скопируешь. у нас сборкой из файлов занимался M4
extraConfig = import ./apache-extra-config.nix;
// вопиющие случай смешения синтаксиса и семантики! парсер должен знать про это всё!
option domain-name-servers 62.42.230.24, 62.42.63.52;
hardware ethernet 8:0:20:c0:ff:ee;


Ещё обратим внимание что в «ncnf» есть key-value запись как примитивных значений, так и для блоков. К сожалению, это показалось нам необходимым, и от этого избавиться не удалось. То есть, такая конструкция как boot = { ... } очень приятна на вид и идеологически, наверное, более правильна, но она нам оказалась недостаточной, ибо нельзя иметь таких адресуемых штук больше чем одну.
С одной стороны, key-value для блоков это не самая простая конструкция, и поэтому можно считать, что ncnf можно было упростить. А с другой стороны, тут есть такой момент что появляется некая униформность: у любого узла в дереве есть key и value, как у атрибута (a "b"), так и у узла (a "b" { ... }). Короче, это момент, который в nix можно признать более приятным, чем в ncnf, но и то не факт.
(no subject) - http://apps.breds.ru/k.pierre.k - Dec. 31st, 2010 03:28 pm (UTC) - Expand
(no subject) - lionet - Dec. 31st, 2010 03:31 pm (UTC) - Expand
(no subject) - http://apps.breds.ru/k.pierre.k - Dec. 31st, 2010 03:45 pm (UTC) - Expand
(no subject) - http://apps.breds.ru/k.pierre.k - Dec. 31st, 2010 03:49 pm (UTC) - Expand
(no subject) - lionet - Dec. 31st, 2010 04:50 pm (UTC) - Expand
_slw
Jan. 1st, 2011 01:00 pm (UTC)
спасибо, ты ответил на вопрос, который я хотел тебе задать но не успел сформулировать
lionet
Jan. 1st, 2011 03:02 pm (UTC)
что за вопрос-то? я заинтригован.
(no subject) - _slw - Jan. 1st, 2011 03:19 pm (UTC) - Expand
kurilka
Jan. 1st, 2011 06:07 pm (UTC)
Лев, может я что-то пропустил, но о том, что сейчас в Echo вы пользуете, не скажешь?
lionet
Jan. 2nd, 2011 03:19 am (UTC)
pssh ;(
(no subject) - kurilka - Jan. 2nd, 2011 09:20 am (UTC) - Expand
aristarh1970
Jan. 3rd, 2011 05:49 am (UTC)
А почему не ХМЛ? Может это региональное?
В смысле что у вас там "на Диком Западе" ХМЛ не любят и предпочитают разношерстие старомодных олд-стайл "конфиг"- и "пропертиз"- файлов?
ПМСМ, и я, и мои знакомцы-коллеги из НЙ, Коннектикута и Джёзи не мудрствуя лукаво использовали б ХМЛ.
lionet
Jan. 3rd, 2011 06:35 am (UTC)
Может у вас там и на Джаве программируют? И — типун мне на язык — аутсорсингом балуются?
Вы и сами поди в курсе - aristarh1970 - Jan. 3rd, 2011 05:11 pm (UTC) - Expand
Re: Вы и сами поди в курсе - lionet - Jan. 3rd, 2011 07:20 pm (UTC) - Expand
Перспективы F# - lionet - Jan. 12th, 2011 11:27 am (UTC) - Expand
(no subject) - ext_55374 - Jan. 5th, 2011 05:04 pm (UTC) - Expand
erthad
Oct. 14th, 2014 07:58 am (UTC)
Некоторое время назад появился Pallet (http://palletops.com/) -- это configuration management, который использует Clojure в качестве DSL.
lionet
Oct. 17th, 2014 03:36 am (UTC)
Значит, не взлетит.
(no subject) - erthad - Oct. 17th, 2014 06:00 am (UTC) - Expand
(no subject) - lionet - Oct. 19th, 2014 07:42 am (UTC) - Expand
(no subject) - erthad - Oct. 20th, 2014 07:42 am (UTC) - Expand
(no subject) - dmzlj - Feb. 23rd, 2017 06:18 am (UTC) - Expand
( 53 comments — Leave a comment )