1、Jinja2介紹html
Jinja2是基於python的模板引擎,功能比較相似於PHP的smarty,J2ee的Freemarker和velocity。它能徹底支持unicode,並具備集成的沙箱執行環境,應用普遍。jinja2使用BSD受權java
Jinja2的語法是由variables(變量)和statement(語句)組成,以下;python
一、variables:能夠輸出數據mysql
` my_variables `nginx
{{ some_dudes_name | capitalize }}web
二、statements: 能夠用來建立條件和循環等sql
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容許在模板中使用諸如繪製時間此類的一些額外的模板變量apache
第一個例子:引用變量api
#cd roles/template/ . ├── meta │ └── main.yml ├── tasks │ ├── template.yml │ └── main.yml ├── templates │ ├── order.j2 └── vars └── main.yml
總調度yml文件:bash
#cat templates.yml --- - hosts: 10.0.90.27 user: root gather_facts: false roles: - role: template
注意:這裏 - role: template 和 - template 是同樣的!
其餘yml文件,以下:
#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目錄結構:
#cd /etc/ansible/roles/test_hosts . ├── meta │ └── main.yml ├── tasks │ ├── file1.yml │ └── main.yml ├── templates │ └── test1.j2 └── vars └── main.yml
各個目錄下yml文件內容:
# 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 函數作二次處理。
執行結果:
#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語句
說明:若是定義端口號,就綁定定義的端口號,若是不定義端口號,就綁定默認端口號
ansible目錄結果 #cd /etc/ansible/roles/mysql_cnf #tree . ├── meta │ └── main.yml ├── tasks │ └── main.yml ├── templates │ └── test3.j2 └── vars
主要的yml文件是templates目錄下面的test3.j2
# cat templates/test3.j2 {% if PORT %} bind_address=10.0.90.27:{{ PORT }} {% else %} bind_address=10.0.90.27:3306 {% endif %}
playbook主文件
# 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
執行:
# 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
查看
# cat my.cnf bind_address=10.0.90.27:3136
若是將vars變量去掉,執行結果:
# 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
查看:
# cat my.cnf bind_address=10.0.90.27:3306
三、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) }}
2、ansible使用jiaja2生成apache多主機配置
一、建立目錄,建立好以後以下:
#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
二、建立tasks調度文件,以下:
#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
三、建立apache的jinja2模板文件,以下:
#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 %}
四、建立變量,以下:
#cat vars/main.yml apache_vhost: - {servername: "apache.test1.com", documentroot: "/data/test1/"} - {servername: "apache.test2.com", documentroot: "/data/test2/"}
五、建立總調度yml文件,以下:
#cat /etc/ansible/apache_test.yml --- - hosts: 10.0.90.27 user: root gather_facts: no roles: - { role: apache_conf }
六、測試:
#ansible-playbook apache_test.yml --syntax-check playbook: apache_test.yml
七、執行測試
#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
八、到客戶端查看
#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>
3、ansible使用jiaja2生成nginx一個模板多種不一樣配置
說明:爲2臺Nginx Proxy,1臺Nginx Web經過一套模板生成對應的配置
一、ansible目錄結構:
# cd roles/nginx_conf/ #tree . ├── files ├── meta │ └── main.yml ├── tasks │ ├── file.yml │ └── main.yml ├── templates │ └── nginx.conf.j2 └── vars └── main.yml
二、tasks目錄下文件內容:
#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
三、nginx模板文件
#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 %} }
四、ansible變量文件
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文件
#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
五、測試並執行:
#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
六、查看檢測執行結果
到Nginx Proxy 服務器查看配置文件
#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 服務器上查看配置文件
#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強大的模板功能的同時,也須要看到模板質量的重要性。
參考連接:http://mp.weixin.qq.com/s?__biz=MzIyMDA1MzgyNw==&mid=2651968051&idx=1&sn=922b6cc8c8e6ff6e1c4b822e78ea31c3&scene=0#wechat_redirect 一個很好地ansible微信公衆號,歡迎關注共同窗習。