Ansible Playbooks

Playbooks简介

与ad-hoc任务执行模式相比,Playbooks使用ansible是一种完全不同的方式,并且功能特别强大。

简而言之,playbooks是真正简单的配置管理和多机器部署系统的基础,与已有的系统不同,并且非常适合部署复杂的应用程序。

Playbooks可以声明配置,但它们也可以协调任何手动有序流程的步骤,即使不同的步骤必须按照特定顺序在机器组之间来回跳转。它们可以同步或异步启动任务。
更多playbooks的介绍参考官方文档

Playbooks以YAML格式表示(请参阅YAML语法),具有最少的语法,它不是编程语言或脚本,而是配置或进程的模型。

每个剧本由列表中的一个或多个“戏剧”组成。戏剧的目标是将一组主机映射到一些定义明确的角色,由ansible调用任务表示。在基本级别,任务只不过是对ansible模块的调用(请参阅使用模块)。

通过编写多个“戏剧”的剧本,可以编排多机部署,在Web服务器组中的所有计算机上运行某些步骤,然后在数据库服务器组上执行某些步骤,然后在Web服务器组上执行更多命令,等等。。

你可以有很多戏剧影响你的系统做不同的事情。这并不是说你只是定义了一个特定的状态或模型,而是可以在不同的时间运行不同的戏剧。

Playbooks Demo

以下是只包含一个戏剧的剧本:

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
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service:
name: httpd
state: started
handlers:
- name: restart apache
service:
name: httpd
state: restarted

  • 文件开头三个横杠代表yaml文件。
  • hosts表示一个主机组。
  • tasks表示动作集合。
  • name是一个注释说明。
  • yum和下面两行,表示使用yum安装最新版的httpd。
  • template和下面两行,表示使用ansible的template模块传输/srv/httpd.j2作为客户机的/etc/httpd.conf。和copy相比,template支持jinja语法。
  • notify和下面一行,表示传输成功后触发重启apache命令。它需要和handlers组合使用。
  • handlers中的name和notify中的信息要完全相同。service和下面两行,表示重启httpd。

Playbooks可以包含多个戏剧。您可能有一个首先针对Web服务器,然后是数据库服务器的playbook。例如:

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
---
- hosts: webservers
remote_user: root

tasks:
- name: ensure apache is at the latest version
yum:
name: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf

- hosts: databases
remote_user: root

tasks:
- name: ensure postgresql is at the latest version
yum:
name: postgresql
state: latest
- name: ensure that postgresql is started
service:
name: postgresql
state: started

入门实例

目标:编写一个playbook,在客户机上安装chrony,然后检查启动情况。

1、新建chrony.yml,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
---
- hosts: commonservers
tasks:
- name: install chrony
apt:
name: chrony
state: latest
notify:
- restart chrony
- name: ensure chrony is running
service:
name: chrony
state: started
handlers:
- name: restart chrony
service:
name: chrony
state: restarted

上面的playbook中用到了apt模块,如果有疑问可以查看帮助,ansible-doc apt。实际上,有一种更加简单的写法,就是把apt模块换成command模块,然后直接写命令。

2、检查playbook
ansible-playbook chrony.yml --syntax-check

3、以sudo权限执行playbook
ansible-playbook chrony.yml --user=voidking --private-key=/home/voidking/.ssh/id_rsa -s

4、在客户机测试
chronyc sources

角色

如果需要将一个大文件拆分为各个小文件,我们经常使用的就是include,这也是原先ansible拆分文件的做法。如今ansible使用roles来拆分文件,将nginx、mysql等分为各个角色,在各个角色内定义具体的小任务,方便管理。另一方面,类似于php类的自动加载,roles基于一个已知的文件结构,可以自动去加载某些vars_files、tasks、handlers等。

目标:使用角色的方式,编写配置playbook,在客户机上安装chrony,然后检查启动情况。

1、创建chrony角色目录
mkdir -p roles/chrony/tasks

mkdir -p roles/chrony/handlers

2、创建总的入口文件site.yml,内容为:

1
2
3
4
---
- hosts: commonservers
roles:
- chrony

3、创建安装剧本
vim roles/chrony/tasks/main.yml,内容为:

1
2
3
4
5
6
7
8
9
10
11
---
- name: install chrony
apt:
name: chrony
state: latest
notify:
- restart chrony
- name: ensure chrony is running
service:
name: chrony
state: started

vim roles/chrony/handlers/main.yml,内容为:

1
2
3
4
5
---
- name: restart chrony
service:
name: chrony
state: restarted

4、以sudo权限执行playbook
ansible-playbook site.yml --user=voidking --private-key=/home/voidking/.ssh/id_rsa -s

5、在客户机测试
chronyc sources

简单编程

变量

1
2
3
4
5
6
7
8
9
10
11
12
13
---
- hosts: commonservers
vars:
pre1: all info is
pre2: hostname is
tasks:
- name: register vars
shell: hostname
register: info
- name: display info
debug: msg="{{pre1}} {{info}}"
- name: display hostname
debug: msg="{{pre2}} {{info.stdout}}"

基本循环

1
2
3
4
5
6
7
8
9
---
- hosts: commonservers
tasks:
- name: loops demo
debug: msg="{{item}}"
with_items:
- one
- two
- three

循环字典

1
2
3
4
5
6
7
8
9
---
- hosts: commonservers
tasks:
- name: loops dict
debug: msg="key -> {{item.key}},value -> {{item.value}}"
with_items:
- {key: 1, value: "one"}
- {key: 2, value: "two"}
- {key: 3, value: "three"}

嵌套循环

1
2
3
4
5
6
7
8
---
- hosts: commonservers
tasks:
- name: loops2
debug: msg="item0 -> {{item[0]}},item1 -> {{item[1]}}"
with_nested:
- ['1','2']
- ['one','two','three']

散列循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
---
- hosts: commonservers
vars:
user:
voidking:
name: voidking
tel: 17600000000
haojin:
name: haojin
tel: 15100000000
tasks:
- name: loops3
debug: msg="key -> {{item.key}},value -> {{item.value}}"
with_dict:
- "{{user}}"

文件循环

1
2
3
4
5
6
7
---
- hosts: commonservers
tasks:
- name: loop file
debug: msg="{{item}}"
with_fileglob:
- /home/voidking/*.yml

命令循环

1
2
3
4
5
6
7
8
9
10
11
---
- hosts: commonservers
tasks:
- name: exec command
shell: "{{item}}"
with_items:
- hostname
- uname
register: ret
- name: display result
debug: msg="{% for i in ret.results %} {{i.stdout}} {% endfor %}"

条件判断

ansible的条件判断使用关键字when,有两种方式:

  • python语法支持的原生态格式 conditions > 1 or conditions == “ss”,in,not等等
  • ansible Jinja2 filters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
---
- hosts: commonservers
vars:
pre: hostname is
tasks:
- name: register vars
shell: hostname
register: info
- name: display hostname
debug: msg="{{pre}} {{info.stdout}}"
- name: print true
debug: msg="result is ubuntu14"
when: info.stdout == "ubuntu14"
- name: print false
debug: msg="result is not ubuntu14"
when: info.stdout != "ubuntu14"
- name: print warning
debug: msg="client OS is ubuntu"
when: info['stdout'].startswith('u')

后记

至此,playbooks最基础的东西学习完毕。更高级的用法,在使用中再慢慢学习。

书签

Ansible Documentation

Ansible中文权威指南

Ansible精讲

0%