一、template模板
二、playbook中的条件判断
三、PlayBook中的循环
四、角色(roles)
一、template模板
template使用了Jinjia2格式作为文件模版,进行文档内变量的替换的模块。它的每次使用都会被ansible标记为”changed”状态。基于模板方式生成一个文件复制到远程主机
常用参数:
1
2
3
4
5
6
7
|
参数名 是否必须 默认值 选项 说明 backup no no yes /no 建立个包括timestamp在内的文件备份,以备不时之需.
dest yes 远程节点上的绝对路径,用于放置template文件。 // 必须是绝对路径
group no 设置远程节点上的的template文件的所属用户组 mode no 设置远程节点上的template文件权限。类似Linux中 chmod 的用法 //group ,owner
owner no 设置远程节点上的template文件所属用户 src yes 本地Jinjia2模版的template文件位置。 // 绝对或者相对路径
|
一般编程语言都有把自己嵌入到文本的模板语言
php:直接嵌入
python:Jinja2 //ansible就是python写的
Jinja2 中常用的编程元素
字面量:字符串,单引号或者双引号引用即可
数字:整数和浮点数
列表:[item1,item2,...]
元祖:(item1,itme2,...) //不可变
字典:{key1:value1,key2:value2,...}
布尔型:true/false
算数运算:
+,-,*,/,%, //,** //:表示只要熵
比较运算:
==,!=,>=,<=,<,
逻辑运算符:
and,or,not
ansible-doc -s template
利用模板:实现对不同主机的nginx配置成不同的启动processor
vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }}; //使用模板变量
listen {{ http_port }}; //自定义变量
注:这个参数是在setup模板中
worker_processes {{ ansible_processor_vcpus-1 }}; //可以直接增加或减去
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf mode=0644
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf owner=bin group=wheel mode="u=rw,g=r,o=r"
vim ansible/hosts
[websrvs]
192.168.4.100 http_port=888
192.168.4.116 http_port=808 //使用主机变量
[root@localhost ~]# cat nginx.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
- hosts: websrvs remote_user: root
tasks:
- name: install nginx
yum: name=nginx state=present
- name: install conf
template : src=nginx.conf.j2 dest=/etc/nginx/nginx.conf mode=0644
notify: restart nginx
tags: instconf
- name: start nginx service
service: name=nginx state=started
handlers:
- name: restart nginx
service: name=nginx state=restarted
|
ansible-playbook --check nginx.yaml
ansible-playbook nginx.yaml
注意:6和7的配置nginx配置文件不一样
执行结果
RUNNING HANDLER [restart nginx]
************************************************
changed: [192.168.4.110] //发生改变的话,就会执行 restart nginx
changed: [192.168.4.106]
handlers:用于当关注的资源发生变化时触发一定的操作。
“notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作
取而代之,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。
二、playbook中的条件判断
多个条件:and/when/or
1.条件测试:tasks上使用when语句,在tasks上使用,Jinja2的语法格式。根据不同的OS分配不同的机制
字符串要加引号{单双都可},数值一定不加引号
ansible all -m setup | grep "ansible_distribution" //版本信息
"ansible_distribution": "CentOS",
"ansible_distribution_major_version": "6",
"ansible_distribution_release": "Final",
"ansible_distribution_version": "6.6",
tasks:
- name: install conf file
template: src=nginx.conf.7
when: ansible_distribution_major_version == '7' 4tasks:
- name: install conf file
template: src=nginx.conf.6
when: ansible_distribution_major_version == '6'
条件测试1: when
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
- hosts: websrvs remote_user: root
tasks:
- name: copy file 6
template: src= /tmp/6 .txt dest= /tmp
when: ansible_distribution_major_version == '6'
notify: restart nginx
- name: copy file 7
template: src= /tmp/7 .txt dest= /tmp
when: ansible_distribution_major_version == '7'
notify: restart nginx
handlers: - name: restart nginx service: name=nginx state=restarted
|
2.register
示例,判断sda6是否存在。存在就执行一些相应的脚本,则可以为该判断注册一个register变量,并用它来判断是否存在,存在返回 succeeded, 失败就是 failed.
1
2
3
4
5
6
7
8
9
10
|
- name: Create a register to represent the status if the /dev/sda6 exsited
shell: df -h | grep sda6
register: dev_sda6_result
ignore_errors: True
tags: docker
- name: Copy docker-thinpool.sh to all hosts copy: src=docker-thinpool.sh dest= /usr/bin/docker-thinpool mode=0755
when: dev_sda6_result | succeeded
tags: docker
|
假如我们想忽略某一错误,通过执行成功与否来做决定,我们可以像这样:
tasks:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|success
- command: /bin/still/something_else
when: result|skipped
三、PlayBook中的循环
循环:迭代,需要重复执行的任务;
例如需要同时安装,nginx,httpd,php-fpm,php-mysql,mariabd等
对迭代项的引用,固定变量名为"item"
而后,要在task中使用with_items给定要迭代的元素列表
列表方法:
字符串:
字典:
1.标准循环:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
- name: install some packages
yum: name={{ item }} state=present
with_items:
- nginx
- memcached
- php-fpm
// 将可以安装多个软件同时安装
循环测试脚本:item [root@localhost ~] # cat e.yaml
- hosts: websrvs remote_user: root
tasks:
- name: install pkgs
yum: name={{ item }} state=present
with_items:
- telnet
- vim
- tree
|
循环测试脚本3.
创建三个用户分别属于不同组
[root@localhost ~]# cat f.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
- hosts: websrvs remote_user: root
tasks:
- name: group add
group: name={{ item }} state=present // 注意:引用的时候使用的是{{ }}没有s,列举参数的时候使用的是复数,items
with_items:
- group11
- group12
- group13
- name: add users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user11' , group: 'group11' }
- { name: 'user12' , group: 'group12' }
- { name: 'user13' , group: 'group13' }
|
==============================
[root@localhost ~]# cat c.yaml
1
2
3
4
5
6
7
8
|
- hosts: testweb remote_user: root
tasks:
- name: install user
user: name={{ item.name }} state=present groups ={{ item. groups }}
with_items:
- { name: 'testuser1' , groups : 'wheel' }
- { name: 'testuser2' , groups : 'root' }
|
//创建testuser1{wheel},testuser2{root}
注意:
1.hosts 不是host
2.严格对齐,列表和内容分开
3.name: 'user11' //中间必须有空格,字符必须用引号,
4.目标主机存在user11或其中一个用户的话,也会返回错误
5.whih_itmes后的内容为下一个key-value (先加空格)
2.嵌套循环:
1
2
3
4
5
6
7
8
9
10
11
|
-name:give users access to multiple databases
mysql_user:name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs= yes password=foo
with_nested:
-[ 'alice' , 'bob' ] // 表示item[0],nested:嵌套
-[ 'clientdb' , 'employeedb' , 'providerdb' ]
- name: here, 'users' contains the above list of employees
mysql_user: name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs= yes password=foo
with_nested:
- "{{users}}"
- [ 'clientdb' , 'employeedb' , 'providerdb' ]
|
[root@localhost ~]# cat c.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
- hosts: testweb remote_user: root
tasks:
- name: install user
user: name={{ item.name }} state=present groups ={{ item. groups }}
with_items:
- { name: 'testuser1' , groups : 'wheel' }
- { name: 'testuser2' , groups : 'root' }
- name: give users access to multiple databases
command : "echo name={{ item[0] }} priv={{ item[1] }} test={{ item[2] }}"
with_nested:
- [ 'alice' , 'bob' ]
- [ 'clientdb' , 'employeedb' , 'providerdb' ]
- [ '1' , '2' , ]
tags: netsted
|
输出:
1
2
3
4
5
6
7
8
9
10
11
12
|
skipping: [192.168.2.122] => (item=[u 'alice' , u 'clientdb' , u '1' ])
skipping: [192.168.2.122] => (item=[u 'alice' , u 'clientdb' , u '2' ])
skipping: [192.168.2.122] => (item=[u 'alice' , u 'employeedb' , u '1' ])
skipping: [192.168.2.122] => (item=[u 'alice' , u 'employeedb' , u '2' ])
skipping: [192.168.2.122] => (item=[u 'alice' , u 'providerdb' , u '1' ])
skipping: [192.168.2.122] => (item=[u 'alice' , u 'providerdb' , u '2' ])
skipping: [192.168.2.122] => (item=[u 'bob' , u 'clientdb' , u '1' ])
skipping: [192.168.2.122] => (item=[u 'bob' , u 'clientdb' , u '2' ])
skipping: [192.168.2.122] => (item=[u 'bob' , u 'employeedb' , u '1' ])
skipping: [192.168.2.122] => (item=[u 'bob' , u 'employeedb' , u '2' ])
skipping: [192.168.2.122] => (item=[u 'bob' , u 'providerdb' , u '1' ])
skipping: [192.168.2.122] => (item=[u 'bob' , u 'providerdb' , u '2' ])
|
3.字典循环
假如你有以下变量:
users:
alice:
name: Alice Appleworth
telephone: 123-456-7890
bob:
name: Bob Bananarama
telephone: 987-654-3210
你想打印出每个用户的名称和电话号码.你可以使用 with_dict 来循环哈希表中的元素:
tasks:
- name: Print phone records
debug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
with_dict: "{{users}}"
4.遍历文件whith_file,whith_fileglob
with_file 是将每个文件的文件内容作为item的值
1
2
3
4
5
6
7
8
|
- hosts: all tasks:
# first ensure our target directory exists
- file : dest= /etc/fooapp state=directory
# copy each file over that matches the given pattern //注意copy必须要用 “-”
- copy: src={{ item }} dest= /etc/fooapp/ owner=root mode=600
with_fileglob:
- /playbooks/files/fooapp/ *
|
with_fileglob 是将每个文件的全路径作为item的值, 在文件目录下是非递归的, 如果是在role里面应用改循环, 默认路径是roles/role_name/files_directory
5.并行数据循环
已知变量:
alpha: [ 'a', 'b', 'c', 'd' ]
numbers: [ 1, 2, 3, 4 ]
如果你想得到’(a, 1)’和’(b, 2)’之类的集合.可以使用’with_together’:
tasks:
- debug: msg="{{ item.0 }} and {{ item.1 }}"
with_together:
- "{{alpha}}"
- "{{numbers}}"
还有更多的循环介绍方法请参考本文尾部链接地址...
四、角色:(roles)
一个主机可以担任多种角色:
定义为多个身份,用的时候直接调用该身份即可
角色名就是目录名,任何角色都不能引用自己所属目录之外的其他目录文件
roles/
mysql/
httpd/
nginx/
memcached/
每个角色,以特定的层级目录结构进行组织: 注意:大多数都是复数"s",除了meta
mysql/
files/ 存放由copy或script模块等调用的文件
templates/ template模块查找所需要的模板文件目录;
handlers/ 至少应该包含一个名为main.yml文件
vars/ 至少一个main.yml
tasks/ 基本元素:至少一个名为main.yml的文件,其他的文件需要在此文件中通过include进行包含
meta/ main.yml,定义当前角色的特殊设定,及其依赖关系
default/ 设定默认变量时使用此目录中的main.yml文件
调用角色:
- hosts: websrvs
remote_user: root
roles:
- mysql //会自动到mysql目录中跑一遍
- memcached
- nginx
mkdir /etc/ansible/roles/nginx/{files,tasks,templates,handlers,vars,default,meta} -pv
cd /etc/ansible/roles/nginx/
1.tasks
[root@localhost nginx]# cat tasks/main.yml
1
2
3
4
5
6
|
- name: install nginx pkg
yum: name=nginx state=present
- name: install conf file
template: src=nginx.conf dest= /etc/nginx/nginx .conf. test ///nginx .conf不在同级目录,但是role可以直接识别为template中的文件
- name: start nginx service: name=nginx state=started enabled= true
|
templates 目录中有存放的nginx.conf
2.在其他地方创建nginx.yaml //这个可以放在其他地方
1
2
3
4
|
- hosts: websrvs remote_user: root
roles:
- nginx
|
执行:
ansible-playbook --check nginx.yaml
1
2
3
4
5
6
7
8
9
10
|
/etc/ansible/roles/nginx/ ├── default ├── files ├── handlers ├── meta ├── tasks │ └── main.yml ├── templates │ └── nginx.conf └── vars |
3.添加handler
修改handlers/main.yml
- name: restart nginx //注意,前面的 - 不可少,代表是handler的一个清单
service: name=nginx state=restarted
创建tasks/main.yml
1
2
3
4
5
6
7
8
|
- name: install nginx pkg
yum: name=nginx state=present
- name: install conf file
template: src=nginx.conf dest= /etc/nginx/nginx .conf. test
notify: restart nginx
tags: instconf
- name: start nginx service: name=nginx state=started enabled= true
|
修改一下nginx.conf //否则不会触发handler
ansible-playbook -t instconf --check g.yaml
4.变量
[root@localhost yaml]# cat h.yaml
1
2
3
4
5
6
7
8
9
10
|
- hosts: websrvs remote_user: root
vars:
- username: testuser1
- groupname: testgroup1
tasks:
- name: create group
group: name={{ groupname }} state=present
- name: create user
user: name={{ username }} group={{ groupname }} state=present
|
在playbook中定义变量的方法
vars:
- var1: value1
- var2: value2
ansible-playbook -e "groupname=mygrp1" -e "username=myuser" --check h.yaml
//可以覆盖变量,在命令行中定义的变量,会覆盖
5.变量使用,roles中
vim nginx/vars/main.yml
username: nginx
vim templates/nginx.conf
user {{ username }} //让nginx以该用户的身份运行
其他不修改
ansible
问题:
[root@localhost yaml]# ansible-playbook --check g.yaml
ERROR! The vars/main.yml file for role 'nginx' must contain a dictio
nary of variables
原因:vars/main.yml 前面不需要 - ,和其他的main.yml不一样
ansible-playbook -e "username=adm" --check nginx.yml //假如想改变运行nginx的用户,直接修改即可
6.在playbook中调用角色方法2
vim nginx.yaml
- hosts: websrvs
remote_user: root
roles:
- {role: nginx, username: nginx} //向该角色传递变量
键role用于指定角色名称,后续的k/v用于传递变量给角色
还可以基于条件测试,实现角色调用;
例如:
roles:
- {role: nginx,when: "ansible_distribution_major_version == '7' }
//条件满足时,应用该角色
[root@localhost yaml]# cat i.yaml
- hosts: websrvs
remote_user: root
roles:
- { role: nginx, username: nginx, when: "ansible_distribution_major_version == '7'" }
//只有在OS为7才会执行
7.安装memcached,占用内从空间为当前可用空间的1/3
mkdir -pv memcached/{tasks,vars,templates,hanlers}
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
|
vim tasks /main .yml
- name: install pack
yum: name=memcached state=present
- name: install conf
template: src=memcached.j2 dest= /etc/sysconfig/memcached
notify: restart memcached
tags: memconf
- name: start memcached service: name=memcached state=started enabled= true
vim templates /memcached
PORT= "11211"
USER= "memcached"
MAXCONN= "1024"
CACHESIZE= "{{ ansible_memtotal_mb//4 }}" // 除以4,可能是小数,因此 // 取出整数
OPTIONS= ""
vim handlers /main .yml
- name: restart memcached service: name=memcached state=restarted
vim lnm.yaml // 同时调用两个role
- hosts: websrvs remote_user: root
- roles:
- { role: nginx, when: ansible_distribution_version == '7' }
- { role: memcached, when: ansible_hostname == 'memcached' }
|
ansible-playbook -t memconf lnm.yaml
出错原因:
1.main.yml中,template是没有s的,但是目录名是有s的
2.notify不是nofify
=======================================================
yaml和yml格式的区别:
1.yml不需要hosts,remote_user //这些在yaml中定义
- name: install pkgs
yum: name=memcached state=present
2.yaml一定要-hosts,-remote_user
- hosts: all
remote_user: root
roles:
- { role: nginx,when:ansible_distribution_version == '7' }
ansible all -m setup //查看所有内置变量
www.ansible.com.cn //站点,
推荐:参考ansible官方role的写法,自行创建role进行练习
http://blog.youkuaiyun.com/kellyseeme/article/details/50619562
http://www.ansible.com.cn/docs/playbooks_loops.html
https://www.cnblogs.com/v394435982/p/5593274.html
本文转自MT_IT51CTO博客,原文链接:http://blog.51cto.com/hmtk520/2058293,如需转载请自行联系原作者