Jinja2で設定ファイルを生成する
目標
環境ごとに異なる設定ファイルを、1つのテンプレートとデータに分解し、レンダリング結果がきれいで、検証された状態で配置されるようにします。
なぜ重要なのか
設定ファイルを環境の数だけ置くと、それらのファイルは必ず互いに違っていきます。テンプレートは「ひな形は1つ、データは複数」という形で、その分岐をなくします。実務でテンプレートを台無しにするのは、文法ではなく2つのことです。1つは空白です。制御構文が残した空行が、YAMLの設定を壊します。もう1つは毎回変わるレンダリング結果です。タイムスタンプ1行のせいでファイルが実行のたびに変わり、ハンドラーが毎回動いて、サービスが毎回再起動されます。最後に、validateは、誤った設定がサービスを落とす経路を塞ぐ、最も安い安全装置です。自動デプロイを有効にした瞬間から、このオプションは選択ではなくなります。
ステップ
- このラボのプレイブックは、
/root/ans/tpl/site.yml1つを使います。/root/ans/tpl/templates/basic.j2から/root/ans/tpl/out/basic.confを作成してください。結果にservice = checkoutの行が必要です。 /root/ans/tpl/templates/filters.j2から/root/ans/tpl/out/filters.confを作成してください。UPPER=CHECKOUT、TIMEOUT=30(定義されていない変数のデフォルト値)、REPLICAS=3の3行が出力される必要があります。/root/ans/tpl/templates/upstream.j2から/root/ans/tpl/out/upstream.confを作成してください。バックエンド3つが、server 10.0.0.11:8080;の形式で1行ずつ出力される必要があります。- 同じテンプレートを異なる変数でレンダリングして、
/root/ans/tpl/out/prod.conf(tls = on、debugなし)と/root/ans/tpl/out/dev.conf(tls = off、debugあり)を作成してください。 upstream.confに空行が1つもなく、server行の前に不要なインデントがないように、空白を制御してください。{%- -%}を使うか、/root/ans/tpl/site.ymlのtemplateタスクでtrim_blocks/lstrip_blocksを有効にすれば実現できます。/root/ans/tpl/templates/node.j2から/root/ans/tpl/out/node.confを作成してください。hostnameとarchはファクトから、generated_forはinventory_hostname(=web1)から取得します。/root/ans/tpl/site.ymlのtemplateタスクにvalidateとbackup: trueを付けて、/root/ans/tpl/out/validated.confを作成してください。内容はkey=valueの1行です。/root/ans/tpl/out/site.nginxを作成してください。upstream checkout_backend {ブロックの中に、4スペースでインデントしたserver行が3つ入り、さらにlisten 8080;とserver_name checkout.labhub.internal;が、それぞれ4スペースのインデントで入ります。空行は1行以下である必要があります。
参考
- ラボの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を参考にできます。 templateモジュールは、srcにロール/プレイブック基準の相対パスを、destに対象パスを受け取ります。- フィルターはつなげて書けます:
{{ name | default('unknown') | upper }} - よくある間違い1:
{% for %}をそのままにして、結果に空行が残ることです。 - よくある間違い2: テンプレートに時刻やランダムな値を入れて、毎回結果が変わることです。そうすると冪等性が壊れます。
変数を入れた基本テンプレートのレンダリング
このラボのプレイブックは、/root/ans/tpl/site.yml1つを使います。/root/ans/tpl/templates/basic.j2から/root/ans/tpl/out/basic.confを作成してください。結果にservice = checkoutの行が必要です。
{{ 변수 }}(プレースホルダーは変数です)で値を出力します。結果にJinja2の構文が残っていたら、レンダリングされていません。
upperとdefaultフィルターを使う
/root/ans/tpl/templates/filters.j2から/root/ans/tpl/out/filters.confを作成してください。UPPER=CHECKOUT、TIMEOUT=30(定義されていない変数のデフォルト値)、REPLICAS=3の3行が出力される必要があります。
フィルターはパイプでつなぎます。定義されていない変数にデフォルト値を与えるフィルターが何か、考えてみてください。
リストを回す繰り返しを入れる
/root/ans/tpl/templates/upstream.j2から/root/ans/tpl/out/upstream.confを作成してください。バックエンド3つが、server 10.0.0.11:8080;の形式で1行ずつ出力される必要があります。
{% for %}と{% endfor %}の間に、繰り返す行を置きます。バックエンド3つが、それぞれ1行になる必要があります。
環境に応じて異なる設定を出力する
同じテンプレートを異なる変数でレンダリングして、/root/ans/tpl/out/prod.conf(tls = on、debugなし)と/root/ans/tpl/out/dev.conf(tls = off、debugあり)を作成してください。
同じテンプレートを異なる変数で2回レンダリングします。prodにはdebugが出力されてはいけません。
空白の制御で空行をなくす
upstream.confに空行が1つもなく、server行の前に不要なインデントがないように、空白を制御してください。{%- -%}を使うか、/root/ans/tpl/site.ymlのtemplateタスクでtrim_blocks/lstrip_blocksを有効にすれば実現できます。
{%-/-%}、またはtemplateモジュールのtrim_blocks/lstrip_blocksを使ってください。結果に空行が1つもない必要があります。
ファクトとinventory_hostnameを使う
/root/ans/tpl/templates/node.j2から/root/ans/tpl/out/node.confを作成してください。hostnameとarchはファクトから、generated_forはinventory_hostname(=web1)から取得します。
ファクト変数はansible_で始まります。対象の名前はinventory_hostnameです。
validateとbackupを付ける
/root/ans/tpl/site.ymlのtemplateタスクにvalidateとbackup: trueを付けて、/root/ans/tpl/out/validated.confを作成してください。内容はkey=valueの1行です。
validateでは、%sの位置に一時ファイルのパスが入ります。検査に失敗すると、配置されません。
グループ変数でnginxの設定をまるごと作る
/root/ans/tpl/out/site.nginxを作成してください。upstream checkout_backend {ブロックの中に、4スペースでインデントしたserver行が3つ入り、さらにlisten 8080;とserver_name checkout.labhub.internal;が、それぞれ4スペースのインデントで入ります。空行は1行以下である必要があります。
upstreamブロックの中のserver行は、4スペースのインデントです。空白の制御と繰り返しを一緒に使う必要があります。