Марионетка - стиль кодирования
В Puppet стиль кодирования определяет все стандарты, которым нужно следовать, пытаясь преобразовать инфраструктуру конфигурации машины в код. Puppet работает и выполняет все определенные задачи, используя ресурсы.
Определение языка Puppet помогает структурированно указать все ресурсы, что необходимо для управления любой целевой машиной, которой необходимо управлять. Puppet использует Ruby в качестве языка кодирования, который имеет несколько встроенных функций, что позволяет очень легко выполнять задачи с помощью простой конфигурации на стороне кода.
Фундаментальные единицы
Puppet использует несколько основных стилей кодирования, которые легко понять и которыми легко управлять. Ниже приводится список немногих.
Ресурсы
В Puppet ресурсы известны как фундаментальные единицы моделирования, которые используются для управления любой целевой системой или ее изменения. Ресурсы охватывают все аспекты системы, такие как файлы, службы и пакеты. Puppet имеет встроенную возможность, позволяющую пользователям или разработчикам разрабатывать собственные ресурсы, которые помогают в управлении любой конкретной единицей машины.
В Puppet все ресурсы объединяются вместе либо с помощью “define” или же “classes”. Эти функции агрегирования помогают в организации модуля. Ниже приведен пример ресурса, который состоит из нескольких типов, заголовка и списка атрибутов, с которыми Puppet может поддерживать несколько атрибутов. Каждый ресурс в Puppet имеет собственное значение по умолчанию, которое при необходимости можно изменить.
Пример ресурса марионетки для файла
В следующей команде мы пытаемся указать разрешение для конкретного файла.
file {
'/etc/passwd':
owner => superuser,
group => superuser,
mode => 644,
}
Каждый раз, когда указанная выше команда выполняется на любом компьютере, она проверяет, что файл passwd в системе настроен, как описано. Файл перед двоеточием - это заголовок ресурса, который может называться ресурсом в других частях конфигурации Puppet.
Указание локального имени в дополнение к заголовку
file { 'sshdconfig':
name => $operaSystem ? {
solaris => '/usr/local/etc/ssh/sshd_config',
default => '/etc/ssh/sshd_config',
},
owner => superuser,
group => superuser,
mode => 644,
}
Используя заголовок, который всегда один и тот же, очень легко ссылаться на файловый ресурс в конфигурации без необходимости повторять логику, связанную с ОС.
Другой пример - использование службы, зависящей от файла.
service { 'sshd':
subscribe => File[sshdconfig],
}
С этой зависимостью sshd сервис всегда будет перезапускаться, как только sshdconfigфайл изменяется. Здесь следует помнитьFile[sshdconfig] это объявление как File в нижнем регистре, но если мы изменим его на FILE[sshdconfig] тогда это была бы ссылка.
Один фундаментальный момент, о котором нужно помнить при объявлении ресурса, заключается в том, что он может быть объявлен только один раз для каждого файла конфигурации. Повторное объявление одного и того же ресурса более одного раза вызовет ошибку. Благодаря этой фундаментальной концепции Puppet гарантирует, что конфигурация хорошо смоделирована.
У нас даже есть возможность управлять зависимостью от ресурсов, что помогает управлять множественными отношениями.
service { 'sshd':
require => File['sshdconfig', 'sshconfig', 'authorized_keys']
}
Метапараметры
Метапараметры известны как глобальные параметры в Puppet. Одна из ключевых особенностей метапараметра заключается в том, что он работает с любым типом ресурсов в Puppet.
Ресурс по умолчанию
Когда нужно определить значение атрибута ресурса по умолчанию, Puppet предоставляет набор синтаксиса для его архивирования, используя спецификацию ресурса с заглавной буквы, у которой нет заголовка.
Например, если мы хотим установить путь по умолчанию для всех исполняемых файлов, это можно сделать с помощью следующей команды.
Exec { path => '/usr/bin:/bin:/usr/sbin:/sbin' }
exec { 'echo Testing mataparamaters.': }
В приведенной выше команде первый оператор Exec устанавливает значение по умолчанию для ресурса exec. Для ресурса Exec требуется полный путь или путь, который выглядит как исполняемый файл. Таким образом, можно определить один путь по умолчанию для всей конфигурации. Значения по умолчанию работают с любым типом ресурсов в Puppet.
Значения по умолчанию не являются глобальными, однако они влияют только на область, в которой они определены, или на ближайшую к ней переменную. Если кто-то хочет определитьdefault для полной конфигурации, то мы определяем default и класс в следующем разделе.
Коллекции ресурсов
Агрегация - это метод объединения вещей. Puppet поддерживает очень мощную концепцию агрегирования. В Puppet агрегация используется для группировки ресурсов, которые являются фундаментальной единицей Puppet. Эта концепция агрегирования в Puppet достигается с помощью двух мощных методов, известных какclasses и definition.
Классы и определение
Классы отвечают за моделирование фундаментальных аспектов узла. Они могут сказать, что узел - это веб-сервер, и этот конкретный узел является одним из них. В Puppet классы программирования одноэлементны, и их можно оценивать один раз для каждого узла.
С другой стороны, определение можно использовать много раз на одном узле. Они работают так же, как если бы человек создал свой собственный тип Puppet, используя язык. Они созданы для многократного использования с разными входными данными каждый раз. Это означает, что в определение можно передавать значения переменных.
Разница между классом и определением
Единственное ключевое различие между классом и определением заключается в том, что при определении структуры здания и распределении ресурсов класс оценивается только один раз для каждого узла, при этом, с другой стороны, определение используется несколько раз на одном и том же узле.
Классы
Классы в Puppet вводятся с использованием ключевого слова class, а содержимое этого конкретного класса заключено в фигурные скобки, как показано в следующем примере.
class unix {
file {
'/etc/passwd':
owner => 'superuser',
group => 'superuser',
mode => 644;
'/etc/shadow':
owner => 'vipin',
group => 'vipin',
mode => 440;
}
}
В следующем примере мы использовали короткую руку, аналогичную приведенной выше.
class unix {
file {
'/etc/passwd':
owner => 'superuser',
group => 'superuser',
mode => 644;
}
file {'/etc/shadow':
owner => 'vipin',
group => 'vipin',
mode => 440;
}
}
Наследование в кукольных классах
В Puppet концепция наследования ООП поддерживается по умолчанию, при этом классы могут расширять функциональность предыдущего без копирования и повторной вставки бита полного кода во вновь созданный класс. Наследование позволяет подклассу переопределять параметры ресурсов, определенные в родительском классе. При использовании наследования следует помнить об одном ключевом моменте: класс может наследовать функции только одного родительского класса, а не более одного.
class superclass inherits testsubclass {
File['/etc/passwd'] { group => wheel }
File['/etc/shadow'] { group => wheel }
}
Если есть необходимость отменить некоторую логику, указанную в родительском классе, мы можем использовать undef command.
class superclass inherits testsubcalss {
File['/etc/passwd'] { group => undef }
}
Альтернативный способ использования наследования
class tomcat {
service { 'tomcat': require => Package['httpd'] }
}
class open-ssl inherits tomcat {
Service[tomcat] { require +> File['tomcat.pem'] }
}
Вложенный класс в Puppet
Puppet поддерживает концепцию вложенности классов, в которой он позволяет использовать вложенные классы, что означает, что один класс находится внутри другого. Это помогает добиться модульности и масштабирования.
class testclass {
class nested {
file {
'/etc/passwd':
owner => 'superuser',
group => 'superuser',
mode => 644;
}
}
}
class anotherclass {
include myclass::nested
}
Параметризованные классы
В Puppet классы могут расширять свои функциональные возможности, позволяя передавать параметры в класс.
Чтобы передать параметр в класс, можно использовать следующую конструкцию -
class tomcat($version) {
... class contents ...
}
Один ключевой момент, о котором следует помнить в Puppet, заключается в том, что классы с параметрами не добавляются с помощью функции include, а полученный класс можно добавить как определение.
node webserver {
class { tomcat: version => "1.2.12" }
}
Значения по умолчанию как параметры в классе
class tomcat($version = "1.2.12",$home = "/var/www") {
... class contents ...
}
Этапы выполнения
Puppet поддерживает концепцию этапа выполнения, что означает, что пользователь может добавить несколько этапов в соответствии с требованиями для управления любым конкретным ресурсом или несколькими ресурсами. Эта функция очень полезна, когда пользователь хочет разработать сложный каталог. В сложном каталоге имеется большое количество ресурсов, которые необходимо скомпилировать, помня, что зависимости между определенными ресурсами не должны изменяться.
Этап выполнения очень полезен при управлении зависимостями ресурсов. Это можно сделать, добавляя классы на определенных этапах, на которых конкретный класс содержит набор ресурсов. На этапе выполнения Puppet гарантирует, что определенные этапы будут выполняться в указанном предсказуемом порядке каждый раз, когда каталог запускается и применяется к любому узлу Puppet.
Чтобы использовать это, необходимо объявить дополнительные этапы помимо уже существующих этапов, а затем Puppet можно настроить для управления каждым этапом в указанном порядке с использованием того же синтаксиса взаимосвязи ресурсов, прежде чем потребовать “->” и “+>”. Тогда связь будет гарантировать порядок классов, связанных с каждым этапом.
Объявление дополнительных этапов с помощью декларативного синтаксиса марионетки
stage { "first": before => Stage[main] }
stage { "last": require => Stage[main] }
После того, как этапы были объявлены, класс может быть связан с этапом, отличным от основного, использующего этап.
class {
"apt-keys": stage => first;
"sendmail": stage => main;
"apache": stage => last;
}
Все ресурсы, связанные с классом apt-key, будут запущены первыми. Все ресурсы в Sendmail будут основным классом, а ресурсы, связанные с Apache, будут последним этапом.
Определения
В Puppet сбор ресурсов в любом файле манифеста осуществляется либо классами, либо определениями. Определения очень похожи на класс в Puppet, однако они вводятся сdefine keyword (not class)и они поддерживают аргумент, а не наследование. Они могут работать в одной и той же системе несколько раз с разными параметрами.
Например, если кто-то хочет создать определение, которое управляет репозиториями исходного кода, где вы пытаетесь создать несколько репозиториев в одной и той же системе, тогда можно использовать определение, а не класс.
define perforce_repo($path) {
exec {
"/usr/bin/svnadmin create $path/$title":
unless => "/bin/test -d $path",
}
}
svn_repo { puppet_repo: path => '/var/svn_puppet' }
svn_repo { other_repo: path => '/var/svn_other' }
Здесь следует отметить ключевой момент: как переменную можно использовать с определением. Мы используем ($) переменная знака доллара. Выше мы использовали $ title. Определения могут иметь как $ title, так и $ name, с помощью которых могут быть представлены имя и заголовок. По умолчанию $ title и $ name имеют одно и то же значение, но можно установить атрибут title и передать другое имя в качестве параметра. $ title и $ name работают только в определении, но не в классе или другом ресурсе.
Модули
Модуль можно определить как набор всех конфигураций, которые будут использоваться мастером Puppet для применения изменений конфигурации на любом конкретном узле Puppet (агенте). Они также известны как переносимый набор различных конфигураций, необходимых для выполнения конкретной задачи. Например, модуль может содержать все ресурсы, необходимые для настройки Postfix и Apache.
Узлы
Узлы - это очень простой оставшийся шаг, который заключается в том, как мы сопоставляем то, что мы определили («так выглядит веб-сервер»), с тем, какие машины выбраны для выполнения этих инструкций.
Определение узла в точности похоже на классы, включая поддерживающее наследование, однако они особенные, так что когда узел (управляемый компьютер, на котором запущен марионеточный клиент) подключается к главному демону Puppet, его имя будет отображаться в заданном списке узлов. Определенная информация будет оценена для узла, а затем узел отправит эту конфигурацию.
Имя узла может быть коротким именем хоста или полным доменным именем (FQDN).
node 'www.vipin.com' {
include common
include apache, squid
}
Приведенное выше определение создает узел с именем www.vipin.com и включает в себя общие классы, классы Apache и Squid.
Мы можем отправить одну и ту же конфигурацию на разные узлы, разделив их запятыми.
node 'www.testing.com', 'www.testing2.com', 'www3.testing.com' {
include testing
include tomcat, squid
}
Регулярное выражение для совпадающих узлов
node /^www\d+$/ {
include testing
}
Наследование узла
Node поддерживает модель ограниченного наследования. Как и классы, узлы могут наследовать только от одного другого узла.
node 'www.testing2.com' inherits 'www.testing.com' {
include loadbalancer
}
В приведенном выше коде www.testing2.com наследует все функции от www.testing.com в дополнение к дополнительному классу балансировщика нагрузки.
Расширенные поддерживаемые функции
Quoting- В большинстве случаев нам не нужно заключать строку в кавычки в Puppet. Любая буквенно-цифровая строка, начинающаяся с буквы, должна быть оставлена без кавычек. Однако рекомендуется всегда заключать строку в кавычки для любых неотрицательных значений.
Переменная интерполяция с кавычками
До сих пор мы упоминали переменную в терминах определения. Если нужно использовать эти переменные со строкой, используйте двойные кавычки, а не одинарные. Строка одинарных кавычек не будет выполнять интерполяцию переменных, подойдет строка двойных кавычек. Переменная может быть заключена в квадратные скобки{} что упрощает их совместное использование и понимание.
$value = "${one}${two}"
Рекомендуется использовать одинарные кавычки для всех строк, которые не требуют интерполяции строк.
Заглавные буквы
Использование заглавных букв - это процесс, который используется для ссылки, наследования и установки атрибутов по умолчанию для определенного ресурса. Есть два основных способа его использования.
Referencing- Это способ ссылки на уже созданный ресурс. Он в основном используется для целей зависимости, нужно использовать имя ресурса с большой буквы. Пример, require => file [sshdconfig]
Inheritance- При переопределении настройки родительского класса из подкласса используйте версию имени ресурса в верхнем регистре. Использование строчной версии приведет к ошибке.
Setting Default Attribute Value - Использование ресурса, написанного с заглавной буквы, без названия позволяет установить ресурс по умолчанию.
Массивы
Puppet позволяет использовать массивы в нескольких областях [один, два, три].
Некоторые члены типа, такие как псевдоним в определении хоста, принимают массивы в своих значениях. Ресурс хоста с несколькими псевдонимами будет выглядеть следующим образом.
host { 'one.vipin.com':
alias => [ 'satu', 'dua', 'tiga' ],
ip => '192.168.100.1',
ensure => present,
}
Приведенный выше код добавит хост ‘one.brcletest.com’ в список хостов с тремя псевдонимами ‘satu’ ‘dua’ ‘tiga’. Если кто-то хочет добавить несколько ресурсов к одному ресурсу, это можно сделать, как показано в следующем примере.
resource { 'baz':
require => [ Package['rpm'], File['testfile'] ],
}
Переменные
Puppet поддерживает несколько переменных, как и большинство других языков программирования. Переменные марионетки обозначены$.
$content = 'some content\n'
file { '/tmp/testing': content => $content }
Как указывалось ранее, Puppet - это декларативный язык, а это означает, что его область действия и правила назначения отличаются от императивного языка. Основное отличие состоит в том, что нельзя изменить переменную в пределах одной области, потому что они зависят от порядка в файле для определения значения переменной. Порядок не имеет значения на декларативном языке.
$user = root
file {
'/etc/passwd':
owner => $user,
}
$user = bin
file {
'/bin':
owner => $user,
recurse => true,
}
Переменная область
Область действия переменной определяет, действительны ли все определенные переменные. Как и в случае с последними функциями, Puppet в настоящее время имеет динамическую область видимости, что в терминах Puppet означает, что все определенные переменные оцениваются в их области действия, а не в местоположении, в котором они определены.
$test = 'top'
class Testclass {
exec { "/bin/echo $test": logoutput => true }
}
class Secondtestclass {
$test = 'other'
include myclass
}
include Secondtestclass
Квалифицированная переменная
Puppet поддерживает использование квалифицированных переменных внутри класса или определения. Это очень полезно, когда пользователь желает использовать ту же переменную в других классах, которые он определил или собирается определить.
class testclass {
$test = 'content'
}
class secondtestclass {
$other = $myclass::test
}
В приведенном выше коде значение переменной $ other оценивает содержимое.
Условные
Условия - это ситуации, когда пользователь желает выполнить набор инструкций или кода, когда определенное условие или требуемое условие удовлетворяется. Puppet поддерживает два типа условий.
Условие селектора, которое может использоваться только в пределах определенных ресурсов для выбора правильного значения машины.
Условия оператора - это более широко используемые условия в манифесте, которые помогают включать дополнительные классы, которые пользователь желает включить в тот же файл манифеста. Определите отдельный набор ресурсов внутри класса или примите другие структурные решения.
Селекторы
Селекторы полезны, когда пользователь желает указать атрибут ресурса и переменные, которые отличаются от значений по умолчанию на основе фактов или других переменных. В Puppet индекс селектора работает как многозначный трехсторонний оператор. Селекторы также могут определять пользовательские значения по умолчанию без значений, которые определены в манифесте и соответствуют условию.
$owner = $Sysoperenv ? {
sunos => 'adm',
redhat => 'bin',
default => undef,
}
В более поздних версиях Puppet 0.25.0 селекторы можно использовать как регулярные выражения.
$owner = $Sysoperenv ? {
/(Linux|Ubuntu)/ => 'bin',
default => undef,
}
В приведенном выше примере селектор $Sysoperenv значение соответствует либо Linux, либо Ubuntu, тогда выбранным результатом будет корзина, в противном случае пользователь будет установлен как неопределенный.
Состояние выписки
Условие оператора - это другой тип условного оператора в Puppet, который очень похож на условие переключения регистра в сценарии Shell. В нем определяется несколько наборов операторов case, и заданные входные значения сопоставляются с каждым условием.
Оператор case, который соответствует заданному условию ввода, выполняется. Это условие оператора case не имеет никакого возвращаемого значения. В Puppet очень распространенным вариантом использования оператора условия является выполнение набора битов кода на основе базовой операционной системы.
case $ Sysoperenv {
sunos: { include solaris }
redhat: { include redhat }
default: { include generic}
}
Заявление Case также может указывать несколько условий, разделяя их запятыми.
case $Sysoperenv {
development,testing: { include development } testing,production: { include production }
default: { include generic }
}
Утверждение If-Else
Puppet поддерживает концепцию работы на основе условий. Для этого оператор If / else предоставляет параметры ветвления на основе возвращаемого значения условия. Как показано в следующем примере -
if $Filename {
file { '/some/file': ensure => present }
} else {
file { '/some/other/file': ensure => present }
}
Последняя версия Puppet поддерживает переменные выражения, в которых оператор if также может разветвляться на основе значения выражения.
if $machine == 'production' {
include ssl
} else {
include nginx
}
Чтобы добиться большего разнообразия в коде и выполнять сложные условные операции, Puppet поддерживает вложенный оператор if / else, как показано в следующем коде.
if $ machine == 'production' {
include ssl
} elsif $ machine == 'testing' {
include nginx
} else {
include openssl
}
Виртуальный ресурс
Виртуальные ресурсы - это те ресурсы, которые не отправляются клиенту, если они не реализованы.
Ниже приведен синтаксис использования виртуального ресурса в Puppet.
@user { vipin: ensure => present }
В приведенном выше примере пользовательский vipin определяется виртуально, чтобы реализовать определение, которое можно использовать в коллекции.
User <| title == vipin |>
Комментарии
Комментарии используются в любом бите кода для создания дополнительного узла о наборе строк кода и его функциональности. В Puppet в настоящее время поддерживаются два типа комментариев.
- Комментарии в стиле оболочки Unix. Они могут быть в своей строке или в следующей строке.
- Многострочные комментарии в стиле c.
Ниже приведен пример комментария в стиле оболочки.
# this is a comment
Ниже приведен пример многострочного комментария.
/*
This is a comment
*/
Приоритет оператора
Приоритет оператора Puppet соответствует стандартному приоритету в большинстве систем, от самого высокого до самого низкого.
Ниже приводится список выражений
- ! = нет
- / = раз и разделить
- - + = минус, плюс
- << >> = сдвиг влево и сдвиг вправо
- ==! = = не равно, равно
- > = <=> <= больше равно, меньше или равно, больше, меньше
Выражение сравнения
Выражение сравнения используется, когда пользователь хочет выполнить набор операторов, когда данное условие удовлетворяется. Выражения сравнения включают проверки на равенство с использованием выражения ==.
if $environment == 'development' {
include openssl
} else {
include ssl
}
Не равный пример
if $environment != 'development' {
$otherenvironment = 'testing'
} else {
$otherenvironment = 'production'
}
Арифметическое выражение
$one = 1
$one_thirty = 1.30
$two = 2.034e-2 $result = ((( $two + 2) / $one_thirty) + 4 * 5.45) -
(6 << ($two + 4)) + (0×800 + -9)
Логическое выражение
Булевы выражения возможны с использованием or, and, & not.
$one = 1
$two = 2
$var = ( $one < $two ) and ( $one + 1 == $two )
Регулярное выражение
Puppet поддерживает сопоставление регулярных выражений с использованием = ~ (совпадение) и! ~ (Не совпадение).
if $website =~ /^www(\d+)\./ {
notice('Welcome web server #$1')
}
Подобно совпадению регистра и селектора, регулярное выражение создает переменную с ограниченной областью видимости для каждого регулярного выражения.
exec { "Test":
command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt",
unless => "/bin/which php"
}
Точно так же мы можем использовать if, если не выполняем команду все время, за исключением команды ниже, если не завершится успешно.
exec { "Test":
command => "/bin/echo now we don’t have openssl installed on machine > /tmp/test.txt",
unless => "/bin/which php"
}
Работа с шаблонами
Шаблоны используются, когда кто-то хочет иметь заранее определенную структуру, которая будет использоваться в нескольких модулях в Puppet, и эти модули будут распространяться на нескольких машинах. Первым шагом к использованию шаблона является создание шаблона, который отображает содержимое шаблона с помощью методов шаблона.
file { "/etc/tomcat/sites-available/default.conf":
ensure => "present",
content => template("tomcat/vhost.erb")
}
Puppet делает несколько предположений при работе с локальными файлами, чтобы обеспечить организацию и модульность. Puppet ищет шаблон vhost.erb внутри папки apache / templates внутри каталога модулей.
Определение и запуск служб
В Puppet у него есть ресурс под названием service, который способен управлять жизненным циклом всех служб, работающих на любой конкретной машине или среде. Ресурсы служб используются, чтобы убедиться, что службы инициализированы и включены. Они также используются для перезапуска службы.
Например, в предыдущем шаблоне tomcat, который у нас есть, мы устанавливаем виртуальный хост apache. Если кто-то хочет убедиться, что apache перезапускается после изменения виртуального хоста, нам нужно создать ресурс службы для службы apache, используя следующую команду.
service { 'tomcat':
ensure => running,
enable => true
}
При определении ресурсов нам необходимо включить опцию уведомления, чтобы запустить перезапуск.
file { "/etc/tomcat/sites-available/default.conf":
ensure => "present",
content => template("vhost.erb"),
notify => Service['tomcat']
}