Ansible Jinja2 模板

Posted 徐中祥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Ansible Jinja2 模板相关的知识,希望对你有一定的参考价值。

一、playbook忽略错误

默认playbook会检测task执行的返回状态,如果遇到错误则会立即终止playbook的后续task执行,然鹅有些时候playbook即使执行错误了也要让其继续执行
- hosts: web_group
  tasks:
    - name: Check Httpd Server
      #使用命令检查服务启动状态时,如果服务没有启动则会得到错误结果,剧本会停止运行
      command: systemctl is-active httpd
      #配置忽略错误可以继续执行剧本
      ignore_errors: yes
      register: check_httpd

    - name: debug outprint
      debug: 
        msg: "{{ check_httpd }}"

    - name: Httpd Restart
      service:
        name: httpd
        state: restarted
      when: check_httpd.rc == 0

二、错误处理

如上所述,当task执行失败时,playbook将不再继续执行,包括如果在task中设置了handler也不会被执行。

但是我们可以采取强制措施...

1.强制调用handlers

[root@m01 ~]# cat handler.yml 
- hosts: web_group
  vars:
    - http_port: 8080
  force_handlers: yes
  tasks:
    - name: config httpd server
      template:
        src: ./httpd.j2
        dest: /etc/httpd/conf
      notify: 
        - Restart Httpd Server
        - Restart php Server

    - name: Install Http Server
      yum:
        name: htttpd
        state: present

    - name: start httpd server
      service:
        name:httpd
        state: started
        enabled: yes

  handlers:
    - name: Restart Httpd Server
      systemd:
        name: httpd
        state: restarted

    - name: Restart PHP Server
      systemd:
        name: php-fpm
        state: restarted

2.抑制changed

被管理主机没有发生变化,可以使用参数将change状态改为ok

    - name: Check php Install Status
      shell: "rpm -qa | grep php | wc -l"
      register: get_php_instll_status
      changed_when: false

Ansible Jinja2 模板概述

一、jinja2模板概述

#什么是jinja2模板
jinja2是Python的全功能模板引擎

#Jinja2与Ansible啥关系
Ansible通常会使用jinja2模板来修改被管理主机的配置文件等...在saltstack中同样会使用到jinja2
如果在100台主机上安装redis,每台redis的监听地址都不一样,如何解决?

#Ansible如何使用Jinja2
使用Ansible的jinja2模板也就是使用template模块,该模块和copy模块一样,都是将文件复制到远端主机上去,但是区别在于,template模块可以获取到文件中的变量,而copy则是原封不动的把文件内容复制过去。之前我们在推送rsync的backup脚本时,想把脚本中的变量名改成主机名,如果使用copy模块则推送过去的就是{{ ansible_fqdn }},不变,如果使用template,则会变成对应的主机名。

#Ansible使用Jinja2注意事项
Ansible允许jinja2模板中使用条件判断和循环,但是不允许在playbook中使用。
注意:不是每个管理员都需要这个特性,但是有些时候jinja2模块能大大提高效率。

二、Ansible Jinja2 模板使用

1.变量使用语法

{{ EXPR }} 输出变量值,会输出自定义的变量值或facts
1.playbook文件使用template模块
2.模板文件里面变量使用 {{ 名称 }},比如 {{ PORT }} 或使用facts

2.Jinja2模板逻辑判断语法

#shell中的判断语法
[root@m01 project]# vim pd.sh 
#!/bin/bash
age=$1
if [ $age -lt 18 ];then
    echo "小姐姐"
else
    echo "大妈"
fi

#Jinja2模板判断语法
#条件判断
{% if EXPR %}
{% elif EXPR %}
{% else %}
{% endif %}

3.Jinja2模板循环语法

#shell中的循环
[root@m01 project]# vim xh.sh
#!/bin/bash
for i in `seq 10`
  do
      echo $i
  done
  
#Jinja2模板循环语法
#循环表达式
{% for i in EXPR %}
{% endfor %}

4.注释

#shell中的注释
使用 # 写在注释内容最前面

