Использование 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/