Ansibleのtemplatesテンプレート

16382 ワード

一、jinja 2概要解
Jinja 2はPythonの次の広く応用されているモデルエンジンで、彼の設計思想はDjanjoのテンプレートエンジンに由来し、その文法と一連の強力な機能を拡張した.ansibleのテンプレートプロファイルはjinja 2というテンプレートプログラミング言語で書かれていますが、jinja 2で使用される文字数は次のような形式があります.
1)文字列:一重引用符または二重引用符で囲まれた部分
2)数値:整数、浮動小数点数(小数)をサポートする
3)リスト:pythonのリストと同様に、中括弧で囲まれ、各要素間は[item 1,item 2,....]のようにカンマで区切られています.
4)メタグループ:pythonのメタグループと同じように括弧で囲まれ、各要素間をカンマで区切る(item 1,item 2,....)
5)辞書:pythonの辞書と同様に括弧で囲まれ、各k/v(キー値ペア)はカンマで区切られ、キーと値は「:」で区切られ、例えば{key 1:value 1,key 2:value 2,....}
6)ブール型:他の言語ブール型と同様、ture/false
7)算数演算をサポートする:+,-,*,/,//(整除,床除),%(型取り,残数取り),**(べき乗演算)
8)比較操作をサポートする:==(2つの値が等しいかどうかを比較)!=(等しくない),>,>=(以上)
9)論理演算をサポートする:and(and)、or(または)、not(非)
10)for(ループ)、if(判定)、when(ある条件が満たされたときにwhenが存在するコードブロックを実行し始め、ifのような役割を果たす)をサポートする
このほか、jinja 2では、変数が定義されているかどうかを判断するには、vars is definedなどのdefinedを使用し、vars定義の場合はtrueを返し、falseを返すなどの「test」テスト文もサポートされています.同様にundefined(definedとは逆)、equalto("=="と等価)、even(オブジェクトが偶数であるか否かを判断)、iterable(オブジェクトが反復可能であるか否かを判断)もある.
二、jinja 2文法
jinja 2には次の構文があります.
1)制御構造は、私たちが他の言語を書く制御構造と似ています.唯一異なるのは、そのforループが「{%}」で囲まれ、2つのパーセンテージの間に書かなければなりません.後に1つの{%endfor$}でforループの終わりを表します.同じif文も、「{%}」の2つのパーセンテージの間に書かなければなりません.後の終わりにも{%endif%}があります.if文の終わりを表すために、もちろんif文はelif,elseをサポートします.  これはpythonのifの使い方と同じです.
2)変数参照,jinja 2の変数参照はansibleの変数適用と類似しており,いずれも中括弧で囲まれた内容を表す変数である
3)注釈は「{#」で始まり、中間部分は注釈を表し、「#}」で終わりは注釈の終わりを表し、複数行の注釈と当行の注釈をサポートする
例:
1)forリサイクル
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}

説明:以上のテンプレートは、nginx_vhostsリストからループし、nginx_vhostsにはいくつかの要素があり、それは何回ループし、毎回ループした値をvhost変数で置き換え、その用法タイプshellのforループとpythonのforループ
2)ifシングルブランチ選択使用
{% if vhost.server_name is defined %}
    server_name {{ vhost.server_name }}
{% endif %}

3)ifマルチブランチ選択使用
{%if vhost.port is undefined %}
    http_port=80
{%elif vhost.port == 81%}
    http_port=81
{%else%}
    http_port = 83
{%endif%}

