zoukankan      html  css  js  c++  java
  • 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强大的模板功能的同时,也需要看到模板质量的重要性。

  • 相关阅读:
    Keras -- 词向量 CNN
    KUDU实时分析
    Keras
    Kalfka
    Linux云
    管理KUDU
    列存储与行存储
    算法笔记 第5章 入门篇(3) --数学问题 学习笔记
    算法笔记 上机训练实战指南 第4章 入门篇(2) --算法初步 4.6two pointers 学习笔记
    算法笔记 上机训练实战指南 第4章 入门篇(2) --算法初步 4.4贪心 学习笔记
  • 原文地址:https://www.cnblogs.com/nineep/p/8946587.html
Copyright © 2011-2022 走看看