#Jinja2模板注释语法
{# COMMENT #}

三、jinja2模板测试

1.实例一

1)配置登陆文件的 jinja2 模板

[root@m01 project]# vim motd.j2
Welcome to {{ ansible_fqdn }}
This system total mem is : {{ ansible_memtotal_mb }} MB
This system free mem is: {{ ansible_memfree_mb }} MB

2)编写剧本

[root@m01 project]# vim motd.yml
- hosts: all
  tasks:
    - name: Config motd
      template:
        src: ./motd.j2
        dest: /etc/motd

3)执行并查看结果

[root@m01 project]# ansible-playbook motd.yml
#查看结果
Connecting to 10.0.0.51:22...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.

Last login: Thu Dec 24 15:29:37 2020 from 10.0.0.61
Welcome to db01
This system total mem is : 972 MB
This system free mem is: 267 MB

2.实例二

1)配置数据库配置文件

[root@m01 project]# vim /etc/my.cnf
innodb_buffer_pool_size = {{ ansible_memtotal_mb * 0.8 }}M

2)编写剧本

[root@m01 project]# cat my.yml 
- hosts: db01
  tasks:
    - name: Config Mariadb
      template:
        src: /etc/my.cnf
        dest: /etc/

3)执行并查看

[root@m01 project]# ansible-playbook my.yml 

#检查
[root@db01 ~]# vim /etc/my.cnf
[mysqld]
innodb_buffer_pool_size = 777.6M

4)jinja2模板修改

[root@m01 project]# vim /etc/my.cnf

[mysqld]

{% if ansible_memtotal_mb == 972 %}
innodb_buffer_pool_size = 800M
{% elif ansible_memtotal_mb == 1980 %}
innodb_buffer_pool_size = 1600M
{% endif %}

5)再次执行查看

#查看服务器
	1.如果服务器内存是 972M,则配置为  innodb_buffer_pool_size = 800M
	2.如果服务器内存是 1980M,则配置为  innodb_buffer_pool_size = 1600M

3.实例三:使用jinja2模板配置nginx负载均衡

0)先给负载均衡安装nginx

1)准备负载均衡配置文件

#正常的配置文件
[root@m01 project]# vim conf/upstream.conf
upstream web {
    server 172.16.1.7;
    server 172.16.1.8;
}

server {
    listen 80;
    server_name linux.wp.com;

    location / {
        proxy_pass http://web;
        proxy_set_header Host $http_host;
    }
}

#不正经的配置文件
[root@m01 project]# vim conf/upstream.j2
upstream {{ server_name }} {
{% for i in range(7,20) %}
    server {{ net_ip }}.{{ i }};
{% endfor %}
}

server {
    listen {{ web_port }};
    server_name {{ server_name }};

    location / {
        proxy_pass http://{{ server_name }};
        proxy_set_header Host $http_host;
    }
}

2)配置变量文件

[root@m01 project]# vim upstream_vars.yml
server_name: linux.wp.com
web_port: 80
net_ip: 172.16.1

3)编写剧本

[root@m01 project]# vim lb.yml
- hosts: lb_server
  vars_files: ./upstream_vars.yml
  tasks:
    - name: Config Nginx Upstream
      template:
        src: conf/upstream.j2
        dest: /etc/nginx/conf.d/upstream.conf
      notify: restert_upstream

    - name: Start Nginx Server
      systemd:
        name: nginx
        state: started

  handlers:
    - name: restert_upstream
      systemd:
        name: nginx
        state: restarted

4)执行并测试

[root@m01 project]# ansible-playbook lb.yml

4.实例四:使用jinja2模板配置keepalived

1)准备keepalived配置文件

#正经的配置文件
[root@m01 project]# vim conf/keepalived.conf
global_defs {
    router_id lb02
}
vrrp_instance VI_1 {
    state BACKUP        
    interface eth0
    virtual_router_id 50
    priority 100
    advert_int 1
    authentication {    
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.3
    }
}

