Puppet

使用 hiera 訪問另一個節點的事實

  • September 21, 2021

我們要做的是為 iptables 生成防火牆規則(puppetlabs/firewall)。我們的節點在概念上是這樣分組的:

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

節點“specific4”將始終需要訪問“shared2”上的埠 8080 和“site1”上的埠 10000。“specific1”同樣需要訪問“shared1”上的 8080。每個節點的規則總是相同的,但它們將取決於它們屬於哪個組。

我正在努力尋找一種方法來在不重複的情況下在 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/主機進行收集。也許我錯過了一些東西,但我認為這是不可能的,因為導出是在解析資源時發生的,而不是在實現包含該資源的節點時發生的。

因此,您希望某些主機從另一個主機的事實中獲取資訊,但事實來自哪個主機將根據特定主機的配置而有所不同。那是對的嗎?

如果是這樣,我還建議使用導出的資源並使用標籤來指定要使用的特定資源。原因是主機基本上有兩種方法可以了解另一主機的事實。兩者都需要啟用 storeconfigs。一種是讓 puppet master 對 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”。

引用自:https://serverfault.com/questions/503812