Назад | Перейти на главную страницу

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

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

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

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

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

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

--
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 факты, основанные на данных hiera, и с использованием 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 / хост для сбора. Возможно, я что-то упустил, но не думаю, что это возможно, поскольку экспорт происходит при анализе ресурса, а не при реализации узла, содержащего этот ресурс.

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

Если это так, я бы также рекомендовал использовать экспортированные ресурсы и использовать теги для указания конкретного ресурса, который нужно использовать. Причина этого в том, что у одного хоста есть два основных способа получить информацию о другом хосте. Оба требуют включения 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/