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:

nginx_vhosts:

- 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:

nginx_vhosts:

- 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 %}

 

上一篇:ansible简述


下一篇:Ansible-playbook 安装redis