ansible特性
特性:
1.模块化: 调用特定模块,完成特定任务,每个模块就相当于单条linux命令 (单一命令)
2.有Paramiko,PyYAML,Jinja2(模板语言) 三个关键模块
3.支持自定义模块
4.基于python语言实现
5.部署简单,基于python和SSH
6.安全,基于OpenSSh
7.支持Playbook编排任务(复杂任务编排)
8.幂等性:一个任务,或者一个账号已经创建,就不会再执行了,不会因重复执行带来意外情况
9.无需代理
10.可使用任何编程语言写模块
11.YAML格式,编排任务,支持丰富的数据结构
12.较强大的多层解决方案(编角色)
应用场景
管理主机 ,管理设备(较少)
Ansible重要组成部分
AD-Hoc即ansible命令(单条临时命令)
Ansible Playbooks: 任务剧本(任务集),编排定义
1 2 3 4 5 6 7 8 9 10 11 12 |
Ansible-playbook(剧本) 执行过程 1.将已有编排好的任务集,写入ansable-playbook 2.通过ansable-playbook命令拆分任务集至逐条ansable命令 Ansible主要操作对象 1.HOST主机 2.NETWORKING网络设备 注意事项 1.执行Ansable的主机一般称为主控端,中控,master或堡垒机 2.主控端的Python版本需要2.6或以上 3.被控端Python版本小于2.4需要安装python-simplejson 4.被控端如果开启SELinux需要安装libseLinux-python 5.windows不能作为主控端 |
Ansible安装(yum)
1 2 3 4 |
设置rpm包安装:EPEL源: yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm yum install ansible -y |
Ansible编译安装
1 2 3 4 5 6 7 8 9 |
yum install python-jinja2 PyYAML python-paramiko python-bable python-crypto tar -zxvf ansible-1.5.4.tar.gz cd ansible-1.5.4 python setup.py build python setup.py install mkdir /opt/ansible cp -r examples/* /opt/ansible |
ansible主要配置文件
1 2 3 4 5 6 |
rpm -ql ansible| less /etc/ansible/ansible.cfg #主配置文件,一般不用动 /etc/ansible/hosts #主机清单,需要把你要管理的主机的清单写在这个里面 /etc/ansible/roles/ #角色清单,角色存放目录 |
ansible主程序
1 2 3 4 5 6 7 |
/usr/bin/ansible #主程序,临时命令执行工具 /usr/bin/ansible-doc #查看配置文档,模块功能查看工具(相当于man帮助) /usr/bin/ansible-galaxy #下载/上传优秀代码或roles模块官网平台 /usr/bin/ansible-playbook #定制自动化任务,编排剧本工具 /usr/bin/ansible-pull #远程命令执行工具 /usr/bin/ansible-vault #文件加密工具(加密playbook) /usr/bin/ansible-console #基于Console界面与用户交互的执行工具 |
ansible命令
1 2 |
ansible --version ansible --help |
例如:ansible执行ping模块测试与其他服务器状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
ansible [被控制主机ip] -m [option选项/模块] #如果对方服务器回应了,会返回一个pong ansible 192.168.66.179 -m ping -k(如果你没有配key可以先用-k 用密码登录连接) #需要先把要控制的主机加到清单里 vim /etc/ansible/hosts(这里的ping走的是ssh协议而不是snmp协议) ansible 192.168.66.179,192.168.66.180,192.168.66.181 -m ping -k #也可以是多个 如果你感觉这样写太麻烦,ansible提供了主机清单 1.ansible主要功能用于批量主机操作,为了便捷的使用其中的部分主机,可以在inventory file中将其分组命名 2.默认的inventory file为/etc/ansible/hosts 3.inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成 vim /etc/ansible/hosts [shooter] 192.168.66.179 192.168.66.180 192.168.66.181 也可以这样写,省事 [shooter] 192.168.66.17[0:9] 也可以带上账号密码 192.168.66.17 ansible_ssh_user=root ansible_ssh_pass=123456 那么这三个ip就属于 shooter 分组 ansible shooter -m ping -k |
附: 配置ansible免密码私钥登录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
1. 编辑开启私钥登录 vim /etc/ansible/ansible.cfg [ssh_connection] control_path =./ssh_keys #存放主机私钥目录 scp_if_ssh = True 2. 新建并复制私钥到指定目录 mkdir -p /etc/ansible/ssh_keys #新建 cp /root/.ssh/id_rsa /etc/ansible/ssh_key/id_rsa.key 3.然后配置ansible host ssh登录 [myhost] 192.168.0.212 ansible_ssh_private_key_file=ssh_keys/id_rsa.key ansible_ssh_user=root 4.在主机/root/.ssh下添加config(不添加登录不了哦还是要输入密码) vim config Host 192.168.0.205 HostName 192.168.0.205 User root Port 22 IdentityFile ~/.ssh/id_rsa IdentitiesOnly yes |

1 2 3 4 5 |
如果生产的机器使用的不是22端口,那么你就需要指定端口 [shooter] 192.168.66.179:55422 192.168.66.180:55789 192.168.66.181 |
配置文件讲解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#inventory = /etc/ansible/hosts #主机列表配置文件 #library = /usr/share/my_modules/ #库文件存放目录 #module_utils = /usr/share/my_module_utils/ #模块库文件存放目录 #remote_tmp = ~/.ansible/tmp #临时py文件存放在远程主机目录 #local_tmp = ~/.ansible/tmp #本机的临时命令执行目录 #plugin_filters_cfg = /etc/ansible/plugin_filters.yml #forks = 5 #默认并发数,每次同时执行5个主机,执行完轮询到下一组 #poll_interval = 15 # #sudo_user = root #默认sudo 用户 #ask_sudo_pass = True #每次执行ansible命令是否询问sudo ssh密码 #ask_pass = True #是否支持用户口令 #transport = smart #传输 #remote_port = 22 #默认ssh端口 #module_lang = C #module_set_locale = False #host_key_checking = False #检查远程主机的时候,是否去验证对方的公钥,这里最好是设置为false(强烈推荐启用) #log_path = /var/log/ansible.log #ansible日志存放目录(一般建议启用起来,可以记录我们管理了哪些主机,执行了哪些命令)(强烈推荐开启) #将ansible返回值设为json格式(方便获取有用的返回值) stdout_callback = json bin_ansible_callbacks = True |
jq 参数用法
1 2 3 4 5 6 7 8 9 10 11 |
-c 紧凑输出json数据 -e 根据输出结果设置命令退出状态码 -s 读取所有输入到一个数组 -r 输出原始字符串,而不是一个JSON格式 -C 高亮显示 -M 单色显示 -S 排序对象 --tab 使用tab缩进 例:/usr/bin/ansible dev -m script -a "/usr/bin/ps -ef | grep kedu-sale | grep -v grep | awk '{print \$2}'" | jq '.plays' | jq [.[].tasks[]] |
注意:ansible修改配置,不需要重启服务,执行命令即可生效
ansible-doc命令使用
1 2 3 4 5 6 |
例:查看命令如何使用:(例:查看ping命令如何使用) ansible-doc ping #查看ping命令如何使用 ansible-doc -l #列出当前的模块列表有哪些 ansible-doc -l | grep zabbix #查看zabbix有哪些模块 ansible-doc -l | wc -l #查看ansiable有多少个模块 |

1 2 |
ansible-doc -s moudul #简短介绍模块使用方法 ansible-doc modul #详细介绍模块使用方法 |
ansible命令使用
1 2 |
ansible all --list-host #查看当前管理的所有清单里的主机列表 ansible 192.168.6.121 -m ping #这条命令会以当前的用户来连接,如果你当前宿主机的用户是root,他就会以root连接 |

查看对方主机文件信息 -a ‘参数命令’
1 2 3 |
ansible 192.168.6.121 -m command -a 'cat /etc/passwd' #前提你的这个用户得有查看权限,command可以不写,默认就是command |

如果你想以其他用户来连接,他就会以其他用连接,如果你想换个身份连接,那么指定-u
1 2 3 4 5 6 7 8 9 10 |
ansible 192.168.6.121 -m command -u mars -a 'cat /etc/passwd' -k [密码] 如果mars没有权限,你需要使用-b命令切为root权限,当然你也需要输入sudo的密码-K(大写) ansible 192.168.6.121 -m command -a 'cat /etc/passwd' -u mars -k -b -K #此处会让你输入2次密码,一次是mars 的密码,一次是sudo的密码-K,mars账号必须在对方主机已经进行了sudo授权 visudo 给mars授权sudo |

通配符
1 2 3 |
ansible * -m ping ansible 192.168.2.* -m ping ...... |


ansible命令执行过程

查看ansible命令执行详细过程
1 2 3 |
ansible 192.168.6.121 -m ping -v ansible 192.168.6.121 -m ping -vv ansible 192.168.6.121 -m ping -vvv |
执行带$变量的命令,最好用shell模块,command不支持
1 2 3 4 5 |
例如:使用管道命令更改用户密码 echo 123456|passwd --stdin shooter ansible 192.168.6.121 -m shell -a 'echo 123456|passwd --stdin shooter' shell>command command能干的活shell都能干,所以后面还是用shell |

脚本模块script模块,可以批量在所有主机执行,当前ansible主机脚本命令
1 2 |
ansible shooter -m script -a '/root/script/hostname.sh' 获取所有主机的hostname |

copy模块
1 2 3 4 5 6 7 8 9 10 11 12 13 |
修改关闭远程主机的selinux,怎么改呢,先把自己本地主机的selinux拷贝一份,然后更改为disabled ,再用ansible拷贝到远程主机覆盖 ansible shooter -m copy 'src=/root/ansible/selinux dest=/etc/selinux/config backup=yes' content="生成文件的时候写文件内容" src:源,就是复制文件的路径 dest:复制到远程哪个目录的路径 backup=yes:是否备份原文件 mode=600:更改权限 owner=root:更改所有者 ansible shooter -m copy -a 'src=/root/script/hostname.sh dest=/root/ mode=644 owner=shooter' ansible shooter -m copy -a 'content="你好啊大佬" dest=/root/test.sh mode=644 owner=shooter' |

把远程主机文件抓取回来

synchronize模块
例1: 将主控方/tmp/test/ 目录文件推送到指定节点的/tmp/test/目录下。
1 |
ansible all -m synchronize -a "src=/tmp/test/ dest=/tmp/test/ compress=yes" |
1 |
ansible dev -m synchronize -a "src=/root/cctv-qs dest=/root/logs/cctv/ mode=push checksum=yes perms=yes owner=yes group=yes times=yes" |
1 2 3 4 5 6 7 8 9 10 |
执行效果: delete=yes 使两边的内容一样(即以推送方为主) compress=yes 开启压缩,默认为开启 checksum=yes 检测sum值,防止文件篡改,默认关闭 --exclude=.git 忽略同步.git 结尾的文件 由于模块,默认都是推送push。因此,如果你在使用拉取pull 功能的时候,可以参考如下来实现mode=pull 更改推送模式为拉取模式 |

file模块
1 2 3 4 5 |
ansible 192.168.6.121 -m file -a '' 批量删除 ansible all -m file -a 'name=/root/hostname.sh state=absent' #删除文件 创建软链接 ansible all -m file -a 'src=/root/ruanjian dest=/home/testfile-link state=link' |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
file:设置文件属性(状态,属组,属主,权限)不支持批删 ansible all -m file -a 'path=/root/a.sh owner=zhang mode=755' ansible all -m file -a 'src=/data/test1 dest=/tmp/test state=link' ansible all -m file -a 'name=/data/f3 state=touch' #创建文件 ansible all -m file -a 'name=/data/f3 state=absent' #删除文件 ansible all -m file -a 'name=/data state=directory' #创建目录 ansible all -m file -a 'src=/etc/fstab dest=/data/fstab.link state=link' archive打包模块 unarchive 解打包模块 hostname 管理主机名 ansible 192.168.10.24 -m hostname -a “name=kso-bj6-zw-zhangwei”#永久生效(但hosts文件需要手动更改) |
cron 计划任务
1 2 3 4 5 6 7 8 9 10 |
支持时间:minute,hour,day,month,weekday ansible all -m cron -a 'minute=*/5 weekday=1,3,5 job="/usr/sbin/ntpfata 172.16.0.1 & >/dev/null" name=Synctime' 创建任务 ansible all -m cron -a "disabled=true job='/usr/sbin/ntpfata 172.16.0.1 & >/dev/null' name=Synctime" 禁用任务(加#号注释) ansible all -m cron -a "disabled=no job='/usr/sbin/ntpfata 172.16.0.1 & >/dev/null' name=Synctime" 启用任务 ansible all -m cron -a 'state=absent name=Synctime' 删除任务 job:要执行的脚本命令 脚本命令要加双引号,命令也可以带参数,上面参数是个ip name:给计划任务起个名字 state:删除任务会使用到的状态 |

