Ansible基础-Playbook入门

Paste_Image.png

1
2
3
4
难度指数: 4星(满星5星)
技术指数: 5星(满星5星)
理论指数: 4星(满星5星)
面向人群: 自动化运维&运维开发

1. Playbook简介

像很多其它配置文件管理方法一样,Ansible使用一种比较直白的方法来描述自己的任务配置文件。
Ansible 的任务配置文件被称之为“playbook”,我们可以称之为“剧本”。每一出剧本(playbook)中都包含一系列的任务,这每个任务在ansible中又被称为一出“戏剧”(play)。一个剧本(playbook)中包含多出戏剧(play),这很容易理解。

为了便于理解,再给大家举个栗子~

NAB球队教练手里都有一个叫战术板的东西,每次暂停,主教练都会在战术板上布置一系列战术(playbook),球员在场上做出一系列的跑动和相互掩护来完成这个战术,这其中每一个跑位和掩护就可以被称之为“play”。

Paste_Image.png

在Ansible中,我们就充当编剧的角色,亲自编写剧本(一系列的服务器操作),让一出出精彩的戏剧(play)巧妙配合,完成对服务器的一系列精确控制。

1.1 Playbook语法简介

Playbook采用一种可读性很高的且容易被人类阅读的语法的YAML语法编写,YAML: “YAML Ain’t a Markup Language”(YAML不是一种置标语言)。该语言在被开发时,YAML 的意思其实是:”Yet Another Markup Language”(仍是一种置标语言),格式如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
house:
family:
name: Doe
parents:
- John
- Jane
children:
- Paul
- Mark
- Simone
address:
number: 34
street: Main Street
city: Nowheretown
zipcode: 12345

1.2 YAML简介

