Ansible使用jinja2管理配置文件以及jinja2语法简介

一、Jinja2介绍

Jinja2是基于python的模板引擎,功能比较类似于PHP的smarty,J2ee的Freemarker和velocity。它能完全支持unicode,并具有集成的沙箱执行环境,应用广泛。jinja2使用BSD授权

Jinja2的语法是由variables(变量)和statement(语句)组成,如下;

1、variables:可以输出数据

{{ my_variables }}

{{ some_dudes_name | capitalize }}

2、statements: 可以用来创建条件和循环等

1
2
3
4
5
6
7
8
9
if 语句:
{%  if  my_conditional %} 
...
{% endif %}
for  语句:
{%  for  item  in  all_items %}
{{item}} 
……
{% endfor %}

从上面第二个variables的例子中可以看出,jinja2支持使用带过滤器的Unix型管道操作符,有很多的内置过滤器可供使用。我们可以仅仅用一堆简单if和for就可以建立几乎任何的常规配置文件,不过如果你有意更进一步,jinja2 documentation (http://jinja.pocoo.org/docs/dev/)包含了很多有趣的东西可供了解。我们可以看到ansible允许在模板中使用诸如绘制时间此类的一些额外的模板变量

第一个例子:引用变量

1
2
3
4
5
6
7
8
9
10
11
#cd roles/template/
.
├── meta
│   └── main.yml
├── tasks
│   ├── template.yml  
│   └── main.yml
├── templates
│   ├── order.j2
└── vars
     └── main.yml

总调度yml文件:

1
2
3
4
5
6
7
#cat templates.yml
---
- hosts: 10.0.90.27
   user: root
   gather_facts:  false
   roles:
    - role: template

注意:这里 - role: template 和 - template 是一样的!

其他yml文件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#cat tasks/main.yml
- include: template.yml
#cat tasks/template.yml
- name: create {{ PROJECT }} directory
   file : dest= /data/ {{ PROJECT }} state=directory
- name: template transfor java  dir
   template: src=order.j2 dest= /data/ {{ PROJECT }} /order .conf
#cat templates/order.j2
project: {{ PROJECT }}
switch: {{ SWITCH }}
dbport: {{ DBPORT }}
#cat vars/main.yml
PROJECT:  "JAVA"
SWITCH:  "ON"
DBPORT:  "8080"
测试:
# ansible-playbook templates.yml --syntax-check
playbook: templates.yml
执行:
# ansible-playbook templates.yml 
PLAY [10.0.90.27] **************************************************************
TASK [template : include] ***************************************************
included:  /etc/ansible/roles/template/tasks/template .yml  for  10.0.90.27
TASK [template : create JAVA directory] *************************************
changed: [10.0.90.27]
TASK [template : template transfor java  dir ] ********************************
changed: [10.0.90.27]
PLAY RECAP *********************************************************************
10.0.90.27                 : ok=3    changed=2    unreachable=0    failed=0   
到10.0.90.27查看结果
#cat /data/JAVA/order.conf
project: JAVA
switch: ON
dbport: 8080

第二个例子:for 语句

为远程主机生成服务器列表,加入该列表从192.168.13.201 web01.test.com 到192.168.13.211 web11.test.com 结束,如果手动添加就很不科学了,这里需要使用jinja2语法的for循环通过模板批量生成对应的配置文件,如下:

ansible目录结构:

1
2
3
4
5
6
7
8
9
10
11
#cd /etc/ansible/roles/test_hosts
.
├── meta
│   └── main.yml
├── tasks
│   ├── file1.yml
│   └── main.yml
├── templates
│   └── test1.j2
└── vars
     └── main.yml

各个目录下yml文件内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
# cat tasks/file1.yml 
- name: ansible jinja2 template  for  hosts config
   template: src=test1.j2 dest= /etc/httpd/conf/httpd .conf. test
# cat tasks/main.yml 
- include: file1.yml
# cat templates/test1.j2 
{%  for  id  in  range(201,212) %}
192.168.13.{{  id  }} web{{  "%03d"  | format ( id -200) }}. test .com
{% endfor %}
解释:
{{  id  }} 提取 for 循环中对应的变量 id
"%02d"    调用的是python内置的字符串格式化输出(%d格式化整数)因为是01,02这种格式,所以是保留2位,故用02
然后将结果通过管道符 “|” 传递给 format  函数做二次处理。

执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
#cat httpd.conf.test
192.168.13.201 web01. test .com
192.168.13.202 web02. test .com
192.168.13.203 web03. test .com
192.168.13.204 web04. test .com
192.168.13.205 web05. test .com
192.168.13.206 web06. test .com
192.168.13.207 web07. test .com
192.168.13.208 web08. test .com
192.168.13.209 web09. test .com
192.168.13.210 web10. test .com
192.168.13.211 web11. test .com

第三个例子:if语句

说明:如果定义端口号,就绑定定义的端口号,如果不定义端口号,就绑定默认端口号

1
2
3
4
5
6
7
8
9
10
11
ansible目录结果
#cd /etc/ansible/roles/mysql_cnf
#tree
.
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
│   └── test3.j2
└── vars

主要的yml文件是templates目录下面的test3.j2

1
2
3
4
5
6
# cat templates/test3.j2 
{%  if  PORT %}
bind_address=10.0.90.27:{{ PORT }}
{%  else  %}
bind_address=10.0.90.27:3306
{% endif %}

playbook主文件

1
2
3
4
5
6
7
8
9
10
# cat jinj2_test.yml 
---
- hosts: 10.0.90.27
   user: root
   gather_facts:  false
   vars:
     PORT: 3136
   tasks:
     - name: copy  file  to client
       template: src= /etc/ansible/roles/mysql_cnf/templates/test3 .j2 dest= /root/my .cnf

执行:

1
2
3
4
5
6
# ansible-playbook jinj2_test.yml
PLAY [10.0.90.27] **************************************************************
TASK [copy  file  to client] *****************************************************
changed: [10.0.90.27]
PLAY RECAP *********************************************************************
10.0.90.27                 : ok=1    changed=1    unreachable=0    failed=0

查看

1
2
# cat my.cnf 
bind_address=10.0.90.27:3136

如果将vars变量去掉,执行结果:

1
2
3
4
5
6
7
8
9
10
# cat jinj2_test.yml 
---
- hosts: 10.0.90.27
   user: root
   gather_facts:  false
   vars:
     PORT:  false
   tasks:
     - name: copy  file  to client
       template: src= /etc/ansible/roles/mysql_cnf/templates/test3 .j2 dest= /root/my .cnf

查看:

1
2
# cat my.cnf 
bind_address=10.0.90.27:3306

3、Jinja default()设定

精通程序编码的朋友皆知,default()默认值的设定有助于程序的健壮性和简洁性。所幸Jinja也支持该功能,上面的例子中生成Mysql配置文件中的端口定义,如果指定则PORT=3136,否则PORT=3306,我们将该案例改造为使用default()试试

编辑/etc/ansible/roles/mysql_cnf/templates/test3.j2内容如下,这种方法更简介。

bind_address=10.0.90.27:{{ PORT | default(3306) }}

二、ansible使用jiaja2生成apache多主机配置

1、创建目录,创建好之后如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#cd /etc/ansible/roles/apache_conf
# tree ./
./
├── meta
│   └── main.yml
├── tasks
│   ├──  file .yml
│   └── main.yml
├── templates
│   └── apache.config.j2
└── vars
     └── main.yml
 
4 directories, 5 files

2、创建tasks调度文件,如下:

1
2
3
4
5
#cat file.yml 
- name: ansible jinja2 template  for  apache config
   template: src=apache.config.j2 dest= /etc/httpd/conf/httpd .conf.template
#cat main.yml 
- include:  file .yml

3、创建apache的jinja2模板文件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#cat apache.config.j2 
NameVirtualHost *:80
{%  for  vhost in apache_vhost %}
<VirtualHost *:80>
ServerName {{ vhost.servername }}
DocumentRoot {{ vhost.documentroot }}
{%  if  vhost.serveradmin is defined %}
ServerAdmin {{ vhost.serveradmin }}
{% endif %}
<Directory  "{{ vhost.documentroot }}" >
AllowOverride All
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
{% endfor %}

4、创建变量,如下:

1
2
3
4
#cat vars/main.yml
apache_vhost:
- {servername:  "apache.test1.com" , documentroot:  "/data/test1/" }
- {servername:  "apache.test2.com" , documentroot:  "/data/test2/" }

5、创建总调度yml文件,如下:

1
2
3
4
5
6
7
#cat /etc/ansible/apache_test.yml 
---
- hosts: 10.0.90.27
   user: root
   gather_facts: no
   roles:
    - { role: apache_conf }

6、测试:

1
2
3
#ansible-playbook apache_test.yml --syntax-check
 
playbook: apache_test.yml

7、执行测试

1
2
3
4
5
6
7
8
#ansible-playbook apache_test.yml 
PLAY [10.0.90.27] **************************************************************
TASK [apache_conf : include] ***************************************************
included:  /etc/ansible/roles/apache_conf/tasks/file .yml  for  10.0.90.27
TASK [apache_conf : ansible jinja2 template  for  apache config] *****************
changed: [10.0.90.27]
PLAY RECAP *********************************************************************
10.0.90.27                 : ok=2    changed=1    unreachable=0    failed=0

8、到客户端查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#cat httpd.conf.template 
NameVirtualHost *:80
<VirtualHost *:80>
ServerName apache.test1.com
DocumentRoot  /data/test1/
<Directory  "/data/test1/" >
AllowOverride All
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
< /Directory >
< /VirtualHost >
<VirtualHost *:80>
ServerName apache.test2.com
DocumentRoot  /data/test2/
<Directory  "/data/test2/" >
AllowOverride All
Options -Indexes FollowSymLinks
Order allow,deny
Allow from all
< /Directory >
< /VirtualHost >

三、ansible使用jiaja2生成nginx一个模板多种不同配置

说明:为2台Nginx Proxy,1台Nginx Web通过一套模板生成对应的配置

1、ansible目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
# cd roles/nginx_conf/
#tree
.
├── files
├── meta
│   └── main.yml
├── tasks
│   ├──  file .yml
│   └── main.yml
├── templates
│   └── nginx.conf.j2
└── vars
     └── main.yml

2、tasks目录下文件内容:

1
2
3
4
5
#cat tasks/file.yml 
- name: nginx.j2 template transfer example 
   template: src=nginx.conf.j2 dest= /etc/nginx/nginx .conf.template
#cat tasks/main.yml 
- include:  file .yml

3、nginx模板文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#cat templates/nginx.conf.j2 
{%  if  nginx_use_proxy %}
{%  for  proxy  in  nginx_proxies %}
upstream {{ proxy.name }}
    #server 127.0.0.1:{{ proxy.port }};
    server {{ ansible_eth0.ipv4.address }}:{{ proxy.port }};
}
{% endfor %}
{% endif%}
server {
     listen 80;
     servername {{ nginx_server_name }};
     access_log off;
     error_log  /etc/nginx/nginx_error .log;
     rewrite ^ https: // $server_name$request_uri? permanent;
}
server {
     listen 443 ssl;
     server_name {{ nginx_server_name }};
     ssl_certificate  /etc/nginx/ssl/ {{ nginx_ssl_cert_name }};
     ssl_certificate_key  /etc/nginx/ssl/ {{ nginx_ssl_cert_key }};
     root {{ nginx_web_root }};
     index index.html index.html;
{%  if  nginx_use_auth %}
    auth_basic   "Restricted" ;
    auth_basic_user_file  /etc/nginx/ {{ project_name }}.htpasswd;
{% endif %}
{%  if  nginx_use_proxy %}
{%  for  proxy  in  nginx_proxies %}
    location {{ proxy.location }} {
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-Proto http;
       proxy_set_header X-Url-Scheme $scheme;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
       proxy_set_header X-NginX-Proxy  true ;
       proxy_redirect off;
       proxy_pass http: // {{ proxy.name }};
       break ;
}
{% endfor %}
{% endif %}
{%  if  nginx_server_static %}
    location / {
        try_files $url $url/ =404;
}
{% endif %}
}

