Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Puppet

Глава 18 из книги "Архитектура приложений с открытым исходным кодом", том 2.
Оригинал: Puppet
Автор: Luke Kanies
Дата публикации: 2 Мая 2012 г.
Перевод: А.Панин
Дата перевода: 27 Августа 2013 г.

18.1. Введение

Puppet является инструментом для управления IT-инфраструктурой, разработанным с использованием языка программирования Ruby и используемым для автоматизации обслуживания датацентров и управления серверами компаний Google, Twitter, Нью-Йоркской фондовой биржи и многих других организаций. Главным образом развитие проекта поддерживается организацией Puppet Labs, которая положила начало его развитию. Puppet может управлять серверами в количестве от 2 до 50,000 и обслуживаться командой, состоящей из одного или сотен системных администраторов.

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

В общем случае Puppet выполняет все возможные действия направленные на то, чтобы использовать функции существующей системы для выполнения своей работы; т.е., в дистрибутивах, основанных на технологиях компании RedHat, он будет использовать утилиту yum для управления пактами и init.d для управления службами, при этом в операционной системе OS X он будет использовать утилиту dmg для управления пактами и launchd для управления службами. Одной из основополагающих целей проекта Puppet является выполнение полезной работы вне зависимости от того, используется ли для этого код проекта Puppet или сама система, поэтому следующие системные стандарты являются критичными.

Проект Puppet создан с учетом опыта использования множества других инструментов. В мире приложений с открытым исходным кодом наибольшее влияние на его развитие оказал проект CFEngine, который являлся первым инструментом конфигурации общего назначения с открытым исходным кодом, а также проект ISconf, который использовал утилиту make для выполнения всей работы, что в свою очередь обусловило особое внимание к явно описанным зависимостям в системе. В мире коммерческого программного обеспечения Puppet может рассматриваться как конкурент проектов BladeLogic и Opsware (которые впоследствии были приобретены более крупными компаниями), каждый из которых успешно продавался в момент появления Puppet, но при этом каждый из этих инструментов продавался руководителям больших компаний, вместо развития в соответствии с непосредственными требованиями к качественным инструментам системных администраторов. Предназначением проекта Puppet было решение аналогичных решаемым этими инструментами проблем, при этом он был предназначен для совершенно других пользователей.

В качестве простого примера метода использования Puppet, ниже приведен фрагмент кода, который позволяет быть уверенным в правильной установке и конфигурации службы безопасной оболочки (SSH):
class ssh {
    package { ssh: ensure => installed }
    file { "/etc/ssh/sshd_config":
        source => 'puppet:///modules/ssh/sshd_config',
        ensure => present,
        require => Package[ssh]
    }
    service { sshd:
        ensure => running,
        require => [File["/etc/ssh/sshd_config"], Package[ssh]]
    }
}

Этот код позволяет быть уверенным в том, что пакет будет установлен, файл будет размещен в необходимом месте и служба будет запущена. Следует отметить, что мы описали зависимости между ресурсами, поэтому всегда будем выполнять любую работу в корректной последовательности. Этот класс может быть ассоциирован с любым узлом для применения заданной конфигурации в рамках этого узла. Обратите внимание на то, что строительными блоками конфигурации Puppet являются структурированные объекты, в данном случае это объекты package, file и service. В терминологии Puppet мы называем эти объекты ресурсами (resources) и любые спецификации конфигурации Puppet состоят из этих ресурсов и зависимостей между ними.

Нормальная установка Puppet будет содержать десятки или даже сотни этих фрагментов кода, называемых нами классами (classes); мы храним эти классы на диске в файлах, называемых манифестами (manifests), а также объединяем логически связанные классы в рамках групп, называемых модулями (modules). Например, вы можете иметь в распоряжении модуль ssh с этим классом ssh и любыми другими логически связанными классами наряду с модулями mysql, apache и sudo.

Большая часть операций взаимодействия с Puppet осуществляется с использованием командной оболочки или постоянно работающих служб HTTP, но существуют и графические интерфейсы для выполнения таких задач, как обработка отчетов. Компания Puppet Labs также предоставляет коммерческие программные продукты для работы с Puppet, которые используют графические веб-интерфейсы.

Первый прототип Puppet был разработан летом 2004 года, а полноценная разработка проекта началась в феврале 2005 года. Изначально он был спроектирован и разработан Luke Kanies, системным администратором, имеющим большой опыт разработки небольших инструментов, но не имеющим опыта разработки проектов, содержащих более 10,000 строк кода. По существу Luke Kanies получил навыки программирования в ходе разработки проекта Puppet, что отразилось на архитектуре проекта как положительно, так и отрицательно.