#不正经的配置文件
[root@m01 project]# vim conf/keepalived.conf
global_defs {
    router_id {{ ansible_fqdn }}
}
vrrp_instance VI_1 {
{% if ansible_fqdn == "lb01" %}
    state MASTER
    priority 100
{% else %}
    state BACKUP
    priority 90
{% endif %}
    interface eth0
    virtual_router_id 50
    advert_int 1
    authentication {  
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.3
    }
}

2)配置剧本

[root@m01 project]# cat keepalived.yml 
- hosts: lb_server
  tasks:
    - name: Install keepalived Server
      yum:
        name: keepalived
        state: present

    - name: Config keepalived Server
      template:
        src: conf/keepalived.j2
        dest: /etc/keepalived/keepalived.conf

    - name: Start keepalived Server
      systemd:
        name: keepalived
        state: started

Ansible Roles

一、Ansible Roles基本概述

1.Ansible Roles介绍

roles不管是Ansible还是saltstack,我在写一键部署的时候,都不可能把所有的步骤全部写入到一个'剧本'文件当中,我们肯定需要把不同的工作模块,拆分开来,解耦,那么说到解耦,我们就需要用到roles官方推荐,因为roles的目录结构层次更加清晰。

例如:我们之前推荐大家写一个base.yml里面写所有基础优化的项目,其实把所有东西摞进去也是很鸡肋的,不如我们把这些功能全部拆分开,谁需要使用,就调用即可。

建议:每个roles最好只使用一个tasks这样方便我们去调用,能够很好的做到解耦。(SOA)

img

production                # inventory file for production servers
staging                   # inventory file for staging environment

group_vars/
   group1.yml             # here we assign variables to particular groups
   group2.yml
host_vars/
   hostname1.yml          # here we assign variables to particular systems
   hostname2.yml

library/                  # if any custom modules, put them here (optional)
module_utils/             # if any custom module_utils to support modules, put them here (optional)
filter_plugins/           # if any custom filter plugins, put them here (optional)

site.yml                  # master playbook
webservers.yml            # playbook for webserver tier
dbservers.yml             # playbook for dbserver tier

roles/
    common/               # this hierarchy represents a "role"
        tasks/            #
            main.yml      #  <-- tasks file can include smaller files if warranted
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies
        library/          # roles can also include custom modules
        module_utils/     # roles can also include custom module_utils
        lookup_plugins/   # or other types of plugins, like lookup in this case

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""

2.创建roles目录

1.手动创建

[root@m01 roles]# mkdir nginx/{tasks,files,templates,vars,handlers,meta} -p

[root@m01 roles]# tree nginx/
nginx/
├── files
├── handlers
├── meta
├── tasks
├── templates
└── vars

2.使用命令创建

[root@m01 roles]# ansible-galaxy init nginx
- Role nginx was created successfully

[root@m01 roles]# tree nginx
nginx					#项目目录名称
├── defaults			#默认的变量(优先级很低)
│   └── main.yml
├── files				#存放文件,使用copy模块时自动获取
├── handlers			#存放触发器的配置
│   └── main.yml
├── meta				#依赖的服务,执行该项目时先执行其他的项目
│   └── main.yml
├── README.md
├── tasks				#默认执行的playbook
│   └── main.yml
├── templates			#存放jinja2模板,使用template模块时自动获取
├── tests
│   ├── inventory
│   └── test.yml
└── vars				#存放变量
    └── main.yml

3.Ansible Roles依赖关系

`roles`允许你再使用roles时自动引入其他的roles。role依赖关系存储在roles目录中meta/main.yml文件中。

例如:推送wordpress并解压,前提条件,必须要安装nginx和php,把服务跑起来,才能运行wordpress的页面,此时我们就可以在wordpress的roles中定义依赖nginx和php的roles
[root@m01 roles]# vim /etc/ansible/roles/wordpress/meta/main.yml
dependencies:
  - { role: nginx }
  - { role: php }
  
如果编写了meta目录下的main.yml文件,那么Ansible会自动先执行meta目录中main.yml文件中的dependencies文件,如上所示,就会先执行nginx和php的安装。

二、重构playbook

1.配置主机清单