4)一方通行注釈
{#% for i in list %#}

5)複数行コメント
{#
    {% for i in list %}
         i+=i
      {% endfor %}
#}

三、playbookでテンプレートを使う
templatesはansibleのモジュールで、テンプレートファイルに基づいてプロファイルを動的に生成する機能を有し、templatesファイルはtemplatesディレクトリの下に保存され、「.j 2」と命名される必要があります.最後に、yaml/ymlファイルはtemplatesディレクトリとレベルを合わせる必要があります.これにより、ymlファイルでテンプレートを呼び出すときに、テンプレートファイルのパスを書く必要はありません.そうしないと、templateモジュールがtemplatesディレクトリの下のテンプレートファイルを自動的に探すため、テンプレートファイルのパスを記述する必要があります.ディレクトリ構造は次のとおりです.
.
├── temnginx.yml
└── templates
   └── nginx.conf.j2

例:playbookでのtemplate変数の置換
gmplatesを使用してnginxプロファイルを同期し、nginx.conf.j 2(worker_processes{{ansible_processor_vcpus}})を変更します.指定したworkerプロセスの個数は、リモートホストのcpu個数によって決まります.
[root@test ~]#ll
    4
-rw-r--r-- 1 root root 212 11  18 14:08 temnginx.yml
drwxr-xr-x 2 root root  27 11  18 14:05 templates
[root@test ~]#tree
.
├── temnginx.yml
└── templates
    └── nginx.conf.j2

1 directory, 2 files
[root@test ~]#head templates/nginx.conf.j2 
# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes {{ ansible_processor_vcpus }};
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
[root@test ~]#cat temnginx.yml 
---
- hosts: websers
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx 
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
 
[root@test ~]#

説明:以上のPlaybookではtemplateテンプレートを使用して動的に生成されたプロファイルであり、コピーではなく、コピーはファイルをそのままコピーしたものであり、templateモジュールはad-hocコマンドラインでは使用できず、Playbookでのみ使用でき、テンプレートファイルは「.j 2」で終わる必要があることに注意してください.
例:playbookにおけるtemplate演算
以上の例では、このように書くことができます.
vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus**2 }};

説明:ansible内蔵変数で算術演算後の値をテンプレートファイルの値として使用できますが、playbookではtemplateモジュールで呼び出せばいいです.
例:テンプレートファイルでのforループの使い方
[root@test ~]#tree
.
├── temnginx.yml
└── templates
    └── nginx.conf.j2

1 directory, 2 files
[root@test ~]#cat templates/nginx.conf.j2 
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}
[root@test ~]#cat temnginx.yml 
---
- hosts: websers
  remote_user: root
  vars:
    nginx_vhosts:
      - listen: 8080
  tasks:
    - name: install nginx
      yum: name=nginx 
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
 
[root@test ~]#  

生成結果:
[root@test ~]#ansible-playbook  temnginx.yml   

PLAY [websers] ******************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218]

TASK [install nginx] ************************************************************************************************
changed: [192.168.0.128]
changed: [192.168.0.218]

TASK [template config to remote hosts] ******************************************************************************
changed: [192.168.0.128]
changed: [192.168.0.218]

PLAY RECAP **********************************************************************************************************
192.168.0.128              : ok=3    changed=2    unreachable=0    failed=0   
192.168.0.218              : ok=3    changed=2    unreachable=0    failed=0   

[root@test ~]#ansible websers -m shell -a 'cat /etc/nginx/nginx.conf'
192.168.0.128 | SUCCESS | rc=0 >>
server {
listen 8080
}

192.168.0.218 | SUCCESS | rc=0 >>
server {
listen 8080
}

[root@test ~]#

例:テンプレートファイルのifの使い方
[root@test ~]#tree
.
├── temnginx.yml
└── templates
    └── nginx.conf.j2

1 directory, 2 files
[root@test ~]#cat temnginx.yml 
---
- hosts: websers
  remote_user: root
  vars:
    nginx_vhosts:
      - web1:
        listen: 8080
        server_name: "web1.test.com"
        root: "/var/www/nginx/web1/"
      - web2:
        listen: 8080
        root: "/var/www/nginx/web2/"
      - web3:
        listen: 8080
        server_name: "web2.test.com"
        root: "var/www/nginx/web3/" 
  tasks:
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
 
[root@test ~]#cat templates/nginx.conf.j2 
{% for vhost in nginx_vhosts %}
        server {
                listen {{ vhost.listen }}
                {% if vhost.server_name is defined %}
                server_name {{ vhost.server_name }}
                {% endif %}
                root {{ vhost.root }}
        }
{% endfor %}
[root@test ~]#

生成結果:
[root@test ~]#ansible-playbook temnginx.yml 

PLAY [websers] ******************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218]

TASK [template config to remote hosts] ******************************************************************************
changed: [192.168.0.128]
changed: [192.168.0.218]

PLAY RECAP **********************************************************************************************************
192.168.0.128              : ok=2    changed=1    unreachable=0    failed=0   
192.168.0.218              : ok=2    changed=1    unreachable=0    failed=0   

