简介
在ansible中playbook是由多个play组成的列表
paly的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色,从根本上讲,所谓的task无非是调用ansible的module讲多个play组织在一个playbook中,即可以让它们连同起来按事先编排好的机制运行
palybook采用的是YAML语言编写的
palybook核心元素
hosts # 执行的远程主机列表
tasks # 任务集
varniables # 内置变量或者自定义变量在playbook中调用
templates # 模板,可替换模板文件中的变量并实现一些简单的逻辑文件
handlers和notify # 两个集合使用,由特点条件触发的操作,满足条件方才执行,否则不执行
tags # 标签,指定某条件任务执行,用于选择运行playbook中的部分代码
# ansible具有幂等性,因此会自动跳过没有变化的代码,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常的长,此时,如果确信其没有变化,就可以通过tags跳过这些代码
常用元素示例
hosts元素
hosts元素 指定被控端的远程主机列表 [root@ansible ~]# vim /root/ansible/hosts.yml --- - hosts: web remote_user: root 在hosts后面的主机列表形式可以是单个主机的主机名、IP地址、组名,或者两个组的并集、交集、差集,比如: brian.com # 单个主机名 192.168.192.129 # 单个IP web # 一个组名 web:db # 两个组的并集 web:!db # 两个组的差集 web:&db # 两个组的交集 remote_user表示的是执行远程的用户,一般为root
tasks元素
tasks元素 指定要执行的任务集 [root@ansible ~]# vim /root/ansible/tasks.yml --- - hosts: web remote_user: root tasks: - name: create new file file: name=/root/ansible/newfile state=touch - name: create new user user: name=zhujingzhi state=present system=yes shell=/sbin/onlogin 这里tasks元素里面写的就是要执行的任务 name 表示一个描述信息 file和user表示使用的模块名,后面跟着的就是使用模块操作的具体的使用方法(这里使用file模块在/root/ansible/创建了一个新的文件,使用user模块创建了一个zhujingzhi的用户)
handlers和notify元素
handlers和notify元素 notify元素,在tasks中的某段代码中定义,作为handlers的触发器(当tasks中的代码中触发到notify的元素,则会执行notify指定的handlers中的代码) handlers元素属于和tasks同级的列表,其主要作用是定义一个任务(和tasks中的任务是一样的)等待tasks中任务触发notify后执行 [root@ansible ~]# vim /root/ansible/nginx.yml --- - hosts: web remote_user: root tasks: - name: install nginx yum: name=nginx - name: copy nginx config file copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes notify: - restart nginx - check service - name: start nginx service: name=nginx state=started enabled=yes handlers: - name: restart nginx service: name=nginx state=restarted - name: check service shell: killall -0 nginx > /tmp/nginx.log 这里在运行的时候出现了在被管理机器上没有killall的命令的错误,解决方法(yum -y install psmisc) killall -0 nginx 的意思就是检查nginx的进程有没有启动返回0启动,返回非0服务有问题
tags元素
tags元素 tags元素为tasks里面的任务打上一个标签,方便在执行的时候单独执行tasks里面的单独的任务和被其他调用 [root@ansible ~]# vim /root/ansible/nginx.yml --- - hosts: web remote_user: root tasks: - name: install nginx yum: name=nginx tags: installnginx - name: copy nginx config file copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes notify: - restart nginx - check service - name: start nginx service: name=nginx state=started enabled=yes tags: startnginx handlers: - name: restart nginx service: name=nginx state=restarted - name: check service shell: killall -0 nginx > /tmp/nginx.log 可单独执行tasks里面的startnginx任务 [root@ansible ~]# ansible-playbook -t startnginx /root/ansible/nginx.yml 也可以指定两个标签执行 [root@ansible ~]# ansible-playbook -t installnginx,startnginx /root/ansible/nginx.yml 温馨提示: 这里多个任务也是可以使用一个标签的名字的 比如: [root@ansible ~]# vim /root/ansible/nginx.yml --- - hosts: web remote_user: root tasks: - name: install nginx yum: name=nginx tags: nginx - name: copy nginx config file copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes notify: - restart nginx - check service - name: start nginx service: name=nginx state=started enabled=yes tags: nginx handlers: - name: restart nginx service: name=nginx state=restarted - name: check service shell: killall -0 nginx > /tmp/nginx.log 使用ansible执行(加-t参数) [root@ansible ~]# ansible-playbook -t nginx /root/ansible/nginx.yml
vars元素
vars元素 vars元素指的是定义变量 变量名:仅能由字母、数字和下划线组成,且只能以字母开头 可以在什么地方定义变量呢?如下: 1.ansible setup facts 远程主机的所有变量都是可以被直接调用的 2.在/etc/ansible/hosts中定义 普通变量:主机组中主机单独定义,优先级高于公共变量 公共(组)变量:针对主机组中所有主机定义统一的变量 3.通过命令行指定变量,优先级最高 ansible-playbook -e varname=value 4.在playbook中定义 vars: - var1: value1 - var2: value2 5.在role中定义(role是模块化的设置模式,在role中var可以定义在一个单独的文件中) 示例: 1.ansible setup查看变量 # 查看所有的远程主机上的可用变量 [root@ansible ~]# ansible all -m setup # grep过滤查看主机名的变量 [root@ansible ~]# ansible all -m setup | grep ansible_fqdn # setup模块的filter方法过滤查看主机名 [root@ansible ~]# ansible all -m setup -a "filter=ansible_hostname" 2.在/etc/ansible/hosts中定义 [root@ansible ~]# vim /etc/ansible/hosts [testserver] 192.168.192.129 http_port=8080 在playbook中使用 --- - hosts: web remote_user: root tasks: - name: set hostname hostname: name=brian{{ http_port }}.python.com 详细的设置请查看:https://www.cnblogs.com/brianzhu/p/10188676.html 3.通过命令行指定变量,优先级最高 playbook的定义如下(使用{{}}双大括号定义中间是变量名): --- - hosts: web remote_user: root tasks: - name: install nginx yum: name={{ pkname1 }} - name: install nginx yum: name={{ pkname1 }} - name: copy nginx config file copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes - name: start nginx service: name={{ pkname }} state=started enabled=yes 在命令行执行指定(使用 -e 参数指定变量变量赋值的定义格式是k=v格式) [root@ansible ~]# ansible-playbook -e 'pkname1=nginx pkname2=vsftpd' /root/ansible/nginx.yml 4.在playbook中定义 直接是用vars元素定义变量列表 --- - hosts: web remote_user: root vars: - pkname1: nginx - pkname2: vsftpd tasks: - name: install nginx yum: name=nginx - name: copy nginx config file copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes - name: start nginx service: name=nginx state=started enabled=yes 5.将使用的变量存放到一个文件中,在playbook里面调用 编辑变量文件 [root@ansible ~]# cat /root/ansible/vars.yml var1: nginx var2: nsftpd 在playbook中调用 --- - hosts: web remote_user: root vars_files: - vars.yml tasks: - name: install nginx yum: name={{ var1 }} - name: install vsftpd yum: name={{ var2 }}
templates元素
templates元素 主要是对配置文件进行远程主机的copy(能够实现根据不同的主机的配置修改不同的配置文件) templates 文件也是一个文本文件,嵌套有脚本(使用模板编程语言编写) 模板文件的编程语言使用的是jinja2语言,支持下面的类型: 字符串: 使用单引号或者双引号 数字: 整数,浮点数 列表: [item1,item2,..] 元组: (item1,item2,..) 字典: {key1:value1,key2:value2,..} 布尔值: true/false 算数运算符: +,-,*,/,//,%,** 比较运算符: ==,!=,>,>=,<,<= 逻辑运算符: and,or,not 流表达式: for if when 示例: 使用nginx的打开的进程数为示例 创建模板目录 [root@ansible ~]# mkdir -p /root/ansible/templates 编辑模板文件 在ansible管理机上安装nginx,并copy nginx.conf到/root/ansible/templates中并改名为nginx.conf.j2(改名是必须的这个是模块的规定) [root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx.conf.j2 这里编辑nginx的模板文件将进程数**2 修改/root/ansible/templates/nginx.conf.j2 [root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2 将 worker_processes auto;改成 worker_processes {{ ansible_processor_vcpus**2 }}; 这里ansible_processor_vcpus是使用ansible setup得到的远程主机的cpu的个数 编写playbook [root@ansible ~]# vim /root/ansible/nginxtemp.yml --- - hosts: web remote_user: root tasks: - name: install nginx yum: name=nginx - name: copy templates file template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf notify: restart nginx - name: start nginx service: name=nginx state=started enabled=yes handlers: - name: restart nginx service: name=nginx state=restarted 执行playbook [root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml 查看结果 这里我的机器是2个CPU的,刚刚在nginx模板文件中设置了worker_processes {{ ansible_processor_vcpus**2 }};所有最后开启的进程是4个 [root@ansible ~]# ansible all -m shell -a "ps aux |grep nginx" 192.168.192.129 | CHANGED | rc=0 >> root 6127 0.0 0.1 125092 2256 ? Ss 17:09 0:00 nginx: master process /usr/sbin/nginx nginx 6128 0.0 0.3 129348 7080 ? S 17:09 0:00 nginx: worker process nginx 6129 0.0 0.3 129348 7080 ? S 17:09 0:00 nginx: worker process nginx 6130 0.0 0.3 129348 7080 ? S 17:09 0:00 nginx: worker process nginx 6131 0.0 0.3 129348 7080 ? S 17:09 0:00 nginx: worker process 模板文件使用变量(改变nginx端口) 这里把变量定义在了/etc/ansible/hosts中为每台主机定义的(也可以使用上面提到的其他方式定义变量) 设置变量 [root@ansible ~]# vim /etc/ansible/hosts [web] 192.168.192.129 http_port=8080 设置模板文件 [root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2 修改: listen {{ http_port }} default_server; listen [::]:{{ http_port }} default_server; 执行playbook [root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml 查看结果 [root@ansible ~]# ansible all -m shell -a "ss -ntl | grep 8080" 192.168.192.129 | CHANGED | rc=0 >> LISTEN 0 128 *:8080 *:* LISTEN 0 128 :::8080 :::*
跳过错误继续执行
作用主要是为了解决在playbook中的tasks元素中某段代码执行出现问题是否继续往下执行的一个解决的方法(其默认是出错及停止的) playbook文件 --- - hosts: web remote_user: root tasks: run this command and ignore the resullt - name: shell start nginx shell: /usr/bin/somecommand || /bin/true 或者 --- - hosts: web remote_user: root tasks: - name: run this command and ignore the resullt shell: /usr/bin/somecommand ignore_errors: True
流程控制语句
when语句
when语句 when语句表示条件的测试,如果需要根据变量、facts或者此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过when语句就可以实现 示例: 在生产环境中系统有6的和7的共存的情况,那么配置有些配置文件在不同的操作系统上是不一样的,这时候我们就要创建两个模板文件根据不同的操作系统执行不同的配置文件copy # 定义两个配置文件 [root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx6.conf.j2 [root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx7.conf.j2 编写playbook [root@ansible ~]# vim /root/ansible/nginxtemp.yml --- - hosts: web remote_user: root tasks: - name: install nginx yum: name=nginx - name: copy templates file for centos7 template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf when: ansible_distribution_major_version == '7' notify: restart nginx - name: copy templates file for centos6 template: src=nginx6.conf.j2 dest=/etc/nginx/nginx.conf when: ansible_distribution_major_version == '6' notify: restart nginx - name: start nginx service: name=nginx state=started enabled=yes handlers: - name: restart nginx service: name=nginx state=restarted
with_items语句
with_items语法 with_items表示迭代,当需要执行重复性的任务的时候,就可以使用迭代机制来实现 对于迭代的引用,固定的变量名为"item" 要在tasks中使用with_items给定要迭代的元素列表 支持的列表格式:字符串、字典 示例: 同时执行创建多个文件的任务 编写playbook [root@ansible ~]# vim /root/ansible/items.yml --- - hosts: web remote_user: root tasks: - name: create file file: name=/root/ansible/{{ item }} state=touch with_items: - file1 - file2 - file3 - name: install packages yum: name={{ item }} with_items: - htop - sl - hping3
迭代嵌套子变量
迭代嵌套子变量 创建多个组和用户将多个用户加入到不同的组中 编写playbook [root@ansible ~]# vim /root/ansible/guser.yml --- - hosts: web remote_user: root tasks: - name: add groups group: name={{ item }} state=present with_items: - g1 - g2 - g3 - name: add user for goups user: name={{ item.name }} group={{ item.group }} state=present with_items: - { name: 'user1', group: 'g1'} - { name: 'user2', group: 'g2'} - { name: 'user3', group: 'g3'}
for语句
for语句 最后需要使用for语句生成的例子 server { listen: 81 } server { listen: 82 } server { listen: 83 } 这里需要使用模板文件和变量来配合使用生成 palybook编写 [root@ansible ~]# vim /root/ansible/testfor.yml --- - hosts: web remote_user: root vars: ports: - 81 - 82 - 83 tasks: - name: create for config template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf 模板文件编写 [root@ansible ~]# vim /root/ansible/testfor.conf.j2 {% for p in ports %} server { listen {{ p }} } {% enfor %} 执行playbook [root@ansible ~]# ansible-playbook /root/ansible/testfor.yml 查看结果 [root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf" 192.168.171.129 | CHANGED | rc=0 >> server { listen: 81 } server { listen: 82 } server { listen: 83 } 通过模板文件来获取playbook文件中的设置好的变量并通过for语句进行多次循环(playbook中使用的变量是列表的形式),这样的方式使用起来其实是很灵活的,也可以是上面的列表的形式,也可以是使用字典的形式或者列表嵌套字典的形式 比如: playbook文件 --- - hosts: web remote_user: root vars: weblist: - web: port: 81 name: python.brian.com rootdir: /nginx/python - web2: port: 82 name: php.brian.com rootdir: /nginx/php tasks: - name: create for config template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf 模板文件 {% for w in weblist %} server { listen {{ w.port }} servername {{ w.name }} documentroot {{ w.rootdir }} } {% endfor %}
if语句
if语句 在for语句中使用,判断playbook中有没有设置变量,设置了生成,没有则不生成,这里只是举例子,还有其他使用的方式,比如一个变量等于大于小于多少执行什么任务等等 [root@ansible ~]# vim /root/ansible/testfor.yml playbook文件 --- - hosts: web remote_user: root vars: weblist: - web: port: 81 rootdir: /nginx/python - web2: port: 82 name: php.brian.com rootdir: /nginx/php tasks: - name: create for config template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf 模板文件 [root@ansible ~]# vim /root/ansible/testfor.conf.j2 {% for w in weblist %} server { listen {{ w.port }} {% if w.name is defined %} servername {{ w.name }} {% endif %} documentroot {{ w.rootdir }} } {% endfor %} 执行playbook [root@ansible ~]# ansible-playbook /root/ansible/testfor.yml 查看结果 [root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf" 192.168.171.129 | CHANGED | rc=0 >> server { listen 81 documentroot /nginx/python } server { listen 82 servername php.brian.com documentroot /nginx/php }
上面的示例只是少部分的流程控制语句
温馨提示:
上面是我在生产中常用的元素,语句,这里主要是把每个元素分开来写的,其实真正的playbook是要把上面的元素语句等结合一起使用的