Ansible Inventory
Inventory文件位置定义
# ANSIBLE_HOSTS环境变量
exporter ANSIBLE_HOSTS=/etc/ansible/hosts
# ansibele.cfg内部指定
inventory = /etc/ansible/hosts
# 运行ansible或ansible-playbook用-i参数指定
ansible -i hosts ...
ansible-playbook -i hosts ...
定义主机和主机组
# 主机定义,使用inventory内置变量定义ssh登陆密码
1 172.17.42.101 ansible_ssh_pass ='123456'
2 172.17.42.102 ansible_ssh_pass ='123456'
# 定义组docker,下面四台机器172.12.42.101~172.12.42.103
3 [docker]
4 172.17.42.10[1:3]
# 针对docker组,使用inventory内置变量定义了ssh登陆密码
5 [docker:vars]
6 ansible_ssh_pass ='123456'
# 定义了一个组ansible,包含docker组
7 [ansible:children]
8 docker
多个inventory文件
修改ANSIBLE_HOSTS环境变量或者修改ansible.cfg,此时使用目录即可,目录下可以存放不同主机 测试下来,必须放到inventory目录下;或者放在playbook目录下,-i指定
# ANSIBLE_HOSTS环境变量
exporter ANSIBLE_HOSTS=/root/inventory
# ansibele.cfg内部指定
inventory = /root/inventory
比如:
[root@Master ~ ]# cat inventory/hosts
172.17.42.101 ansible_ssh_pass ='123456'
172.17.42.102 ansible_ssh_pass ='123456'
[root@Master ~ ]# cat inventory/docker
[docker]
172.17.42.10[1:3]
[docker:vars]
ansible_ssh__pass ='123456'
[ansible:children)
docker
动态inventory
将ansible.cfg配置文件中inventory定义成一个脚本即可. 该脚本必须支持2个参数:–list、–host
或 运行ansible、ansible-playbook命令是-i + 脚本名字.
#!/usr/bin/python # 必须加上,否则会被解析为ini文本
# coding:utf-8
'''
动态inventory:
a) 需要支持两个参数,--list(返回组包含的主机列表hosts、主机组变量vars、子组列表children、_meta存放主机变量)
'''
import json
import sys
def groups():
'''groups信息:包含主机列表,组变量,子组等信息'''
host_list = ["172.22.12." + str(i) for i in range(11,14)]
r = dict()
r['docker'] = {'hosts':host_list[0:1]}
r['web'] = {'hosts':host_list[1:]}
print json.dumps(r, indent=4)
def hosts(name):
'''hosts信息:包含主机变量'''
host_var = {
"172.22.12.11":{"ansible_ssh_port":21},
"172.22.12.12":{"ansible_ssh_port":22},
"172.22.12.13":{"ansible_ssh_port":23}
}.get(name)
print json.dumps(host_var, indent=4)
def main():
if len(sys.argv) == 2 and sys.argv[1] == "--list":
groups()
elif len(sys.argv) == 3 and sys.argv[1] == "--host":
hosts(sys.argv[2])
else:
print "Usage: {} --list or --host ".format(sys.argv[0])
if __name__ == "__main__":
main()
```
Inventory参数说明
变量 | 说明 |
---|---|
ansible_ssh_host | 将要连接的远程主机名. |
ansible_ssh_port | ssh端口号 |
ansible_ssh_user | ssh用户名 |
ansible_ssh_pass | ssh密码,建议使用–ask-pass或ssh密钥 |
ansible_sudo_pass | sudo密码,建议使用–ask-sudo-pass |
ansible_sudo_exe | sudo命令路径(适用V1.8及以上) |
ansible_connection | 与主机连接的类型,比如 local、ssh、paramiko;ansible以前默认使用paramiko,以后默认使用 ‘smart’,‘smart’ 方式会根据是否支持 ControlPersist, 来判断’ssh’ 方式是否可行 |
ansible_ssh_private_key_file | ssh使用的私钥文件 |
ansible_shell_type | 目标系统的shell类型,命令的执行使用’sh’语法,可设置为’csh’或’fish’ |
ansible_python_interpreter | 目标主机的python路径 |
定义主机和组变量的方式:
a) /etc/ansible/group_vars/组名 /etc/ansible/host_vars/主机名
b) /etc/ansible/group_vars/组名/{文件1,文件2} # 文件1、文件2中的变量都可以被加载;环境比较复杂时,这种管理方式更好
patterns(匹配执行任务的主机)
下面列举一些常见的匹配条件:
all:匹配所有主机 // ansible和ansible-playbook都支持
webservers:dbservers:冒号表示或的关系,表示主机可以存在于多个group中 ansible和ansible-playbook都支持
webservers:!phoenix:表示属于webservers组,不属于phoenix组的主机 ansible-playbook支持
webservers:&staging:交集,表示同时属于webservers和staging组的主机 ansible-playbook支持
webservers:dbservers:&staging:!phoenix:webserver和dbservers两个组中,隶属于staging组,不属于phoenix组的主机 ansible-playbook支持
~(web|db).*\.example\.com:正则 ansible-playbook支持
Ansible Ad-Hoc命令
ansible-doc -l查看所有自带模块,目前有259个命令
ansible-doc 模块名,查看模块使用方法
执行命令
ansible命令是并发执行的,并发数由ansible.cfg中的forks值控制、或者运行命令时通过-f参数指定.
ansible允许异步执行任务,对于执行时间很长的任务,下发任务后每过一段时间轮询获取任务结果.
# 异步任务超时时间为120s 每个-P参数后秒数轮询获取结果,-P + 0 表示不关心任务结果
ansible docker -B 120 -P 0 -m shell -a 'sleep 10;hostname' -f 5 -o
复制文件
copy模块批量下发文件,文件变化通过MD5值判断.
ansible docker -m copy -a 'src=hosts.py dest=/root/hosts.py owner=root group=root mode=644 backup=yes' -o
# md5值验证 下发三个文件md5值都是一样的.
ansible docker -m shell -a 'md5sum /root/hosts.py' -f 5 -o
包和服务管理
ansible docker -m yum -a 'name=httpd state=latest' -f 5 -o
# 验证包是否安装
ansible docker -m shell -a 'rpm -qa httpd' -f 5 -o
# 验证服务是否启动
ansible docker -m shell -a 'netstat -tpln | grep httpd' -f 5
用户管理
首先通过openssl 命令来生成一个密码,因为ansible user 的password 参数需要接受加密后的值:
[root@Master ~]# echo ansible | openssl passwd -l -stdin
$1$GPMku7yL$.qu3NC2geUvOJ.NvgfCiol
使用user模块批量新建用户
ansible docker -m user - a 'name=shencan password=" $1$GPMku7yL$ . qu3NC2geUvOJ.NvgfCiol"' -f 5 -o
验证远程用户是否创建成功
ssh 172.17.42.103 -l shencan # -l 远端登陆用户
Ansible Playbook
实例:https://github.com/ansible/ansible-examples
基本语法
# -f 指定并行线程 --start-at-tasks 指定开始task
ansible-playbook -i hosts nginx.yml -f 3 --start-at-task='Copy Nginx.conf'
playbook变量与引用
通过Inventory文件定义主机以及主机组变量
# /etc/ansible/hosts
#172.22.12.13 key=13
#172.22.12.14 key=14
[consul]
172.22.12.1[3:4]
[consul:vars]
key: consul
# ansible-playbook variable.yml
---
- hosts: all
gather_facts: false
tasks:
- name: display host variable from hostfile
debug: msg="The {{ inventory_hostname }} value is {{ key }}"
==>
当主机处于主机组,并且同时定义相同的变量时,主机变量生效(比如 上述key=13、14生效);要是变量不同,不影响.
通过/etc/ansible/下文件定义主机和主机组变量
# 主机变量 文件名字和host相同
[root@shzj-o-proxy-12-7 ansible]# head host_vars/*
==> host_vars/172.22.12.13.yaml
key: 172.22.12.13
==> host_vars/172.22.12.14.yaml <==
key: 172.22.12.14
# 主机组变量 主机组变量文件名字和主机组名字相同
[root@shzj-o-proxy-12-7 ansible]# head group_vars/consul
key: consul
通过ansbile-playbook命令行传入
# 支持传入多个变量 空格隔开
ansible-playbook variable.yml -e 'key=KEY'
# 支持文件传入变量
[root@shzj-o-proxy-12-7 ansible]# head var.*
==> var.json <==
{"key": "JSON"}
==> var.yml <==
---
key: YML
ansible-playbook variable.yml -e '@/etc/ansible/var.yml'
在playbook文件内使用vars
[root@shzj-o-proxy-12-7 playbook]# cat variable.yml
---
- hosts: all
gather_facts: false
vars:
key: ansible
tasks:
- name: display host variable from hostfile
debug: msg="The {{ inventory_hostname }} key is {{ key }}"
在playbook 文件内使用vars_files
vars_files:
- /etc/ansible/var/json
使用register注册的变量
tasks:
- name: register variable
shell: hostname
register: info # 接收变量
- name: display host variable from hostfile
debug: msg="The {{ inventory_hostname }} key is {{ info['stdout'] }}" # info是一个dict,此处标准dict取值
使用vars_ prompt 传入
Ansible 还支持在运行playbook 的时候通过交互式的方式给定义好的参数传人变量值,只需在playbook 中定义vars_prompt 的变量名和交互式提示内容即可.
- hosts: all
gather_facts: false
vars_prompt:
- name: 'one'
prompt: 'please input one value'
private: no # yes的话 输入不显示
default: 'good' # 默认值
tasks:
- name: display host variable from hostfile
debug: msg="The {{ inventory_hostname }} key is {{ one }}"
变量引用顺序
yml陷阱
yml要求:要是值以{{foo}}开头的话,我们需要将整行用双引号引起来. 这是为了确认你不是想声明一个yaml字典.
- hosts: app_servers
vars:
app_path: {{ base_path }}/22 错误
app_path: "{{ base_path }}/22"
标准loops
# with_items是python list数据结构
---
- hosts: all
gather_facts: false
tasks:
- name: debug loops
debug: msg="name ---> {{ item }}"
with_items:
- one
- two
# 支持字典
- hosts: all
gather_facts: false
tasks:
- name: debug loops
debug: msg="name ---> {{ item.key }} value ---> {{ item.value }}"
with_items:
- {key: 'one', value: 'VALUE1'}
- {key: 'two', value: 'VALUE2'}
嵌套Loops
嵌套Loops 也是我们编写playbook 中比较常见的一种循环,它主要实现一对多或者多对多的合并.
# 此处多对多关系,A和B会一一和a,b,c对应,循环输出
# 类似python中 [ i+y for i in ['A','B'] for y in ['a','b','c'] ]
- hosts: all
gather_facts: false
tasks:
- name: debug loops
debug: msg="name ---> {{ item[0] }} value ---> {{ item[1] }}"
with_nested:
- ['A','B']
- ['a','b','c']
散列loops(循环哈希表)
散列loops 相比标准loops 就是变量支持更丰富的数据结构,比如标准loops 的最外层数据必须是Python 的list 数据类型,而散列loops 直接支持YAML 格式的数据变量.
---
- hosts: all
gather_facts: false
vars:
user:
shencan:
name: shenchan
shell: bash
tasks:
- name: debug loops
debug: msg="name ---> {{ item.key }} value ---> {{ item.value.name }} shell ---> {{ item.value.shell }}"
with_dict: "{{ user }}" # 注意变量引用格式
文件列表loops(模糊匹配文件)
文件匹配loops 是我们编写playbook 的时候需要针对文件进行操作中最常用的一种循环,比如我们需要针对一个目录下指定格式的文件进行处理,这个时候直接在引用w ith_fileglob 循环去匹配我们需要处理的文件即可.
# 模糊匹配目录下*.yml文件
---
- hosts: all
gather_facts: false
tasks:
- name: debug loops
debug: msg="name ---> {{ item }}"
with_fileglob:
- /opt/ansible/playbook/*.yml
随机选择loops
# 传入的list中随机选择一个 和python的random原理一样
with_random_choice:
- 'one'
- 'two'
条件判断Loops
有时候执行一个task 之后,我们需要检测这个task 的结果是否达到了预想状态,如果没有达到我们预想的状态时,就需要退出整个playbook 执行,这个时候我们就需要对某个task 结果一直循环检测了.
# 检测host变量是否以Master开头,满足执行task 重试5次
tasks:
- name: debug loops
shell: cat /root/Ansible
register: host
until: host.stdout.startswith("Master")
retries: 5
delay: 5
register loops
有多个task结果需要注册时,可以使用
tasks:
- name: debug loops
shell: "{{ item }}"
with_items:
- hostname
- uname
register: ret
- name: display loops
debug: msg="{{ item.stdout }}" # 此处已经是字典了,获取字典key 方式2:var=item.stdout 两者互斥
with_items: "{{ ret.results }}" # 注意,此处ret和单个task结果不一样,results先获取list
playbook lookups
Ansible 还支持从外部数据拉取信息,比如我们可以从数据库里面读取信息然后定义给一个变量的形式.
lookups file
读取文件内容,传递进变量 文件位于主控机器端
# 它的原理就是使用Python 的codecs.open 打开文件然后把结果返回给变量
vars:
contents: "{{ lookup('file', '/etc/sysconfig/network') }}"
tasks:
- name: debug lookups
debug: msg="The contents is {% for i in contents.split("\n") %} {{ i }} {% endfor %}"
lookups password 对传入的内容进行加密
vars:
contents: "{{ lookup('password', 'passwd') }}"
tasks:
- name: debug lookups
debug: msg="The contents is {{ contents }}"
⇒ 输出 ”msg ”:”The contents is Np6mOb9ZqrzVU3Sux5gH"
lookups pipe
控制机器上调用subprocess.Popen 执行命令,然后将命令的结果传递给变量
vars:
contents: "{{ lookup('pipe', 'date +%Y-%m-%d') }}"
tasks:
- name: debug lookups
debug: msg="The contents is {% for i in contents.split("\n") %} {{ i }} {% endfor %}"
⇒ 输出 ”msg ”:”The contents is Np6mOb9ZqrzVU3Sux5gH"
lookups redis_kv
vars:
contents: "{{ lookup('redis_kv', 'redis://localhost:6379,ansible') }}"
lookups template
template 跟file 方式有点类似,都是读取文件,但是template 在读取文件之前需要把jinja 模板渲染完后再读取
# jinja 模板文件
worker_processes {{ ansible_processor_cores }};
IPaddress {{ ansible_eth0.ipv4.address }}
# playbook文件
vars:
contents: "{{ lookup('template', './lookups.j2') }}"
playbook conditionals
实际应用过程中经常会碰到不同的主机可能要执行不同的命令,或者执行某个task 的时候需要进行一个简单的逻辑判断,此刻就需要在写task 的时候进行相应的判断.
目前Ansible 的所有conditionals 方式都是使用when 进行判断, when 的值是一个条件表达式,如果条件判断成立,这个task 就执行某个操作,如果条件判断不成立,该task 不执行或者某个操作会跳过.
# 多个when支持and、or操作
# 和python语言类似,比如对于str:info ['stdout'] . startswith ('M')
---
- hosts: all
tasks:
- name: host 172.22.12.13 run this task
debug: msg="{{ ansible_default_ipv4.address }}"
when: ansible_default_ipv4.address == "172.22.12.13"
一系列Jinja过滤器条件也可以在when语句使用
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
有些时候你得到一个返回参数的值是一个字符串,并且你还想使用数学操作来比较它,那么你可以执行一下操作:
tasks:
- shell: echo "only on Red Hat 6, derivatives, and later"
when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6 # | int 转换类型
在playbooks 和 inventory中定义的变量都可以使用. 下面一个例子,就是基于布尔值来决定一个任务是否被执行:
vars:
epic: true
tasks:
- shell: echo "This certainly is epic!"
when: epic
如果一个变量不存在,你可以使用Jinja2的defined
命令跳过或略过: 这个机制在选择引入变量文件时有时候特别有用
tasks:
- shell: echo "I've got '{{ foo }}' and am not afraid to use it!"
when: foo is defined
- fail: msg="Bailing out. this play requires 'bar'"
when: bar is not defined
和with_item结合
tasks:
- command: echo {{ item }}
with_items: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
在roles语句引入
- hosts: webservers
roles:
- { role: debian_stock_config, when: ansible_os_family == 'Debian' }
条件导入
比如 Apache的包,在CentOS 和 Debian系统中也许不同, 但是这个问题可以一些简单的语法就可以被Ansible Playbook解决:
---
- hosts: all
remote_user: root
vars_files:
- "vars/common.yml"
- [ "vars/{{ ansible_os_family }}.yml", "vars/os_defaults.yml" ] # ansible_os_family来自fact变量,可以设置fact缓存
tasks:
- name: make sure apache is running
service: name={{ apache }} state=running
基于变量选择文件和模板
- name: template a file
template: src={{ item }} dest=/etc/myapp/foo.conf
with_first_found: // 查找第一个找到的文件
- files: // 定义匹配文件
- {{ ansible_distribution }}.conf
- default.conf
paths: // 定义查找路径
- search_location_one/somedir/
- /opt/other_location/somedir/
搭配注册变量,使用when + filter过滤
Jinja filters
JinJa2官网也提供了很多filter
vars:
list: [1,2,3,4,5]
one: "1"
str: "string"
tasks:
- name: run commands
shell: cat /etc/passwd
register: info
# 对info.stdout仅从格式化
- name: debug pprint filter
debug: msg="{{ info.stdout | pprint }}"
# 对info执行状态进行判断
- name: debug conditionals filter
debug: msg="The run commands status is changed"
when: info|changed
# 转换类型
- name: debug int capitalize filter
debug: msg="The int value {{ one | int }} The lower value is {{ str | capitalize }}"
# 对ansible变量引用,没定义引用default值
- name: debug defaulr filter
debug: msg="The Variable value is {{ ansible | default('ansible is not define') }}"
# 计算list的最大值、最小值、总数
- name: debug list max and min filter
debug: msg="The list max value is {{ list | max }} The list min value is {{ list | min }} The list sum value is {{ list | sum }}"
# 生成1000以内随机数,step等于10
- name: debug random filter
debug: msg="The list random value is {{ list | random }} and generate a random value is {{ 1000 | random(1,10) }}"
# list拼接
- name: debug join filter
debug: msg="The join filter value is {{ list | join("+") }}"
# 字符串替换
- name: rebug replace and regex_replace filter
debug: msg="The replace value is {{ str | replace('t','T')}} The regex_replace value is {{ str | regex_replace('.*tr(.*)$','\\1')}}"
playbook内置变量
play book 默认已经内置变量,掌握了这些变量之后,我们就可以很容易实现关于主机相关的逻辑判断了.
变量 | 备注 |
---|---|
groups和group_names | 1.groups 返回所有的组和host 2. groups[‘consul’] 引用consul组的host 3. group_names 返回主机所在的组 |
hostvars | 主机变量 |
inventory_hostname和inventory _hostname_short | 返回主机名、主机名第一部分 |
play_hosts 和inventory_dir | 运行playbook主机列表、清单目录 |
范例说明:
情况1:一般情况下,获取inventory_hostname和hostname,直接使用{{ invenroty_hostname }} {{ hostname }}
情况2:针对主机组执行不同操作可以使用下面方式:
# /etc/ansible/hosts
[zabbix-server]
172.22.5.25 hostname=xxx
[zabbix-proxy]
172.22.5.25 hostname=yyy
# 获取主机和主机组
# 格式:{ungrouped: [], all: [u172.22.5.25], uzabbix-proxy: [u172.22.5.25], uzabbix-server: [u172.22.5.25]}
{% for host in groups['all'] %}
# 获取主机变量
# 格式:{'host == 主机ip':{变量字典}}
{{ hostvars[host]['inventory_hostname'] }} {{ hostvars[host]['hostname'] }}
{% endfor %}
playbook tags使用
对于一个很大的playbook,如果只想运行某个task,必须引入tag.
tasks:
- yum: name={{ item }} state=installed
with_items:
- httpd
- memcached
tags:
- packages
- template: src=templates/src.j2 dest=/etc/foo.conf
tags:
- configuration
运行tag:
ansible-playbook example.yml --tags "configuration,packages" # run多个tags
ansible-playbook example.yml --tags packages # 只run一个tag
跳过某个task:
ansible-playbook example.yml --skip-tags configuration
使用场景:
tags 这个属性也可以被应用到role上,例如:
roles:
- { role: webserver, port: 5000, tags: [ 'web', 'foo' ] }
tags这个属性可以被应用到play上,例如:
---
- name: test1
hosts: all
gather_facts: false
tags:
- all
特殊tag
always: 指定这个tag 后,task任务将永远被执行,而不用去考虑是否使用了–skip-tags标记
tagged: 当 --tags 指定为它时,则只要有tags标记的task都将被执行,–skip-tags效果相反
untagged: 当 --tags 指定为它时,则所有没有tag标记的task 将被执行,–skip-tags效果相反
all: 这个标记无需指定,ansible-playbook 默认执行的时候就是这个标记.所有task都被执行
playbook错误处理
1.忽略错误的命令
# 只对当前task有用
- name: this will not be counted as a failure
command: /bin/false
ignore_errors: yes
2.控制对失败的定义
在 Ansible 1.4及之后的版本中提供了如下的方式来指定这样的特殊行为:
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
failed_when: "'FAILED' in command_result.stderr"
在 Ansible 1.4 之前的版本能通过如下方式完成:
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
ignore_errors: True
- name: fail the play if the previous command did not succeed
fail: msg="the command failed"
when: "'FAILED' in command_result.stderr"
3.覆盖changed结果
tasks:
- shell: /usr/bin/billybass --mode="take me to the river"
register: bass_result
changed_when: "bass_result.rc != 2"
# this will never report 'changed' status
- shell: wall 'beep'
changed_when: False
playbook委任和滚动更新
委任
一般情况下,plays是按照顺序执行的; 如果需要在一个plays里,针对某台主机执行某个操作,那么用到委任;
---
- hosts: all
gather_facts: false
vars:
tmplog: /tmp/connection.log
tasks:
- name: create tmplog
shell: test ! -f {{ tmplog }} && touch {{ tmplog }}
failed_when: false
- name: delegate_to
shell: echo "delegate_to . {{ inventory_hostname }} $(hostname) ." >> {{ tmplog }}
run_once: true # 只执行依次,一般和delegate_to一起使用; 如果单独使用,只会针对inventory清单第一个主机执行:webservers[0]
delegate_to: 172.22.12.13 # 结果会被保存到13这台机器
滚动更新
- hosts: webservers
max_fail_percentage: 30 # 最大失败百分比 这个百分比必须被超过,不仅仅是相等.例如如果serial值呗设置为4,并且你希望任务主动在2个系统失败时候放弃.那么这个百分比应该设置为49而不是50.
serial: 10 # 每次运行主机数量 还可以使用百分比
Ansible Facts
facts是ansible采集被管理机器设备信息的一个功能,我们使用setup模块查机器的所有facts信息,用filter查看指定的信息. 整个facts是json格式.
# 查看主机facts信息
ansible 172.17.42.101 - m setup
# 查看ipv4地址
ansible 172.17.42. 101 -m setup t 'f ilter=ansible all_ipv4_addresses'
扩展factor:可以使用facter或ohai模块扩展facts信息
Ansible role
管理playbook方式,对我们日常使用的playbook目录结构进行一些规范.
roles模块的路径可以在配置文件/etc/ansible/ansible.cfg里roles_path定义.
vim /etc/ansible/ansible.cfg
roles_path = /etc/ansible/roles:/usr/share/ansible/roles
playbook调用role.
方法1:
- hosts: websrvs
remote_user: root
roles:
- mysql
- memcached
- nginx
方法2:传递变量 k = v 条件测试
- hosts: all
roles:
- { role: nginx, username: nginx, when: "ansible_distribution_major_version == '7' " }
- { role: nginx, username: nginx, when: "ansible_distribution_major_version == '7' " }
如果定义了一些tasks,需要在roles之前以及之后执行:
# 需要注意:如果tasks打了tag,那么pre_tasks和post_tasks也需要打上相同的标签.
- hosts: webservers
pre_tasks:
- shell: echo 'hello'
roles:
- { role: some_role }
tasks:
- shell: echo 'still busy'
post_tasks:
- shell: echo 'goodbye'
角色依赖:
"角色依赖"可以允许你将其他roles拉取到现有role中.
保存目录: roles 目录下的 meta/main.yml 文件.
示例:
---
dependencies:
- { role: common, some_parameter: 3 }
- { role: apache, port: 80 }
- { role: postgres, dbname: blarg, other_parameter: 12 }
- { role: '/path/to/common/roles/foo', x: 1 } // 可以通过绝对路径指定
默认情况下,当作角色依赖的role只能执行依次,并且是递归执行. 但是可以添加allow_duplicates: yes到meta/main.yml中,重复执行.
比如:一个role名为’car’, 将’wheel’的role添加到自己的"角色依赖", “wheel"又有自己的角色依赖"tire”、“brake”.
# role为car的角色依赖
---
dependencies:
- { role: wheel, n: 1 }
- { role: wheel, n: 2 }
- { role: wheel, n: 3 }
- { role: wheel, n: 4 }
# role为wheel的角色依赖
---
allow_duplicates: yes
dependencies:
- { role: tire }
- { role: brake }
最终的执行顺序:
tire(n=1)
brake(n=1)
wheel(n=1)
tire(n=2)
brake(n=2)
wheel(n=2)
...
car
Ansible Galaxy
Ansible官网分享role平台
网址:https://galaxy.ansible.com/
在线安装:ansible-galaxy install 作者.role名字,默认安装在/etc/ansible/roles