Puppet разрабатывался изначально и в первую очередь как инструмент для системных администраторов, облегчающий их жизнь, позволяющий выполнять работу быстрее, более эффективно и с меньшим количеством ошибок. Первой ключевой инновацией для реализации этого принципа были описанные выше ресурсы, являющиеся примитивами Puppet; они могут переноситься между операционными системами, при этом абстрактно представляя детали реализации, позволяя пользователю думать о результатах работы, а не о том, как их достичь. Этот набор примитивов был реализован на уровне абстракции ресурсов Puppet (Puppet's Resource Abstraction Layer).

Ресурсы Puppet должны быть уникальными для заданного узла. Вы можете иметь в распоряжении только один пакет с именем "ssh", одну службу с именем "sshd" и один файл с именем "/etc/ssh/sshd_config". Это ограничение предотвращает взаимные конфликты между различными частями ваших конфигураций и вы узнаете об этих конфликтах на раннем этапе процесса конфигурации. Мы ссылаемся на эти ресурсы по их типам и именам, т.е., Package[ssh] и Service[sshd]. Вы можете использовать пакет и службу с одним и тем же именем, так как они относятся к различным типам, но не два пакета или службы с одним и тем же именем.

Второй ключевой инновацией в Puppet является возможность прямого указания зависимостей между ресурсами. Ранее используемые инструменты ставили своей целью выполнение индивидуальных задач без рассмотрения взаимосвязей между этими задачами; Puppet был первым инструментом, который явно устанавливал то, что зависимости являются первостепенной частью ваших конфигураций, которые, в свою очередь, должны моделироваться соответствующим образом. Он создавал граф ресурсов и их зависимостей в качестве одного из основных типов данных и практически все действия Puppet зависели от этого графа (называемого каталогом (Catalog)), его вершин и ребер.

Последним важным компонентом Puppet является язык конфигурации. Этот язык является декларативным и предназначен в большей степени для описания конфигурации, чем для полноценного программирования - он практически полностью повторяет формат конфигурации Nagios, но также был создан под значительным влиянием языков из состава CFEngine и Ruby.

В основе функциональных компонентов Puppet лежат два направляющих его развитие принципа: он должен быть настолько простым в использовании, насколько это возможно, причем предпочтение должно отдаваться удобству в использовании, а не возможностям; а также он должен разрабатываться в первую очередь в форме фреймворка и во вторую - приложения, таким образом при желании сторонние разработчики получат возможность создавать свои приложения на основе программных компонентов Puppet. Было понятно, что в дополнение к фреймворку необходимо также широко применяемое качественное приложение, но в первую очередь разработчики все равно занимались фреймворком, а не приложением. Многие люди все еще считают, что Puppet является этим самым приложением, а не фреймворком, на основе которого оно реализовано.

После создания первого прототипа Puppet, Luke стал в целом неплохим Perl-разработчиком с небольшим опытом разработки сценариев оболочки и небольшим опытом работы с языком C, большей частью полученным при работе с системой CFEngine. В дополнение к этому он имел опыт создания систем разбора данных для простых языков, который был получен при разработке двух таких систем для работы в составе небольших инструментов, а также повторной разработки с нуля системы разбора данных для CFEngine с целью упрощения ее поддержки (этот код не был передан проекту из-за небольших несовместимостей).

Решение об использовании динамического языка для реализации Puppet было принято достаточно быстро ввиду значительно более высокой производительности труда разработчика и распространения данного типа языков, но выбор самого оказался достаточно сложным. Начальные прототипы на языке Perl были отвергнуты, поэтому проводились эксперименты для поиска других языков. Была предпринята попытка использования языка Python, но Luke посчитал это язык значительно противоречащим его взгляду на мир. Услышав рассказ друга о преимуществах нового языка, Luke попробовал использовать язык Ruby и за четыре часа создал работающий прототип. В момент, когда началась полномасштабная разработка Puppet, язык Ruby был практически не известен, поэтому решение о его использовании было сопряжено с большим риском, но в этом случае производительность труда разработчика снова сыграла решающую роль в выборе языка. Главной отличительной чертой языка Ruby, по крайней мере от Perl, была простота создания неиерархических отношений классов, при этом язык не противоречил мыслительной деятельности разработчика Luke, что было критично.


Далее: Обзор архитектуры