再利用できるロールを作る
目標
プレイブックの断片をロールにまとめて再利用可能な単位にし、同じロールを異なる値で複数回呼び出せるようになります。
なぜ重要なのか
ロールの本質は「コードを分けること」ではなく、「規約を決めておいて、設定なしで再利用できるようにすること」です。templates/に置いたファイルはパスを書かなくても見つかり、handlers/main.ymlのハンドラーは登録の手続きなしで使えます。この規約のおかげで、他人が作ったロールも構造を推測できます。再利用性を実際に決めるのは、defaultsとvarsの選択です。ユーザーが変更する値をvarsに置くと優先度が高く、外からオーバーライドできず、そのロールは結局コピー・修正されて再び分岐します。そして、変数名にロール名をプレフィックスとして付ける習慣は、ロールが2つを超えた瞬間に価値を発揮します。
ステップ
/root/ans/roles/roles/webappの下に、tasks、defaults、handlers、templates、metaディレクトリとtasks/main.ymlを作成してください。/root/ans/roles/roles/webapp/defaults/main.ymlに、webapp_port: 8080とwebapp_root: /root/ans/roles/artifactsを定義してください。/root/ans/roles/roles/webapp/tasks/main.ymlに名前の付いたタスクを2つ以上入れ、実行すると/root/ans/roles/artifactsディレクトリが作られるようにしてください。/root/ans/roles/roles/webapp/templates/webapp.conf.j2を作成し、/root/ans/roles/artifacts/webapp.confへレンダリングしてください。結果にport = 8080の行があり、テンプレートはwebapp_port変数を参照している必要があります。/root/ans/roles/roles/webapp/handlers/main.ymlにrestart webappハンドラーを定義し、/root/ans/roles/roles/webapp/tasks/main.ymlのタスクからnotifyしてください。ハンドラーは/root/ans/roles/artifacts/restart.markerを作成します。/root/ans/roles/roles/baselineロール(エントリポイントは/root/ans/roles/roles/baseline/tasks/main.yml)を作成して/root/ans/roles/artifacts/baseline.stampを残すようにし、/root/ans/roles/roles/webapp/meta/main.ymlのdependenciesに宣言してください。/root/ans/roles/site.ymlでwebappロールを2回呼び出してください。1回はデフォルト値で(webapp.conf、port 8080)、もう1回はwebapp_port: 9443で/root/ans/roles/artifacts/staging.confを作るようにします。ロールのディレクトリをコピーしてはいけません。- プレイブックを2回目に実行した出力を
/root/ans/roles/out/run2.txtに、ansible-lintの結果を/root/ans/roles/out/lint.txtに保存してください。2回目の実行はchanged=0で、ハンドラーが動かない必要があります。
参考
- ラボのPodはラボごとに新しく起動します。
/root/ans/inventory/hosts.iniがない場合は、最初のラボで作ったものと同じインベントリ(web1・web2・db1、ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root、[prod:children]にweb・db)を先に作り直してください。構造は/opt/lab/fixtures/ansible/inventory.sample.iniを参考にできます。 ansible-galaxy role init roles/webappで標準構造を一度に作れます。- ロールを呼び出すとき、
- role: webappの下に変数を書くと、その呼び出しにだけ適用されます。 - よくある間違い1: テンプレートで
templates/を含むパスを書くことです。ロールの中では、ファイル名だけを書きます。 - よくある間違い2: ステップ7のためにロールをまるごとコピーすることです。同じソースを2回呼び出すのが要点です。
ロールのスケルトンディレクトリを作る
/root/ans/roles/roles/webappの下に、tasks、defaults、handlers、templates、metaディレクトリとtasks/main.ymlを作成してください。
ansible-galaxy role initが標準構造を作ってくれます。必要なディレクトリはtasks/defaults/handlers/templates/metaです。
デフォルト値を2つ定義する
/root/ans/roles/roles/webapp/defaults/main.ymlに、webapp_port: 8080とwebapp_root: /root/ans/roles/artifactsを定義してください。
オーバーライドされることを想定した値は、defaultsに置きます。名前にはロール名のプレフィックスを付けてください。
ロールのタスクを書いて実行する
/root/ans/roles/roles/webapp/tasks/main.ymlに名前の付いたタスクを2つ以上入れ、実行すると/root/ans/roles/artifactsディレクトリが作られるようにしてください。
tasks/main.ymlがエントリポイントです。タスクは2つ以上で、すべてに名前が必要です。
ロールのテンプレートで設定ファイルを作る
/root/ans/roles/roles/webapp/templates/webapp.conf.j2を作成し、/root/ans/roles/artifacts/webapp.confへレンダリングしてください。結果にport = 8080の行があり、テンプレートはwebapp_port変数を参照している必要があります。
templates/の中のファイルは、名前だけを書けば見つかります。ポートの値はハードコードせず、変数を使ってください。
ロールのハンドラーを定義して発火させる
/root/ans/roles/roles/webapp/handlers/main.ymlにrestart webappハンドラーを定義し、/root/ans/roles/roles/webapp/tasks/main.ymlのタスクからnotifyしてください。ハンドラーは/root/ans/roles/artifacts/restart.markerを作成します。
handlers/main.ymlのハンドラーは自動的に登録されます。実行されたらマーカーファイルを残してください。
依存ロールを設定して先に実行させる
/root/ans/roles/roles/baselineロール(エントリポイントは/root/ans/roles/roles/baseline/tasks/main.yml)を作成して/root/ans/roles/artifacts/baseline.stampを残すようにし、/root/ans/roles/roles/webapp/meta/main.ymlのdependenciesに宣言してください。
baselineロールを別に作り、meta/main.ymlのdependenciesに書きます。依存ロールが先に実行されます。
同じロールを異なる値で2回呼び出す
/root/ans/roles/site.ymlでwebappロールを2回呼び出してください。1回はデフォルト値で(webapp.conf、port 8080)、もう1回はwebapp_port: 9443で/root/ans/roles/artifacts/staging.confを作るようにします。ロールのディレクトリをコピーしてはいけません。
プレイのrolesセクションで、ロール名と一緒に変数を渡せます。ロールをコピーしてはいけません。
再実行での冪等性とリントの通過
プレイブックを2回目に実行した出力を/root/ans/roles/out/run2.txtに、ansible-lintの結果を/root/ans/roles/out/lint.txtに保存してください。2回目の実行はchanged=0で、ハンドラーが動かない必要があります。
2回目の実行でchanged=0になり、ハンドラーも動かない必要があります。ansible-lintの結果も残してください。