Puppetマニフェストを高度かつ複数人で安全に使うための規約例やテクニックおよびすべからず等について記述する。元々Hieraの使い方のロクな資料がなかったので何とかしたくて始めたこのシリーズもやっとここまできたかという感じ。
ここまで読んでくれた方であればHieraを使った構成のスッキリ感と見通しの良さに感動するはず。
なお、hieraの機能の中で最も簡略にマニフェストが書けるようになるhiera_include
の利用のみを焦点として書いている。
Hieraを使ってModuleをスッキリ書く例を紹介していましたが、params Classの内部ブロックで新たにローカル変数を環境に応じて定義するような場合にうまくいかないので消しました。
本シリーズの目次
- Infrastructure as Code 概念の理解
- Puppet環境の準備
- Puppetの基本の理解その1 Resource,Ordering,Class,Define,Node
- Puppetの基本の理解その2 Module,File,Templates,Variable
- Puppetベストプラクティスの理解その1 ディレクトリ構成とその役割j
- Puppetベストプラクティスの理解その2 多種多様なサーバの構成管理
- Puppetベストプラクティスの理解その3 Hieraで世界が変わる? (本ページの内容)
Hieraとは?
公式サイトによるとHieraとは、
- Hiera以前のマニフェストの冗長さを無くして、クラスタのnodeやrole差分を管理可能とする。
ものである。
もうちょっと噛み砕くと、
-
node
定義で構成差分を記載しようとすると冗長になるので、node単位のYAML形式でClass宣言もParameter調整も書けるようにする - さらにそのYAMLは階層構造をもたせるようにして環境差分を書きやすくする
ものである。
うーん、ダメだ。文字だけだと全然うまく書けないわ。
(完全に余談だが、後発の構成管理ツールのAnsibleでは全てのroleやパラメタの設定をYAML形式で書くようになっている。きっとPuppetのHieraやENCを参考としたに違いないと勝手に思っている。)
Hieraを使うと何が嬉しいのか?
node定義がコンパクトになる。
Hieraを使うと、node
定義には以下の情報しか必要なくなる。
- Moduleを跨いだClass間の依存関係(Ordering)しか書かなくて良くなる。
- (もしロールを識別して設定を変えたい場合は、)ロール識別用の変数
もし依存関係が無いnode定義の場合、以下のように書くだけである。
node web01 {
$myrole = "web" #ロール識別用の変数
hiera_include('classes')
}
node定義のClass宣言やParameter調整がスッキリ書ける。
Hieraを使うと、以前はnode定義でしていたClass宣言やParameter変更の記述は全てYAMLでマニフェストとは分離して記載できる。
例えば、
node web01 {
class { 'os':
hosts_tmpl => "os/hosts.web01",
sysctl_addon => ["net.core.somaxconn = 512", "vm.swappiness = 0"],
}
}
というnode
定義は、
---
classes:
- os
os::params::hosts_tmpl: "os/hosts.web01"
os::params::sysctl_addon:
- "net.core.somaxconn = 512"
- "vm.swappiness = 0"
と書けるようになる。
同一ホスト名の商用・試験環境での構成差分をスッキリ書ける。
facterやTopレベル変数、Nodeレベル変数等使って優先度をつけてYAMLを適用できる。
-
hosts/(ホスト名)-(環境名).yaml: 環境名(商用=
production
,試験=test
)でのみホスト名単位で適用されるクラス宣言やParameter調整を記述。 - hosts/(ホスト名).yaml: ホスト名に応じたクラス宣言やParameter調整を記述。
- roles/(ロール名).yaml: WebやDB等のロールに応じたクラス宣言やParameter調整を記述。
- common.yaml: 全てのサーバが行うクラス宣言やParameter調整を記述。
というような任意の階層構造を定義し、上に行くほど優先的な設定となるよう重複なく記述できる。
例えばHiera以前の以下のようなnode
定義群を考える。
# /etc/puppet/manifests/site.pp
$env = "test"
# /etc/puppet/manifests/web.pp
node web01 {
class { 'common':
label => "this is web01"
}
class { 'os':
hosts_tmpl => "os/hosts.web01",
sysctl_addon => ["net.core.somaxconn = 512", "vm.swappiness = 0"],
}
if $env == "production" {
class { 'apache':
document_root => "/opt",
}
} elsif $env == "test" {
class { 'apache':
thread_num => 10,
document_root => "/opt",
}
}
}
node /^web[0-9]{4}.*$/ {
include common
include os
include apache
}
# /etc/puppet/manifests/web.pp
node monitor01 {
class { 'common':
label => "this is monitor01"
}
class { 'os':
hosts_tmpl => "os/hosts.monitor01",
}
include nagios
}
各node
定義でのosやcommon等の共通のClass宣言等かなり冗長に感じるのではないだろうか?
更に商用環境と試験環境でのClass宣言挙動を切り替えるためのenv変数が加わり更に見通しが悪い。そもそも{}が邪魔くさい。
これと同じ構成管理をHieraで記述すると以下のようになる。
# /etc/puppet/manifests/site.pp
$env = "test"
# /etc/puppet/manifests/web.pp
node web01 {
$myrole = "web"
hiera_include('classes')
}
node /^web[0-9]{4}.*$/ {
$myrole = "web"
hiera_include('classes')
}
# /etc/puppet/manifests/monitor.pp
node monitor01 {
$myrole = "monitor"
hiera_include('classes')
}
# /etc/puppet/hieradata/common.yaml
---
classes:
- common
- os
# /etc/puppet/hieradata/roles/web.yaml
---
classes:
- apache
# /etc/puppet/hieradata/hosts/web01.yaml
---
common::params::label: "this is web01"
os::params::hosts_tmpl: "os/hosts.web01"
os::params::sysctl_addon:
- "net.core.somaxconn = 512"
- "vm.swappiness = 0"
apache::params::document_root: "/opt"
# /etc/puppet/hieradata/hosts/web01-test.yaml
---
apache::params::thread_num: 10
# /etc/puppet/hieradata/hosts/monitor01.yaml
---
classes:
- nagios
common::params::label: "this is monitor01"
os::params::hosts_tmpl: "os/hosts.monitor01"
となる。
下層のレイヤでのClass宣言やParameter調整を有効としたままに、更に上層レイヤで上書きや追加ができるのでHieraのほうがシンプルに構成を見通せるということがなんとなく伝わったであろうか。
Hieraの使い方
puppet 3系以降ではhiera機能はデフォルトで使える。
hiera.yamlの作成
Hieraを使うためには、
- HieraによるシステムのYAML設定の置き場所
- Hieraの階層構造
などが記載された/etc/puppet/hiera.yaml
ファイルを準備する必要がある。
以下のファイルを作成する。
---
:backends:
- yaml
:yaml: #ここがシステムのYAML設定の置き場所
:datadir: /etc/puppet/hieradata
:hierarchy: # ここが階層構造を指定する部分。
- hosts/%{::hostname}-%{::env}
- hosts/%{::hostname}
- roles/%{myrole}
- common
この設定は先の例で動くように意識したものとなっている。
階層構造の設計
Hieraでは、hiera.yamlの:datadir:
(この例では/etc/puppet/hieradata
)の末尾に:hierarchy:
を下から順に適用したYAMLファイルを読み込んで行うべきクラス宣言やParameter設定を決定する。
:hierarchy:
で出てくる"%{::hostname}"
はpuppetにおける$::hostname
変数の参照と同じである。
ただし、:hierarchy:
の定義に使える変数はTopレベルもしくはNodeレベルでの変数のみである。
nodeレベルの変数の参照をフルパスで指定する方法は(多分)無いため、動的な名前解決に頼っている。
(ちゃんとNodeレベルの変数を拾ってくれるのか不安なのでModuleであまり使わなそうなmyrole
というnodeレベル変数を今回は使ってみた。)
例えば、monitor01
サーバの場合、
- /etc/puppet/hieradata/common.yaml
- /etc/puppet/hieradata/roles/monitor.yaml
- /etc/puppet/hieradata/hosts/monitor01.yaml
- /etc/puppet/hieradata/hosts/monitor01-test.yaml
の順序でYAMLファイルを探して適用していく。ファイルがなくても問題はない。
Puppetの学習に便利なリンク
-
[PuppetLabs - Docs: Puppet 3.N Reference Manual] (https://docs.puppetlabs.com/puppet/latest/reference/)
- より細かい言語仕様について書かれたページ基本編を越えた状態であれば読み解けるはず。
- このマニュアルを一通り理解したメンバのみでPuppetマニフェストを作れれば相当幸せになれる。
-
- 順を追って書かれており初学者が体系的な学習にお勧め。
- ぶっちゃけこのページはこのリンク先を圧縮したようなものである。
- このチュートリアル用のVMも無料ダウンロードできる。(ただし登録が必要)