4、ansible变量文件

1
2
3
4
5
6
7
8
9
10
cat  vars /main .yml 
nginx_server_name: www.testnginx.com
nginx_web_root:  /data/html/
nginx_proxies:
- name: suspicious
   location: /
   port: 1234
- name: suspicious-api
   location:  /api
   port: 4567

ansible主playbook文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#cat nginx_test.yml 
##The first roles
- name: Nginx Proxy Server's Config Dynamic Create
   hosts:  "10.0.90.25:10.0.90.26"
   remote_user: root
   vars:
     nginx_use_proxy:  true
     nginx_ssl_cert_name: ifa.crt
     nginx_ssl_cert_key: ifa.key
     nginx_use_auth:  true
     project_name: suspicious
     nginx_server_static:  true
   gather_facts:  true
   roles:
      -  role: nginx_conf
##The second roles
- name: Nginx WebServer's Config Dynamic Create
   hosts: 10.0.90.27
   remote_user: root
   vars:
     nginx_use_proxy:  false
     nginx_ssl_cert_name: ifa.crt
     nginx_ssl_cert_key: ifa.crt
     nginx_use_auth:  false
     project_name: suspicious
     nginx_server_static:  false
   gather_facts:  false
   roles:
      -  role: nginx_conf

5、测试并执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ansible-playbook nginx_test.yml --syntax-check
playbook: nginx_test.yml
执行:
# ansible-playbook nginx_test.yml
PLAY [Nginx Proxy Server's Config Dynamic Create] ******************************
 
TASK [setup] *******************************************************************
ok: [10.0.90.25]
ok: [10.0.90.26]
 
TASK [nginx_conf : include] ****************************************************
included:  /etc/ansible/roles/nginx_conf/tasks/file .yml  for  10.0.90.25, 10.0.90.26
 
TASK [nginx_conf : nginx.j2 template transfer example] *************************
changed: [10.0.90.26]
changed: [10.0.90.25]
 
PLAY [Nginx WebServer's Config Dynamic Create] *********************************
 
TASK [nginx_conf : include] ****************************************************
included:  /etc/ansible/roles/nginx_conf/tasks/file .yml  for  10.0.90.27
 
TASK [nginx_conf : nginx.j2 template transfer example] *************************
changed: [10.0.90.27]
 
PLAY RECAP *********************************************************************
10.0.90.25                 : ok=3    changed=1    unreachable=0    failed=0   
10.0.90.26                 : ok=3    changed=1    unreachable=0    failed=0   
10.0.90.27                 : ok=2    changed=1    unreachable=0    failed=0

6、查看检测执行结果

到Nginx Proxy 服务器查看配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#cat nginx.conf.template 
upstream suspicious
    #server 127.0.0.1:1234;
    server 10.0.90.26:1234;
}
upstream suspicious-api
    #server 127.0.0.1:4567;
    server 10.0.90.26:4567;
}
server {
     listen 80;
     servername www.testnginx.com;
     access_log off;
     error_log  /etc/nginx/nginx_error .log;
     rewrite ^ https: // $server_name$request_uri? permanent;
}
server {
     listen 443 ssl;
     server_name www.testnginx.com;
     ssl_certificate  /etc/nginx/ssl/ifa .crt;
     ssl_certificate_key  /etc/nginx/ssl/ifa .key;
     root  /data/html/ ;
     index index.html index.html;
    auth_basic   "Restricted" ;
    auth_basic_user_file  /etc/nginx/suspicious .htpasswd;
    location / {
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-Proto http;
       proxy_set_header X-Url-Scheme $scheme;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
       proxy_set_header X-NginX-Proxy  true ;
       proxy_redirect off;
       proxy_pass http: //suspicious ;
       break ;
}
    location  /api  {
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-Proto http;
       proxy_set_header X-Url-Scheme $scheme;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
       proxy_set_header X-NginX-Proxy  true ;
       proxy_redirect off;
       proxy_pass http: //suspicious-api ;
       break ;
}
    location / {
        try_files $url $url/ =404;
}
}

到Nginx Web 服务器上查看配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#cat nginx.conf.template 
server {
     listen 80;
     servername www.testnginx.com;
     access_log off;
     error_log  /etc/nginx/nginx_error .log;
     rewrite ^ https: // $server_name$request_uri? permanent;
}
server {
     listen 443 ssl;
     server_name www.testnginx.com;
     ssl_certificate  /etc/nginx/ssl/ifa .crt;
     ssl_certificate_key  /etc/nginx/ssl/ifa .crt;
     root  /data/html/ ;
     index index.html index.html;
}

到这里,就结束了。用同样的模板通过简单的if和变量设置就可以完成不同类型主机的Nginx conf配置,所以一方面在了解Ansible强大的模板功能的同时,也需要看到模板质量的重要性。

猜你喜欢

转载自www.cnblogs.com/nineep/p/8946587.html