Ansible Advanced
# Ansible Jinja2
# 什么是jinja2
Jinja2
是Python
的全功能模板引擎
Ansible
需要使用Jinja2
模板来修改被管理主机的配置文件。
- 场景:给10台主机装上
Nginx
服务,但是要求每台主机的端口都不一样,如何解决?
# Ansible如何使用jinja2
ansible
使用jinja2
模板需要借助template
模块实现,那template
模块是用来做什么的?
template
模块和copy
模块完全一样,都是拷贝文件至远程主机,区别在于template
模块会解析要拷贝的文件中变量的值,而copy
则是原封不动的将文件拷贝至被控端。
# jinja模板基本语法
- 要想在配置文件中使用
jinj2
,playbook
中的tasks
必须使用template
模块; - 配置文件里面使用变量,用双大括号括起来;
# jinja模板逻辑关系
循环表达式
{% for i in EXPR %}...{% endfor %}
1判断表达式
{% if EXPR %}...{% elif EXPR %}...{% endif %}
1注释
{# COMMENT #}
1
# jinja模板示例
使用
Playbook
推送文件[root@manager playbook]# cat jinja2.yml - hosts: webservers tasks: - name: Copy template File /etc/motd template: src=./motd.j2 dest=/etc/motd
1
2
3
4
5准备
motd.j2
文件[root@manager playbook]# cat motd.j2 Welcome to {{ ansible_hostname }} This system total Memory is: {{ ansible_memtotal_mb }} MB This system free Memory is: {{ ansible_memfree_mb }} MB
1
2
3
4执行
playbook
[root@manager playbook]# ansible-playbook jinja2.yml PLAY [webservers] ******************************************************************** TASK [Copy template File /etc/motd] ************************************************** changed: [10.0.0.13] changed: [10.0.0.12] PLAY RECAP *************************************************************************** 10.0.0.12 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 10.0.0.13 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1
2
3
4
5
6
7
8
9
10检查执行后的状态
[root@manager playbook]# ssh root@10.0.0.12 Welcome to slave-1 This system total Memory is: 972 MB This system free Memory is: 379 MB [root@manager playbook]# ssh root@10.0.0.13 Welcome to slave-2 This system total Memory is: 972 MB This system free Memory is: 379 MB
1
2
3
4
5
6
7
8
9
上面的例子展示了如何使用facts
变量,当playbook
被执行后,ansible_hostname
和ansible_memtotal_mb
将会被替换成被管理主机上搜集的facts
变量的值
# 案例1-Jinja2管理Nginx
ansible
使用jinja2
的for
循环表达式渲染出nginx
负载均衡的配置文件。
使用
Playbook
推送文件[root@manager playbook]# cat proxy.yml - hosts: webservers vars: http_port: 80 server_name: www.bi.com tasks: - name: Copy template Nginx Configure template: src=./blog.conf.j2 dest=/etc/nginx/conf.d/blog.bi.com.conf notify: Reload Nginx Server handlers: - name: Reload Nginx Server service: name=nginx state=reloaded
1
2
3
4
5
6
7
8
9
10
11
12
13
14准备
blog.conf.j2
配置文件[root@manager playbook]# cat blog.conf.j2 upstream ansible_php { {% for i in groups['webservers'] %} server {{i}}:80; {% endfor %} } server { listen 80; server_name ansible.bi.com; location / { proxy_pass http://ansible_php; proxy_set_header Host $http_hosts; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17执行
playbook
[root@manager playbook]# ansible-playbook proxy.yml PLAY [webservers] ******************************************************************** TASK [Copy template Nginx Configure] ************************************************* changed: [10.0.0.12] changed: [10.0.0.13] RUNNING HANDLER [Reload Nginx Server] ************************************************ changed: [10.0.0.13] changed: [10.0.0.12] PLAY RECAP *************************************************************************** 10.0.0.12 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 10.0.0.13 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1
2
3
4
5
6
7
8
9
10
11
12
13
14检查
jinja
模板渲染出来的配置文件[root@slave-1 ~]# cat /etc/nginx/conf.d/blog.bi.com.conf upstream ansible_php { #设置变量,并进行循环赋值,渲染配置 server 10.0.0.12:80; server 10.0.0.13:80; } server { listen 80; server_name ansible.bi.com; location / { proxy_pass http://ansible_php; proxy_set_header Host $http_hosts; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 案例2-Jinja2管理Keepalived
ansible
使用jinja2
的if
判断表达式渲染出keepalived
的Master
和Slave
的配置文件。
使用
playbook
推送keeplaived
配置文件[root@manager playbook]# cat keepalived.yml - hosts: lb tasks: - name: Copy template Keepalived Configure template: src=./keepalived.j2 dest=/etc/keepalived/keepalived.conf notify: Restart Keepalived Server handlers: - name: Restart Keepalived Server service: name=keepalived state=restarted
1
2
3
4
5
6
7
8
9
10准备
keepalived.j2
配置文件[root@manager playbook]# cat keepalived.j2 global_defs { router_id {{ ansible_fqdn }} } vrrp_instance VI_1 { {% if ansible_fqdn == 'lb01' %} #如果主机名为lb01则使用如下配置 state MASTER priority 150 {% elif ansible_fqdn == 'lb02' %} #如果主机名为lb02则使用如下配置 state Backup priority 100 {% endif %} #相同配置 interface eth0 virtual_router_id 51 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.16.1.3 } }
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执行
playbook
[root@manager playbook]# ansible-playbook keepalived.yml PLAY [lb] ******************************************************************** TASK [Copy template Keepalived Configure] ************************************************* changed: [10.0.0.5] changed: [10.0.0.6] RUNNING HANDLER [Reload Keepalived Server] ************************************************ changed: [10.0.0.5] changed: [10.0.0.6] PLAY RECAP *************************************************************************** 10.0.0.5 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 10.0.0.6 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1
2
3
4
5
6
7
8
9
10
11
12
13
14检查
lb01 Master
的keepalived
配置文件[root@lb01 ~]# cat /etc/keepalived/keepalived.conf global_defs { router_id lb01 } vrrp_instance VI_1 { #如果主机名为lb01则使用如下配置 state MASTER priority 150 #相同配置 interface eth0 virtual_router_id 51 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.16.1.3 } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21检查
lb02 Backup
的keepalived
配置文件[root@lb02 ~]# cat /etc/keepalived/keepalived.conf global_defs { router_id lb02 } vrrp_instance VI_1 { #如果主机名为lb02则使用如下配置 state Backup priority 150 #相同配置 interface eth0 virtual_router_id 51 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 172.16.1.3 } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Ansible Roles
# Roles基本概述
使用Roles
组织playbook
才是最好的方式。
Roles
基于一个已知的文件结构,去自动的加载vars
、tasks
以及handlers
以便playbook
更好的调用。
roles
相比playbook
的结构更加的清晰有层次,但roles
显然要比playbook
更加复杂难理解!
比如:我们无论安装什么软件都会安装时间同步服务,那么每个playbook
都要编写时间同步服务的task
。此时我们可以将时间同步服务task
任务编写好,等到需要使用的时候进行调用就行了。
# Roles目录结构
roles
官方目录结构,必须按如下方式定义。在每个目录中必须有main.yml
文件,这些属于强制要求。
[root@manager ~]# cd /etc/ansible/roles
[root@manager roles]# mkdir {nfs,rsync,web}/{vars,tasks,templates,handlers,files,meta} -p
[root@manager roles]# tree
[root@manager roles]# tree
.
├── nfs #角色名称
│ ├── files #存放文件
│ ├── handlers #触发任务
│ ├── meta #依赖关系
│ ├── tasks #具体任务
│ ├── templates #模板文件
│ └── vars #定义变量
2
3
4
5
6
7
8
9
10
11
12
# Roles依赖关系
roles
允许在使用时自动引入其他role
,role
依赖关系存储在meta/main.yml
文件中。- 例如: 安装
wordpress
项目时:- 需要先确保
nginx
与php-fpm
的role
都能正常运行 - 然后在
wordpress
的role
中定义,依赖关系 - 依赖的
role
有nginx
以及php-fpm
- 需要先确保
#wordpress依赖nginx与php-fpm的role [root@manager playbook]# cat /root/roles/wordpress/meta/main.yml dependencies: - { role: nginx } - { role: php-fpm }
1
2
3
4
5- 例如: 安装
wordpress
的role
会先执行nginx、php-fpm
的role
,最后在执行wordpress
本身
# Roles案例实战
- Roles三步走:
- 创建
roles
目录结构,手动创建或使用ansible-galaxy init testroles
- 编写
roles
的功能,也就是tasks
- 最后
playbook
引用roles
编写好的tasks
- 创建
# 案例-Roles部署NFS
目录结构如下
[root@manager roles]# tree /etc/ansible/roles ├── group_vars │ └── all ├── hosts ├── nfs │ ├── files │ ├── handlers │ │ └── main.yml │ ├── meta │ ├── tasks │ │ └── main.yml │ └── templates │ └── exports.j2 └── site.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14定义
roles
主机清单[root@manager roles]# cat /etc/ansible/roles/hosts [nfs] 10.0.0.12
1
2
3查看
nfs
角色的tasks
任务[root@manager roles]# cat /etc/ansible/roles/nfs/tasks/main.yml - name: Installed NFS Server yum: name: nfs-utils state: present - name: Configure NFS Server template: src: exports.j2 dest: /etc/exports notify: Restart NFS Server - name: Init NFS Server file: path: "{{ nfs_share_directory }}" state: directory owner: "{{ user }}" group: "{{ group }}" - name: Systemd NFS Server systemd: name: nfs state: started enabled: yes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24查看
nfs
角色的handlers
[root@manager roles]# cat /etc/ansible/roles/nfs/handlers/main.yml - name: Restart NFS Server systemd: name: nfs state: restarted
1
2
3
4
5查看
nfs
角色的files
目录[root@manager roles]# cat /etc/ansible/roles/nfs/templates/exports.j2 {{ nfs_share_directory }} {{ nfs_share_ip_pool }}(rw,sync,anonuid={{ user_id }},anongid={{ group_id }})
1
2nfs
对应的变量定义[root@manager roles]# cat /etc/ansible/roles/group_vars/all # all user: www group: www # nfs nfs_share_directory: /ansible_data nfs_share_ip_pool: 10.0.0.0/24 user_id: 666 group_id: 666
1
2
3
4
5
6
7
8
9在
playbook
中使用role
,指定nfs
主机组,执行nfs
服务的roles
[root@manager roles]# cat /etc/ansible/roles/site.yml - hosts: nfs roles: - nfs [root@manager roles]# ansible-playbook -i hosts site.yml PLAY [nfs] *************************************************************************** TASK [nfs : Installed NFS Server] **************************************************** ok: [10.0.0.12] TASK [nfs : Configure NFS Server] **************************************************** ok: [10.0.0.12] TASK [nfs : Init NFS Server] ********************************************************* changed: [10.0.0.12] TASK [nfs : Systemd NFS Server] ****************************************************** ok: [10.0.0.12] PLAY RECAP *************************************************************************** 10.0.0.12 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24