Вопрос или проблема
Я унаследовал сервер Puppet. У него есть несколько десятков управляемых хостов, и в основном он работает нормально.
Когда я говорю “в основном”, есть несколько хостов, которые не работают при проверке:
Ошибка: Не удалось применить каталог: Не удается найти зависимость File[/etc/postfix/main.cf] для Augeas[установить postfix 'relayhost' на 'smtp.mydomain.net']
Я немного покопался и установил, что определение класса находится в файле “default.pp”
postfix::config {
"relayhost": value => "smtp.mydomain.net"
}
Теперь, я (возможно, неправильно) понимаю, что этот файл используется каждым хостом, управляемым Puppet, но проблема существует только на нескольких хостах. Большинство работают нормально.
Следовательно, я работаю по теории, что проблема на стороне клиента, а не сервера.
Очевидно, первое, что нужно проверить, – существует ли файл /etc/postfix/main.cf на проблемных хостах. Он существует.
Я провел день, гугля проблему, и все возможные проблемы, которые я нашел, касались ошибок пользователей при написании манифестов. Я не нашел никого, кто испытывает трудности с конкретными хостами, используя манифест, который, по-видимому, работает нормально на других хостах.
Я нов в Puppet (но не в Linux) и нахожу это интересным, хотя сообщения об ошибках, которые вы получаете от Puppet, могут быть несколько загадочными.
Любая помощь будет очень полезна.
Системы – CentOS 6 с puppet 3.2.3-1
— ОБНОВЛЕНИЕ —
(Извините за задержку с ответом, я в Австралии, так что разница во времени имеет значение)
Хорошо, исходя из ответа Крейга ниже, я выполнил grep в каталоге puppet на сервере Puppet для поиска экземпляров main.cf
root@svd7puppetmaster:/etc/puppet ] # grep -R main.cf *
modules/postfix/manifests/init.pp: file { '/etc/postfix/main.cf':
modules/postfix/manifests/init.pp: source => 'puppet:///modules/postfix/main.cf',
modules/postfix/manifests/config.pp:#конфигурационный файл (/etc/postfix/main.cf).
modules/postfix/manifests/config.pp: incl => '/etc/postfix/main.cf',
modules/postfix/manifests/config.pp: require => File['/etc/postfix/main.cf'],
Содержимое файлов следующее (я удалил заголовки комментариев для краткости);
root@svd7puppetmaster:/etc/puppet ] # cat modules/postfix/manifests/init.pp
class postfix {
# метки selinux различаются от одного дистрибутива к другому
case $::operatingsystem {
RedHat, CentOS: {
case $::lsbmajdistrelease {
'4': { $postfix_seltype="etc_t" }
'5','6': { $postfix_seltype="postfix_etc_t" }
default: { $postfix_seltype = undef }
}
}
default: {
$postfix_seltype = undef
}
}
# Значение по умолчанию для различных параметров
if $postfix_smtp_listen == '' {
$postfix_smtp_listen = '127.0.0.1'
}
if $root_mail_recipient == '' {
$root_mail_recipient="nobody"
}
if $postfix_use_amavisd == '' {
$postfix_use_amavisd = 'no'
}
if $postfix_use_dovecot_lda == '' {
$postfix_use_dovecot_lda="no"
}
if $postfix_use_schleuder == '' {
$postfix_use_schleuder="no"
}
if $postfix_use_sympa == '' {
$postfix_use_sympa="no"
}
if $postfix_mail_user == '' {
$postfix_mail_user="vmail"
}
case $::operatingsystem {
/RedHat|CentOS|Fedora/: {
$mailx_package="mailx"
}
/Debian|kFreeBSD/: {
$mailx_package = $::lsbdistcodename ? {
/lenny|etch|sarge/ => 'mailx',
default => 'bsd-mailx',
}
}
'Ubuntu': {
if (versioncmp('10', $::lsbmajdistrelease) > 0) {
$mailx_package="mailx"
} else {
$mailx_package="bsd-mailx"
}
}
}
$master_os_template = $::operatingsystem ? {
/RedHat|CentOS/ => template('postfix/master.cf.redhat.erb', 'postfix/master.cf.common.erb'),
/Debian|Ubuntu|kFreeBSD/ => template('postfix/master.cf.debian.erb', 'postfix/master.cf.common.erb'),
}
package { 'postfix':
ensure => installed,
}
package { 'mailx':
ensure => installed,
name => $mailx_package,
}
service { 'postfix':
ensure => running,
enable => true,
hasstatus => true,
restart => '/etc/init.d/postfix reload',
require => Package['postfix'],
}
file { '/etc/mailname':
ensure => present,
content => "$::fqdn\n",
seltype => $postfix_seltype,
}
# Псевдонимы
file { '/etc/aliases':
ensure => present,
content => '# файл, управляемый puppet\n',
replace => false,
seltype => $postfix_seltype,
notify => Exec['newaliases'],
}
# Псевдонимы
exec { 'newaliases':
command => '/usr/bin/newaliases',
refreshonly => true,
require => Package['postfix'],
subscribe => File['/etc/aliases'],
}
# Конфигурационные файлы
file { '/etc/postfix/master.cf':
ensure => present,
owner => 'root',
group => 'root',
mode => '0644',
content => $master_os_template,
seltype => $postfix_seltype,
notify => Service['postfix'],
require => Package['postfix'],
}
# Конфигурационные файлы
file { '/etc/postfix/main.cf':
ensure => present,
owner => 'root',
group => 'root',
mode => '0644',
source => 'puppet:///modules/postfix/main.cf',
replace => false,
seltype => $postfix_seltype,
notify => Service['postfix'],
require => Package['postfix'],
}
# Параметры конфигурации по умолчанию
$myorigin = $valid_fqdn ? {
'' => $::fqdn,
default => $valid_fqdn,
}
postfix::config {
'myorigin': value => $myorigin;
'alias_maps': value => 'hash:/etc/aliases';
'inet_interfaces': value => 'all';
}
case $::operatingsystem {
RedHat, CentOS: {
postfix::config {
'sendmail_path': value => '/usr/sbin/sendmail.postfix';
'newaliases_path': value => '/usr/bin/newaliases.postfix';
'mailq_path': value => '/usr/bin/mailq.postfix';
}
}
default: {}
}
mailalias {'root':
recipient => $root_mail_recipient,
notify => Exec['newaliases'],
}
}
и
root@svd7puppetmaster:/etc/puppet ] # cat modules/postfix/manifests/config.pp
define postfix::config ($value, $ensure = present) {
Augeas {
incl => '/etc/postfix/main.cf',
lens => 'Postfix_Main.lns',
notify => Service['postfix'],
require => File['/etc/postfix/main.cf'],
}
case $ensure {
present: {
augeas { "set postfix '${name}' to '${value}'":
changes => "set $name '$value'",
}
}
absent: {
augeas { "rm postfix '${name}'":
changes => "rm $name",
}
}
default: {}
}
}
Манифесты для хостов довольно простые. Для краткости я не буду их здесь размещать, если не попросят. Они почти полностью определяют IP-адрес сети и серверы NTP. Ничто, связанное с postfix, вообще не затрагивается. Они наследуют другой манифест, который касается только некоторых настроек SNMP и системного логирования, и который, в свою очередь, наследует default.pp, содержащий раздел Postfix (показанный в начале этого вопроса), вызывающий проблему (если я закомментирую его, проблема исчезает)
Единственное различие между работающим хостом и неработающим хостом – это буквально имя узла и его IP-адрес, в остальном два манифеста идентичны.
Я могу выложить содержимое этих файлов, если кто-либо хочет их увидеть.
Я также проверил происхождение модуля postfix:
root@svd7puppetmaster:/etc/puppet ] # puppet module list | grep postfix
├── postfix (???)
Я предполагаю, что с учетом того, что модуль не имеет префикса “puppetlabs”, он не является официальным модулем? Я не уверен, как еще это проверить.
— ОБНОВЛЕНИЕ —
Извините за задержку, возникли недоразумения в наших производственных системах, на которые ушло время, поэтому это пришлось отложить.
В любом случае, это меня очень беспокоит. Я взял два хоста, один из которых работает, а другой – нет.
Я создал совершенно пустые манифесты для них обоих:
node myhost1 {
}
Манифест приложения выглядит так:
node application {
}
Тем не менее, когда я запускаю агент puppet на обоих, я получаю разные результаты:
[09:32:55 root@myhost01:~ ] # puppet agent --test
Информация: Извлечение плагина
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/os_maj_version.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/iptables_persistent_version.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/ip6tables_version.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/root_home.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/puppet_vardir.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/concat_basedir.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/pe_version.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/iptables_version.rb
Информация: Кэширование каталога для myhost01.mydomain.net
Информация: Применение версии конфигурации '1426804333'
Уведомление: Завершен запуск каталога за 1.00 секунду
и
[root@myhost02 datawarehouse]# puppet agent --test
Информация: Извлечение плагина
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/os_maj_version.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/root_home.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/iptables_version.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/concat_basedir.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/ip6tables_version.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/puppet_vardir.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/pe_version.rb
Информация: Загрузка фактов в /var/lib/puppet/lib/facter/iptables_persistent_version.rb
Информация: Кэширование каталога для myhost02.mydomain.net
Ошибка: Не удалось применить каталог: Не удается найти зависимость File[/etc/postfix/main.cf] для Augeas[установить postfix 'relayhost' на 'smtp.mydomain.net']
Очевидно, что моё понимание работы Puppet сильно недостаточно, потому что я не понимаю, почему два хоста с пустыми манифестами ведут себя по-разному.
В любом случае, спасибо за вашу помощь, ребята, но кажется, что я пока просто отложу это в долгий ящик.
Это определенно проблема с манифестами на сервере puppetmaster, но, по всей видимости, она вызывается какой-то вариацией на стороне клиентов, что приводит к оценке другой части манифестов Puppet в модуле postfix.
Где-то в модуле postfix будет ресурс augeas с зависимостью от File[‘/etc/postfix/main.cf’] (требование, уведомление, подписка и т. д.), но ресурс file { ‘/etc/postfix/main.cf’: } по какой-то причине не был объявлен (возможно, он находится внутри ‘if’ или что-то подобное). Трудно догадаться, что это, не имея больше информации о модуле postfix.
Модуль postfix из puppetlabs puppetforge? Если да, то какой именно (их много), и какая версия? Если нет, можете ли вы поделиться модулем?
Ваш Ошибка: Не удалось применить каталог: Не удалось найти зависимость File[/etc/postfix/main.cf] для Augeas[установить postfix 'relayhost' на 'smtp.mydomain.net']
означает, что где-то в ваших манифестах есть augeas { "set postfix 'relayhost' to ...."
с require File['/etc/postfix/main.cf']
, что подразумевает, что Puppet должен сначала установить основную конфигурацию postfix, а затем установить ваш relayhost, в то время как искомый файл не является частью применяемого каталога.
К слову об этом: если вы устанавливаете свой основной шаблон postfix каждый раз, а затем используете augeas для редактирования relayhosts: Puppet будет дважды редактировать конфигурацию postfix при каждом выполнении. Вы можете исследовать возможность использования одного шаблона здесь или добавления replace => no
к file{}
, которая устанавливает основную конфигурацию postfix.
Вернемся к вашей проблеме, похоже, что вы включаете postfix::config
, но не включили postfix
сам по себе, что (насколько я понимаю) позаботилось бы об установке основной конфигурации postfix.
Перед тем, как сломать всю конфигурацию postfix, управляемую этим puppetmaster, вам стоит убедиться, что вы работаете в отдельной среде. Затем, как дикая догадка, не имея представления о вашей настройке: отредактируйте свой postfix/manifests/config.pp
, добавив где-то внутри определения postfix::config
:
if (! defined(Class["postfix"])) {
include postfix
}
Обратите внимание, что узел, на котором “это работало”, теперь может быть затронут дублирующимся определением postfix: ищите другие включения, добавляющие эту проверку определения и т. д.
К слову, вы не должны редактировать свои манифесты Puppet, если не знаете, что делаете (учитывая всех зарегистрированных клиентов, которые обновят свою конфигурацию и т. д., даже при наилучших условиях все может сломаться…)
Ответ или решение
Проблема, с которой вы столкнулись, связана с отсутствием зависимости File[/etc/postfix/main.cf]
для ресурса Augeas[set postfix 'relayhost' to 'smtp.mydomain.net']
. Это указывает на то, что при выполнении каталога Puppet на некоторых узлах не удается найти ресурс file { '/etc/postfix/main.cf': }
, необходимый для конфигурации.
Причины проблемы
-
Отсутствие объявления файла: Похоже, что для некоторых узлов файл
/etc/postfix/main.cf
не создается, возможно, из-за условий, прописанных в манифестах. В частности, проверьте, не находится ли создающее этот файл выражение в условииif
, которое может не выполняться на проблемных узлах. -
Разные манифесты: Если у вас есть пустой манифест для обоих узлов, вам следует убедиться, что все узлы правильно наследуют определения классов и все необходимые зависимости.
-
Неправильная конфигурация класса: Возможно, что ваша класс-определение
postfix::config
не включается правильно или полностьюinclude postfix
не вызывается на проблемных узлах, в результате чего зависимости не разрешаются.
Решение проблемы
-
Дополнение в определение класса
postfix::config
: Вам рекомендуется добавить проверку на наличие классаpostfix
внутри классаpostfix::config
. Это можно сделать следующим образом:define postfix::config ($value, $ensure = present) { if (! defined(Class["postfix"])) { include postfix } Augeas { incl => '/etc/postfix/main.cf', lens => 'Postfix_Main.lns', notify => Service['postfix'], require => File['/etc/postfix/main.cf'], } # остальная часть вашего определение класса }
-
Проверка конфигураций: Убедитесь, что проблема не вызвана другими модулями или включениями конфигураций, которые могут нарушать порядок выполнения ресурсов.
-
Логи и выводы: Просматривайте логи Puppet на узлах с помощью
puppet agent --test
для уточнения, в какой момент возникает ошибка. Это может помочь выявить, какие манифесты все еще влияют на «неработающие» узлы. -
Изолированная среда: Всегда тестируйте изменения в изолированной среде. Настройка отдельного окружения позволит избежать влияния на рабочие узлы и поможет вам проверить, как ваши изменения отразятся на поведении ух различных узлов.
Заключение
Наиболее вероятная причина проблемы заключается в том, что не все узлы одинаково обрабатывают ваши манифесты, и это может быть связано с отсутствующими зависимостями или условиями в манифестах, которые должны быть разрешены до вызова postfix::config
.
Если после выполнения данных шагов проблема все еще не решена, рекомендуется проверить детально логи для выявления дополнительных подробностей об ошибках конфигурации и проведении ручных тестов на конкретных узлах.