Пуппет не удалось найти зависимость.

Вопрос или проблема

Я унаследовал сервер 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': }, необходимый для конфигурации.

Причины проблемы

  1. Отсутствие объявления файла: Похоже, что для некоторых узлов файл /etc/postfix/main.cf не создается, возможно, из-за условий, прописанных в манифестах. В частности, проверьте, не находится ли создающее этот файл выражение в условии if, которое может не выполняться на проблемных узлах.

  2. Разные манифесты: Если у вас есть пустой манифест для обоих узлов, вам следует убедиться, что все узлы правильно наследуют определения классов и все необходимые зависимости.

  3. Неправильная конфигурация класса: Возможно, что ваша класс-определение postfix::config не включается правильно или полностью include postfix не вызывается на проблемных узлах, в результате чего зависимости не разрешаются.

Решение проблемы

  1. Дополнение в определение класса 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'],
        }
    
        # остальная часть вашего определение класса
    }
  2. Проверка конфигураций: Убедитесь, что проблема не вызвана другими модулями или включениями конфигураций, которые могут нарушать порядок выполнения ресурсов.

  3. Логи и выводы: Просматривайте логи Puppet на узлах с помощью puppet agent --test для уточнения, в какой момент возникает ошибка. Это может помочь выявить, какие манифесты все еще влияют на «неработающие» узлы.

  4. Изолированная среда: Всегда тестируйте изменения в изолированной среде. Настройка отдельного окружения позволит избежать влияния на рабочие узлы и поможет вам проверить, как ваши изменения отразятся на поведении ух различных узлов.

Заключение

Наиболее вероятная причина проблемы заключается в том, что не все узлы одинаково обрабатывают ваши манифесты, и это может быть связано с отсутствующими зависимостями или условиями в манифестах, которые должны быть разрешены до вызова postfix::config.

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

Оцените материал
Добавить комментарий

Капча загружается...