setup模块常用自带变量:
匹配完整主机名变量
ansible_hostname <主机名变量>
ansible_distribution_major_version <版本号变量>
ansible_all_ipv4_addresses
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量来源:
1 ansible setup facts 远程主机的所有变量都可直接调用
2 在/etc/ansible/hosts中定义
普通变量:主机组中主机单独定义,优先级高于公共变量
公共(组)变量:针对主机组中所有主机定义统一变量
3 通过命令行指定变量,优先级最高
ansible-playbook –e varname=value
4 在playbook中定义
vars:
- var1: value1
- var2: value2
5 在role中定义
变量命名:
变量名仅能由字母、数字和下划线组成,且只能以字母开头
变量定义:key=value
示例:http_port=80
变量调用方式:
1)通过{{ variable_name }} 调用变量,且变量名前后必须有 空格,有时用“{{ variable_name }}”才生效
2)ansible-playbook –e 选项指定
示例:
ansible-playbook test.yml -e "hosts=www user=mageedu"
在palybook里面使用变量能让playboot更加灵活
(一):在playbook里定义变量
看下面的例子:
---
- hosts: web
remote_user: root
tasks:
- name: remove package
yum: name={{ pkname }} state=absent
- name: initall package
yum: name={{ pkname }}
- name: start service
service: name={{ pkname }} state=started
[root@ansiblehost ansible.yaml]#ansible-playbook -e "pkname=httpd " install.ym
上面这个playbook分为三步,
第一步:卸包,
第二步:装包,
第三步:重启服务
"但是注意到没有,而这三步我用的是一个变量,也就是我只要在命令行定义一个变量就可以完成这三个动作"
但是这个还是需要自己手工制定变量,
(二):将变量名与变量名内容直接定义到playboot里
看下面的例子:
---
- hosts: web
remote_user: root
"#vars是专门用于在playboot定义变量的关键词"
vars:
"#username,gropname就是变量名冒号":"后面的就是变量内容"
- username: user1
- groupname: root
tasks:
#任务一创建组
- name: create group
group: name={{ groupname }}
"#创建用户并把该用户加入上面创建的组里面,再创键家目录到/app下"
- name: create user
user: name={{ username }} group={{ groupname }} home=/app/{{ username }}
执行playbook的方法:"而这时候调用playboot就不需要用-e指定变量内容了"
[root@ansiblehost 16:15:27 ansible.yaml]#"ansible-playbook useradd.yml"
PLAY [web] *************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************
ok: [192.168.136.5]
ok: [192.168.136.6]
TASK [create group] ****************************************************************************************************************************
ok: [192.168.136.6]
ok: [192.168.136.5]
TASK [create user] *****************************************************************************************************************************
ok: [192.168.136.6]
changed: [192.168.136.5]
PLAY RECAP *************************************************************************************************************************************
192.168.136.5 : ok=3 changed=1 unreachable=0 failed=0
192.168.136.6 : ok=3 changed=0 unreachable=0 failed=0
(三):使用setup中自带的变量
看下面的例子:
---
- hosts: web
remote_user: root
tasks:
- name: create file
file: name=/app/{{ ansible_hostname }}.txt state=touch
[root@ansiblehost 16:27:44 ansible.yaml]#ansible web -a 'ls -l /app/'
192.168.136.5 | SUCCESS | rc=0 >>
total 0
-rw-r--r-- 1 root root 0 Jan 18 16:26 "localhost.txt" #利用变量创建的变量
drwxr-xr-x 2 user1 root 62 Jan 18 07:05 user1
192.168.136.6 | SUCCESS | rc=0 >>
total 4
-rw-r--r-- 1 root root 0 Jan 14 09:40 "centos6-102.txt" #利用变量创建出的文件
-rw-r--r-- 1 root root 0 Jan 14 01:49 testsrv
drwx------ 4 user1 root 4096 Jan 14 09:15 user1
playbook中使用的变量ansible_hostname就是setpu模块中过滤出来的变量,这种方法让我们可以不用定义变量,直接所使用setup模块里自带的变量。
(四):/etc/ansible/hosts主机清单配置文件中定义变量
1)定义普通变量;普通变量就是对每一个主机单独定义一个变量只能这个主机使用
请看下面的例子:
[web]
192.168.136.6 hostname="httpd"
这个可以在命令行调用
#这个例子就是利用在主机清单中定义的变量修改主机名
[root@ansiblehost 17:06:29 ansible.yaml]#ansible 192.168.136.6 -m hostname -a 'name={{ hostname }}'
192.168.136.6 | SUCCESS => {
"ansible_facts": {
"ansible_domain": "magedu.com",
"ansible_fqdn": "centos6-102.magedu.com",
"ansible_hostname": "httpd",
"ansible_nodename": "httpd"
},
"changed": true,
"name": "httpd"
}
2)在/etc/ansible/hosts文件中定义公共变量;公共变量就是一个主机组定义一个共有的变量
看下面的例子:
[web]
192.168.136.6
192.168.136.5
"#中括号里的【web】表示上面的web组,重点是冒号后面的vars加上这个关键次就表示对上面的web组创建共有变量。变量可以有多个"
[web:vars]
hostname=websrvs
port=80
利用变量更改主机名:
[root@ansiblehost 17:24:39 ansible.yaml]#ansible web -m hostname -C -a 'name="{{ hostname }}-{{ port }}"'
192.168.136.6 | SUCCESS => {
"ansible_facts": {
"ansible_domain": "",
"ansible_fqdn": "httpd",
"ansible_hostname": "websrvs-80",
"ansible_nodename": "websrvs-80"
},
"changed": true,
"name": "websrvs-80"
}
192.168.136.5 | SUCCESS => {
"ansible_facts": {
"ansible_domain": "localdomain",
"ansible_fqdn": "localhost.localdomain",
"ansible_hostname": "websrvs-80",
"ansible_nodename": "websrvs-80"
},
"changed": true,
"name": "websrvs-80"
}
4)在playbook里面调用在/etc/ansible/hosts文件中定义的变量
看下面的例子:
[web]
192.168.136.6
192.168.136.5
[web:vars]
host=websrvs
port=8080
---
- hosts: web
remote_user: root
tasks:
- name: set hostname
hostname: name={{ host }}-{{ port }}
5),在一个单独的文件存放playbok变量与值
创建一个文件:
touch var.txt
vim var.txt
文件格式:
var1: xiaoming
var2: xiaohang
6)在playbook调用文件var.txt里的变量
#变量文件内容
var1: xiaoming
var2: httpd
playboot内容
---
- hosts: web
remote_user: root
vars_files:
- var.yml
tasks:
- name: create user
user: name={{ var1 }} shell=/bin/bash home=/app/{{ var1 }}
- name: create file
file: name=/app/{{ var2 }}.txt state=touch mode=644 owner=wang
#最后命令执行结果
1)创建用户结果
[root@ansiblehost 19:10:36 ansible.yaml]#ansible web -a 'tail -n1 /etc/passwd'
192.168.136.6 | SUCCESS | rc=0 >>
xiaoming2:x:503:503::/app/xiaoming:/bin/bash
192.168.136.5 | SUCCESS | rc=0 >>
xiaoming2:x:1002:1002::/app/xiaoming:/bin/bash
2)创建文件的结果
[root@ansiblehost 18:45:55 ansible.yaml]#ansible web -a 'ls -l /app'
192.168.136.5 | SUCCESS | rc=0 >>
total 0
-rw------- 1 root root 0 Jan 18 18:45 httpd.txt
drwxr-xr-x 2 xiaoming xiaoming 62 Jan 18 07:05 xiaoming
192.168.136.6 | SUCCESS | rc=0 >>
total 4
-rw------- 1 root root 0 Jan 14 11:59 httpd.txt
drwxr-xr-x 4 xiaoming xiaoming 4096 Dec 17 17:40 xiaoming
template模板模块
1)文本文件,嵌套有脚本(使用模板编程语言编写) 2)Jinja2语言,使用字面量,有下面形式
①:字符串:使用单引号或双引号
②:数字:整数,浮点数
③:列表:[item1, item2, ...]
④:元组:(item1, item2, ...)
⑤:字典:{key1:value1, key2:value2, ...} ⑥:布尔型:true/false
3)算术运算:+, -, *, /, //<整除>, %, **<次方>
4)比较操作:==, !=, >, >=, <, <=
5)逻辑运算:and, or, not
6)流表达式:For If When
功能:
templates功能:根据模块文件动态生成对应的配置文件
templates文件必须存放于templates目录下,且命名为 .j2 结尾
yaml/yml 文件需和templates目录平级,目录结构如下:
./
├── temnginx.yml #调用temnginx模块的文件必须跟真正存放模板的文件属于平级关系
└── templates
└── nginx.conf.j2 #模板文件
使用templates模块功能需要创建一个目录名为templates,然后在这个目录下存放模板文件,而文件名推荐改下后缀<.j2>
示例:利用templates同步nginx配置文件
1)准备templates/nginx.conf.j2文件
2)编辑playbook文件
vim temnginx.yml
---
- hosts: web
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
#调用template模块,src表示本机的template目录下的某一个文件 ,dest表示远程被控主机的存放路径,做用类似copy模块,但是template模板文件里可以支持变量以及算数运算
"- name: templates
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf"
- name: start nginx
service: name=nginx state=started
这个例子作用就是:
第一步:在远程被控主机安装nginx
第二步:将本机template模板文件复制到远程被控主机上
第三步:启动nginx服务
可能有时候我们需要判断某一个版本,在复制某一个文件到对应的机器上,这时候可以加上when这个关键词,就可以帮我们来解决这个问题,
"when关键字的用法,作用类似一判断当满足某一个条件时就执行这个动作"
看下面的例子
[root@ansiblehost 19:36:47 ansible.yaml]#ls templates/
nginx-6.conf.j2 nginx-7.conf.j2
[root@ansiblehost 19:36:54 ansible.yaml]#cat temnginx.yml
---
- hosts: web
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
- name: templates 6
template: src=nginx-6.conf.j2 dest=/etc/nginx/nginx.conf
#这是setup模块里的一个存放主版本的变量"ansible_distribution_major_version" 而"=="就表示判断的意思,作用就是判断如果主版本号是否等于6
when: ansible_distribution_major_version=="6"
- name: templates 7
template: src=nginx-7.conf.j2 dest=/etc/nginx/nginx.conf
#同上面的when作用相同
when: ansible_distribution_major_version=="7"
- name: start nginx
service: name=nginx state=started
上面这个例子:作用是在web这个主机组里面的所有主机上都安装nginx服务,并把判断如果系统是centos6是复制本机上的6的nginx配置文件,同时7也是一样,然后在启动nginx服务
迭代 with_item
迭代的作用就类似与shell里的for循环的作用,with_item会把它里面定义的所有值,每次都传递一个给item这个特殊的变量里面,而with_item理由几个值item就循环几次知道没有才会停止
请看下面的例子
[root@ansiblehost 19:44:12 ansible.yaml]#cat user_with_items.yml
---
- hosts: web
remote_user: root
tasks:
- name: add several users
#item特殊变量代表的就是with_items里面的每一个值
user: name={{ "item" }} group=root
#with_items下面的所有值都属于被循环的值
"with_items":
- xiaohong
- xiaolan
执行结果:
[root@ansiblehost 19:43:59 ansible.yaml]#ansible web -a 'tail -n2 /etc/passwd'
192.168.136.6 | SUCCESS | rc=0 >>
xiaohong:x:504:0::/home/xiaohong:/bin/bash
xiaolan:x:505:0::/home/xiaolan:/bin/bash
192.168.136.5 | SUCCESS | rc=0 >>
xiaohong:x:1003:0::/home/xiaohong:/bin/bash
xiaolan:x:1004:0::/home/xiaolan:/bin/bash
上面的例子作用就是创建两个普通用户,但是使用with_items关键词来完成的
迭代嵌套子变量
看下面的例子:
[root@ansiblehost 20:34:28 ansible.yaml]#cat user_with_items.yml
---
- hosts: web
remote_user: root
tasks:
- name: add group
group: name={{ item }}
with_items:
- group1
- group2
- group3
- name: add users
#item.name <.>后面的name以及group都属于item的自变量
user: name={{ item.name }} group={{ item.group }}
#这个写法,迭代里面嵌套了另外的子变量(name)(group)
with_items:
- { name: 'laifu3',group: group1 }
- { name: 'laifu2',group: group2 }
- { name: 'laifu3',group: group3 }
[root@ansiblehost 20:38:10 ansible.yaml]#ansible web -m shell -a 'id laifu3'
192.168.136.6 | SUCCESS | rc=0 >>
uid=506(laifu3) gid=506(group3) groups=506(group3)
192.168.136.5 | SUCCESS | rc=0 >>
uid=1005(laifu3) gid=1005(group3) groups=1005(group3)
[root@ansiblehost 20:34:01 ansible.yaml]#ansible web -a 'tail -n3 /etc/group'
192.168.136.6 | SUCCESS | rc=0 >>
group1:x:504:
group2:x:505:
group3:x:506:
192.168.136.5 | SUCCESS | rc=0 >>
group1:x:1003:
group2:x:1004:
group3:x:1005:
这个playbook作用就是创建组,再创键新用户,然后再把用户加到创建好的组里面去
playbook中使用template模板文件的for循环 if判断
例子一:for循环
模板文件
[root@ansiblehost 09:26:20 ansible.yaml]#cat templates/for1.conf.j2
"#for循环的列表ports来自下面的文件中定义的vaes变量中的ports变量的值。而每一次循环都会把ports里的值赋给port这个 变量,因为ports只有3个值所以只会循环3三遍"
语法要求:
开头:双{%里面的格式与shell里的格式基本相同%}
中间:循环内容
结尾:双{%endfor%}
{%for port in ports%}
server {
listen {{ port }}
}
{%endfor%}
playbook文件
[root@ansiblehost 09:26:31 ansible.yaml]#cat for.yml
---
- hosts: web
remote_user: root
vars:
ports:
- 81
- 82
- 83
tasks:
- name: tesk for
template: src=for1.conf.j2 dest=/app/for1.conf
执行结果:
[root@ansiblehost 09:25:48 ansible.yaml]#ansible web -a 'cat /app/for1.conf'
192.168.136.6 | SUCCESS | rc=0 >>
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
192.168.136.5 | SUCCESS | rc=0 >>
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
例子二:for循环嵌套子变量
template模板文件
[root@ansiblehost 09:51:47 ansible.yaml]#cat templates/for2.conf.j2
{%for port in ports%}
server {
listen {{ port.listen_port }}
}
{%endfor%}
playbook文件
[root@ansiblehost 09:52:07 ansible.yaml]#cat for2.yml
---
- hosts: web
remote_user: root
vars:
ports:
- listen_port: 81
- listen_port: 82
- listen_port: 83
tasks:
- name: tesk for
template: src=for2.conf.j2 dest=/app/for2.conf
执行结果:
[root@ansiblehost 09:51:11 ansible.yaml]#ansible web -a 'cat /app/for2.conf'
192.168.136.6 | SUCCESS | rc=0 >>
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
192.168.136.5 | SUCCESS | rc=0 >>
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
例子三:for循环嵌套多个元素
template模板文件
[root@ansiblehost 10:13:41 ansible.yaml]#cat templates/for3.conf.j2
{%for vhost in vhosts%}
server {
port {{ vhost.port }}
webserver {{ vhost.name }}
webdir {{ vhost.root }}
}
{%endfor%}
playbook文件
[root@ansiblehost 10:13:43 ansible.yaml]#cat for3.yml
---
- hosts: web
remote_user: root
vars:
vhosts:
- web1:
port: 81
name: web1.magedu.com
root: /app/webroot1
- web2:
port: 82
name: web1.magedu.com
root: /app/webroot2
- web3:
port: 83
name: web1.magedu.com
root: /app/webroot3
tasks:
- name: tesk for
template: src=for3.conf.j2 dest=/app/for3.conf
执行结果
[root@ansiblehost 10:12:15 ansible.yaml]#ansible web -a 'cat /app/for3.conf'
192.168.136.6 | SUCCESS | rc=0 >>
server {
port 81
webserver web1.magedu.com
webdir /app/webroot1
}
server {
port 82
webserver web1.magedu.com
webdir /app/webroot2
}
server {
port 83
webserver web1.magedu.com
webdir /app/webroot3
}
192.168.136.5 | SUCCESS | rc=0 >>
server {
port 81
webserver web1.magedu.com
webdir /app/webroot1
}
server {
port 82
webserver web1.magedu.com
webdir /app/webroot2
}
server {
port 83
webserver web1.magedu.com
webdir /app/webroot3
}
例子四:for循环嵌套if判断
template模板文件
[root@ansiblehost 10:23:29 ansible.yaml]#cat templates/for4.conf.j2
{%for vhost in vhosts%}
server {
port {{ vhost.port }}
#判断循环列表中变量"vhost.name"是否定义,如果定义了就把它的值复制到目标主机,
"语法要求:
开头:{%前面可以任意变量,后面必须写"is defined关键词"%}
中间:执行的任务
结尾:{%endif%}"
"{%if vhost.name is defined %}"
webserver {{ vhost.name }}
"{%endif%}"
webdir {{ vhost.root }}
}
{%endfor%}
playbook文件
[root@ansiblehost 10:23:50 ansible.yaml]#cat for4.yml
- hosts: web
remote_user: root
vars:
vhosts:
- web1:
port: 81
root: /app/webroot1
- web2:
port: 82
name: web1.magedu.com
root: /app/webroot2
- web3:
port: 83
root: /app/webroot3
tasks:
- name: tesk for
template: src=for4.conf.j2 dest=/app/for4.conf
执行结果:
[root@ansiblehost 10:23:04 ansible.yaml]#ansible web -a 'cat /app/for4.conf'
192.168.136.6 | SUCCESS | rc=0 >>
server {
port 81
webdir /app/webroot1
}
server {
port 82
webserver web1.magedu.com
webdir /app/webroot2
}
server {
port 83
webdir /app/webroot3
}
192.168.136.5 | SUCCESS | rc=0 >>
server {
port 81
webdir /app/webroot1
}
server {
port 82
webserver web1.magedu.com
webdir /app/webroot2
}
server {
port 83
webdir /app/webroot3
}
```