変数の優先順位を文書ではなく測定で立てる
目標
同じ名前の変数を12か所に1か所ずつ仕込みながら、何が勝つかを自分で測り、その結果をチームが読める優先順位の表として残せるようになります。
なぜ重要なのか
「確かにgroup_varsに書いたのに別の値が表示される」という報告は、エラーとして現れません。プレイブックは成功し、ファイルは作られ、内容だけが違います。構文チェックもリントも、これを捕まえられません。捕まえられるのは、「今この場所で、この名前が何に解決されるか」を測ることだけです。そのため、このラボはドキュメントの一覧を書き写さず、測定します。一度測ったことのある人は、表を覚えなくても、次に何を最初に疑うかがわかります。そして最後に行き着く結論は、表ではありません。場所を減らす設計は、表を知っていることよりも強いのです。
ステップ
/root/ans/prec/inventory/hosts.iniにweb1・web2を書き(ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root)、/root/ans/prec/roles/probe/に測定用のロールを作成してください。defaults/main.ymlにsvc_tier: role-defaultsとprobe_outを置き、tasks/main.ymlは、WINNER={{ svc_tier }}をdebugで表示したあと、同じ値をprobe_outのパスに書く、2つのタスクで埋めてください。/root/ans/prec/p01.ymlでweb1にこのロールを実行し、/root/ans/prec/out/01.txtを残してください。/root/ans/prec/inv-vars/をディレクトリインベントリとして作成してください。hosts.ymlにwebグループ(web1・web2)とdbグループ(db1)を書き、group_vars/all.ymlにinv-all、group_vars/web.ymlにinv-web、host_vars/web2.ymlにinv-hostを、svc_tierとして仕込んでください。/root/ans/prec/p02.ymlで3つのホストすべてを測定し、/root/ans/prec/out/02-<호스트>.txt(プレースホルダーはホスト名です)を残してください。/root/ans/prec/p03.ymlを作成し、プレイのvars:にsvc_tier: play-varsを仕込んで、web1を測定してください。インベントリはステップ2のinv-varsを使い、結果は/root/ans/prec/out/03.txtに残してください。/root/ans/prec/vars/tier.ymlにsvc_tier: vars-fileを書き、/root/ans/prec/p04.ymlは、ステップ3とまったく同じく、プレイのvars:にplay-varsを残したまま、vars_files:でそのファイルを読み込むようにしてください。結果は/root/ans/prec/out/04.txtです。/root/ans/prec/roles/probe_locked/に2つ目の測定用ロールを作成してください。vars/main.ymlにsvc_tier: role-varsを置き(defaultsにはprobe_outだけを置きます)、tasks/main.ymlはprobeと同じように書きます。/root/ans/prec/p05.ymlは、ステップ4と同じ2か所をそのまま残したまま、このロールを呼び出して/root/ans/prec/out/05.txtを残してください。/root/ans/prec/p06.ymlを作成してください。プレイはvars_files:でtier.ymlを読み込み、ブロック1つにvars: {svc_tier: block-vars}を付けます。ブロックの中の最初のタスクはprobe_lockedロールを呼び出して/root/ans/prec/out/06-block.txtを残し、2つ目のタスクは自分のvars:にsvc_tier: task-varsを付けて、/root/ans/prec/out/06-task.txtに値を書いてください。/root/ans/prec/p07.ymlを作成してください。まずset_factでsvc_tier: set-factを立て、そのあと、タスクのvars:にtask-varsを付けたタスクが、値を/root/ans/prec/out/07-setfact.txtに書くようにし、最後にprobe_lockedロールを呼び出してsvc_tier: role-paramを渡し、/root/ans/prec/out/07-roleparam.txtを残してください。/root/ans/prec/vars/limits.ymlにbase_limitsとsvc_limitsを{cpu: "1", memory: 1Gi}で置き、/root/ans/prec/p08.ymlが-e svc_tier=extra-varsと一緒に実行されたとき、/root/ans/prec/out/08.txtにコマンドラインの値が書かれるようにしてください。同じプレイブックで、タスクのvars:でsvc_limits: {memory: 2Gi}を渡した結果と、combineでマージした結果を、/root/ans/prec/out/08-hash.jsonにreplaced・combinedの2つのキーで残し、12か所の測定結果を/root/ans/prec/out/rank.mdに表として書いてください。
参考
- 測定用のロールは、値を判断しません。今見えている値を、画面(
WINNER=...)とファイルにそのまま移すだけです。この物差しをステップ1で作り、最後まで使います。 - インベントリの中での勝負は、プレイブックがなくても見られます。
ansible-inventory -i <인벤토리> --list(プレースホルダーはインベントリです)が、マージされた結果をJSONで返します。 - ディレクトリとして渡したインベントリの中では、無視される拡張子があります。ホストが1つも見えなければ、まずファイル名を疑ってください。
- よくある間違い: 優劣を測りながら、下の場所を消してしまうことです。2か所が同時に存在してはじめて、何が勝ったのかがわかります。
- よくある間違い: 出力物のファイルを手で直すことです。採点は、ファイルだけでなく、プレイブックをチェックモードで再実行して、今も同じ値が出るかを確認します。
- Using Variables・Precedence rules・Build your inventory・combine filter
最下位の場所: ロールのデフォルト値
/root/ans/prec/inventory/hosts.iniにweb1・web2を書き(ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root)、/root/ans/prec/roles/probe/に測定用のロールを作成してください。defaults/main.ymlにsvc_tier: role-defaultsとprobe_outを置き、tasks/main.ymlは、WINNER={{ svc_tier }}をdebugで表示したあと、同じ値をprobe_outのパスに書く、2つのタスクで埋めてください。/root/ans/prec/p01.ymlでweb1にこのロールを実行し、/root/ans/prec/out/01.txtを残してください。
このロールが、このラボの間ずっと使う物差しです。どの場所から値が来ても、ロールは「今見えている値」を書くだけで構いません。結果のファイルのパスはプレイごとに違う必要があるので、それも変数で受け取ってください。
インベントリの中の3か所
/root/ans/prec/inv-vars/をディレクトリインベントリとして作成してください。hosts.ymlにwebグループ(web1・web2)とdbグループ(db1)を書き、group_vars/all.ymlにinv-all、group_vars/web.ymlにinv-web、host_vars/web2.ymlにinv-hostを、svc_tierとして仕込んでください。/root/ans/prec/p02.ymlで3つのホストすべてを測定し、/root/ans/prec/out/02-<호스트>.txt(プレースホルダーはホスト名です)を残してください。
ディレクトリインベントリの中では、無視される拡張子があります。ホストが1つも見えなければ、まずファイル名を疑ってください。結果のファイル名にホストを入れるには、パス自体をテンプレートにすれば構いません。
プレイのvarsがインベントリを上書きする
/root/ans/prec/p03.ymlを作成し、プレイのvars:にsvc_tier: play-varsを仕込んで、web1を測定してください。インベントリはステップ2のinv-varsを使い、結果は/root/ans/prec/out/03.txtに残してください。
インベントリにすでに値があるのに、この場所が勝つかどうかを見るのが目的です。ロールはそのまま使い、プレイだけを新しく書きます。
意外な場所: vars_files
/root/ans/prec/vars/tier.ymlにsvc_tier: vars-fileを書き、/root/ans/prec/p04.ymlは、ステップ3とまったく同じく、プレイのvars:にplay-varsを残したまま、vars_files:でそのファイルを読み込むようにしてください。結果は/root/ans/prec/out/04.txtです。
下に書いたものが、上に書いたものに勝つ場所です。2か所を両方残さないと優劣がわからないので、プレイのvarsを消さないでください。
外から上書きしにくい場所: ロールのvars
/root/ans/prec/roles/probe_locked/に2つ目の測定用ロールを作成してください。vars/main.ymlにsvc_tier: role-varsを置き(defaultsにはprobe_outだけを置きます)、tasks/main.ymlはprobeと同じように書きます。/root/ans/prec/p05.ymlは、ステップ4と同じ2か所をそのまま残したまま、このロールを呼び出して/root/ans/prec/out/05.txtを残してください。
同じロールのディレクトリの中でも、defaultsとvarsは正反対の性格です。片方は一番下、もう片方はずっと上です。そのため新しいロールを別に作ります。probeは最下位の場所を測る物差しとして、そのまま残しておきます。
狭いほど高い: ブロックとタスク
/root/ans/prec/p06.ymlを作成してください。プレイはvars_files:でtier.ymlを読み込み、ブロック1つにvars: {svc_tier: block-vars}を付けます。ブロックの中の最初のタスクはprobe_lockedロールを呼び出して/root/ans/prec/out/06-block.txtを残し、2つ目のタスクは自分のvars:にsvc_tier: task-varsを付けて、/root/ans/prec/out/06-task.txtに値を書いてください。
ブロックの中でロールを呼び出すと、ロールのvarsの上にブロックの変数が載ります。2つ目のタスクは、ロールを経由せず、直接ファイルを書いても構いません。測りたいのは場所であって、ロールではありません。
実行中にできた値とロールに渡した引数
/root/ans/prec/p07.ymlを作成してください。まずset_factでsvc_tier: set-factを立て、そのあと、タスクのvars:にtask-varsを付けたタスクが、値を/root/ans/prec/out/07-setfact.txtに書くようにし、最後にprobe_lockedロールを呼び出してsvc_tier: role-paramを渡し、/root/ans/prec/out/07-roleparam.txtを残してください。
実行中に立てた値は、あらかじめ書いておいた場所より高いです。ところが、その上にもう1つあります。ロールを呼び出すときに渡した値です。
コマンドラインとディクショナリ、そして優先順位の表
/root/ans/prec/vars/limits.ymlにbase_limitsとsvc_limitsを{cpu: "1", memory: 1Gi}で置き、/root/ans/prec/p08.ymlが-e svc_tier=extra-varsと一緒に実行されたとき、/root/ans/prec/out/08.txtにコマンドラインの値が書かれるようにしてください。同じプレイブックで、タスクのvars:でsvc_limits: {memory: 2Gi}を渡した結果と、combineでマージした結果を、/root/ans/prec/out/08-hash.jsonにreplaced・combinedの2つのキーで残し、12か所の測定結果を/root/ans/prec/out/rank.mdに表として書いてください。
コマンドラインの値が本当に勝つのかを見るには、プレイの中にほかの場所も残しておく必要があります。表は低い場所から1行ずつ、各行にその場所で測定された値を書いてください。前のステップの出力物が根拠です。