文章目录
- 0、概述
- `优点`
- 一、ansible用法
- `1.1.安装ansible`
- `1.2.ansible参数选项`
- 二、相关文件介绍
- `2.1.配置文件`
- 2.1.1./etc/ansible/ansible.cfg解释
- 2.1.2./etc/ansible/hosts格式
- `2.2.可执行文件`
- 三、配置基于root用户Key的验证
- 四、ansible命令执行过程
- 五、执行状态
- 六、常用模块
- 七、ansible-galaxy
- 八、ansible-vault
- 九、ansible-playbook
- `9.1.核心元素`
- `9.2.playbook格式`
- `9.3.常用技巧`
- 1、ignore_errors忽略错误信息
- 2、拷贝文件使用相对路径
- 3、handlers+notify解决修改配置文件不生效的问题
- 4、tags打标签
- 5、when条件判断
- 6、迭代:with_items
- 7、become提权
- 8、lineinfile(类似于sed)
- 9、register注册变量,返回shell脚本执行结果
- 10、failed_when关键字
- 判断操作系统
- 匹配多个条件
- 11、任务委派功能delegate_to
- 12、本地操作功能local_action或connection
- 13、判断文件是否存在
- 14、判断指定路径是否为一个目录
- 15、include
- 16、block模块
- 17、pre_tasks在roles之前执行
- 18、set_fact设置变量
- 19、validate: 在复制之前执行检测,如果要引用目标文件名,则使用 %s
- `9.4.使用变量`
- a.系统facts收集
- b.在yaml文件中通过vars定义
- c.在/etc/ansible/group_vars/all定义[推荐使用]
- d.在/etc/ansible/hosts中定义
- e.通过ansible-playbook -e传入变量,优先级高于/etc/ansible/hosts【不推荐】
- `9.5.常用命令`
- `9.6.模板templates`
- 1、简单运算
- 2、for循环+if判断
- 3、在模板中获取主机组的IP
- 4、在模板中定义列表
- 5、获取主机组数量
- 十、roles
- `10.1.流程图`
- `10.2.各目录作用`
- `10.3.示例`
- `10.4.在main.yml调用其它角色的任务`
- `10.5.给角色定义标签`
- `10.6.委托其它机器执行角色`
参考视频:https://www.bilibili.com/video/BV18t411f7CN?p=5
参考文章:
一文掌握 Ansible 自动化运维
0、概述
原则:去中心化、“简单就是一切”
第一个版本0.0.1,发布于2012年3月9日,作者Michael DeHaan
优点
优点
批量管理(支持上千台)、幂等性、模板、模块化、无服务端和客户端(去中心化)
一、ansible用法
1.1.安装ansible
1.1.安装ansible
yum -y install epel-release
yum -y install ansible
1.2.ansible参数选项
1.2.ansible参数选项
选项 | 解释 |
-m | 指定要执行的模块,默认为command |
-a | 指定模块的参数 |
-u | ssh连接的用户名,默认用root,ansible.cfg中可以配置 |
-b,–become | 相当于sudo |
–become-user | sudo到哪个用户,默认为root |
-k | 提示输入sudo密码,当不是NOPASSWD模式时使用 |
-C | 只是测试一下会改变什么内容,不会真正去执行 |
-f | fork多少进程并发处理,默认为5个 |
-i | 指定hosts文件路径,默认default=/etc/ansible/hosts |
–list-host | 只打印有哪些主机会执行这个命令,不会实际执行 |
–private-key | 私钥路径 |
-T | ssh连接超时时间,默认是10秒 |
-t | 日志输出到该目录,日志文件名以主机命名 |
-vvv | 显示详细日志 |
举例:
ansible all --list-host #列出inventory定义的所有主机
ansible all -m ping -b --become-user root #sudo到root执行ping模块
二、相关文件介绍
2.1.配置文件
2.1.配置文件
/etc/ansible/ansible.cfg #主配置文件
/etc/ansible/hosts #主机清单
/etc/ansible/roles/ #存放角色目录
2.1.1./etc/ansible/ansible.cfg解释
Ansible查找ansible.cfg文件的位置及顺序
1)ANSIBLE_CONFIG:首先,Ansible命令会检查环境变量,及这个环境变量将指向的配置文件
2)./ansible.cfg:其次,将会检查当前目录下的ansible.cfg配置文件
3)~/.ansible.cfg:再次,将会检查当前用户home目录下的.ansible.cfg配置文件
4)/etc/ansible/ansible.cfg:最后,将会检查在用软件包管理工具安装Ansible时自动产生的配置文件
inventory = /etc/ansible/hosts #存放主机清单文件
forks = 5 #并发执行数量
poll_interval = 15 #回频率或轮询间隔时间,单位s
sudo_user = root #远程主机sudo到什么用户,默认为root
ask_sudo_pass = True #sudo时是否需要输入密码
ask_pass = True #执行ansible-playbook是否需要密码.默认为no
transport = smart
remote_port = 22 #远程主机端口号
module_lang = C #模块和系统之间通信的语言
module_set_locale = False
roles_path = /etc/ansible/roles #默认下载的Roles存放的目录
host_key_checking = False #首次连接是否需要检查key认证。设置为False,第一次连接远程主机不需要输入yes
timeout = 10 #SSH超时时间
remote_user = root #使用/usr/bin/ansible-playbook链接的默认用户名,默认使用当前用户名称
log_path = /var/log/ansible.log #日志文件存放路径
executable = /bin/sh #执行的shell环境,用户shell模块
jinja2_extensions = jinja2.ext.do,jinja2.ext.i18 #允许开启jinja2扩展模块
private_key_file = /path/to/file #私钥文件存储位置
system_warnings = True #禁用系统运行Ansible潜在问题警告
deprecation_warnings = True #PlayBook输出禁用“不建议使用”警告
nocolor = 1 #输出带上颜色区别,0表示开启,1表示关闭
pipelining = False #是否开启pipe SSH通道优化
host_key_checking = False #配置ssh免密时不提示yes/no
gathering = explicit #不收集系统信息,默认收集
[privilege_escalation]
become=True #是否sudo
become_method=sudo #sudo方式
become_user=root #sudo后变为root用户
become_ask_pass=False #sudo后不验证密码
2.1.2./etc/ansible/hosts格式
[DB] #表示DB组,下面的主机均属于该组
192.168.1.2
192.168.1.3
[fastdfs]
192.168.1.2
192.168.1.3 GROUP_NAME="g1" #定义局部变量
[k8s]
192.168.1.[4:10] #[4:10]表示连续的主机,包含4和10
[webserver]
192.168.1.11:2222 #默认为22端口,如果不是,需指定
[groups:children] #children是ansible内置变量,可以实现多个组的调用
DB
k8s
[DB:vars]
mysql_port="3306" #组变量
[all:vars] #定义全局变量
db_master_ip="{{groups['DB'][0]}}" #取DB组中的第一个IP
2.2.可执行文件
2.2.可执行文件
/usr/bin/ansible #主程序
/usr/bin/ansible-doc #查看文档
/usr/bin/ansible-galaxy #连接https://galaxy.ansible.com/下载相应的roles
/usr/bin/ansible-playbook #调用playbook剧本
/usr/bin/ansible-vault #文件加密工具
三、配置基于root用户Key的验证
以root用户登录到主控端机器,ssh-keygen生成密钥对,通过ssh-copy-id 远程主机,将公钥拷贝到远程主机
四、ansible命令执行过程
- 加载自己的配置文件,默认/etc/ansible/ansible.cfg
- 加载自己对应的模块文件,如command,或者ping
- 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件
- 给文件+x执行
- 执行并返回结果
- 删除临时py文件,退出
五、执行状态
绿色:执行成功并且不需要做改变的操作
黄色:执行成功并且对目标主机做变更
红色:执行失败
六、常用模块
ansible 192.168.1.2 -m ping -k #测试主机是否可以通信;默认通过key验证,-k指定以用户名密码验证
ansible all -m ping #检测主机清单文件中的所有主机
ansible db -m ping #只检测db组内的主机
ansible *ser* -m ping #支持通配符
ansible 'db:web' -m ping #取db和web组的并集
ansible 'db:&web' -m ping #取db和web组的交集
ansible 'db:!web' -m ping #在db,不在web
ansible-doc -l #列出所有模块
ansible-doc ping #查看ping模块
ansible-doc -s ping #简单了解ping模块
ansible all --list #列出主机清单所有主机
ansible all -a 'ls /root' #默认使用command模板,不支持变量、<、>、|、&、;等,需使用shell模块
ansible all -a 'creates=/ansible mkdir /ansible' #不存在/ansible,则执行后面的mkdir
ansible all -a 'chdir=/root ls' #切换到/root下执行ls
ansible all -m shell -a 'echo $HOSTNAME'
ansible all -m script -a '/etc/ansible/scripts/host.sh' #会自动把主控端的脚本拷贝到被控端,并执行
ansible all -m copy -a 'src=/etc/hosts dest=/ansible/' #拷贝本机文件到远程主机
ansible 192.168.119.134 -m copy -a "src=/etc/ansible dest=/tmp owner=root group=root mode=0755" # 拷贝本机目录到远程客户端
ansible all -m copy -a 'content="hello world" dest=/ansible/f1' #把content里面的内容写入到f1文件,会覆盖之前的内容
ansible all -m fetch -a 'src=/etc/hosts dest=files/ flat=yes' #拷贝远程主机文件到当前路径的files/目录下;flat只拷贝hosts文件本身,不拷贝hosts文件所在的绝对路径
ansible all -m file -a 'path=/ansible/f2 state=touch' #创建文件
ansible all -m file -a 'path=/ansible/f2 state=absent' #删除文件
ansible all -m file -a 'path=/ansible/dir1 state=directory' #创建目录
ansible all -m file -a 'src=/etc/hosts dest=/tmp/host state=link' #创建软链接
ansible 10.93.62.156 -m hostname -a 'name=Master' #修改主机名
ansible all -m cron -a 'minute=* weekday=2,4 job="/usr/bin/wall test warning" name=testcron' #定时任务
ansible all -m cron -a 'disabled=true job="/usr/bin/wall test warning" name=testcron' #取消定时任务
ansible all -m cron -a 'state=absent job="/usr/bin/wall test warning" name=testcron' #删除定时任务
ansible all -m yum -a 'name=vsftpd update_cache=yes' #yum装包,更新缓存
ansible all -m yum -a 'name=vsftpd state=removed' #卸载包
ansible all -m user -a 'name=zhangsan shell=/bin/bash' #创建用户
ansible web -m command -a "chdir=/tmp pwd" #切换目录,执行命令
ansible模块大全
七、ansible-galaxy
ansible-galaxy collection install nginxinc.nginx_core -c #下载角色;-c忽略证书认证
ansible-galaxy list #列出本机所有角色
八、ansible-vault
ansible-vault encrypt hello.yml #加密yaml文件,需设置密码
ansible-vault view hello.yml #查看yaml文件内容
ansible-vault edit hello.yml #修改yaml文件内容
ansible-vault rekey hello.yml #修改加密口令
ansible-vault decrypt hello.yml #解密yaml文件
九、ansible-playbook
9.1.核心元素
9.1.核心元素
hosts #执行的远程主机列表
tasks #任务集
templates #模板
handlers #也是task列表,和一般的task并没有什么区别.Handlers由通知者进行notify, 如果没有被notify,handlers不会执行.不管有多少个通知者进行了notify,等到 play 中的所有 task 执行完成之后,handlers 也只会被执行一次
tags #打标签,通过标签调用特定的任务;多个任务可以共用一个标签
vars #定义变量
9.2.playbook格式
9.2.playbook格式
--- #习惯写法,区分不同的档案
# 创建文件
- hosts: db,myql #选择hosts文件中的主机;可以选择多个主机,使用逗号分隔
remote_user: root #指定远程主机用什么用户执行
gather_facts: no #收集远程主机信息,默认为yes
tasks: #任务列表
- name: create file #任务说明
file: path=/ansible/f2 state=touch mode=0500 #使用file模块,创建文件;mode设置权限
- name: test1
shell: echo "{{ groups['mysql'][0] }}" >> /tmp/t1.txt #获取[mysql]组的第一个成员
- hosts: redis:!redis[0] #排除redis组的第一个成员
9.3.常用技巧
9.3.常用技巧
1、ignore_errors忽略错误信息
任务执行失败,不会影响后面任务的执行
- name: create file
file: path=/ansible1/f2 state=touch
ignore_errors: True
2、拷贝文件使用相对路径
src使用相对路径,会去与该yaml文件同级的files目录下寻找,通常把要拷贝的文件同一放到files目录下
- name: copy hosts
copy: src=hosts dest=/ansible/ backup=yes
3、handlers+notify解决修改配置文件不生效的问题
当执行copy模板后,通过notify发送通知给名字为restart httpd service的handlers,执行对应的service模板,重启httpd服务
tasks:
- name: copy conf file
copy: src=httpd.conf dest=/etc/httpd/conf/ backup=yes
notify:
- restart httpd service
- name: start service
service: name=httpd state=started enabled=yes
handlers:
- name: restart httpd service
service: name=httpd state=restarted
4、tags打标签
特殊tags:always #无论如何都会运行
- name: copy hosts
copy: src=hosts dest=/ansible/
tags: copyfile
调用多个标签用逗号分隔
ansible-playbook -t copyfile,sql file.yml
5、when条件判断
ansible条件判断
根据操作系统的类型来执行对应的任务
tasks:
- name: create file for RedHat
file: path=/ansible/redhat state=touch
when: ansible_os_family == "RedHat"
- name: create file for ubuntu
file: path=/ansible/ubuntu state=touch
when: ansible_os_family == "Ubuntu"
自定义条件判断
根据action的值去判断

