目录
Playbook
Playbook 与 Ad-Hoc 对比
YAML 语言特性
YAML语法简介
支持的数据类型
写法格式
1 scalar 标量 建议缩进两个空格,可多
2 Dictionary 字典
3 List 列表
三种常见的数据格式
Playbook 核心组件 不要用 tab 可以#注释
hosts
remote_user 组件 指定账户默认root
nginx安装 #默认会去files文件里找 把文件放里面不用加前面的
性能优化
方法1
方法2
register 注册变量
在主机清单中定义主机和主机组的变量
变量的优先级从高到低如下
Template 模板
jinja2语言
template 专门存放模板文件
template中使用流程控制 for 和 if
for 循环
if 条件判断
使用循环迭代
迭代 loop (with_items)
until 循环
with_lines 逐行处理
条件判断 when
分组 block
关闭 changed 状态
利用 changed_when 检查task返回结果
滚动执行
委派至其它主机执行
只执行一次
环境变量
Yaml 文件的相互调用
import_playbook 由一个yml统一调用
Roles 角色
roles目录结构:
Roles各目录作用
YAML 支持以下常用几种数据类型:
key对应value
name: wang
age: 18
使用缩进的方式
name:
wang
age:
18
格式
格式
使用缩进方式
account:
name: wang
age: 18
gender: male
范例:
#不同行
# An employee record
name: Example Developer
job: Developer
skill: Elite(社会精英)
#同一行,也可以将key:value放置于{}中进行表示,用,分隔多个key:value
# An employee record
{name: "Example Developer", job: "Developer", skill: "Elite"}
列表由多个元素组成, 本质就是数组
每个元素放在不同行,每个元素一行,且元素前均使用中横线 - 开头,并且中横线 - 和元素之间有一个空
格
也可以将所有元素用 [ ] 括起来放在同一行,每个元素之间用逗号分隔
格式
course: [ linux , golang , python ]
也可以写成以 - 开头的多行
course:
- linux
- golang
- python
元素里也可以包含字典
course:
- linux: manjaro
price: 10000
- golang: gin
class: 49
- python: django
范例:
#不同行,行以-开头,后面有一个空格
# A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
#同一行
[Apple,Orange,Strawberry,Mango]
范例:YAML 表示一个家庭
name: John Smith
age: 41
gender: Male
spouse: { name: Jane Smith, age: 37, gender: Female } # 写在一行里
name: Jane Smith #也可以写成多行
age: 37
gender: Femalechildren: [ {name: Jimmy Smith,age: 17, gender: Male}, {name: Jenny Smith, age:
13, gender: Female}, {name: hao Smith, age: 20, gender: Male } ] #写在一行
- name: Jimmy Smith #写在多行,更为推荐的写法
age: 17
gender: Male
- {name: Jenny Smith, age: 13, gender: Female}
- {name: hao Smith, age: 20, gender: Male }
可以用工具互相转换,参考网站: JSON在线解析及格式化验证 - JSON.cn
#vim /etc/ansible/hosts
[webservers] #最下面 在vim里 按G 跳到最下面
10.0.0.8
10.0.0.18
[dbservers]
10.0.0.18
10.0.0.[101:102]
一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:
--syntax,--syntax-check #语法检查,功能相当于bash -n
-C --check #模拟执行dry run ,只检测可能会发生的改变,但不真正执行操作
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行
ansible-playbook --limit 10.0.0.8 nginx.yaml
-i INVENTORY, --inventory INVENTORY #指定主机清单文件,通常一个项对应一个主机清单文件
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK为任务的
name
-v -vv -vvv #显示过程
vim hello.yaml
--- 不强制写
# 第一个Playbook 文件
- hosts: webservers #针对的主机 可多个
tasks: #针对的任务
- name: test ping #这个任务做什么的 可汉字
ping: #有参数可以写 没有就这样
- name: shell pwd #做什么
shell: 'hostname -I' #命令及参数
ansible-playbook -C hello.yaml #模拟执行检查
ansible-playbook --syntax-check hello.yaml #语法检查
[root@ubuntu2004 ~]#ansible-playbook -vv hello.yaml #-v查看信息 最多4个 可以不加
组件 Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用 于指定要执行指定任务的主机,须事先定义在主机清单中
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
webservers:dbservers #或者,两个组的并集
webservers:&dbservers #与,两个组的交集
webservers:!dbservers #在webservers组,但不在dbservers组
案例
- hosts: webservers:appservers
remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可 用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: wange
sudo: yes #默认sudo为root
sudo_user:wang #将wange用户sudo为wang
---
# nginx
- hosts: 10.0.0.8
remote_user: root
tasks:
- name: 安装
yum:
name: nginx
state: present
- name: 复制
copy:
src: /data/nginx.conf #默认会去files文件里找 把文件放里面不用加前面的
dest: /etc/nginx/nginx.conf 也是
- name: 页面
copy:
src: /data/index.html
dest: /usr/share/nginx/html/index.html
- name: 启动
service:
name: nginx
state:
started
enabled: yes
大家肯定疑问,这个facts是个啥?
facts组件是Ansible用于采集被管理机器设备信息的一个功能,采集的机器设备信息主要包含IP地址,操作系统,以太网设备,mac 地址,时间/日期相关数据,硬件信息等。
那话又说回来了,采集这些信息有什么用呢?有的时候我们需要根据远程主机的信息作为执行条件操作,例如,根据远程服务器使用的操作系统版本,可以安装不同版本的软件包;或者也可以显示与每台远程计算机相关的一些信息,例如每台设备上有多少RAM可用。
所以,在一些业务场景中,facts对我们是很有帮助的,省去了我们好多工作,大大提高了工作效率。
性能优化
每次执行playbook,默认会收集每个主机的所有facts变量,将会导致速度很慢,可以采用下面方法加速
方法1
关闭facts采集加速执行,此方法将导致无法使用facts变量
- hosts: all
gather_facts: no
方法2
当使用 gather_facts: no 关闭 facts,确实能加速 Ansible 执行,但是有时候又需要使用 facts 中的内容,还希望执行的速度快,这时候可以设置facts 的缓存,将facts变量信息存在redis服务器中
[root@ansible ~]# cat /etc/ansible/ansible.cfg
[defaults]
# smart 表示默认收集 facts,但 facts 已有的情况下不会收集,即使用缓存 facts
# implicit 表示默认收集 facts,要禁止收集,必须使用 gather_facts: False
# explicit 则表示默认不收集,要显式收集,必须使用gather_facts: Truegathering = smart #在使用 facts 缓存时设置为smart
fact_caching_timeout = 86400 #缓存时长
fact_caching = redis #缓存存在redis中
fact_caching_connection = 10.0.0.100:6379:0 #0表示redis的0号数据库
#若redis设置了密码
fact_caching_connection = 10.0.0.100:6379:0:password
在playbook执行的过程中,难免会遇到一些错误。由于playbook遇到错误后,不会执行之后的任务,不便于调试,此时,可以使用ignore_errors来暂时忽略错误,使得playbook继续执行。
ignore_errors: yes #执行忽略上面错误 True 一样
在playbook中可以使用register将捕获命令的输出保存在临时变量中,方便后续调用此变量,比如可以使用debug模块进行显示输出
[root@centos8 ~]#cat register1.yml
- hosts: dbservers
tasks:
- name: get variable
shell: hostname
register: name
- name: "print variable"
debug:
msg: "{{ name }}" #输出register注册的name变量的全部信息,注意
变量要加" "引起来
#msg: "{{ name.cmd }}" #显示命令
#msg: "{{ name.rc }}" #显示命令成功与否
#msg: "{{ name.stdout }}" #显示命令的输出结果为字符串形式,所有结果都放
在一行里显示,适合于结果是单行输出
#msg: "{{ name.stdout_lines }}" #显示命令的输出结果为列表形式,逐行标准输出,适
用于多行显示
#msg: "{{ name['stdout_lines'] }}" #显示命令的执行结果为列表形式,和效果上面相同
#msg: "{{ name.stdout_lines[0] }}" #显示命令的输出结果的列表中的第一个元素
#说明
第一个 task 中,使用了 register 注册变量名为 name ;当 shell 模块执行完毕后,会将数据放到该
变量中。
第二给 task 中,使用了 debug 模块,并从变量name中获取数据。
[root@centos8 ~]#ansible-playbook register1.yml
- hosts: webservers
tasks:
- name: get variable
shell: hostname
register: name
- name: "print variable"
debug:
#msg: "{{ name }}" #这里那么输出的是一堆东西,需要括号
msg: "{{ name.stdout_lines }}" #指定显示什么变量 ,需要加什么里面的
[root@rocky-100 ansible]#cat /dev/urandom |tr -dc '[:alnum:]' |head -c10 #取随机字符
Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质 上的不同,只有在关注的资源发生变化时,才会采取一定的操作。
Notify对应的action 在所有task都执行完才会最后被触发,这样可避免多个task多次改变发生时每次都 触发执行指定的操作,Handlers仅在所有的变化发生完成后一次性地执行指定操作。
在notify中列出的操作称为handler,也即notify中调用handler中定义的操作
列:
# nginx
- hosts: 10.0.0.8
tasks:
- name: 安装
yum:
name: nginx
state: present
- name: 复制
copy:
src: /data/nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx # 注释 上下一样的名字 预示着这里改变就执行下面的命令 不变不执行
- name: 页面
copy:
src: /data/index.html
dest: /usr/share/nginx/html/index.html
- name: 启动
service:
name: nginx
state:
started
enabled: yes
handlers:
- name: restart nginx # 注释 上下一样的名字 最好别汉语又可能出问题
service: name=nginx state=restarted
如果不论前面的task成功与否,都希望handlers能执行, 可以使用force_handlers: yes 强制执行handler 范例: 强制调用handlers\
- hosts: webservers
force_handlers: yes #无论task中的任何一个task失败,仍强制调用handlers
tasks:
- name: config file
copy: src=nginx.conf dest=/etc/nginx/nginx.conf
notify: restart nginx
- name: install package
yum: name=no_exist_package
handlers:
- name: restart nginx
service: name=nginx state=restarted
vim httpd.yml
---
# tags example
- hosts: webservers
remote_user: root
gather_facts: no
tasks:
- name: Install httpd
yum: name=httpd state=present
tags: service #如果一个标签 在两个地方都执行
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
tags: [ conf,file ] #写在一行
- conf #写成多行
- file
- name: start httpd service
tags: service
service: name=httpd state=started enabled=yes
#列出标签
[root@ansible ~]#ansible-playbook --list-tags httpd.yml
#执行有指定标签的任务
[root@ansible ~]#ansible-playbook -t conf,service httpd.yml
#忽略执行指定标签的task
[root@ansible ~]#ansible-playbook --skip-tags conf httpd.yml
#忽略执行没有标签的任务,即只执行有标签的任务
[root@ansible ~]#ansible-playbook httpd.yml --skip-tags untagged
变量调用方式: 通过 {{ variable_name }} 调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才生效
-e 选项定义变量 -->playbook中vars_files --> playbook中vars变量定义 -->host_vars/主机名
文件 -->主机清单中主机变量--> group_vars/主机组名文件-->group_vars/all文件--> 主机清单组变量
127.0.0.1 ansible_connection=local 可以连接自己
ansible webservers -m setup #查看自己的变量
root@rocky-100 ~]#vim varl.yaml
- hosts: dbservers
tasks:
- name: create file
file:
name: /tmp/{{ ansible_hostname }}.log
state: touch
- name: change hostname
hostname:
name: "ubuntu-{{ ansible_eth0.ipv4.address.split('.')[-1] }}" #起名 用本主机标量
#Ubuntu20.04的ansible不支持Rocky8的hostname修改
[root@ansible ansible]#cat hostname2.yml
- hosts: webservers
tasks:
- name: genarate random
shell:
cmd: openssl rand -base64 12 |tr -dc '[:alnum:]' #取随机数
register:
num
- name: show random
debug:
msg: "{{ num }}" #输出 一大堆
- name: change hostname
hostname:
name: web-{{ num.stdout }} # 只取随机数
[root@rocky-100 data]#cat var2.yml
---
- hosts: webservers
remote_user: root
tasks:
- name: install package {{ pkname1 }}
yum: name={{ pkname1 }} state=present
[root@rocky-100 data]#ansible-playbook -e pkname1=sl var2.yml
[root@rocky-100 data]#cat var2.yml
---
- hosts: webservers
remote_user: root
vars:
pkname:sl #也可以在这里定义变量
tasks:
- name: install package {{ pkname1 }}
yum: name={{ pkname1 }} state=present
[root@rocky-100 data]#ansible-playbook -e pkname1=sl var2.yml #但是优先级还是外面高
可以在一个独立的playbook文件中定义公共变量,在其它的playbook文件中可以引用变量文件中的变量
此方式比playbook中定义的变量优化级高
[root@rocky-100 data]#cat vars.yaml #变量文件 最好引号引起来
pkname: "redis"
lile: "test.log"
[root@rocky-100 data]#cat var3.yaml
---
- hosts: webservers
remote_user: root
vars_files:
- vars.yaml #指定变量文件名
tasks:
- name: "install package {{ pkname }}"
yum: name={{ pkname }} state=present
10.0.0.101 host=web01 #单独针对这个IP有效的变量
10.0.0.102 host=web02
[webservers:vars] #针对这个组有效的变量
domain=wang
[appservers]
10.0.0.[7:8]
10.0.0.101
[all:vars] #大家都有效
suffix=edu
[root@ubuntu2004 ansible]#vim yum5.yaml #指定上面定义的变量
- hosts: webservers
tasks:
- name: set hostname
hostname:
name: "{{ host }}.{{ domain }}.{{ suffix }}"
上面的方式是针对所有项目都有效,而官方更建议的方式是使用ansible特定项目的主机变量和组变量 生产建议在每个项目对应的目录中创建额外的两个变量目录,分别是host_vars和group_vars
host_vars下面的文件名和主机清单主机名一致,针对单个主机进行变量定义
group_vars下面的文件名和主机清单中组名一致, 针对单个组进行变量定义
group_vars/all文件内定义的变量对所有组都有效
将变量放在文件里,不放在变量也行
变量的优先级从高到低如下
-e 选项定义变量 -->playbook中vars_files --> playbook中vars变量定义 -->host_vars/主机名
文件 -->主机清单中主机变量--> group_vars/主机组名文件-->group_vars/all文件--> 主机清单组变量
Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全:
特性:
template功能:可以根据和参考模块文件,动态生成相类似的配置文件
template文件存建议放于templates目录下,且命名为 .j2 结尾
yaml/yml 文件和templates目录平级,此时playbook中指定模板文件时可不用指定路径, 目录结构如下
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
template变更替换
#修改文件nginx.conf.j2
[root@ansible ~]#mkdir templates
[root@ansible ~]#vim templates/nginx.conf.j2
......
worker_processes {{ ansible_processor_vcpus }}; 本机的cpu个数,可以+*等
......
例:
[root@rocky-100 templates]#cat nginx.conf.j2 #变量及核心
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user {{ user }}; #定义的用户变量
worker_processes {{ ansible_processor_vcpus +2}}; #定义的cpu变量
········
[root@rocky-100 templates]#cat nginx.yaml.j2 安装
---
# nginx
- hosts: 10.0.0.8
remote_user: root
vars: #定义的用户变量可以指定亦可以写在这里
user: root
tasks:
- name: 安装
yum:
name: nginx
state: present
- name: 复制
template: #使用template模块实现文件复制到远程主机,和copy的区别就是可以用变量
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
- name: 页面
copy:
src: /data/index.html
dest: /usr/share/nginx/html/index.html
- name: 启动
service:
name: nginx
state:
started
enabled: yes
handlers:
- name: restart nginx
service: name=nginx state=restarted
template中也可以使用流程控制 for 循环和 if 条件判断,实现动态生成文件功能
格式
{% for i in EXPR %} #开始
...
{% endfor %} #结束#示例:
{% for i in range(1,10) %}
server_name web{{i}};
{% endfor %}
for.yam #引用下面
test.conf.j2
#temlnginx2.yml
---
- hosts: webservers
remote_user: root
vars:
nginx_vhosts: #赋值 3个
- 81
- 82
- 83
tasks:
- name: template config
template: src=nginx.conf2.j2 dest=/data/nginx.conf#templates/nginx.conf2.j2
{% for vhost in nginx_vhosts %} #vhost循环取值nginx_vhosts
server {
listen {{ vhost }}
}
{% endfor %}
ansible-playbook -C templnginx2.yml --limit 10.0.0.8#生成的结果:
server {
listen 81
}
server {
listen 82
}
server {
listen 83
}
循环,提取建网站
结果
有的有server_name有的没有if判断
[root@rocky-100 ansible]#vim templnginx6.yml
- hosts: webservers
remote_user: root
vars:
nginx_vhosts:
- web1:
listen: 8080
root: "/var/www/nginx/web1/"
- web2:
listen: 8080
server_name: "web2.wang.org"
root: "/var/www/nginx/web2/"
- web3:
listen: 8080
server_name: "web3.wang.org"
root: "/var/www/nginx/web3/"
tasks:
- name: template config to
template: src=nginx.conf5.j2 dest=/data/nginx5.conf
[root@rocky-100 ansible]#vim templates/nginx.conf5.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
{% if vhost.server_name is defined %} #if判断如果有vhost.server_name 就有下面
server_name {{ vhost.server_name }} #注意缩进 就是这样的格式,不然变形
{% endif %}
root {{ vhost.root }} #注意缩进
}
{% endfor %}
[root@rocky-100 ansible]#ansible-playbook templnginx6.ym #执行
[root@rocky8 ~]#cat /data/nginx5.conf #执行结果
server {
listen 8080
root /var/www/nginx/web1/ #注意缩进
}
server {
listen 8080
server_name web2.wang.org #注意缩进
root /var/www/nginx/web2/ #注意缩进
}
server {
listen 8080
server_name web3.wang.org #注意缩进
root /var/www/nginx/web3/ #注意缩进
}
迭代:当有需要重复性执行的任务时,可以使用迭代机制
列表元素格式:
字符串
- 字典 key: value
类似if循环
范例: 安装多个软件包
#方法1
# cat install_packages.yml
- hosts: webservers
tasks:
- name: Installed Httpd Php-fpm Package
yum: name={{ pack }} state=latest
vars:
pack:
- httpd
- php-fpm
#方法2
# cat install_packages2.yml
- hosts: webservers
tasks:
- name: Installed Httpd Php-fpm Package
yum:
name: "{{ item }}" #item 固定写法 变量最好引号引起来
state: latest
loop: #推荐用loop
- httpd
- php-fpm
#until为false时才会执行循环,为true则退出循环
[root@ansible ansible]#cat until.yml
- hosts: localhost
gather_facts: false
tasks:
- debug: msg="until"
until: false
retries: 3 #默认值即为3次 循环三次
delay: 1 #停顿一次 1秒
范例: 以轮询的方式等待服务同步完成
- name: 以轮询的方式等待服务同步完成
shell: "systemctl is-active mysqld.service" #执行命令
register: mysqld_status #结果保存在在里面
until: '"inactive" in mysqld_status.stdout' #检查这里里面是否有,有退出
retries: 3 #试几次
delay: 2 #停顿几秒
逐行处理,一行打印一次
[root@ansible ansible]#cat with_lines.yml
- hosts: localhost
tasks:
- debug: msg={{ item }}
with_lines: ps aux
when语句可以实现条件测试
范例: 判断OS版本
#ansible all -m setup -a 'filter=ansible_distribution_file_variety' #查看什么系列的
ansible_distribution_file_variety": "RedHat", #红帽系列的rocky
···
"ansible_distribution_file_variety": "Debian", # Debian的ubuntu
[root@ansible ansible]#cat when.yml
- hosts: all
tasks:
- name: install httpd
yum:
name: "httpd"
when:
- ansible_distribution_file_variety == "RedHat" #执行 yum安装
- name: install package
apt:
name: "apache2"
when:
- ansible_distribution_file_variety == "Debian" #执行apt安排
范例: 数据类型转换
有些数字被当成字符串"6",没办法当成数字引用.这时候可以用数据类形转换
- hosts: all
tasks:
- shell: echo "only on Red Hat 6, derivatives, and later"
when: ansible_distribution_file_variety == "RedHat" and ansible_facts['lsb']['major_release'] | int > 7
当想在满足同样条件下,执行多个任务时,就可以分组。
- hosts: appservers
tasks:
- block:
- shell: echo "task1"
- shell: echo "task2"
when:
- ansible_distribution_file_variety == "RedHat"
- ansible_facts['lsb']['major_release'] | int > 7
当确定某个task不会对被控制端做修改时但执行结果却显示是黄色的changed状态
可以通过 changed_when: false 关闭changed状态
执行命令完他会显示黄,这样可以显示绿
[root@ansible ansible]#cat test_changed.yml
---
- hosts: webservers
tasks:
- name: check sshd service
shell: ps aux| grep sshd
changed_when: false #关闭changed状态
changed_when 检查task返回结果,决定是否继续向下执行
---
- hosts: webservers
tasks:
- name: install nginx
yum: name=nginx
- name: config file
template: src="nginx.conf.j2" dest="/etc/nginx/nginx.conf"
notify: restart nginx
- name: check config
shell: /usr/sbin/nginx -t #检查是否成功
register: check_nginx_config #变量导入
changed_when:
- check_nginx_config.stdout.find('successful') #如果执行结果中有successful字
符串,则继续执行,如果没有则停止向下执行
- false #nginx -t 每次成功执行是changed状态,关闭此changed状态
- name: start service
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx
service: name=nginx state=restarted
管理节点过多导致的超时问题解决方法
默认情况下,Ansible将尝试并行管理playbook中所有的机器。对于滚动更新用例,可以使用serial关键字定义Ansible一次应管理多少主机,还可以将serial关键字指定为百分比,表示每次并行执行的主机数占总数的比例
范例: 一次两台机器执行
#vim test_serial.yml
---
- hosts: all
serial: 2 #每次只同时处理2个主机,将所有task执行完成后,再选下2个主机再执行所有task,直至所
有主机
gather_facts: False
tasks:
- name: task one
command: hostname
- name: task two
command: hostname
name: test serail
hosts: all
serial: "20%" #每次只同时处理20%的主机,主机数不足时,向下取整
利用委托技术,可以在非当前被控主机的其它主机上执行指定操作
注意: 当前执行的被管理端主机需要实现到被委派主机的ssh key 验证才能实现委派
范例: 将任务委派给指定的主机执行
[root@ansible ansible]#cat delegate.yml
#在10.0.0.8上执行hostname -I,而非当前主机的localhost上执行
- hosts: localhost
tasks:
- name: show ip address
command: hostname -I
delegate_to: 10.0.0.8 #指定当前任务被委派的目标主机
delegate_facts: true #收集被委派的目标主机的facts信息
范例: 将任务被委派给控制端ansible主机执行
#在本地执行ifconfig,而非10.0.0.8
[root@ansible ansible]#cat delegate2.yml
- hosts: 10.0.0.8
tasks:
- name: show ip address
local_action: command ifconfig #被委派给控制端ansible主机执行
- name: show hostname
shell: hostname
connection: local #被委派给控制端ansible主机执行
- name: kernel version
shell: hostname -I
delegate_to: localhost #被委派给控制端ansible主机执行
run_one: truce #委派任务只执行一次
利用 run_once 指令可以只执行一次,而非在所有被控主机都执行
root@ansible ~]#cat run_once.yml
- hosts: webservers
tasks:
- command: hostname
run_once: true #只执行一次[root@ansible ~]#ansible-playbook run_once.yml --list-hosts
playbook: run_once.yml
play #1 (webservers): webservers TAGS: []
pattern: ['webservers']
hosts (2):
10.0.0.8
10.0.0.7
[root@ansible ~]#ansible-playbook run_once.yml
临时修改环境变量,只针对当前动作的task有效
[root@ansible ~]#cat environment.yml
- hosts: localhost
tasks:
- shell: echo $PATH
environment:
PATH: /usr/local/app/bin:{{ ansible_env.PATH }}
[root@ansible ~]#ansible-playbook environment.yml -v
include
利用include 或 include_tasks 可以在某个task中调用其它的只有task内容的yaml文件
[root@ansible ansible]#cat a.yml
---
- hosts: webservers
tasks:
- name: run a job
command: wall run a job
- name: excute b.yml
include: b.yml #调用另一个yaml文件
#include_tasks: b.yml #另一种写法
[root@ansible ansible]#cat b.yml
- name: run b job
command: wall run b job
还可以将多个包含完整内容的yml文件由一个yml统一调用
[root@ansible ansible]#cat main.yml #在这里统一执行
- import_playbook: tasks1.yml
- import_playbook: tasks2.yml
[root@ansible ansible]#cat tasks1.yml #把任务写在这里
---
- hosts: webservers
tasks:
- name: run task1 job
command: wall run task1 job
[root@ansible ansible]#cat tasks2.yml
---
- hosts: dbservers
tasks:
- name: run task2 job
command: wall run task2 job
[root@ansible ansible]#ansible-play main.yml
roles:多个角色的集合目录, 可以将多个的role,分别放至roles目录下的独立子目录中,如下示例
roles/
mysql/
nginx/
tomcat/
redis/
playbook1.yml
playbook2.yml
roles/
project1/
tasks/
files/
vars/
templates/
handlers/
defaults/
meta/
project2/
tasks/
files/
vars/
templates/
handlers/
defaults/
meta/
roles/project/ :项目名称,有以下子目录
默认找mian.yml
- files/ :存放由copy或script模块等调用的文件
- templates/:template模块查找所需要模板文件的目录
- tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件;其它的文件需要在此
- 文件中通过include进行包含
- handlers/:至少应该包含一个名为main.yml的文件;此目录下的其它的文件需要在此文件中通过include进行包含
- vars/:定义变量,至少应该包含一个名为main.yml的文件;此目录下的其它的变量文件需要在此文件中通过include进行包含,也可以通过项目目录中的group_vars/all定义变量,从而实现角色通用代码和项目数据的分离
- meta/:定义当前角色的特殊设定及其依赖关系,至少应该包含一个名为main.yml的文件,其它文件需在此文件中通过include进行包含
- defaults/:设定默认变量时使用此目录中的main.yml文件,比vars的优先级低