简介
Playbook(剧本),是 Ansible 的任务配置文件。每一出剧本中都包含一些任务,这每个任务在 Ansible 中又被称为一出 play(戏剧)。Playbook 采用一种 YAML 语法编写。
YAML
YAML是一种置标语言。
特性:
- 可读性好
- 与脚本语言的交互性好
- 使用实现语言的数据类型
- 有一个一致的信息模型
语法:
- 注释: #,单行注释
- 清单成员,单行表示, " - "(空格加短横),或者,"[x , x , x]"(逗号加空格)
- 杂凑表的成员,"key : value"(冒号加空格)
- 在单一档案中,可用连续三个连字号(---)区分多个档案。还可以选择性的使用三个点号(...)表示文档结尾
playbook 基本用法
Ansible 可以将 shell 脚本或简单的 shell 命令转换为 Ansible play。
例如,安装 apache 的 shell 脚本:
# 安装 Apache
yum install --quiet -y httpd httpd-devel
# 复制配置文件
cp /path/to... /etc...
cp /path/to... /etc...
# 启动 Apache,并设置开机自启
service httpd start
chkconfig httpd on
转换为完整的 playbook 后:
---
- host: all
tasks:
- name: "安装 Apache "
command: yum install --quiet -y httpd httpd-devel
- name: "复制配置文件"
command: cp /path/to... /etc...
command: cp /path/to... /etc...
- name: "启动 Apache,并设置开机自启"
command: service httpd start
command: chkconfig httpd on
将以上内容放在一个名为playbook.yml的文件中,直接调用ansible-playbook命令,即可运行。
ansible-playbook ./playbook.yml
上述 playbook 中,我们用的 command 模块来运行了标准的 shell 命令,还给了每一出 play 一个 name。
Ansible 还有很多其他的内置模块,可以大幅提升处理复杂配置的能力。如:
---
- 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
---
: YAML 语法中注释的用法。相当于 shell 中的 #。
- host: all
:告诉 Ansible 具体要在哪些主机上运行我的剧本。 all 代表所有主机。
sudo: yes:
: 告诉 Ansible 通过 sudo 来运行相应命令,yes 表示以 root 身份运行。
tasks:
: 指定一系列将要运行的任务。
- name:
: name 字段不是一个模块,不会执行实质性的任务,它只是给每一个 task 一个易于识别的名称,即使删除 name,也不会有任何问题。
yum:
: 本例中我们使用yum模块来安装Apache。
with_items:
: 说 with_items 前要先说一下 YAML 中变量的定义;
在 yaml 中可以使用 vars 关键字来定义变量。
vars:
var_name: value
然后用{{ var_name }}的方式引用变量。
当有需要重复性执行的任务时可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用并通过with_items语句来指明迭代的元素列表即可。
示例:在被控端添加 2 个用户
方式1,最简单做法:
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
- name: add user testuser2
user: name=testuser2 state=present groups=wheel
方式2,使用变量方式:
- name: add several users
vars:
user1: testuser1
user2: testuser2
user: name={{ user1 }} state=present groups=wheel
user: name={{ user2 }} state=present groups=wheel
方式3使用迭代方式
- name: add several users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
事实上with_items中可以使用元素还可为hashes例如
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
所以,上述写法:
tasks:
- name: 安装Apache
yum: name={{ item }} state=present
with_items:
- httpd
- httpd-devel
就是通过迭代的方式来执行yum install --quiet -y httpd httpd-devel
,
state=present
选项来确保软件被安装,或者使用state=absent
来确保软件被删除。
copy:
: 使用copy模块来将"src"定义的源文件(必须是ansible所在服务器上的本地文件) 复制到"dest"定义的目的地址(此地址为远程主机的上地址)去,在传递文件的同时,还定义了文件的属主,属组和权限。
Playbook与Shell脚本差异对比:
当我们把shell脚本转换为playbook运行的时候,ansible会留下清晰的执行痕迹,明确告诉我们在每一台主机上的每一步都做了什么。
当我们重复执行一个playbook时,当ansible发现系统的现有状态符合playbook所定义的状态时,anbile将自动跳过该操作。
在正式运行playbook之前,可以使用--check 或 -C 选项来检测playbook都会改变哪些内容,显示的结果跟真正执行时一模一样,但不会真的对被管理的服务器产生影响。
Ansible-playbook 其他常用命令:
限定执行范围:
如果我们运行上面的例子,会发现所有被ansible管理的主机都会被操作。
我们可以通过修改"- hosts:"字段来指定哪些主机将会应用playbook的操作:
指定一台主机:www.magedu.com
指定多台主机:www.magedu.com,www.osstep.com
指定一组主机:dbserver
当然,也可以直接通过ansible-playbook命令来指定主机:ansible-playbook playbook.yml --limit webservers
这样一来(假设你的inventory文件中包含webserver组),即便playbook中设定“hosts: all”,但也仅对webserver组生效。
如果想知道在执行playbook时,哪些主机将会受影响,则使用--list-hosts选项:
ansible-playbook playbook.yml --list-hosts
用户与权限设置
Playbook中,如果在与hosts同组的字段中没有定义user,那么Ansible将会使用你在inventory文件中定义的用户,如里inventory文件中也没定义用户,Ansible将默认使用当前系统用户身份来通过SSH连接远程主机,在远程主机中运行play内容。
我们也可以直接在ansible-playbook中使用--remote-user
选项来指定用户:
ansible-playbook playbook.yml --remote-user=tom
在某些情况下,我们需要传递sudo密码到远程主机,来保证sudo命令的正常运行。这时,可以使用--ask-sudo-pass (-K)
选项来交互式的输入密码。
--ask-sudo-pass
使用--sudo选项,可以强制所有play都使用sudo用户,同时使用--sudo-user选项指定切换到具体哪个用户,如果不指定,则默认以root身份运行。
比如,当前用户Tom想以Jerry的身份运行playbook,命令如下:
ansible-playbook playbook.yml --sudo --sudo-user=jerry --ask-sudo-pass
执行过程中,会要求用户输入Jerry的密码。
还有一些命令
--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中定义的所有任务将在每台远程主机上进行检测,但并不真正执行
一些疑问
ansible-playbook 如何收集多台服务器的信息,做统一的汇总report?
ansible有一个模块叫setup, 直接在命令行运行:ansible all -m setup即可获取所有主机的各种信息,当然该模块也可在playbook中使用。