...

понедельник, 16 сентября 2013 г.

[Из песочницы] puppet: уменьшение автоматизации без потери функционала

Любой, кто занимается администрированием более двух одинакого настраиваемых серверов, рано или поздно, начинает смотреть на системы, позволяющие автоматизировать процесс настройки. Я для этого использую puppet и хотел бы поделиться опытом его применения на большом количестве серверов (в данный момент управляемая инфраструктура — около 120 Linux серверов (Centos 5 + Centos 6), котоыре можно разделить на три неравные логические группы), которые должны работаь в режиме 24/7/365.



Автоматизации, иногда, бывает слишком много




Puppet удобен тем, что все сценарии хранятся на центральном сервере и автоматически распространяются на клиентсие машины. Это означает, что любая пропущенная ошибка, за конечное время, распространится на все серверы. Puppet предлагает, в принципе, готове решение — environment, с помощью которого можно задать поведения клиента для разных случаев. Но это означает что нужно отдельное хранилище для тестируемых правок раз, отдельный puppet-master два, дополнительный рестрат puppet-клиента (с новым environment) три.

Что бы этого избежать можно воспользоваться системой ручного запуска манифестов. Для этого манифесты должны находится на локальной машине и вызов осуществляется через puppet apply. Для синхронизации клиента и mater'a тоже используется puppet



class sync {

include site_settings


file {

"/etc/puppet/":

source => «puppet://$site_settings::master/files/»,

ensure => 'directory',

recurse => true,

purge => true,

force => true,

ignore => ['.svn','.*.swp'],

}

}



По сколку не используется автоматическое распространение изменений на клиентские машины правки можно делать прямо на мастере, синхронизировать один узел и тестироваться на нем. Затем, например через pdsh, синхронизировать остальные серверы и, опять же через pdsh, запускать нужные классы на всех серверах через puppet apply -e "include some_class"


Установка и перенасройка — одно и тоже




Второе, с чем редко сталкиваешься, когда читаешь статьи о системах управления, — первичная установка сервера.

При правильно написаных сценариях, болшую часть установки можно выполнить на этапе разливки узла, через %post kikstart файлов.

Что бы каждый раз не думать какие класы должны исполняться для настрйоки узла, размуно вызывать всего один — install, который «подумает» за вас, примерно таким образом

class install {

include site_settings

if $site_settings::mlist {

$scripts_dir=$site_settings::scripts_dir

$list="$scripts_dir/install_list.sh"

$mlist=$site_settings::mlist


File {owner=> 'root', group => 'root', mode => 0700}

file {"$scripts_dir":

ensure => 'directory'

} ->

file {"$list":

content => inline_template("#!/bin/sh -x\n<% mlist.each do |val| -%>puppet apply -e 'include <%= val %>::install' && \\\n<% end -%>exit 0 || exit 1"),

} ->

exec {"$list":

provider => 'shell',

logoutput => true,

timeout => 0,

}

}

}



Сам же mlist определяется на основе типа узла из двух частей: общей для всех узлов и специфичной для конкретного типа узла





$mlist_default = ['hosts','dns', 'modules', 'sudo', 'ntp', 'mail','firstboot', 'firewall', 'ssh', 'yum', 'nagios', 'staff', 'logwatch']



$mlist_addons = $group? {



'nagios' => ['x509', 'nagios'],



default => ['']

}


$mlist = split(inline_template("<%= (@mlist_default+@mlist_addons).join(',') %>"),',')





Таким образом, как только мы захотели получить настроенный узел, puppet apply -e 'include install' сделает это для нас в любой момент времени и из любого места

install подкласс в каждом классе описывает то в каком порядке какие подклассы нужно подключать, но об этом ниже. Таким обрзом, например. настройка ssh — это puppet apply -e 'include ssh::install'

Порядок прежде всего




К сожалению, а может и к счастью, puppet устроен так, что невозможно четко задать порядое подключения классов.

Например


incldue class1

include class2

include class3





в большинстве случаев подключит все в правильном порядке. Но как только class2 у нас имеет что-нибудь вроде


include class2.1

include class4





говорить о том, что class4 отработает до class 3 нельзя. Не спазает даже подключение классов как объектов Class{"calss1": } -> Class{"clas2":}-> Class{"class3":}

c lass2 долен выполнится до class3, но условия причинности на все подключаемые внутри класса подклассы не распространяются.

Что бы исключить подобные ситуации проще всего от последовательного подключения классов перейти к созданию и запуску shell скриптов.

Как было отмечено выше, подкласс install отвечает за правильный порядок выполненя манифеста.

На примере того же ssh



class ssh {

include site_settings


$install_list=['sshd', 'ssh_root_keys']

}

class ssh::install inherits ssh {

$install_list=$ssh::install_list

apply::by_list{"${module_name}_install": list=> $install_list}


}




define apply::by_list($list, $sub_class='none') {

if ( $sub_class == 'none' ) {

$script="$site_settings::scripts_dir/${caller_module_name}"

$m_name=$caller_module_name

} else {

$script="$site_settings::scripts_dir/${caller_module_name}_${sub_class}"

$m_name="${caller_module_name}::${sub_class}"

}

File {mode => 0700, owner => 'root', group =>'root'}


file {"$site_settings::scripts_dir":

ensure => 'directory'

} ->


file {"$script":

content => inline_template ("#!/bin/sh -x \n<% list.each do |val| -%>puppet apply -e 'include <% if val == @m_name then %><%= @m_name %><% else %><%= @m_name %>::<%= val %><% end %>' && \\\n<% end -%>exit 0 || exit 1")

} ->


exec {"$title":

command => "$script",

provider => 'shell',

logoutput => true,

timeout => 0,

}

}



Такой подход позволяет игнорировать мнение puppet о том в каком порядке подключать классы и делать это в том порядке, в котором это нужно нам.

Кроме этого, это позволяет разбивать манифесты на смысловые части, и, например, не обновлять rpm, когда нужно только обновить конфигурационные файлы.


Такой отказ от излишней, в нашем случае, автоматизации puppet позволяет, без потери функционала, существенно повысить удобство администрирование вычислительного комплекса и избегать многих ошибок.


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at fivefilters.org/content-only/faq.php#publishers. Five Filters recommends:



Комментариев нет:

Отправить комментарий