6、迭代:with_items
当需要有重复性执行的任务时,可以使用迭代机制
示例:创建多个文件
tasks:
- name: create files
file: path=/ansible/{{ item }} state=touch
with_items:
- file1
- file2
示例:迭代嵌套子变量
tasks:
- name: create group
group: name={{ item }}
with_items:
- g1
- g2
- name: create user
user: name={{ item.name }} group={{ item.group }}
with_items:
- { name: "user1", group: "g1"}
- { name: "user2", group: "g2"}
7、become提权
- name: copy hosts
copy: src=hosts dest=/ansible/
become: yes
become_user: root #提升为root权限,类似sudo
8、lineinfile(类似于sed)
regexp正则匹配,如果匹配上,则整行替换,类似sed的c操作;如果未匹配,则在末尾添加,类似sed的a操作
- name: modify file
lineinfile: dest=/ansible/file1 regexp="zabbix soft" line="zabbix soft nproc 65535"
playbook的一个bug:如果内容中有:号会报错,用下面的写法可以避免
- name: add paas sudo
lineinfile:
path: /etc/sudoers
regexp: "paas ALL=(ALL) NOPASSWD: ALL"
line: "paas ALL=(ALL) NOPASSWD: ALL"
9、register注册变量,返回shell脚本执行结果
使用 register 注册变量,名为 result,会把shell模块的输出存入到result
debug模块使用result的值进行判断
tasks:
- name: install mysql
shell: cd /data/shell/ && sh InstallMySql.sh
register: result
- name: show install mysql debug
debug: var=result.stdout_lines verbosity=0
result.stdout #标准正确输出保存到字符串中
result.stdout_lines #标准正确输出保存到列表中,输出更美观
result.stderr_lines #标准错误输出保存到列表中
verbosity #为1,代表-v;为2,代表-vv;为3,代表-vvv
10、failed_when关键字
’ failed_when’不会影响shell模块的执行过程,只会在条件成立时影响shell模块最终的执行状态,以便停止playbook的运行。
---
- hosts: db
remote_user: root
tasks:
- debug:
msg: "I execute normally"
- shell: "echo 'This is a string for testing error' && exit 1"
register: result
failed_when: result.rc != 0
- debug:
msg: "I never execute,Because the playbook has stopped
类似于shell中的
if [[ $? -ne 0 ]];then
exit 1
fi
判断操作系统
- hosts: redhat
gather_facts: True
tasks:
- name: copy redhat7 packages
copy:
src: /tmp/redhat7.tar
dest: /tmp/redhat7.tar
mode: '0755'
when: ansible_distribution == "RedHat" and ansible_distribution_major_version == "7"
匹配多个条件
1、两个条件都满足
failed_when: ' "error" in result.stdout and "fail" in result.stdout'
2、满足两个条件中的任意一个
failed_when: ' "error" in result.stdout or "fail" in result.stdout'
11、任务委派功能delegate_to
实现在当前playbook主机组外的机器上执行操作
run_noce: true 在一个主机上面只执行一次一个任务. ,如果没有这个参数的话,每个playbook中的组的主机都会执行一次
- name: test
shell: echo "1" >> /root/a.txt
delegate_to: 127.0.0.1
run_once: true
委派Ansible所在的机器(即主控端)执行shell里面的操作
12、本地操作功能local_action或connection
ansible的delegate_to、connection、和local_action
13、判断文件是否存在
如果不存在,则创建
- name: Check a.txt exists
stat:
path: /etc/ansible/a.txt
register: file_status
- name: create a.txt
shell: touch a.txt
when: file_status.stat.exists == False
14、判断指定路径是否为一个目录
- hosts: test
vars:
testpath1: "/testdir/test"
testpath2: "/testdir"
tasks:
- debug:
msg: "file"
when: testpath1 is file
- debug:
msg: "directory"
when: testpath2 is directory
15、include
1、调用其它yml
例如:在tasks目录有main.yml和upgrade_sql.yml,则可以在main.yml中调用upgrade_sql.yml
- include: upgrade_sql.yml
16、block模块
将多个任务组合成一个块,并且可以对这个块做条件判断,以及当块里面的任务失败时,进行失败处理
1、当when的判断语句一样时,可以将任务合并
- name: block的用法
hosts: node
tasks:
- debug:
msg: "task1 not in block"
- block:
- debug:
msg: "task2 in block1"
- debug:
msg: "task3 in block1"
when: 2 > 1
2、"错误处理"功能
- hosts: testuser
remote_user: root
tasks:
- block:
- command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing'
rescue: #当上面的块失败时,该关键字下面的任务将被执行
- command: /bin/false
- debug:
msg: 'I also never execute'
always: #不管block块是否执行成功,该关键字定义的任务都要被执行。
- debug:
msg: "This always executes"
when: 2>1
17、pre_tasks在roles之前执行
如果想在调用roles之前执行tasks任务,得用pre_task,不然会跳过tasks,直接调用roles
- hosts: web
pre_tasks:
- name: pre check
shell: echo "预检查"
roles:
- nginx
18、set_fact设置变量
获取本机IP地址,并赋值给变量host_ip_address
- hosts: mysql
tasks:
- name: get host ip address
shell: "ip addr |awk '/inet /' |sed -n '2p' |awk -F' ' '{print $2}' |awk -F'/' '{print $1}'"
register: host_ip
changed_when: false
- name: set host_ip_address variable
set_fact:
host_ip_address: "{{ host_ip.stdout }}"
- name: show host_ip_address
debug: msg={{ host_ip_address }}
19、validate: 在复制之前执行检测,如果要引用目标文件名,则使用 %s
- name: copy nginx.conf to {{ NGINX_DATA }}/conf
template:
src: nginx.conf.j2
dest: "{{ NGINX_DATA }}/conf/nginx.conf"
backup: yes
validate: 'nginx -t -c %s'
9.4.使用变量
9.4.使用变量
变量名由字母、数字、下划线组成,只能以字母开头
打印所有变量
ansible web -m debug -a 'var=vars'
a.系统facts收集
系统变量在playbook中可以直接通过{{ 名字 }}调用,如{{ ansible_hostname }}
ansible web -m setup #打印所有系统信息
ansible web -m setup -a 'filter=ansible_hostname' #获取主机名
ansible web -m setup -a 'filter=ansible_all_ipv4_addresses' #获取IP地址
b.在yaml文件中通过vars定义
- hosts: db
remote_user: root
vars:
- filename: f4
tasks:
- name: create file
file: path=/ansible/{{ filename }} state=touch
c.在/etc/ansible/group_vars/all定义[推荐使用]
定义的是全局变量,主机清单中的主机均可以调用
ANSIBLE_DIR: "/opt/ansible" #存放ansible拷贝的文件
SERVICE_USER: "admin" #启动服务的用户
DATA_DIR: "/app" #数据主目录
JDK_DIR: "{{ DATA_DIR }}/jdk" #jdk数据路径
d.在/etc/ansible/hosts中定义
http_port为针对单台主机设置的变量,nodename为针对web组所有主机设置的变量
[web]
10.93.91.80 http_port=80
10.93.65.2 http_port=81
[web:vars]
nodename=www
[all:vars] #定义全局变量
web_master_ip="{{groups['web'][0]}}" #取web组中的第一个IP
e.通过ansible-playbook -e传入变量,优先级高于/etc/ansible/hosts【不推荐】
playbook调用变量(两个双花括号里面写变量名)
- name: create file
file: path=/ansible/{{ filename }} state=touch
通过-e传入变量
ansible-playbook -e 'filename=f3' file.yml
9.5.常用命令
9.5.常用命令
选项 | 解释 |
-f | 并发执行数量,默认为5 |
–ssh-common-args | 指定要传递给sftp/scp/ssh的公共参数(例如ProxyCommand) |
-i | 指定主机清单文件,如果安装了ansible工具,不指定默认使用/etc/ansible/hosts文件 |
ansible-playbook -C file.yml #只检测可能会发生的改变,并不真正执行
ansible-playbook file.yml #执行playbook
ansible-playbook file.yml --list-hosts #列出运行任务的主机
ansible-playbook file.yml --limit 10.93.65.2 #只在指定的主机执行
ansible-playbook file.yml --list-tasks #查看任务列表
ansible-playbook file.yml --list-tags #查看标签列表
python ./ansible-playbook -f 3 -i hosts-192.168.137.3 /tmp/test.yml #通过python调用ansible-playbook,把ansible-playbook的内容放到ansible-playbook目录下即可
9.6.模板templates
9.6.模板templates
使用jinjia2语言
在与playbook同级的目录下创建templates目录
文件名以.j2结尾
1、简单运算
vi templates/nginx.conf.j2
这里面做了一个简单的计算,让远程主机CPU的个数乘以2
user nginx
workproceess {{ ansible_processor_vcpus*2 }}
playbook写法
- name: copy templates
template: src=nginx.conf.j2 dest=/ansible/nginx.conf
执行之后的结果,CPU的个数是8
2、for循环+if判断
for循环格式:
{% for port in ports %}
语句块1
语句块2
...
{% endfor %}
if判断格式:
单分支
{% if p.name is defined %} #如果变量不为空,则执行里面的语句块
语句块
{% endif %}
#多分支
{% if db_type== "mysql" %}
DB_IP=192.168.1.2
{% elif db_type== "oracle" %}
DB_IP=192.168.1.3
{% endif %}
playbook写法:
- hosts: all
remote_user: root
vars:
ports:
- port: 80
name: web1
- port: 81
tasks:
- name: copy templates
template: src=nginx.conf.j2 dest=/ansible/nginx.conf
模板文件:
{% for p in ports %}
server {
listen {{ p.port }}
{% if p.name is defined %}
servername {{ p.name }}
{% endif %}
}
{% endfor %}
执行结果:
3、在模板中获取主机组的IP
groups[‘web’]可以获取hosts文件中的web主机组定义的主机
{% if groups['web'] is defined and groups['web'][0] is defined %} #如果web组定义,且至少有一个主机
upstream web {
{% for ip in groups['web'] %}
server {{ ip }}:{{ WEB_PORT}} fail_timeout=5s max_fails=3;
{% endfor %}
{% endif %}
4、在模板中定义列表
{% for service_name in ['web','mysql'] %}
{{ service_name }}
{% endfor %}
5、获取主机组数量
"{{ groups['master'] | length }}"
十、roles
用于层次性、结构化地组织playbook,可以看成是一大堆playbook的集合。
分别将变量、文件、模板、任务放置于单独的目录中
10.1.流程图
10.1.流程图
10.2.各目录作用
10.2.各目录作用
10.3.示例
10.3.示例
调用role的playbook需要与roles目录位于同级目录下
nginx_role.yml内容:
- hosts: web
remote_user: root
roles:
- nginx
roles目录结构
main.yml内容,作为任务总入口,用来调用子任务
- include: group.yml
- include: user.yml
- include: config.yml
- include: copy.yml
ansible-playbook nginx_role.yml
10.4.在main.yml调用其它角色的任务
10.4.在main.yml调用其它角色的任务
- include: roles/mysql/tasks/install.yml
10.5.给角色定义标签
10.5.给角色定义标签
- hosts: web
remote_user: root
roles:
- { role: nginx, tags: ['web', 'nginx'] }
- { role: httpd, tags: ['web', 'httpd'], when: ansible_os_family == "RedHat" } #根据when条件执行角色
10.6.委托其它机器执行角色
10.6.委托其它机器执行角色
- hosts: web
remote_user: root
roles:
- { role: nginx, delegate_to: 127.0.0.1 }