yum:管理包
1 2 3 4 5 6 |
ansible all -m yum -a 'name=httpd state=latest'安装 ansible all -m yum -a 'name=httpd disable_gpg_check=yes' 忽略key安装 ansible all -m yum -a 'name=dstat update_cache=yes' 更新缓存 ansible all -m yum -a 'name=httpd state=ansent' 卸载 [注:dstat--监控工具https://www.jianshu.com/p/49b259cbcc79] |
service:管理服务
1 2 3 4 |
ansible all -m service -a 'name=httpd state=stopped' ansible all -m service -a 'name=httpd state=started enabled=yes' #开启自启 ansible all -m service -a 'name=httpd state=reload' ansible all -m service -a 'name=httpd state=restart' |
user:管理用户
1 2 3 4 5 |
ansible all -m user -a 'name=user1 comment="test user" uid=2048 home=/data/home/user1 group=root' 创建用户,以及uid,家目录,并描述(comment) ansible all -m user -a 'name=zhangwei shell=/sbin/nologin system=yes home=/data/home/zhangwei' 创建不可登陆的系统用户 ansible all -m user -a 'name=zhangwei state=absent remove=yes'删除用户及家目录 system=yes :系统目录 |
group:管理组
1 2 3 4 |
ansible all -m group -a "name=testgroup system=yes gid=80" ansible all -m group -a "name=testgroup state=absent" gid:组id可有可无 |
在介绍ansible-galaxy playbook之前我们先来详细解下角色roles(深入浅出)
ansible角色Roles
1 |
roles角色,相当于把很多playbook综合到一起的一套应用 |
创建了一个示例角色,示例角色的目录结构如下:

我创建的示例角色的角色名为demorole,demorole目录就代表了这个角色,此目录中包含了defaults 、files 、handlers 、meta 、tasks 、templates 、vars等子目录,而且在defaults 、handlers 、meta 、tasks 、vars等目录中,还都有一个名为”main.yml”的文件,那么这样的目录结构代表了什么含义呢?我们一起来了解一下,在角色中,上述目录结构的作用如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
tasks目录:角色需要执行的主任务文件放置在此目录中,默认的主任务文件名为main.yml,当调用角色时,默认会执行main.yml文件中的任务,你也可以将其他需要执行的任务文件通过include的方式包含在tasks/main.yml文件中。 handlers目录:当角色需要调用handlers时,默认会在此目录中的main.yml文件中查找对应的handler defaults目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,通常,defaults/main.yml文件中的变量都用于设置默认值,以便在你没有设置对应变量值时,变量有默认的值可以使用,定义在defaults/main.yml文件中的变量的优先级是最低的。 vars目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,看到这里你肯定会有疑问,vars/main.yml文件和defaults/main.yml文件的区别在哪里呢?区别就是,defaults/main.yml文件中的变量的优先级是最低的,而vars/main.yml文件中的变量的优先级非常高,如果你只是想提供一个默认的配置,那么你可以把对应的变量定义在defaults/main.yml中,如果你想要确保别人在调用角色时,使用的值就是你指定的值,则可以将变量定义在vars/main.yml中,因为定义在vars/main.yml文件中的变量的优先级非常高,所以其值比较难以覆盖。 meta目录:如果你想要赋予这个角色一些元数据,则可以将元数据写入到meta/main.yml文件中,这些元数据用于描述角色的相关属性,比如 作者信息、角色主要作用等等,你也可以在meta/main.yml文件中定义这个角色依赖于哪些其他角色,或者改变角色的默认调用设定,在之后会有一些实际的示例,此处不用纠结。 templates目录: 角色相关的模板文件可以放置在此目录中,当使用角色相关的模板时,如果没有指定路径,会默认从此目录中查找对应名称的模板文件。 files目录:角色可能会用到的一些其他文件可以放置在此目录中,比如,当你定义nginx角色时,需要配置https,那么相关的证书文件即可放置在此目录中。 |
当然,上述目录并不全是必须的,也就是说,如果你的角色并没有相关的模板文件,那么角色目录中并不用包含templates目录,同理,其他目录也一样,一般情况下,都至少会有一个tasks目录。 具体请看这里大神讲解roles 传送门
Ansible-galaxy playbook

例: 下载角色
1 |
ansible-galaxy install nginxinc.nginx_controller_install |

删除角色:
1 2 3 |
直接使用rm -rf 删除目录或者用下面命令删除也行 ansible-galaxy remove nginxinc.nginx_controller_install |

下来写个简单的剧本:
1 2 3 4 5 6 7 8 9 |
vim test.yaml --- - hosts: vm remote_user: root tasks: - name: hello command: hostname |

这样这个简单的剧本就写完了,下来运行这个剧本
1 |
ansible-playbook test.yaml |

加密解密剧本

1 2 3 4 5 6 |
ansible-vault encrypt hello.yml 加密 ansible-vault decrypt hello.yml 解密 ansible-vault view hello.yml 查看 ansible-vault edit hello.yml 编辑加密文件 ansible-vault rekey hello.yml 修改口令 ansible-vault crete hello.yml 创建新文件 |
一旦加密,这个文件的内容就无法看清了

现在你想要运行这个剧本,就必须先解密,否则无法运行。
交互式命令 ansible-console

1 2 3 4 5 |
ansible-console command hostname 就相当于-a 'hostname' 当然也可以执行其他命令 例如:切换到某一台主机用命令 cd 192.168.6.179 |

Playbook

playbook使用yaml语言编写





Playbook核心元素

下面编写简单的yaml
1 2 3 4 5 6 7 8 9 10 11 |
--- - hosts: vm remote_user: root #以什么身份连接对方呢 tasks: #要执行的任务 - name: hello #任务描述 file: name=/root/new.txt state=touch #调用的模块,例如要新建文件,调用file模块(一个模块就是一个action 你也可以写成 action: [module] [参数]) #如果你有多个任务,除了建立文件你还想干点别的,可以继续在写任务描述,和下一个调用的模块 - name: okok shell: ls -l /root/ - name: install nginx yum: name=nginx |
然后检查一下剧本是否有语法错误
1 |
ansible-playbook -C test.yaml |

当剧本执行到某一模块执行错误,那么后续操作是不会再执行的。如果你想后续剧本继续执行,请在模块命令后加上 “|| /bin/true”

执行ansible-playbook

1 2 3 |
ansible-playbook -hosts test.yml --limit 192.168.6.179 #表明这个剧本只在这台机器执行,虽然这个test.yaml里hosts制定了主机群有三台,但是只让他在这台主机执行 ansible-playbook -hosts test.yml --list-tasks #列出脚本任务列表 |
一个模块对应一个name 一个模块对应一个name ,不要一个name对应多个模块 这样是不可以的。
如果没有指定路径src=files/xxx.txt,默认files获取的是当前用户家目录下
下来我们介绍Handlers 和 (通知(Notify)

1 |
notify用于在某个action被触发后,他就要通知handlers执行某项操作,类似于后置操作,比如配置文件发生改变,后置操作需要重启服务。 |
notify用法:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
--- - hosts: vm remote_user: root #以什么身份连接对方呢 tasks: #要执行的任务 - name: hello #任务描述 file: name=/root/new.txt state=touch #调用的模块,例如要新建文件,调用file模块 - name: okok shell: ls -l /root/ - name: install nginx apt: name=nginx - name: config file: src=/etc/nginx/config/nginx.conf dest=/root/config/nginx.conf backup=yes notify: restart service #当配置文件发生改变,触发handlers - name: start nginx service: name=nginx state=startd enabled=yes - name: checkcheck shell: netstat -nptl|grep 80 handlers: - name: restart service service: name=nginx state=restartd |
tags标签
tags相当于给其中一个action打了个标签,方便调用
例如:
1 2 3 4 5 6 7 8 9 10 11 12 |
--- - hosts: vm remote_user: root #以什么身份连接对方呢 tasks: #要执行的任务 - name: hello #任务描述 file: name=/root/new.txt state=touch #调用的模块,例如要新建文件,调用file模块 tags: sohello - name: okok shell: ls -l /root/ - name: install nginx apt: name=nginx |
在这样一段配置文件中,有个标签sohello,我可以单独只执行这个标签
1 2 3 4 5 |
ansible-playbook -t sohello main.yaml 也可以,执行多个标签,逗号分隔就好 ansible-playbook -t sohello,pychanm,... main.yaml 其中,多个动作公用一个标签也是可以的,当你执行的时候,所有叫这哥标签的action都会依次执行 |
下面我只执行sohello这个标签的action

vars变量

比如我们将创建文件的文件名定义为一个变量
1 2 3 4 5 6 7 |
--- - hosts: vm remote_user: root tasks: - name: create file file: name=/root/{{ filename }}.txt state=touch |
执行的时候需要使用-e传入变量名
1 2 3 4 5 |
ansible-playbook -e 'filename=mone' shooter.yaml 当然我们也可以定义多个变量,每个变量传入不同action ansible-playbook -e 'filename=mone toec=passdown' shooter.yaml |


在playbook里面也可以直接定义变量,具体如下
1 2 3 4 5 6 7 8 |
--- - hosts: vm remote_user: root tasks: - name: create file file: name=/root/{{ filename }}.txt state=touch vars: - filename: tangshao |
在主机组文件中定义变量
1.单个主机设置变量

2.为主机组设置变量

单一主机变量的优先级要高于,主机模块组变量
模板template
在实际生产环境中,不同主机的配置是不同的,那么我们利用copy模块复制到每个主机的配置文件不能完全一样,最好是能够根据当前主机情况生成适合自身的配置文件,那么怎么做呢,模板就起作用了。

模板语言是用jinjia2语言编写的
1 |
比如书写一个template模板,模板中可以调用setup的线管变量,自动根据不同机器自身情况灵活输出配置文件,然后playbook在task中对template进行调用. |
1 2 3 4 5 6 7 8 9 10 11 |
--- - hosts: vm remote_user: root tasks: - name: install package apt: name=nginx update_cache=yes - name: template template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf - name: start service service: name=nginx state=startd enabled=yes |
when条件判断

现在又出现一个新的需求,2台centos7,1台ubuntu,我的模板只支持centos7 ,并不支持ubuntu,所以我就要判断哪些机器是centos7,就使用yum模块安装,哪些机器是deban就使用apt命令安装。
1 2 3 4 5 6 7 8 9 10 11 |
--- - hosts: vm remote_user: root tasks: - name: "ReadHat install nginx" yum: name=nginx when: ansible_os_family=="RedHat" #当我的操心系统是ReadHat就执行yum这个模块来安装nginx - name "Deban install nginx" apt: name=nginx when: ansible_os_family=="Deban" #当我的操作系统是Deban就执行apt这个模块来安装nginx |
with_items迭代

需求,比如我要安装多个包,创建多个文件,难不成一直-name action -name action? 那要是1000个要写到什么时候
这个时候迭代,就可以替我们操作重复性任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
--- - hosts: vm remote_name: root tasks: - name:create file file: name=/home/test/{{item}} state=touch with_items: - file1 - file2 - file3 #这样我们就能创建三个新文件了,相当于for循环,类似,或者你要装多个安装包也是可以的 --- - hosts: vm remote_name: root tasks: - name:create file yum: name={{item}} with_items: - htop - sl - lrzsz |
例:当前有这样一个需求,要求创建三个用户组,并且给每个组添加对应用户,那么with_items就起到了作用

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
--- - hosts: vm remote_user: root tasks: - name: create some group group: name={{item}} state=present with_items: - gmuch1 - gmuch2 - gmuch3 - name: create some users user: name={{item.name}} group={{item.group}} state=present with_items: - {name: 'must1', group: 'gmuch1'} - {name: 'must2', group: 'gmuch2'} - {name: 'must3', group: 'gmuch3'} |

for循环:

例如现在有个,往nginx中添加多个网站配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
--- - hosts: vm remote_user: root vars: prots: - 81 - 82 - 83 name: - shooter1: woaini #键值对 - shooter2: wohenni tasks: - name: copy nginx conf template: src=for1.conf.j2 dest=/root/test/for1.conf |
template: for1.conf.j2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{% for port in ports %} server{ listen {{prot}} } {% endfor %} #循环取出上面ymal文件定义的ports值 or 加上if条件判断 {% for n in name %} {% if n.shooter1 is define %} {{n.shooter1}} {% endif%} {% endfor %} |

角色Roles

角色就是将playbook 剧本拆分开来,变量是变量,文件是文件,任务是任务。
我们来创建一个角色
1 2 3 4 |
mkdir -p .ansible/roles/nginx #nginx目录就代表了这个角色 nginx此目录中包含了defaults 、files 、handlers 、meta 、tasks 、templates 、vars等子目录. 而且在defaults 、handlers 、meta 、tasks 、vars等目录中,还都有一个名为"main.yml"的文件,那么这样的目录结构代表了什么含义呢? |

1 2 3 4 5 6 7 8 9 10 11 12 13 |
tasks目录:角色需要执行的主任务文件放置在此目录中,默认的主任务文件名为main.yml,当调用角色时,默认会执行main.yml文件中的任务,你也可以将其他需要执行的任务文件通过include的方式包含在tasks/main.yml文件中。 handlers目录:当角色需要调用handlers时,默认会在此目录中的main.yml文件中查找对应的handler defaults目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,通常,defaults/main.yml文件中的变量都用于设置默认值,以便在你没有设置对应变量值时,变量有默认的值可以使用,定义在defaults/main.yml文件中的变量的优先级是最低的。 vars目录:角色会使用到的变量可以写入到此目录中的main.yml文件中,看到这里你肯定会有疑问,vars/main.yml文件和defaults/main.yml文件的区别在哪里呢?区别就是,defaults/main.yml文件中的变量的优先级是最低的,而vars/main.yml文件中的变量的优先级非常高,如果你只是想提供一个默认的配置,那么你可以把对应的变量定义在defaults/main.yml中,如果你想要确保别人在调用角色时,使用的值就是你指定的值,则可以将变量定义在vars/main.yml中,因为定义在vars/main.yml文件中的变量的优先级非常高,所以其值比较难以覆盖。 meta目录:如果你想要赋予这个角色一些元数据,则可以将元数据写入到meta/main.yml文件中,这些元数据用于描述角色的相关属性,比如 作者信息、角色主要作用等等,你也可以在meta/main.yml文件中定义这个角色依赖于哪些其他角色,或者改变角色的默认调用设定,在之后会有一些实际的示例,此处不用纠结。 templates目录: 角色相关的模板文件可以放置在此目录中,当使用角色相关的模板时,如果没有指定路径,会默认从此目录中查找对应名称的模板文件。 files目录:角色可能会用到的一些其他文件可以放置在此目录中,比如,当你定义nginx角色时,需要配置https,那么相关的证书文件即可放置在此目录中。 |
下来我们来写一个简单的demo
1 2 3 4 5 6 |
需求: 1.创建nginx用户组 2.创建nginx用户,并加入用户组 3.安装nginx服务 4.创建nginx模板配置文件 5.启动服务 |
tasks目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
创建各个剧本 user.yaml 创建用户和用户组 nginx.yaml 安装nginx服务 template.yaml 创建模板文件 service.yaml 启动nginx服务 main.yaml 入口调用文件include [root@localhost tasks]# cat user.yaml - name: create group group: name={{groupname}} - name: create user user: name={{username}} group={{groupname}} [root@localhost tasks]# cat nginx.yaml - name: install nginx service yum: name=nginx [root@localhost tasks]# cat config.yaml - name: create config template: src=nginx.conf.j2 dest=/root/test/nginx.conf [root@localhost tasks]# cat service.yaml - name: start nginx service service: name=nginx state=started enabled=yes [root@localhost tasks]# cat main.yml - include: user.yaml - include: nginx.yaml - include: config.yaml - include: service.yaml [root@localhost tasks]# |
vars目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
main.yaml 模板变量 groupname: nginx username: nginx whomain: - serv1: name: www.test01.com port: 80 - serv2: name: www.test02.com port: 81 - serv3: name: www.test03.com port: 83 |
template目录
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
nginx.conf.j2 生成的nginx模板配置文件 nginx配置文件部分: {% for w in whomain %} server { listen {{w.port}}; server_name {{w.name}}; location ~/group([0-9])/M00 { alias /data-fdfs/storage/data; add_header Content-Disposition "attachment;filename=$arg_attname"; ngx_fastdfs_module; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } access_log /usr/local/nginx/logs/access.log main; } {% endfor %} |
角色根目录 nignx.yaml
1 2 3 4 5 6 7 |
nginx.yaml 角色调用文件 [root@localhost roles]# cat nginx.yaml - hosts: vm remote_user: root roles: - nginx #调用角色roles |
运行:
1 |
ansible-playbook nginx.yaml |

如果你想执行多个角色,那就在执行文件里继续调用角色即可
1 2 3 4 5 6 7 |
- hosts: vm remote_user: root roles: - role:nginx #调用角色roles - role:httpd - role:mysql ..... |
如果再当前角色nginx中想引用其他角色怎么办?
例如:我现在想在nginx里边去借调 httpd的copy剧本
1 2 3 4 5 |
- include: user.yaml - include: nginx.yaml - include: config.yaml - include: service.yaml - include: roles/httpd/tasks/copyfile.yaml #这样就可以调用别的角色剧本了,跨项目借调。 |
通过标签来执行角色
为角色定义标签:
1 2 3 4 5 6 |
- hosts: vm remote_user: root roles: - { role: nginx,tags: ['web','nginx'] } - { role: httpd,tags: ['web','httpd'] } - { role: mysql,tags: ['web','mysql'] } |
标签调用执行
1 2 3 4 5 |
当我们需要执行整套角色的时候,直接调用web标签即可 ansible-playbook -t web demo.yaml 当我们只需要执行单个角色的时候,调用单个角色标签即可,mysql,httpd ... ansible-playbook -t httpd demo.yaml |
如果我想在特定的条件下才去执行某个标签,那么需要when语句
1 2 3 4 5 6 |
- hosts: vm remote_user: root roles: - { role: nginx,tags: ['web','nginx'], when ansible_distribution_major_version=="7"} #这样的话 只有系统版本是centos 7才会执行 - { role: httpd,tags: ['web','httpd'] } - { role: mysql,tags: ['web','mysql'] } |
基础使用就到这。
这里有大神的有道云笔记:传送门
1 |
其他文档详见https://blog.51cto.com/u_16099194/9998585 |
- 本文固定链接: https://www.yoyoask.com/?p=3842
- 转载请注明: shooter 于 SHOOTER 发表