TT Lab
はじめる
学ぶ 学習パス コース

Ansible実戦

変数の優先順位を文書ではなく測定で立てる

TT Labで続きを見る

目標

同じ名前の変数を12か所に1か所ずつ仕込みながら、何が勝つかを自分で測り、その結果をチームが読める優先順位の表として残せるようになります。

なぜ重要なのか

「確かにgroup_varsに書いたのに別の値が表示される」という報告は、エラーとして現れません。プレイブックは成功し、ファイルは作られ、内容だけが違います。構文チェックもリントも、これを捕まえられません。捕まえられるのは、「今この場所で、この名前が何に解決されるか」を測ることだけです。そのため、このラボはドキュメントの一覧を書き写さず、測定します。一度測ったことのある人は、表を覚えなくても、次に何を最初に疑うかがわかります。そして最後に行き着く結論は、表ではありません。場所を減らす設計は、表を知っていることよりも強いのです。

ステップ

  1. /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を残してください。
  2. /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(プレースホルダーはホスト名です)を残してください。
  3. /root/ans/prec/p03.ymlを作成し、プレイのvars:にsvc_tier: play-varsを仕込んで、web1を測定してください。インベントリはステップ2のinv-varsを使い、結果は/root/ans/prec/out/03.txtに残してください。
  4. /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です。
  5. /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を残してください。
  6. /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に値を書いてください。
  7. /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を残してください。
  8. /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に表として書いてください。

参考

最下位の場所: ロールのデフォルト値

/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行ずつ、各行にその場所で測定された値を書いてください。前のステップの出力物が根拠です。