1.2.1 YAML特性

  • 1 YAML的可读性好
  • 2 YAML和脚本语言的交互性好
  • 3 YAML使用实现语言的数据类型
  • 4 YAML有一个一致的信息模型
  • 5 YAML易于实现

    1.2.2 YAML语法

  • 1 YAML使用可打印的Unicode字符,可使用UTF-8或UTF-16。
  • 2 使用空白字符未文件缩排来表示结构;不过不能使用跳格字符。
  • 3 注解由井字号( # )开始,可以出现在一行中的任何位置,而且范围只有一行(也就是一般所谓的单行注解)
  • 4 每个清单成员以单行表示,并用短杠+空白( - )起始。或使用方括号( [ ] ),并用逗号+空白( , )分开成员。
  • 5 每个杂凑表的成员用冒号+空白( : )分开键值和内容。或使用大括号( { } ),并用逗号+空白( , )分开。 杂凑表的键值可以用问号 ( ? )起始,用来明确的表示多个词汇组成的键值。
  • 6 字串平常并不使用引号,但必要的时候可以用双引号 ( “ )或单引号 ( ‘ )框住。使用双引号表示字串时,可用倒斜线( \ )开始的跳脱字符(这跟C语言类似)表示特殊字符。
  • 7 区块的字串用缩排和修饰词(非必要)来和其他资料分隔,有新行保留(preserve)(使用符号 | )或新行折叠(flod)(使用符号 > )两种方式。
  • 8 在单一档案中,可用连续三个连字号(——)区分多个档案。另外,还有选择性的连续三个点号( … )用来表示档案结尾。
  • 9 重复的内容可使从参考标记星号 ( * )复制到锚点标记( & )。
  • 10 指定格式可以使用两个惊叹号 ( !! ),后面接上名称。
  • 11 档案中的单一文件可以使用指导指令,使用方法是百分比符号( % )。有两个指导指令

    2. Playbook实战

    之前我们分享的Ansbile基础模块使用时,那种Ad-hoc点对点的,一次执行一个模块的操作方式已经使得Andsible一中非常强大的管理工具;但playbook将会使Ansible成为超一流的管理工具。

2.1 Shell脚本与Playbook的转换

现在越来越多的DevOPS也开始将目光移向了Ansible,因为Ansible可以轻松的将shell脚本或简单的shell命令转换为Ansible plays.

下面有一个安装apache的shell脚本,大家来感受一下:

1
2
3
4
5
6
7
8
9
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd httpd-devel
# 复制配置文件
cp /path/to/config/httpd.conf /etc/httpd/conf/httpd.conf
cp /path/to/httpd-vhosts.conf /etc/httpd/conf/httpd-vhosts.conf
# 启动Apache,并设置开机启动
service httpd start
chkconfig httpd on

将其转换为一个完整的playbook后:

1
2
3
4
5
6
7
8
9
10
11
12
---
- hosts: all

tasks:
- name: "安装Apache"
command: yum install --quiet -y httpd httpd-devel
- name: "复制配置文件"
command: cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
command: cp /tmp/httpd-vhosts.conf /etc/httpd/conf/httpd-vhosts.conf
- name: "启动Apache,并设置开机启动"
command: service httpd start
command: chkconfig httpd on

Paste_Image.png
将以上内容放在一个名为playbook.yml的文件中,直接调用ansible-playbook命令,即可运行,运行结果和脚本运行结果一致:

1
# ansible-playbook ./playbook.yml

也就是说,只要你有编写shell脚本的基本能力,你就可以快速的学会利用playbook来发挥Ansible的强大威力。

在上述playbook中,我们使用了“command”模块来运行了标准的shell命令。我们还给了每一出play一个“name”,因此当我们运行playbook时,每一个play都会有非常易读的的信息输出:

Paste_Image.png


上面的playbook已经可以很好的运行shell脚本了,但是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
25
26
27
---yaml
- hosts: all
sudo: yes

tasks:
- name: 安装Apache
yum: name={{ item }} state=present
with_items:
- httpd
- httpd-devel
- name: 复制配置文件
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: root
group: root
mode: 0644
with_items:
- {
src: "/tmp/httpd.conf",
dest: "/etc/httpd/conf/httpd.conf" }
- {
src: "/tmp/httpd-vhosts.conf",
dest: "/etc/httpd/conf/httpd-vhosts.conf"
}
- name: 检查Apache运行状态,并设置开机启动
service: name=httpd state=started enabled=yes

运行结果如下:

2.2 Playbook案例逐行剖析

现在我们已经对playbook有了一个大概的了解,接一下,让我们详细解剖一下上面的playbook都做了是什么以及怎么工作的。

  • 1 第一行,“—”,这个是YAML语法中注释的用法,就像shell脚本中的“#”号一样
  • 2 第二行,“- hosts: all”,告诉ansible具体要在哪些主机上运行我的剧本(playbook),在本例中是all,即所有主机
  • 3 第三行,“sudo: yes”,告诉ansible通过sudo来运行相应命令,这样所有命令将会以root身份执行
  • 4 第四行,“tasks:”,指定一系列将要运行的任务
    • 每一个任务(play)以“- name: 安装Apache”开头。“- name:”字段并不是一个模块,不会执行任务实质性的操作,它只是给“task” 一个易于识别和名称。即便把name字段对应的行完全删除,也不会有任何问题。
    • 本例中我们使用yum模块来安装Apache,替代了“yum -y install httpd httpd-devel”
    • 在每一个play当中,都可以例用 with_items 来定义变量,并通过“”的形式来直接使用使用yum模块的state=present选项来确保软件被安装,或者使用state=absent来确保软件被删除
    • 第二个任务(play)同样是“- name”字符开头
    • 我们使用copy模块来将“src”定义的源文件(必须是ansible所在服务器上的本地文件 )复制到“dest”定义的目的地址(此地址为远程主机的上地址)去,在传递文件的同时,还定义了文件的属主,属组和权限
    • 这个play中,我们用数组的形式给变量赋值,使用{var1: value, var2: value} 的格式来赋值,变量的个数可以任意多,不同变量间以逗号分隔,使用的形式来调用变量,本例中为:
    1. 第三个任务(play)使用了同样的结构,调用了service模块,以保证服务的正常开启

2.3 Playbook与Shell脚本差异对比

当我们把shell脚本转换为playbook运行的时候,ansible会留下清晰的执行痕迹,明确告诉我们在每一台主机上的每一步都做了什么。

更厉害的是,当我们重复执行一个playbook时,当ansible发现系统的现有状态符合playbook所定义的状态时,anbile将自动跳过该操作。

比如下图,我们再次执行playbook: temp.yml,当ansible发现playbook中的play都已被完成,它将直接返回ok状态码,速度非常之快。
如果是shell脚本,肯定会硬着头皮,把所用操作再做一遍。

Paste_Image.png

在正式运行playbook之前,可以使用–check 或 -C 选项来检测playbook都会改变哪些内容,显示的结果跟真正执行时一模一样,但不会真的对被管理的服务器产生影响

3. Ansible-playbook命令详解

3.1 限定执行范围

1
--limit   

如果我们运行上面的例子,会发现所有被ansible管理的主机都会被操作。
我们可以通过修改“- hosts:”字段来指定哪些主机将会应用playbook的操作,

指定一台主机:www.magedu.com
指定多台主机:www.magedu.com,www.osstep.com
指定一组主机:dbserver

当然,也可以直接通过ansible-playbook命令来指定主机:

1
# ansible-playbook playbook.yml --limit webservers

这样以来(假设你的inventory文件中包含webserver组),即便playbook中设定“hosts: all”,但也仅对webserver组生效。

1
--list-hosts

如果想知道在执行playbook时,哪些主机将会受影响,则使用–list-hosts选项:

1
# ansible-playbook playbook.yml --list-hosts

运行结果:

Paste_Image.png
(由于用测试的被管理主机只有一台,所以count结果为1)

4. Ansible-playbook: 用户与权限设置

1
--remote-user

Playbook中,如果在与hosts同组的字段中没有定义user,那么Ansible将会使用你在inventory文件中定义的用户,如里inventory文件中也没定义用户,Ansible将默认使用当前系统用户身份来通过SSH连接远程主机,在运程程主机中运行play内容。

我们也可以直接在ansible-playbook中使用 –remote-user选项来指定用户:

1
# ansible-playbook playbook.yml --remote-user=tom
1
--ask-sudo-pass

在某些情况下,我们需要传递sudo密码到远程主机,来保证sudo命令的正常运行。这时,可以使用–ask-sudo-pass (-K)选项来交互式的输入密码。

–sudo
使用–sudo选项,可以强制所有play都使用sudo用户,同时使用–sudo-user选项指定切换到具体哪个用户,如果不指定,则默认以root身份运行。

比如,当前用户Tom想以Jerry的身份运行playbook,命令如下:
$ ansible-playbook playbook.yml –sudo –sudo-user=jerry –ask-sudo-pass
执行过程中,会要求用户输入Jerry的密码。

5. Ansible-playbook: 其它选项

Ansible-playbook命令还有一些其他选项:

–inventory=PATH (-i PATH):指定inventory文件,默认文件是/etc/ansible/hosts
–verbose(-v):显示详细输出,也可以使用-vvvv显示精确到每分钟的输出
–extra-vars=VARS(-e VARS):定义在playbook使用的变量,格式为:”key=value,key=value”
–forks=NUM ( -f NUM):指定并发执行的任务数,默认为5,根据服务器性能,调大这个值可提高ansible执行效率
–connection=TYPE ( -c TYPE):指定连接远程主机的方式,默认为ssh,设为local时,刚只在本地执行playbook,建议不做修改
–check:检测模式,playbook中定义的所有任务将在每台远程主机上进行检测,但并不直正执行

以上这些参数即可满足大部分的工作需求。