zoukankan      html  css  js  c++  java
  • Jinja2 for better Ansible(渲染文件中配置项到template模板配置文件中)

    Jinja2 is a modern and designer-friendly templating language for Python frameworks. It is fast, reliable and widely used for dynamic file generation based on its parameter. In this blog, I like to share how and where jinja2 template language used in Ansible and how we can create better Ansible playbook.

    How it works

    The Jinja variables and expressions indicated using the default delimiters as follows:

    • {% … %} for control statements (conditions)
    • {{ … }} for expressions (variables)
    • {# … #} for comments (describe the task)

    Here’s an example Jinja expressions:

    - hosts: 127.0.0.1
      vars_files:
        - vars.yml
      tasks:
        - name: Checking the IP address
          debug:
            msg: "IP address {{ ip }}"
        - name: Checking OS name
          debug:
            msg: "OS NAME {{ os_name }}"

    Variable definitions are needed for Jinja to resolve expressions. In the above example, definitions are required for ip and os_name.

    In Ansible, more then 21 places we can declare or define variable or value to the variable, below we have shared three important places:

    • Role defaults d
    • Passing a YAML or JSON file with the –vars-file option
    • Environment variables

    Variable files (vars_file or vars)

    Pass the path to a file containing variable definitions using the –vars-file option. The file path must be one of the following:

    • Absolute file path
    • Relative to the project path
    • Relative to the ansible folder

    When –vars-file is passed, Ansible Container checks if the path is an absolute path to a file. If not, it checks for the file relative to the project path, which is the current working directory. If the file is still not found, it looks for the file relative to the ansible folder within the project path.

    Variable files can also be specified using the vars_files directive under settings in container.yml. For example:

    - hosts: 127.0.0.1
      vars_files:
        - vars.yml
      tasks:
        ...

    This templating will helpful for many automation. It can be used to create a dynamic configuration for MySQL, Nagios depend upon the resources.

    Example:

    MySQL innodb_buffer_pool have to be 70% of total RAM for better performance. So it’s easy to make it from ansible variables like,

    mysql_innodb_buffer_pool_size: "{{ (ansible_memtotal_mb * 0.7) | int }}M"

    Breakdown:

    ansible_memtotal_mb will be retrieved from the setup module. Basically, it will return the system stats and assigned it to respected variables.

    Command to get complete stats about the system.

    To get stats about the local system:

    ansible --connection=local 127.0.0.1 -m setup

    To get stats about the remote system from the inventory file:

    ansible -i inventory_file group_name -m setup

    This can be disabled by adding the “gather_facts: no” in the respected host.

    Sample:

    - hosts: all
      gather_facts: no

    Auto generated variable definitions using the ansible stats (system resources). Based on the condition it will revert the values for the respected variables.

    Below is the sample yaml file which has the syntax and the variables.

    mysql_conf.yml:

    
    
    ---
    # MySQL connection settings.
    
    mysql_port: "3306"
    mysql_data_dir: "/var/lib/mysql"
    mysql_pid_file: "{{ mysql_data_dir }}/mysqld.pid"
    mysql_socket: "{{ mysql_data_dir }}/mysql.sock"
    
    # Slow query log settings.
    mysql_slow_query_log_enabled: yes
    mysql_slow_query_time: "2"
    mysql_slow_query_log_file: "{{ mysql_data_dir }}/mysql-slow.log"
    
    # Based on resources
    
    mysql_max_connections: "{{ (ansible_memtotal_mb // 12) | int }}"
    # Set .._buffer_pool_size up to 70% of RAM but beware of setting too high.
    mysql_innodb_buffer_pool_size: "{{ (ansible_memtotal_mb * 0.7) | int }}M"
    # Set .._log_file_size to 25% of buffer pool size.
    mysql_innodb_log_file_size: '{{ ((mysql_innodb_buffer_pool_size | string | replace("M", "") | int) * 0.25) | int }}M'
    
     

    When we have the variable definition ready we need to apply it for generating the configuration file with required fields.

    mysql_conf.j2: (template)

    
    
    # {{ ansible_managed }}
    
    [client]
    port = {{ mysql_port }}
    socket = {{ mysql_socket }}
    [mysqld]
    port = {{ mysql_port }}
    datadir = {{ mysql_data_dir }}
    socket = {{ mysql_socket }}
    pid-file = {{ mysql_pid_file }}
    
    # Slow query log configuration.
    
    {% if mysql_slow_query_log_enabled %}
    slow_query_log = 1
    slow_query_log_file = {{ mysql_slow_query_log_file }}
    long_query_time = {{ mysql_slow_query_time }}
    {% endif %}
    
    # InnoDB settings.
    
    innodb_buffer_pool_size = {{ mysql_innodb_buffer_pool_size }}
    innodb_log_file_size = {{ mysql_innodb_log_file_size }}
    
    # Setting max connections
    
    {% if mysql_max_connections | int > 3000 %}
    max_connections = 3000
    thread_cache_size = {{ (3000 * 0.15) | int }}
    {% elif mysql_max_connections | int < 150 %}
    max_connections = 150
    thread_cache_size = {{ (150 * 0.15) | int }}
    {% else %}
    max_connections = {{ mysql_max_connections }}
    thread_cache_size = {{ (mysql_max_connections | int * 0.15) | int }}
    {% endif %}
    
    
    
    
     

    Above will have the condition mapping along with the variable precedence. If the condition matches it will return the values with respect to the resource or it will keep the default value.

    Playbook:

    
    
    - hosts: 127.0.0.1
      vars_files:
        - mysql_conf.yml
      tasks:
        - name: Creating my.cnf with respected resources
          template: src=mysql_conf.j2  dest=my.cnf
    
    
    

     Command to generate my.cnf using the template:

    ansible-playbook playbook.yml

    Output:

     ansible-playbook playbook.yml
     [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
    
    /usr/lib/python2.7/site-packages/requests/__init__.py:91: RequestsDependencyWarning: urllib3 (1.24.1) or chardet (2.2.1) doesn't match a supported version!
      RequestsDependencyWarning)
    
    PLAY [127.0.0.1] ************************************************************************************************************************************************************
    
    TASK [Gathering Facts] ******************************************************************************************************************************************************
    Monday 24 August 2020  14:50:16 +0800 (0:00:00.151)       0:00:00.151 *********
    ok: [127.0.0.1]
    
    TASK [Creating my.cnf with respected resources] *****************************************************************************************************************************
    Monday 24 August 2020  14:50:18 +0800 (0:00:01.565)       0:00:01.717 *********
    changed: [127.0.0.1]
    
    PLAY RECAP ******************************************************************************************************************************************************************
    127.0.0.1                  : ok=2    changed=1    unreachable=0    failed=0
    
    Monday 24 August 2020  14:50:18 +0800 (0:00:00.139)       0:00:01.857 *********
    ===============================================================================
    Gathering Facts ------------------------------------------------------------------------------------------------------------------------------------------------------ 1.57s
    Creating my.cnf with respected resources ----------------------------------------------------------------------------------------------------------------------------- 0.14s
    

    my.cnf: (OUTPUT)

    
    
    cat my.cnf
    # Ansible managed
    
    [client]
    port = 3306
    socket = /var/lib/mysql/mysql.sock
    [mysqld]
    port = 3306
    datadir = /var/lib/mysql
    socket = /var/lib/mysql/mysql.sock
    pid-file = /var/lib/mysql/mysqld.pid
    
    # Slow query log configuration.
    
    slow_query_log = 1
    slow_query_log_file = /var/lib/mysql/mysql-slow.log
    long_query_time = 2
    
    # InnoDB settings.
    
    innodb_buffer_pool_size = 5474M
    innodb_log_file_size = 1368M
    
    # Setting max connections
    
    max_connections = 651
    thread_cache_size = 97
    

    ansible 命令行执行方式:
    ansible  127.0.0.1 -m template --connection=local -a "src=mysql_conf.j2 dest=dest=my.cnf" -e "@mysql_conf.yml"
    

     

     The above cnf was generated using the template. I hope it will give you a better idea about templating using Jinja2.

    Key takeaways:

    1. Easy to debug. Line numbers of exceptions directly point to the correct line in the template even with the column number.
    2. Configurable syntax with respected the yaml files.

    source: https://mydbops.wordpress.com/2019/04/17/jinja2-for-better-ansible/

  • 相关阅读:
    【iCore1S 双核心板_FPGA】例程十五:基于I2C的ARM与FPGA通信实验
    【iCore4 双核心板_ARM】例程二十一:LWIP_TCP_SERVER实验——以太网数据传输
    【iCore1S 双核心板_ARM】例程十五:USB_HID实验——双向数据传输
    【iCore4 双核心板_ARM】例程二十:LWIP_TCP_CLIENT实验——以太网数据传输
    【iCore1S 双核心板_FPGA】例程十四:FSMC总线通信实验——独立地址模式
    【iCore4 双核心板_FPGA】例程十五:基于单口RAM的ARM+FPGA数据存取实验
    【iCore4 双核心板_FPGA】例程十四:基于I2C的ARM与FPGA通信实验
    【iCore1S 双核心板_FPGA】例程十三:FSMC总线通信实验——复用地址模式
    【iCore4 双核心板_FPGA】例程十二:基于UART的ARM与FPGA通信实验
    【发布iCore3&iCore4ADM资料】
  • 原文地址:https://www.cnblogs.com/weifeng1463/p/13553697.html
Copyright © 2011-2022 走看看