В чем основное отличие между конвергенцией и идемпотенцией у шеф-повара?
Разница между конвергенцией и идемпотенцией у шеф-повара
Ответ 1
Конвергенция и идемпотентность не зависят от шеф-повара. Они, как правило, приписываются теории управления конфигурацией, хотя и используются в других областях, в частности в математике.
Давайте начнем с более простого, идемпотента. Мы проигнорируем математическое использование идемпотента и сосредоточимся на том, что люди управления конфигурацией имеют в виду, когда говорят об этом. То есть: "несколько приложений одного и того же действия не имеют побочных эффектов в состоянии системы". Простой пример идемпотентной операции: mkdir -p
:
mkdir -p /var/lib/statedir/myapp
Независимо от того, сколько раз мы запускаем эту команду, это приведет к созданию этого дерева. Другой способ заявить об этом идемпотентных операциях: "запуск инструмента снова и снова не меняет систему после первого раза".
Теперь сравним это с конвергенцией. В общем, для сближения значит объединить [людей или]. В управлении конфигурацией конвергенция означает, чтобы привести состояние системы в соответствие с определенной политикой. То есть, изменения производятся в системе только в том случае, если они должны быть сделаны. Простой пример сходящейся операции:
if [ ! -d /var/lib/statedir/myapp ]; then
mkdir -p /var/lib/statedir/myapp
fi
Это сходится, потому что мы выполняем только команду mkdir, если нужный каталог не существует. Мы также называем это "испытанием и ремонтом". То есть мы проверяем текущее состояние конкретной вещи, которую мы управляем, а затем восстанавливаем ее с помощью определенной команды или операции, если она не находится в этом состоянии. Это то, что шеф-повар делает за кулисами с таким ресурсом:
directory '/var/lib/statedir/myapp' do
recursive true
end
То, как мы (шеф-повар) говорим об этом, - это то, что Шеф принимает идемпотентные действия, чтобы свести систему к состоянию, объявленному различными ресурсами. Каждый ресурс в Chef декларативен и выполняет проверку текущего состояния ресурса, а затем восстанавливает систему в соответствии с этим.
Чтобы глубже проникнуть в сорняки о том, как работает Шеф-повар, он имеет фазу "компиляции" и фазу "сближения" в работе шеф-повара. На этапе "компиляция" он вычисляет рецепты Ruby на node и ищет объекты ресурсов, которые он добавляет к "коллекции ресурсов". После того, как он оценил все рецепты, он затем переходит на фазу "сходиться", где он выполняет итерацию по сбору ресурсов, предпринимая соответствующие действия, чтобы поместить ресурсы в нужное состояние, в результате чего создаются пользователи, файлы записываются, устанавливаются пакеты, и т.д.
Ответ 2
Отказ от ответственности: я аутсайдер в сообществе по управлению конфигурациями, и мне потребовались часы, чтобы понять, что из этого следует.В этом ответе я критикую сообщество управления конфигурацией, поэтому вы должны знать, что его мир - не мой мир, я даже не использую никаких инструментов управления конфигурацией в своей текущей работе, и я оцениваю их только по тому, что могу найти в гугле
Определения
Сказать, что операция сходится, примерно означает, что она переводит любую часть системы, которой она управляет, в указанное состояние.
Когда люди, отвечающие за управление конфигурацией, говорят, что операция идемпотентна, они обычно подразумевают, что если вы запустите ее второй раз сразу после ее запуска, второй запуск будет немедленно завершен без выполнения какой-либо избыточной работы.
Когда ресурс описывается как идемпотент, в частности, в контексте Chef, это означает, что последующий запуск Chef после того, как ресурс уже переведен в желаемое состояние, не считается его "обновленным" в сообщении обновления ресурсов x/y по адресу конец пробега.
Обратите внимание, что большинство встроенных ресурсов удовлетворяют этому окончательному, строжайшему определению идемпотентности по умолчанию, и вы можете достичь его в своих собственных рецептах и пользовательских ресурсах, используя only_if
и not_if
guards и converge_if_changed
.
Некоторые комментарии и заметки о других определениях
Смущает, что большинство определений "идемпотента", которые вы найдете в Интернете, не будет соответствовать ни одному из тех, что я только что дал. Вместо того, чтобы доверять тому, что эксперты называют определением, я делаю вывод из наблюдения, как они на самом деле используют этот термин. Бешено часто находить, что кто-то дает определение "идемпотент", а затем использует слово таким образом, который явно не согласуется с этим определением несколькими параграфами позже.
Чтобы исследовать это, давайте начнем с изучения определений "идемпотента", которые существуют за пределами области управления конфигурацией. Многие из таких определений перечислены в Википедии по адресу https://en.wikipedia.org/wiki/Idempotence. Те, которые чаще всего (ошибочно) получают как значение идемпотентности в контексте управления конфигурацией, таковы:
- В математике функция f называется идемпотентной, если f (f (x)) = f (x) для всех возможных значений x.
- В математике целый ряд других видов математических объектов называется идемпотентными, если они встречают какое-то формальное или иное определение (как правило, с общей темой "повторное выполнение операции имеет тот же эффект, что и выполнение ее один раз").
- В программировании сказать, что функция или процедура идемпотентна, означает одно из двух:
- В случае функции, которая принимает аргумент и возвращает значение, точно такое же, как и математическое значение.
- В случае функции, которая имеет побочные эффекты, после однократного вызова функции последующие вызовы оставляют состояние системы без изменений.
Множество запутанных источников дают одно из этих определений в качестве значения "идемпотента" в контексте управления конфигурацией, а затем быстро переходят к использованию термина таким образом, который дает понять, что это не совсем то определение, которое они используют. Некоторые примеры:
-
Пейс конкурирующий ответ на этот самый вопрос. Там он утверждает, что:
Шаг является идемпотентным, если после многократного выполнения шага в системе (базовое состояние которого не изменилось) результат будет таким же, как если бы шаг был выполнен один раз.
но затем приводит это в качестве примера шага, который не идемпотентен:
rm -rf /var/log/myapp mkdir -p /var/log/myapp
Ясно, что этот шаг фактически соответствует определению идемпотентности Pace, так как запуск его несколько раз подряд приводит нас к тому же конечному состоянию, что и запуск его один раз (а именно, состояние, в котором
/var/log/myapp
существует и является пустым). Однако при повторном запуске он выполняет избыточную работу, поэтому Пейс описывает ее как неидемпотентную. -
Книга Миша Тейлора и Сета Варго Обучающий повар: руководство по управлению конфигурацией и автоматизации. Там они утверждают:
Когда код Chef является идемпотентным, он может выполняться несколько раз в одной и той же системе, и результаты всегда будут идентичны, не вызывая непреднамеренных побочных эффектов.
но потом, комментируя один из их примеров рецептов:
Наш рецепт проходит тест на идемпотентность? К сожалению нет.... Шеф по ошибке считает, что все еще нужно что-то делать - 2/3 ресурсов обновляется во втором запуске. Если рецепт был действительно идемпотентным, см. Обновленные ресурсы 0/3. Chef будет проверять состояние системы, распознавать, что ничего не изменилось с момента последнего запуска - никто не трогал узел между двумя запусками - и не выполнять обновления ресурсов
Опять же, они заявляют определение идемпотентности, основанное на неизменности состояния системы, когда рецепт запускается несколько раз, но на самом деле использование слова означает, что ненужной работы избегают.
-
Бен Форд Идемпотентность: не просто большое и страшное слово в блоге Puppet, где он впервые дает определение идемпотентности...
Идемпотентность - это просто слово, описывающее операцию, которая будет иметь тот же эффект, если вы запустите ее один раз или 10 001 раз. Добавление одного не идемпотентно, потому что результат продолжает увеличиваться, но умножение на одно идемпотентно, потому что ответ один и тот же, независимо от того, сколько раз вы его умножите!
Затем он приводит этот пример идемпотентности, который, хотя и согласуется с приведенным выше определением, немного подозрительно - поскольку он сосредоточен на последующих исполнениях, не выполняющих избыточную работу, а не на достижении того же результата:
Представьте себе время, когда вам было 12 лет, и ваша мама попросила вас вынести мусор. Будучи хорошим ребенком, вы были, вы бросили GameBoy и вскочили, чтобы сделать, как вас просили, да?
Но спустя 30 минут, когда она вернулась в гостиную и увидела, что вы свернулись калачиком на диване, играя в "Супер Марио Лэнд", она снова сказала вам вынести мусор. Я сильно подозреваю, что вы не вскочили, чтобы взять пустой мешок для мусора. Вместо этого ты сказал: "Уже сделал это, мама!" Это идемпотентность. Эффект от того, что один раз сказали убрать мусор, такой же, как эффект от того, что вам сказали дважды. Вы не сделали это снова, потому что это уже было сделано.
Затем, наконец, он отказывается от своего определения и приводит пример операции, которая, по его словам, не идемпотентна, несмотря на то, что ее повторное выполнение приведет к тому же результату:
Так как насчет того времени, когда вас наказали за то, что вы написали неидемпотентных руководителей? У новичков в Puppet обычно есть сценарии оболочки, которые они заменяют, и они пишут код, который выглядит примерно так:
exec { '/usr/bin/curl http: //server.net/packages/package.tar.gz -o /tmp/package.tar.gz ': } -> exec { 'tar -xf /tmp/package.tar.gz -C /tmp/package': } -> exec { '/tmp/package/installer.sh': } file { '/tmp/package': ensure => absent, force => true, require => Exec[ '/tmp/package/installer.sh'], } file { '/tmp/package.tar.gz': ensure => absent, force => true, require => Exec[ '/tmp/package/installer.sh'], }
Так что не так с этим? Это работает, верно? Загрузите tarball, распакуйте его, установите вещь, затем уберите за собой. Похоже, что он должен работать отлично, не допуская опечаток или проблем с сетью. И это будет. Но он будет работать идеально каждый раз, когда запускает Puppet. Другими словами, он будет загружать и запускать скрипт установки каждые тридцать минут!
Но результат будет таким же, Бен! Раньше та деталь, которую вы рассказали нам об определении идемпотентности, вращалась вокруг!
Очевидно, что Бен действительно применяет определение идемпотентности "избегать лишней работы", несмотря на то, что он утверждает.
Может ли операция быть идемпотентной, но не сходящейся?
Да. Такая операция будет такой, которая не приводит систему в указанное конечное состояние, но позволяет избежать избыточной работы при последовательных запусках. Ответ Pace дает пример такой операции, а Thinking Like A Chef - другую:
Система может быть идемпотентной, не сходясь. Например, если бы у нас был псевдокод,
if file X does not exist, write the current timestamp to file X
, который будет идемпотентным, но на самом деле нельзя сказать, что он сходится в конкретном конечном состоянии.
Лучший практический пример, который я могу представить для операции, которую можно охарактеризовать как идемпотентную, но не конвергентную, - это установка пакета с помощью обычной команды install
менеджера пакетов, которая:
- устанавливает последнюю версию, если пакет не установлен, но
- не обновляет старую версию, если она уже установлена.
Состояние (версия пакета, который вы получаете) не определяется рецептом, поэтому, возможно, оно не сходится, но оно успешно избегает ненужной работы.
Может ли операция быть сходящейся, но не идемпотентной?
Да, конечно! Простой пример - Бен Форд, уже цитированный выше, безоговорочно загружающий файл по некоторому локальному пути. Он сходится, потому что конечное состояние всегда одинаково (файл существует), но не идемпотентно, поскольку выполняет ненужную работу по повторной загрузке файла при каждом запуске.
Что бы это ни стоило, меня расстраивает то, что сообщество по управлению конфигурациями присвоило термин, который уже имел ясное значение в более широком мире программирования, а затем использовало его связанным, но все же явно другим способом, даже не предоставив формального определения что это значит в их мире. Поиск в документах Chef (https://www.google.co.uk/search?q=site%3Ahttps%3A%2F%2Fdocs.chef.io+idempotent) дает много вариантов использования этого термина, но без определения. Неудивительно, что эта тема сбивает с толку людей, когда большинство определений этого термина не совпадают с употреблением.
Мне удалось найти только одного человека, который когда-либо давал определения идемпотентности, которые согласуются с тем, как используется этот термин, и этим кодрангером (он же Ной Кантровиц). В " Мышлении как шеф-повара", который я цитировал ранее, он пишет:
"Идемпотентно"... означает, что актер делает как можно меньше для достижения желаемого состояния.
и в разговоре с IRC от 2015 года он пишет:
Идемпотент означает не предпринимать действий, когда они не нужны, конвергентный означает, что он "оседает" в определенном конечном состоянии.
Кроме этого человека, я буквально не смог найти никого другого, кто когда-либо давал определение термина, которое соответствует тому, как его использует все сообщество по управлению конфигурациями.
Ответ 3
@Марк Эмери попросил более удовлетворительный пример различий между ними, поэтому я постараюсь это представить.
Шаг сходится, если при успешном завершении шага система была переведена в известное состояние.
Шаг является идемпотентным, если после многократного выполнения шага в системе (базовое состояние которого не изменилось) результат будет таким же, как если бы шаг был выполнен один раз.
Сходимость без идемпотентности
Шаг, который сходится, но не идемпотентен:
rm -rf /var/log/myapp
mkdir -p /var/log/myapp
После успешного завершения этого шага мы точно знаем, что /var/log/myapp
- это пустой каталог, который существует.
Он не идемпотентен, потому что каждый раз /var/log/myapp
каталог /var/log/myapp
. Идемпотентность желательна, потому что она уменьшает ненужный отток в системе. Очевидно, что любые приложения, пишущие в каталог /var/log/myapp
, не будут удовлетворены вышеуказанным шагом.
Идемпотентность без схождения
Шаг, который идемпотентен, но не сходится:
test "$(ls -A /home/foo 2>/dev/null)" || tempfile -d /home/foo
Этот скрипт создаст файл со случайным именем в /home/foo
только если в /home/foo
нет файлов. Это идемпотент, после первого запуска каталог не будет пустым, поэтому будущие запуски ничего не сделают.
Тем не менее, это не сходится. Вы не могли бы сказать, что этот шаг переводит систему в какое-либо известное состояние, поскольку создаваемый файл будет иметь произвольное имя.
Конвергенция желательна, потому что она помогает создавать системы, которые находятся в идентичных состояниях и, таким образом, с большей вероятностью ведут себя предсказуемо.
Слово предостережения
Эти термины похожи на абстракции, они не являются точными и могут утекать. Например, вы могли бы заявить, что операция не идемпотентна, поскольку использует циклы ЦП. Вы могли бы заявить, что одна операция идемпотентного тестирования и ремонта, которая выполняет дорогостоящий тест, является "менее идемпотентной", чем другая операция, которая выполняет дешевый тест, даже если "менее идемпотентный" не является фактической вещью.
Вы можете попытаться указать, что шаг, на котором устанавливается MySQL версии X, не сходится, потому что при запуске на разных компьютерах он оставляет другую метку времени в файлах. В качестве альтернативы вы могли бы сказать, что шаг, который я опубликовал выше, является конвергентным, поскольку он оставляет систему в состоянии "/home/foo существует и содержит ровно один файл".
Вот что происходит, когда математика ускользает от классной доски.