[root@test ~]#ansible websers -m shell -a 'cat /etc/nginx/nginx.conf'
192.168.0.128 | SUCCESS | rc=0 >>
server {
        listen 8080
                server_name web1.test.com
                root /var/www/nginx/web1/
}
server {
        listen 8080
                root /var/www/nginx/web2/
}
server {
        listen 8080
                server_name web2.test.com
                root var/www/nginx/web3/
}

192.168.0.218 | SUCCESS | rc=0 >>
server {
        listen 8080
                server_name web1.test.com
                root /var/www/nginx/web1/
}
server {
        listen 8080
                root /var/www/nginx/web2/
}
server {
        listen 8080
                server_name web2.test.com
                root var/www/nginx/web3/
}

[root@test ~]#

説明:定義された変数リストにweb 2がserver_nameを定義していないため、2番目のserverにはserver_nameがないことがわかります.
四、playbookでwhen条件テストを使用する
条件テスト:変数、facts、またはこれまでのタスクの実行結果に基づいてtaskが実行するかどうかの前提とする必要がある場合に条件テストを使用し、when文で実現し、taskでjinja 2の構文フォーマットを使用し、when文はjinja 2式構文をサポートする.
例:
[root@test ~]#cat test.yml 
---
- hosts: all 
  remote_user: root

  tasks:
    - name: set hostname centos6
      hostname: name=ansible_centos6
      when: ansible_distribution_major_version == "6"
    - name: set hostname centos7
      hostname: name=ansible_centos7
      when: ansible_distribution_major_version == "7" 
[root@test ~]#ansible all -m shell -a 'hostname'
192.168.0.128 | SUCCESS | rc=0 >>
localhost

192.168.0.218 | SUCCESS | rc=0 >>
localhost.localdomain

192.168.0.217 | SUCCESS | rc=0 >>
centos7

[root@test ~]#ansible-playbook test.yml 

PLAY [all] **********************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218]
ok: [192.168.0.217]

TASK [set hostname centos6] *****************************************************************************************
skipping: [192.168.0.217]
changed: [192.168.0.218]
changed: [192.168.0.128]

TASK [set hostname centos7] *****************************************************************************************
skipping: [192.168.0.128]
skipping: [192.168.0.218]
changed: [192.168.0.217]

PLAY RECAP **********************************************************************************************************
192.168.0.128              : ok=2    changed=1    unreachable=0    failed=0   
192.168.0.217              : ok=2    changed=1    unreachable=0    failed=0   
192.168.0.218              : ok=2    changed=1    unreachable=0    failed=0   

[root@test ~]#ansible all -m shell -a 'hostname'
192.168.0.128 | SUCCESS | rc=0 >>
ansible_centos6

192.168.0.218 | SUCCESS | rc=0 >>
ansible_centos6

192.168.0.217 | SUCCESS | rc=0 >>
ansible_centos7

[root@test ~]#

説明:以上のplaybookはwhen文を利用してシステムバージョン番号を判断し、異なるシステムバージョン番号を通じて、異なるホスト名を設定することを実現した.
五、playbook反復with_items
反復:反復が必要なタスクがある場合は反復メカニズムを使用します.反復項目の参照には、ansibleには「item」という固定不変の変数があります.taskでwith_itemsを使用して反復する要素のリストを指定するには、リストフォーマットは文字列、辞書です.
例:ユーザーの一括作成
[root@test ~]#cat adduser.yml 
---
- hosts: websers
  remote_user: root
  
  tasks:
    - name: add users
      user: name={{ item }} state=present home=/home/{{ item }} groups=root,bin,wheel
      with_items:
        - user1
        - user2
        - user3
[root@test ~]#ansible-playbook adduser.yml

PLAY [websers] ******************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218]

TASK [add users] ****************************************************************************************************
changed: [192.168.0.128] => (item=user1)
changed: [192.168.0.218] => (item=user1)
changed: [192.168.0.128] => (item=user2)
changed: [192.168.0.218] => (item=user2)
changed: [192.168.0.128] => (item=user3)
changed: [192.168.0.218] => (item=user3)

PLAY RECAP **********************************************************************************************************
192.168.0.128              : ok=2    changed=1    unreachable=0    failed=0   
192.168.0.218              : ok=2    changed=1    unreachable=0    failed=0   

