Ansible之playbook
【介绍】
Playbook与ad-hoc(点对点)相比,是一种完全不同的运用ansible的方式。
playbook是由一个或者多个play组成的列表,让他们可以联同起来同时按照预先编排好的机制执行。
task呢,其实更简单,其实就是调用ansible的一个模块。
要注意的是,模块执行是幂等的,意思是说,多次执行结果一致。
【核心元素】
Host |
执行的远程主机列表 |
Tasks |
任务集 |
Varniables |
内置变量或自定义变量在playbook中调用 |
Templates |
模板,即使用模板语法的文件,比如配置文件等 |
Handlers |
和notity结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行 |
tags |
标签,指定某条任务执行,用于选择运行playbook中的部分代码 |
【语法】
使用yaml语法格式,后缀可以是yaml,也可以是yml
单一playbook文件中,” — “区分多个play,” … “代表play结尾(可省略)。
次行一般为描述。
缩进必须统一。
k/v的值可同行写也可以换行写。同行使用:分隔。
v可以是个字符串,也可以是一个列表
最少元素包括 name: task
【示例】
# 创建playbook文件 [root@ansible ~]# cat playbook01.yml — #固定格式 – hosts: 192.168.1.31 #定义需要执行主机 remote_user: root #远程用户 vars: #定义变量 http_port: 8088 #变量
tasks: # 定义一个任务的开始 – name: create new file # 定义任务的名称 file: name=/tmp/playtest.txt state=touch # 调用模块,具体要做的事情
– name: create new user user: name=test02 system=yes shell=/sbin/nologin
– name: install package yum: name=httpd
– name: config httpd template: src=./httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: # 定义执行一个动作(action)让handlers来引用执行,与handlers配合使用 – restart apache # notify要执行的动作,这里必须与handlers中的name定义内容一致
– name: copy index.html copy: src=/var/www/html/index.html dest=/var/www/html/index.html
– name: start httpd service: name=httpd state=started
handlers: # 处理器:tasks中notify定义的action触发执行相应的处理动作 – name: restart apache # 要与notify定义的内容相同 service: name=httpd state=restarted # 触发要执行的动作 |
【常用选项】
–check or -C |
#只检测可能会发生的改变,但不真正执行操作 |
–list-hosts |
#列出运行任务的主机 |
–list-tags |
#列出playbook文件中定义所有的tags |
–list-tasks |
#列出playbook文件中定义的所以任务集 |
–limit |
#主机列表 只针对主机列表中的某个主机或者某个组执行 |
-f |
#指定并发数,默认为5个 |
-t |
#指定tags运行,运行某一个或者多个tags。(前提playbook中有定义tags) |
-v |
#显示过程 -vv -vvv更详细 |
【元素属性】
主机以及用户
— – hosts: 192.168.1.31 remote_user: root |
除此之外,在tasks内也可以专门指定远程用户
tasks: – name: run df -h remote_user: test shell: name=df -h |
也可以指定sudo:
tasks: – name: run df -h sudo_user: test sudo: yes shell: name=df -h |
每一个playbook中可以包含一个或者多个tasks任务列表;
每一个task必须有一个名称name:
tasks: – name: create new file file: path=/tmp/test01.txt state=touch – name: create new user user: name=test001 state=present |
notify actions会在playbook的每一个task结束时被触发;
即使有多个不同task通知改动的发生,notify actions知会被触发一次:
[root@ansible ~]# cat httpd.yml #用于安装httpd并配置启动 — – hosts: 192.168.1.31 remote_user: root
tasks: – name: install httpd yum: name=httpd state=installed – name: config httpd template: src=/root/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: – restart httpd – name: start httpd service: name=httpd state=started
handlers: – name: restart httpd service: name=httpd state=restarted |
【变量】
这里配置了两个组,一个apache组和一个nginx组
[root@ansible PlayBook]# cat /etc/ansible/hosts [apache] 192.168.1.36 192.168.1.33
[nginx] 192.168.1.3[1:2] |
执行playbook时候通过参数-e传入变量,这样传入的变量在整个playbook中都可以被调用,属于全局变量:
[root@ansible PlayBook]# cat variables.yml — – hosts: all remote_user: root
tasks: – name: install pkg yum: name={{ pkg }}
#执行playbook 指定pkg [root@ansible PlayBook]# ansible-playbook -e “pkg=httpd” variables.yml |
也可以在文件中定义变量;
可以针对每个主机(优先级更高)定义不同的变量,也可以定义一个组的变量:
# 编辑hosts文件定义变量 [root@ansible PlayBook]# vim /etc/ansible/hosts [apache] 192.168.1.36 webdir=/opt/test #定义单个主机的变量 192.168.1.33 [apache:vars] #定义整个组的统一变量 webdir=/web/test
[nginx] 192.168.1.3[1:2] [nginx:vars] webdir=/opt/web |
# 编辑playbook文件 [root@ansible PlayBook]# cat variables.yml — – hosts: all remote_user: root
tasks: – name: create webdir file: name={{ webdir }} state=directory #引用变量
# 执行playbook [root@ansible PlayBook]# ansible-playbook variables.yml |
如果在执行playbook时,又通过-e参数指定变量的值,那么会以-e参数指定的为准。
调用setup模块获取变量:
# 编辑playbook文件 [root@ansible PlayBook]# cat variables.yml — – hosts: all remote_user: root
tasks: – name: create file file: name={{ ansible_fqdn }}.log state=touch #引用setup中的ansible_fqdn
# 执行playbook [root@ansible PlayBook]# ansible-playbook variables.yml |
也可以将所有的变量统一放在一个独立的变量YAML文件中,laybook文件直接引用文件调用变量即可:
# 定义存放变量的文件 [root@ansible PlayBook]# cat var.yml var1: vsftpd var2: httpd
# 编写playbook [root@ansible PlayBook]# cat variables.yml — – hosts: all remote_user: root vars_files: #引用变量文件 – ./var.yml #指定变量文件的path(这里可以是绝对路径,也可以是相对路径)
tasks: – name: install package yum: name={{ var1 }} #引用变量 – name: create file file: name=/tmp/{{ var2 }}.log state=touch #引用变量
# 执行playbook [root@ansible PlayBook]# ansible-playbook variables.yml |
【标签】
通过 -t选择指定标签执行,也可以通过 –skip-tags选择除了某个标签外全部执行。
# 编辑playbook [root@ansible PlayBook]# cat httpd.yml — – hosts: 192.168.1.31 remote_user: root
tasks: – name: install httpd yum: name=httpd state=installed tags: inhttpd
– name: start httpd service: name=httpd state=started tags: sthttpd
– name: restart httpd service: name=httpd state=restarted tags: – rshttpd – rs_httpd |
只执行任务3
ansible-playbook -t rshttpd httpd.yml
执行任务2,3
ansible-playbook –skip-tags inhttpd httpd.yml
【template】
使用jinja2语言,提供动态配置服务
[root@ansible PlayBook]# cat testtmp.yml #模板示例 — – hosts: all remote_user: root vars: – listen_port: 88 #定义变量
tasks: – name: Install Httpd yum: name=httpd state=installed – name: Config Httpd template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf #使用模板 notify: Restart Httpd – name: Start Httpd service: name=httpd state=started
handlers: – name: Restart Httpd service: name=httpd state=restarted |
httpd.conf.j2:
Listen {{ listen_port }} |
使用when;
两个配置文件:
[root@ansible PlayBook]# tree templates/ templates/ ├── httpd6.conf.j2 #6系统2.2.15版本httpd配置文件 └── httpd7.conf.j2 #7系统2.4.6版本httpd配置文件
0 directories, 2 files |
通过setup模块获取系统版本去判断:
[root@ansible PlayBook]# cat testtmp.yml #when示例 — – hosts: all remote_user: root vars: – listen_port: 88
tasks: – name: Install Httpd yum: name=httpd state=installed – name: Config System6 Httpd template: src=httpd6.conf.j2 dest=/etc/httpd/conf/httpd.conf when: ansible_distribution_major_version == “6” #判断系统版本,为6便执行上面的template配置6的配置文件 notify: Restart Httpd – name: Config System7 Httpd template: src=httpd7.conf.j2 dest=/etc/httpd/conf/httpd.conf when: ansible_distribution_major_version == “7” #判断系统版本,为7便执行上面的template配置7的配置文件 notify: Restart Httpd – name: Start Httpd service: name=httpd state=started
handlers: – name: Restart Httpd service: name=httpd state=restarted |
当有需要重复性执行的任务时,可以使用迭代机制with_items:
[root@ansible PlayBook]# cat testwith.yml # 示例with_items — – hosts: all remote_user: root
tasks: – name: Install Package yum: name={{ item }} state=installed #引用item获取值 with_items: #定义with_items – httpd – vsftpd – nginx |
[root@ansible PlayBook]# cat testwith01.yml # 示例with_items嵌套子变量 — – hosts: all remote_user: root
tasks: – name: Create New Group group: name={{ item }} state=present with_items: – group1 – group2 – group3
– name: Create New User user: name={{ item.name }} group={{ item.group }} state=present with_items: – { name: ‘user1’, group: ‘group1’ } – { name: ‘user2’, group: ‘group2’ } – { name: ‘user3’, group: ‘group3’ } |
for,if;
[root@ansible PlayBook]# cat testfor01.yml # template for 示例 — – hosts: all remote_user: root vars: nginx_vhost_port: – 81 – 82 – 83
tasks: – name: Templage Nginx Config template: src=nginx.conf.j2 dest=/tmp/nginx_test.conf # 循环playbook文件中定义的变量,依次赋值给port [root@ansible PlayBook]# cat templates/nginx.conf.j2 {% for port in nginx_vhost_port %} server{ listen: {{ port }}; server_name: localhost; } {% endfor %} |
[root@ansible PlayBook]# cat testfor02.yml # template for 示例 — – hosts: all remote_user: root vars:
– web1: listen: 8081 server_name: “web1.example.com” root: “/var/www/nginx/web1” – web2: listen: 8082 server_name: “web2.example.com” root: “/var/www/nginx/web2” – web3: listen: 8083 server_name: “web3.example.com” root: “/var/www/nginx/web3” tasks: – name: Templage Nginx Config template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf [root@ansible PlayBook]# cat templates/nginx.conf.j2 {% for vhost in nginx_vhosts %} server{ listen: {{ vhost.listen }}; server_name: {{ vhost.server_name }}; root: {{ vhost.root }}; } {% endfor %} |
[root@ansible PlayBook]# cat testfor03.yml # template for 示例 — – hosts: all remote_user: root vars:
– web1: listen: 8081 root: “/var/www/nginx/web1” – web2: server_name: “web2.example.com” root: “/var/www/nginx/web2” – web3: listen: 8083 server_name: “web3.example.com” root: “/var/www/nginx/web3” tasks: – name: Templage Nginx Config template: src=nginx.conf.j2 dest=/tmp/nginx_vhost.conf [root@ansible PlayBook]# cat templates/nginx.conf.j2 {% for vhost in nginx_vhosts %} server{ {% if vhost.listen is defined %} listen: {{ vhost.listen }}; {% else %} listen: 8888; {% endif %} {% if vhost.server_name is defined %} server_name: {{ vhost.server_name }}; {% endif %} root: {{ vhost.root }}; } {% endfor %} |