Ansibleでの意思決定に関する前のチュートリアルでは、 blockinfileを使用して簡単なファイル変更を行う方法を学びました。 またはインライン Ansibleモジュール。
このチュートリアルでは、 Jinja2の使用方法を学習します より複雑で動的なファイル変更を実行するためのテンプレートエンジン。
Jinja2テンプレートで変数とファクトにアクセスする方法を学習します。さらに、Jinja2で条件ステートメントとループ構造を使用する方法を学習します。
このチュートリアルの例を試すには、RHCEAnsibleチュートリアルシリーズ全体を正しい順序で実行する必要があります。
Jinja2の変数へのアクセス
Ansibleは、プロジェクトディレクトリまたは templatesという名前のディレクトリでjinja2テンプレートファイルを検索します プロジェクトディレクトリの下。
テンプレートディレクトリを作成して、物事をよりクリーンで整理された状態に保ちましょう:
[[email protected] plays]$ mkdir templates
[[email protected] plays]$ cd templates/
次に、 index.j2という名前で最初のJinja2テンプレートを作成します。 :
[[email protected] templates]$ cat index.j2
A message from {{ inventory_hostname }}
{{ webserver_message }}
Jinja2テンプレートのファイル名は.j2拡張子で終わる必要があることに注意してください。
Inventory_hostname は、プレイで繰り返される「現在の」ホストを参照する別のAnsible組み込み(別名、特殊または魔法)変数です。 webserver_message プレイブックで定義する変数です。
次に、プロジェクトディレクトリに戻り、次の check-apache.ymlを作成します。 :
[[email protected] plays]$ cat check-apache.yml
---
- name: Check if Apache is Working
hosts: webservers
vars:
webserver_message: "I am running to the finish line."
tasks:
- name: Start httpd
service:
name: httpd
state: started
- name: Create index.html using Jinja2
template:
src: index.j2
dest: /var/www/html/index.html
httpdに注意してください パッケージは前のチュートリアルですでにインストールされています。
このプレイブックでは、最初にApacheが最初のタスクStart httpd
で実行されていることを確認します。 。次に、テンプレートを使用します 2番目のタスクのモジュールCreate index.html
Jinja2toを使用して、 index.j2を処理および転送します 宛先に作成したJinja2テンプレートファイル/var/www/html/index.html 。
先に進み、プレイブックを実行します:
[[email protected] plays]$ ansible-playbook check-apache.yml
PLAY [Check if Apache is Working] **********************************************
TASK [Gathering Facts] *********************************************************
ok: [node3]
ok: [node2]
TASK [Start httpd] *************************************************************
ok: [node2]
ok: [node3]
TASK [Create index.html using Jinja2] ******************************************
changed: [node3]
changed: [node2]
PLAY RECAP *********************************************************************
node2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0
node3 : ok=3 changed=1 unreachable=0 failed=0 skipped=0
これまでのところ、すべてが良さそうです。簡単なアドホックAnsibleコマンドを実行して、 index.htmlの内容を確認しましょう。 Webサーバーノード:
[[email protected] plays]$ ansible webservers -m command -a "cat /var/www/html/index.html"
node3 | CHANGED | rc=0 >>
A message from node3
I am running to the finish line.
node2 | CHANGED | rc=0 >>
A message from node2
I am running to the finish line.
すばらしい! Jinja2がinventory_hostnameの値を取得する方法に注目してください。 組み込み変数とwebserver_message プレイブックの変数。
カールを使用することもできます 両方のWebサーバーから応答を受け取るかどうかを確認するコマンド:
[[email protected] plays]$ curl node2.linuxhandbook.local
A message from node2
I am running to the finish line.
[[email protected] plays]$ curl node3.linuxhandbook.local
A message from node3
I am running to the finish line.
Jinja2のファクトへのアクセス
プレイブックからファクトにアクセスするのと同じ方法で、Jinja2テンプレートのファクトにアクセスできます。
実例を示すために、テンプレートに変更します ディレクトリを作成し、 info.j2を作成します 次の内容のJinja2ファイル:
[[email protected] templates]$ cat info.j2
Server Information Summary
--------------------------
hostname={{ ansible_facts['hostname'] }}
fqdn={{ ansible_facts['fqdn'] }}
ipaddr={{ ansible_facts['default_ipv4']['address'] }}
distro={{ ansible_facts['distribution'] }}
distro_version={{ ansible_facts['distribution_version'] }}
nameservers={{ ansible_facts['dns']['nameservers'] }}
totalmem={{ ansible_facts['memtotal_mb'] }}
freemem={{ ansible_facts['memfree_mb'] }}
info.j2に注意してください 8つの異なる事実にアクセスします。次に、プロジェクトディレクトリに戻り、次の server-info.ymlを作成します。 プレイブック:
[[email protected] plays]$ cat server-info.yml
---
- name: Server Information Summary
hosts: all
tasks:
- name: Create server-info.txt using Jinja2
template:
src: info.j2
dest: /tmp/server-info.txt
/tmp/server-info.txtを作成していることに注意してください info.j2に基づくすべてのホスト テンプレートファイル。先に進み、プレイブックを実行します:
[[email protected] plays]$ ansible-playbook server-info.yml
PLAY [Server Information Summary] *******************************************
TASK [Gathering Facts] **********************************
ok: [node4]
ok: [node1]
ok: [node3]
ok: [node2]
TASK [Create server-info.txt using Jinja2] ********
changed: [node4]
changed: [node1]
changed: [node3]
changed: [node2]
PLAY RECAP *************************
node1 : ok=2 changed=1 unreachable=0 failed=0 skipped=0
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0
node3 : ok=2 changed=1 unreachable=0 failed=0 skipped=0
node4 : ok=2 changed=1 unreachable=0 failed=0 skipped=0
すべてがよさそうだ!次に、簡単なアドホックコマンドを実行して、 /tmp/server-info.txtの内容を調べます。 ノードの1つにファイル:
[[email protected] plays]$ ansible node1 -m command -a "cat /tmp/server-info.txt"
node1 | CHANGED | rc=0 >>
Server Information Summary
--------------------------
hostname=node1
fqdn=node1.linuxhandbook.local
ipaddr=10.0.0.5
distro=CentOS
distro_version=8.2
nameservers=['168.63.129.16']
totalmem=1896
freemem=1087
ご覧のとおり、Jinja2はすべての事実にアクセスして処理することができました。
Jinja2の条件文
ifを使用できます さまざまな条件をテストし、変数を比較するためのJinja2の条件ステートメント。これにより、テスト条件に従ってファイルテンプレートの実行フローを決定できます。
デモンストレーションするには、テンプレートに移動します ディレクトリを作成し、次の selinux.j2を作成します テンプレート:
[[email protected] templates]$ cat selinux.j2
{% set selinux_status = ansible_facts['selinux']['status'] %}
{% if selinux_status == "enabled" %}
"SELINUX IS ENABLED"
{% elif selinux_status == "disabled" %}
"SELINUX IS DISABLED"
{% else %}
"SELINUX IS NOT AVAILABLE"
{% endif %}
テンプレートの最初のステートメントは、新しい変数selinux_statusand
を作成します その値をansible_facts['selinux']['status']
に設定します 。
次に、selinux_status
を使用します あなたのもし SELinuxかどうかを判断するためのテスト条件 有効、無効、またはインストールされていません。 3つの異なるケースのそれぞれで、Selinuxのステータスを反映するメッセージを表示します。
if Jinja2のステートメントは、Pythonの if を模倣しています 声明; {% endif %}
を使用することを忘れないでください 。
次に、プロジェクトディレクトリに戻り、次の selinux-status.ymlを作成します。 プレイブック:
[[email protected] plays]$ cat selinux-status.yml
---
- name: Check SELinux Status
hosts: all
tasks:
- name: Display SELinux Status
debug:
msg: "{{ ansible_facts['selinux']['status'] }}"
- name: Create selinux.out using Jinja2
template:
src: selinux.j2
dest: /tmp/selinux.out
先に進み、プレイブックを実行します:
[[email protected] plays]$ ansible-playbook selinux-status.yml
PLAY [Check SELinux Status] ****************************************************
TASK [Gathering Facts] *********************************************************
ok: [node4]
ok: [node2]
ok: [node3]
ok: [node1]
TASK [Display SELinux Status] **************************************************
ok: [node1] => {
"msg": "enabled"
}
ok: [node2] => {
"msg": "disabled"
}
ok: [node3] => {
"msg": "enabled"
}
ok: [node4] => {
"msg": "Missing selinux Python library"
}
TASK [Create selinux.out using Jinja2] *****************************************
changed: [node4]
changed: [node1]
changed: [node3]
changed: [node2]
PLAY RECAP *********************************************************************
node1 : ok=3 changed=1 unreachable=0 failed=0 skipped=0
node2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0
node3 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 node4 : ok=3 changed=1 unreachable=0 failed=0 skipped=0
プレイブックの出力から。 SELinuxが両方のnode1で有効になっていることがわかります およびnode3 。 node2でSELinuxを無効にしました プレイブックとnode4を実行する前に UbuntuはSELinuxの代わりにAppArmorを使用しているため、SELinuxはインストールされていません。
最後に、次のアドホックコマンドを実行して、 selinux.outのコンテンツを検査できます。 すべての管理対象ホスト:
[[email protected] plays]$ ansible all -m command -a "cat /tmp/selinux.out"
node4 | CHANGED | rc=0 >>
"SELINUX IS NOT AVAILABLE"
node2 | CHANGED | rc=0 >>
"SELINUX IS DISABLED"
node3 | CHANGED | rc=0 >>
"SELINUX IS ENABLED"
node1 | CHANGED | rc=0 >>
"SELINUX IS ENABLED"
Jinja2でループする
forを使用できます リストや範囲などの項目をループするJinja2のステートメント。たとえば、次のforループは、 range(1,11)の数値を繰り返し処理します。 したがって、1から10までの数字が表示されます:
{% for i in range(1,11) %}
Number {{ i }}
{% endfor %}
Jinja2のforループがPythonのforループの構文をどのように模倣しているかに注目してください。ここでも、{% endfor %}
でループを終了することを忘れないでください 。
次に、Jinja2のforループの能力を示す完全な例を作成しましょう。テンプレートディレクトリに移動し、次の hosts.j2を作成します テンプレートファイル:
[[email protected] templates]$ cat hosts.j2
{% for host in groups['all'] %}
{{ hostvars[host].ansible_facts.default_ipv4.address }} {{ hostvars[host].ansible_facts.fqdn }} {{ hostvars[host].ansible_facts.hostname }}
{% endfor %}
ここで、新しい組み込みの特別な(魔法の)変数 hostvarsを使用したことに注意してください。 これは基本的に、インベントリ内のすべてのホストとそれらに割り当てられた変数を含む辞書です。
インベントリ内のすべてのホストを繰り返し、次に各ホストを繰り返しました。 3つの変数の値を表示しました:
- {{hostvars [host] .ansible_facts.default_ipv4.address}}
- {{hostvars [host] .ansible_facts.fqdn}}
- {{hostvars [host] .ansible_facts.hostname}}
/ etc / hosts の形式に一致させるには、これら3つの変数を同じ行に並べて含める必要があることにも注意してください。 ファイル。
次に、プロジェクトディレクトリに戻り、次の local-dns.ymlを作成します。 プレイブック:
[[email protected] plays]$ cat local-dns.yml
---
- name: Dynamically Update /etc/hosts File
hosts: all
tasks:
- name: Update /etc/hosts using Jinja2
template:
src: hosts.j2
dest: /etc/hosts
次に、プレイブックを実行します:
[[email protected] plays]$ ansible-playbook local-dns.yml
PLAY [Dynamically Update /etc/hosts File] *********************************************
TASK [Gathering Facts] ***************************
ok: [node4]
ok: [node2]
ok: [node1]
ok: [node3]
TASK [Update /etc/hosts using Jinja2] ***********************************************
changed: [node4]
changed: [node3]
changed: [node1]
changed: [node2]
PLAY RECAP **********************
node1 : ok=2 changed=1 unreachable=0 failed=0 skipped=0
node2 : ok=2 changed=1 unreachable=0 failed=0 skipped=0
node3 : ok=2 changed=1 unreachable=0 failed=0 skipped=0
node4 : ok=2 changed=1 unreachable=0 failed=0 skipped=0
これまでのところ、すべてが良さそうです。次に、次のアドホックコマンドを実行して、 / etc / hostsであることを確認します。 node1でファイルが適切に更新されます :
[[email protected] plays]$ ansible node1 -m command -a "cat /etc/hosts"
node1 | CHANGED | rc=0 >>
10.0.0.5 node1.linuxhandbook.local node1
10.0.0.6 node2.linuxhandbook.local node2
10.0.0.7 node3.linuxhandbook.local node3
10.0.0.8 node4.linuxhandbook.local node4
完全!期待どおりに適切にフォーマットされているように見えます。
AnsibleのJinja2テンプレートの威力を実感していただければ幸いです。 AnsibleVaultを使用して機密情報とファイルを保護する方法を学ぶ次のチュートリアルにご期待ください。