[root@test ~]#ansible websers -m shell -a 'tail -3 /etc/passwd'
192.168.0.128 | SUCCESS | rc=0 >>
user1:x:503:503::/home/user1:/bin/bash
user2:x:504:504::/home/user2:/bin/bash
user3:x:505:505::/home/user3:/bin/bash

192.168.0.218 | SUCCESS | rc=0 >>
user1:x:1213:1213::/home/user1:/bin/bash
user2:x:1214:1214::/home/user2:/bin/bash
user3:x:1215:1215::/home/user3:/bin/bash

[root@test ~]#ansible websers -m shell -a 'id user1'           
192.168.0.218 | SUCCESS | rc=0 >>
uid=1213(user1) gid=1213(user1)  =1213(user1),0(root),1(bin),10(wheel)

192.168.0.128 | SUCCESS | rc=0 >>
uid=503(user1) gid=503(user1)  =503(user1),0(root),1(bin),10(wheel)

[root@test ~]# 

例:反復ネストされたサブ変数
[root@test ~]#cat adduser2.yml 
---
- hosts: websers
  remote_user: root
  
  tasks:
    - name: create groups
      group: name={{ item }}
      with_items:
        - group1
        - group2
        - group3
    - name: create users
      user: name={{ item.name }} group={{ item.group }} state=present
      with_items:
        - {name: 'test1',group: 'group1'}
        - {name: 'test2',group: 'group2'}
        - {name: 'test3',group: 'group3'}
[root@test ~]#ansible-playbook adduser2.yml

PLAY [websers] ******************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************
ok: [192.168.0.128]
ok: [192.168.0.218]

TASK [create groups] ************************************************************************************************
changed: [192.168.0.128] => (item=group1)
changed: [192.168.0.218] => (item=group1)
changed: [192.168.0.128] => (item=group2)
changed: [192.168.0.218] => (item=group2)
changed: [192.168.0.128] => (item=group3)
changed: [192.168.0.218] => (item=group3)

TASK [create users] *************************************************************************************************
changed: [192.168.0.128] => (item={u'group': u'group1', u'name': u'test1'})
changed: [192.168.0.218] => (item={u'group': u'group1', u'name': u'test1'})
changed: [192.168.0.128] => (item={u'group': u'group2', u'name': u'test2'})
changed: [192.168.0.218] => (item={u'group': u'group2', u'name': u'test2'})
changed: [192.168.0.128] => (item={u'group': u'group3', u'name': u'test3'})
changed: [192.168.0.218] => (item={u'group': u'group3', u'name': u'test3'})

PLAY RECAP **********************************************************************************************************
192.168.0.128              : ok=3    changed=2    unreachable=0    failed=0   
192.168.0.218              : ok=3    changed=2    unreachable=0    failed=0   

[root@test ~]#ansible websers -m shell -a 'tail -3 /etc/passwd'
192.168.0.128 | SUCCESS | rc=0 >>
test1:x:506:506::/home/test1:/bin/bash
test2:x:507:507::/home/test2:/bin/bash
test3:x:508:508::/home/test3:/bin/bash

192.168.0.218 | SUCCESS | rc=0 >>
test1:x:1216:1216::/home/test1:/bin/bash
test2:x:1217:1217::/home/test2:/bin/bash
test3:x:1218:1218::/home/test3:/bin/bash

[root@test ~]#ansible websers -m shell -a 'id test1'           
192.168.0.218 | SUCCESS | rc=0 >>
uid=1216(test1) gid=1216(group1)  =1216(group1)

192.168.0.128 | SUCCESS | rc=0 >>
uid=506(test1) gid=506(group1)  =506(group1)

[root@test ~]#ansible websers -m shell -a 'id test2'
192.168.0.128 | SUCCESS | rc=0 >>
uid=507(test2) gid=507(group2)  =507(group2)

192.168.0.218 | SUCCESS | rc=0 >>
uid=1217(test2) gid=1217(group2)  =1217(group2)

[root@test ~]#ansible websers -m shell -a 'id test3'
192.168.0.128 | SUCCESS | rc=0 >>
uid=508(test3) gid=508(group3)  =508(group3)

192.168.0.218 | SUCCESS | rc=0 >>
uid=1218(test3) gid=1218(group3)  =1218(group3)

[root@test ~]#

説明:以上のプレイブックでは、対応するユーザの作成時に対応するグループに参加することを実現しました.