Ansible 変数の定義箇所
Ansibleの変数の優先度、特に複数箇所で同一名で定義された場合の優先順位について調べた。 また meta/main.yml:dependency を用いたrole間の依存関係に基づいたroleの適用順序も調べた。
roleの構造
はじめに role の構造について説明する。 ベストプラクティスをまねた構成が下のようになる。
|
|
大きく分けて4つに分類してみる。
カテゴリ | ディレクトリ名 |
---|---|
ロール自体について | meta |
適用項目 | tasks, handlers |
変数 | vars, defaults |
Ansibleの拡張 | library, module_utils, lookup_plugins |
role間の依存関係
これに関わるのは meta ディレクトリ。 meta/main.yml ファイルでは項目 dependencies を使って他の role への依存を定義できる。 また依存先の role で使われる変数の値も指定できる。
|
|
次の節で詳しく書くが、この場合 other_role_a は普通に呼ばれるが、 other_role_b の適用時での var_foo の値は value_bar が用いられる。
roleの適用順序
基本的には playbook の roles に記載されている role が上から順に適用されていく。 下の場合には roleA,roleB,roleC と適用されていく。
|
|
ここで roleB が meta/main.yml で roleZ への依存が定義されていた場合、 roleZ の適用が roleB の適用に先行し、全体としては roleA,roleZ,roleB,roleC と適用されることになる。
複数の role が1つの role に依存している場合
不明瞭だった複数の role が同一 role に依存している場合の適用順序について調べた。
先に結果を具体例を用いて説明する。 下記の依存関係がある場合、 roleZ の適用は roleA,roleB,roleD の前に1回ずつ全部で3回呼ばれる。また roleD,roleE で other_var が異なる値に解決されるとしても、適用箇所には無関係だった。
roleA -> {"role": "roleZ"}
roleB -> {"role": "roleZ", "var": "value"}
roleC -> {"role": "roleZ"}
roleD -> {"role": "roleZ", "var": "{{ other_var }}"}
roleE -> {"role": "roleZ", "var": "{{ other_var }}"}
これらから下の規則が推測される。
- 各呼び出し元の依存定義の種類毎に1回ずつ呼ばれる
- 変数の値が別の値を参照している場合でも role 適用時には値は解決されず文字列として扱われる
- 値が解決されるのはあくまで task 内で利用される時に限られる
変数の値の解決順序
続いて、変数の値の解決について調べた。 まず、基本の確認。
"{{ var }}"
を tasks,defaults,vars,templates などで使うと評価され値に展開される。
var: "{{ foo }}"
などと値がまた別の変数を参照している時には再帰的に展開される。
Ansible は複数のデプロイ先を同時に扱える。また変数定義や task の適用はホストやグループ毎に制御できる。 なので変数はホスト単位で管理されていると考えて問題ない。
変数は複数箇所で値を設定できる。自分が知ってて使う場所は以下の通り。(他にもあるかも知れないけど扱わない)
- meta の dependencies による指定
- role の vars 配下
- set_fact モジュール task で定義
- register による task の実行結果
- playbook の vars_files による定義
- playbook の vars による定義
- inventory ファイル内
- role の defaults 配下
これよりも強い指定方法もあるけど、あまり使ってない。 基本的に状況が絞られてるものほど優先度が高くなっている。 playbook での指定より task, role での指定の方が基本的に優先されている。
複数の role で同一変数を定義している場合
role はデプロイを分割する機構であるものの変数は role をまたいで干渉するため、整理しないと混乱する。そこで role に関わる vars,defaults,meta:dependencies での指定について調べた。
探される順序は下の様になった(上で見つかったらそこ確定)
- meta/main.yml での指定
- 現在の role の vars 内での定義
- 他の role の vars 内での定義(複数存在する場合、最後に定義した role の値)
- 現在の role の defaults 内での定義
- 他の role の defaults 内での定義(複数存在する場合、最後に定義した role の値)