|
一、template模板
二、playbook中的条件判断
三、PlayBook中的循环
四、角色(roles)
一、template模板
template使用了Jinjia2格式作为文件模版,进行文档内变量的替换的模块。它的每次使用都会被ansible标记为”changed”状态。基于模板方式生成一个文件复制到远程主机
常用参数:
参数名 是否必须 默认值 选项 说明
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
- 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
- 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.
- 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.标准循环:
- 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
- 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
- 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.嵌套循环:
-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
- 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
输出:
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的值
- 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
- 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 //这个可以放在其他地方
- hosts: websrvs
remote_user: root
roles:
- nginx
执行:
ansible-playbook --check nginx.yaml
/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
- 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
- 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}
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.csdn.net/kellyseeme/article/details/50619562
http://www.ansible.com.cn/docs/playbooks_loops.html
https://www.cnblogs.com/v394435982/p/5593274.html |
|