[root@m01 roles]# vim /etc/ansible/hosts 
[lb_server]
lb01 ansible_ssh_pass='1'
lb02 ansible_ssh_pass='1'

[web_group]
web01 ansible_ssh_pass='1'
web02 ansible_ssh_pass='1'

[nfs_server]
nfs ansible_ssh_pass='1'

[rsync_server]
backup ansible_ssh_pass='1'

[db_server]
db01 ansible_ssh_pass='1'

[nginx:children]
web_group
lb_server

2.配置hosts

[root@m01 roles]# vim /etc/hosts
10.0.0.4 lb01
10.0.0.5 lb02
10.0.0.7 web01
10.0.0.8 web02
10.0.0.31 nfs
10.0.0.41 backup
10.0.0.51 db01

3.优化部分

[root@m01 roles]# cat base/tasks/main.yml 
- hosts: all
  tasks:
    - name: Stop Firewalld
      systemd:
        name: firewalld
        state: stopped
        enabled: no

    - name: Stop Selinux
      selinux:
        state: disabled

    - name: Create www Group
      group:
        name: www
        gid: 666
        state: present
      when: ansible_fqdn != "db01"

    - name: Create www User
      user:
        name: www
        uid: 666
        group: www
        shell: /sbin/nologin
        create_home: false
        state: present
      when: ansible_fqdn != "db01"

4.nginx部分

1)准备包和配置文件

[root@m01 roles]# cd nginx/files/
[root@m01 files]# ll
total 772
-rw-r--r-- 1 root root 784272 Dec 10 09:13 nginx-1.16.1-1.el7.ngx.x86_64.rpm
-rw-r--r-- 1 root root    641 Dec 24 17:16 nginx.conf

2)安装nginx

[root@m01 roles]# vim nginx/tasks/main.yml 
- hosts: nginx
  tasks:
    - name: Push nginx rpm
      copy:        src: nginx-1.16.1-1.el7.ngx.x86_64.rpm
        dest: /tmp/

    - name: Install Nginx Server
      yum:
        name: /tmp/nginx-1.16.1-1.el7.ngx.x86_64.rpm
        state: present

    - name: Config Nginx Server
      copy:
        src: nginx.conf
        dest: /etc/nginx/
      notify: restart_nginx

    - name: Start Nginx Server
      systemd:
        name: nginx
        state: started

3)配置触发器

[root@m01 roles]# vim nginx/handlers/main.yml 
- name: restart_nginx
  systemd:
    name: nginx
    state: restarted

5.php部分

1)准备配置文件

[root@m01 roles]# cd php/files/
[root@m01 files]# ll
total 19508
-rw-r--r-- 1 root root    62646 Dec 21 11:04 php.ini
-rw-r--r-- 1 root root 19889622 Nov 22 15:52 php.tar.gz
-rw-r--r-- 1 root root    17962 Dec 22 15:10 www.conf

2)编写安装PHP的剧本

[root@m01 roles]# vim php/tasks/main.yml
- hosts: web_group
  tasks:
    - name: Tar php Package
      unarchive:
        src: php.tar.gz
        dest: /tmp/

    - name: Check php Install Status
      shell: "rpm -qa | grep php | wc -l"
      register: get_php_install_status
      changed_when: false

    - name: Install php Server
      shell: "yum localinstall -y /tmp/*.rpm"
      when: get_php_install_status.stdout_lines == 0

    - name: Config php Server
      copy:
        src: "{{ item.src }}"
        dest: "{{ item.dest }}"
      with_items:
        - { src: "php.ini", dest: "/etc" }
        - { src: "www.conf", dest: "/etc/php-fpm.d/" }
      notify: restart_php

    - name: Start php Server
      systemd:
        name: php-fpm
        state: started

3)配置触发器

[root@m01 roles]# vim php/handlers/main.yml 
- name: restart_php
  systemd:
    name: php-fpm
    state: restarted

6.数据库部分

