Использование hiera для доступа к фактам другого узла

Мы пытаемся создать правила брандмауэра (puppetlabs/firewall) для iptables. Наши узлы сгруппированы следующим образом:

-- site1
---- shared1
------ specific1
------ specific2
---- shared2
------ specific3
------ specific4

Узлу "specific4" всегда потребуется доступ к порту 8080 на "shared2" и порту 10000 на "site1". "specific1" также должен будет получить доступ к 8080 на "shared1". Правила всегда будут одинаковыми для каждого узла, но они будут полагаться на то, к какой группе они принадлежат.

Я изо всех сил пытаюсь найти способ представить это в hiera без дублирования. Можно ли получить факты из совершенно отдельного узла?

Я думаю, что хочу иметь возможность сделать что-то вроде этого (упрощенно):

--
hosts:
  host specific4:
    rules:
      rule:
        port: 8080
        ip: get_ip(get_my_shared())

Но очевидно, что вы не можете вызывать функции из yaml файл. Будет ли лучший способ сделать это с использованием пользовательских фактов? На самом деле я еще не использовал hiera - поэтому я не уверен в лучших практиках, а что нет. Любые мягкие толчки в правильном направлении будут наиболее цениться.

Редактировать:

Это решение, с которым я столкнулся, но если я могу использовать экспортированные ресурсы, я могу удалить зависимость от puppetdb-query.

# helper for creating rules from an array
define firewall_rules($port, $service_type) {
    $source = $name
    firewall { "$port $service_type $source":
        proto       => 'tcp',
        dport       => $port,
        state       => 'NEW',
        source      => "$source",
        action      => 'accept'
    }
}

class profile::specific inherits profile {
    $site = hiera('site')
    $shared = hiera('shared')
    $query = "site=\"$site\" and shared=\"$shared\""
    $shared_hosts = query_nodes($query)
    $specific_port = hiera('specific_ports', '8080')
    firewall_rules { $shared_hosts:
        port           => $specific_port,
        service_type   => 'SPECIFIC'
    }
}

Затем я экспортирую site а также shared факты, основанные на данных иера и использования puppet-stdlib загрузить их из file ресурсы на хосте.

class profile::facts {

    $site       = hiera('site', 'none')
    $shared     = hiera('shared', 'none')
    $specific   = hiera('specific', 'none')
    $role       = hiera('role', 'none')
    $grouping   = "site=$site\nshared=$shared\nspecific=$specific\nrole=$role"

    notify { "facts being set: $grouping ": }

    file { ['/etc/facter/', '/etc/facter/facts.d/']:
        ensure  => directory,
        owner   => 'root',
        group   => 'root'
    }->
    file { '/etc/facter/facts.d/grouping.txt':
        ensure  => file,
        owner   => 'root',
        group   => 'root',
        mode    => '0775',
        content => $grouping
    }
}

Как я уже сказал, это работает, но я бы предпочел использовать экспортируемые ресурсы, если это возможно. Проблема, с которой я столкнулся, заключалась в том, что ресурс, выполняющий экспорт, не мог также экспортировать свой собственный IP/ хост для сбора. Возможно, я что-то пропустил, но я не думаю, что это возможно, поскольку экспорт происходит, когда ресурс анализируется, а не когда реализуется узел, содержащий этот ресурс.

2 ответа

Решение

Таким образом, вы хотите, чтобы определенные хосты получали информацию из фактов другого хоста, но от того, с какого хоста поступают факты, зависит от конфигурации конкретного хоста. Это верно?

Если это так, я бы также рекомендовал использовать экспортируемые ресурсы и использовать теги, чтобы указать конкретный ресурс для использования. Причина этого заключается в том, что у хозяина есть два основных способа узнать факты другого хоста. Оба требуют включения storeconfigs. Один из них заключается в том, что хозяин марионеток должен выполнять явный поиск независимо от того, что является вашей подсистемой storeconfigs; Я не знаю ни одного модуля, который бы инкапсулировал это, поэтому вам, возможно, придется написать свой собственный. Другой для исходного узла экспортировать ресурсы, которые содержат их факты; это проще и тот, который я опишу ниже.

Это будет проще, если вы создадите свой собственный тип ресурса для переноса правил брандмауэра. Это предотвращает любые конфликты с любыми другими классами, которые экспортируют правила брандмауэра.

define site_firewall ($ipaddr) {
  firewall { '500 allow site access':
    chain       => 'OUTPUT',
    destination => $ipaddr,
    proto       => 'tcp',
    port        => 10000,
  }
}

Далее, каждый из ваших сайтов должен экспортировать свое собственное определение для site_firewall:

@@site_firewall { $hostname:
  ipaddr => $ipaddress,
}

В hiera вы определяете где-то в своей иерархии сайт, членом которого является каждый хост:

sitename: site1

Затем в ваших классах хоста вы создаете соответствующий site_firewall определение:

Site_firewall <<| name == hiera('sitename', 'default') |>>

Аналогичная настройка будет применяться для общих хостов.

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

@@firewall { "500 allow site traffic from ${hostname}":
  tag    => hiera('sitename', 'default-site'),
  source => $ipaddress,
  proto  => 'tcp',
  port   => 10000,
}
@@firewall { "500 allow shared traffic from ${hostname}":
  tag    => hiera('sharedname', 'default-shared'),
  source => $ipaddress,
  proto  => 'tcp',
  port   => 8080,
}

На хостах сайта вам просто нужно собрать правила брандмауэра для этих хостов:

Firewall <<| tag == $hostname |>>

Редактировать: Ага. Я думаю, что нашел проблему, с которой вы столкнулись с экспортированными ресурсами. По крайней мере, это ошибка, которую я запишу здесь для хорошей меры.

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

Другими словами, если у вас есть это определение типа ресурса:

define foo ($bar = $fqdn) {
  notice($bar)
}

И вы экспортируете его с хоста baz.example.com:

@@foo { 'title': }

И вы понимаете это на хосте quux.example.com:

Foo <<| |>>

Тогда значение $bar будет "quux.example.com".

Если вместо этого вы экспортируете его из baz.example.com следующим образом:

@@foo { 'title': bar => $fqdn }

Тогда значение $bar действительно будет "baz.example.com".

Ну, я думаю, что хорошим вариантом для вашего сценария использования является включение "storeconfigs", а затем использование "экспортированных ресурсов". Здесь вы можете найти некоторую документацию по этой теме, включая несколько примеров: http://docs.puppetlabs.com/guides/exported_resources.html

http://www.masterzen.fr/2009/03/08/all-about-puppet-storeconfigs/

Другие вопросы по тегам