[root@m01 roles]# cat mariadb/tasks/main.yml 
- hosts: db01
  tasks:
    - name: Install Mariadb Server
      yum:
        name: mariadb-server
        state: present

    - name: Install MySQL-python Server
      yum:
        name: MySQL-python
        state: present

    - name: Start Mariadb Server
      systemd:
        name: mariadb
        state: started
        enabled: yes

    - name: Create wordpress Database
      mysql_db:
        name: wordpress
        state: present

    - name: Create wordpress Database User
      mysql_user:
        name: "wp"
        host: "172.16.1.%"
        password: "123456"
        priv: 'wordpress.*:ALL'
        state: present

7.博客部分

1)准备文件

[root@m01 roles]# cd wordpress/files/
[root@m01 files]# ll
total 10848
-rw-r--r-- 1 root root      259 Dec 23 18:01 linux.wp.com.conf
-rw-r--r-- 1 root root 11098483 Sep 12 17:52 wordpress-5.0.3-zh_CN.tar.gz
-rw-r--r-- 1 root root     3009 Dec 22 16:00 wp-config.php

2)编写剧本

[root@m01 roles]# vim wordpress/tasks/main.yml
- hosts: web_group
  tasks:
    - name: Create code Dir
      file:
        path: /code
        state: directory

    - name: Tar wordpress Code
      unarchive:
        src: wordpress-5.0.3-zh_CN.tar.gz
        dest: /code/

    - name: Config wordpress DB
      copy:
        src: wp-config.php
        dest: /code/wordpress/

    - name: Chown Code Dir
      file:
        path: /code
        state: directory
        owner: www
        group: www
        recurse: yes

    - name: Config Nginx wordpress
      copy:
        src: linux.wp.com.conf
        dest: /etc/nginx/conf.d/
      notify: restart_nginx

3)配置触发器

[root@m01 roles]# vim wordpress/handlers/main.yml 
- name: restart_nginx
  systemd:
    name: nginx
    state: restarted

8.负载均衡部分

1)准备文件

[root@m01 roles]# cd upstream/templates/
[root@m01 templates]# ll
total 4
-rw-r--r-- 1 root root 270 Dec 24 16:07 upstream.j2

2)编写剧本

[root@m01 roles]# vim upstream/tasks/main.yml 
- name: Config Nginx Upstream
  template:
    src: upstream.j2
    dest: /etc/nginx/conf.d/upstream.conf
  notify: restert_upstream

- name: Start Nginx Server
  systemd:
    name: nginx
    state: started

3)配置触发器

[root@m01 roles]# vim upstream/handlers/main.yml 
- name: restert_upstream
  systemd:
    name: nginx
    state: restarted

9.配置keepalived高可用

1)准备文件

[root@m01 roles]# cd keepalived/templates/
[root@m01 templates]# ll
total 4
-rw-r--r-- 1 root root 381 Dec 24 16:38 keepalived.j2

2)编写剧本

[root@m01 roles]# vim keepalived/tasks/main.yml 
- name: Install keepalived Server
  yum:
    name: keepalived
    state: present

- name: Config keepalived Server
  template:
    src: keepalived.j2
    dest: /etc/keepalived/keepalived.conf

- name: Start keepalived Server
  systemd:
    name: keepalived
    state: started

10.整合剧本

[root@m01 product]# cat site.yml 
- name: 优化部分
  hosts: all
  roles:
    - base

- name: 安装nginx
  hosts: nginx
  roles:
    - nginx

- name: 安装php和搭建博客
  hosts: web_group
  roles:
    - php
    - wordpress

- name: 安装数据库
  hosts: db_server
  roles:
    - mariadb

- name: 配置负载均衡和高可用
  hosts: lb_server
  roles:
    - upstream
    - keepalived

以上是关于Ansible Jinja2 模板的主要内容,如果未能解决你的问题,请参考以下文章

自动化运维工具-Ansible Jinja2模板

Ansible 使用jinja2模板 统计资源使用情况

009.Ansible模板管理 Jinja2

Ansible Jinja2 模板使用

ansible自动化运维详解ansible中变量的设定使用JINJA2模板的使用以及ansible的加密控制

ansible自动化运维详解ansible中变量的设定使用JINJA2模板的使用以及ansible的加密控制