我们做实验经常要使用远程服务器,而运行一些固定的任务流程,例如环境配置、文件同步、运行实验等等是常见的需求。手动编写 Shell 脚本较为繁琐,尤其是需要管理多台机器时格外麻烦。使用 Ansible 即可通过编写 YAML 格式配置文件,一句命令即可在一组服务器上同时进行操作,高效实用。
安装
Ansible Commuity 是开源免费的版本。Ansible 只需要在一台控制机器上安装,它会使用 SSH 和 Python 来进行服务器的管理。因此你只需要保证每台被管理的机器可以正常用 SSH 登陆(最好是免密登陆),且装有 Python 3.5+(Python 2.7 也可以,但并不推荐)。
在控制机器上安装 Ansible 非常简单,Linux 上通常可以用包管理工具进行安装。此外,还可以使用 pip
进行安装。macOS 和 Win 推荐用 pip
安装。
一些功能简介
Ansible 的核心功能在于 Playbook,Playbook 就是用编写好的配置文件管理服务器组。与之相对的有 Ad-hoc 等,是指对一组服务器执行一句即时命令,显然通过配置文件管理是我们最想要的功能,所以我们重点关注 Playbook。
使用 Ansible Playbook 主要关注两个文件,一个是 Inventory 文件,一个是 YAML 格式的配置文件。所谓 Inventory 文件,就是服务器的列表。我们把我们想管理的机器写到这个文件里,可以进行分组管理,可以为不同的机器保存一些不同的变量等等。而在 YAML 格式的配置文件中,编写我们想要的任务逻辑。
执行任务
YAML 是一种很简单的文件格式,通过键值对和列表的嵌套表达信息。如果读者知道 json 格式,那么 YAML 与 json 是很相似的。下面是一个简单的例子:
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=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
第一行中,我们指定了我们要对哪些服务器进行管理,Ansible 会自动去 Inventory 文件中寻找相应的服务器组。这里就是我们定义好的一个叫 webservers 的服务器组,我们想要对它们进行操作。
随后 vars
指定了一些变量。remote_user
指定了服务器上的登陆用户。
tasks
是本次要执行的任务列表,可以看到这里有三个任务。每个任务都有一个名字和任务内容,例如第一个任务是用 yum
安装 httpd
这个包,确保是最新的版本。第二个任务是更新配置文件,并且更新后通过 notify
调用另一个在 handlers
中定义的任务,由此相当于触发一连串的更新。同时可以由此进行任务依赖关系的设定
如果我们将文件保存为 playbook.yml
,并将 Inventory 文件保存为 hosts.ini
(默认是 INI 格式的,也支持 YAML 格式),那么执行以下命令即可执行这些任务:
$ ansible-playbook -i hosts.ini playbook.yml
同步文件
编写这样的任务可以将文件进行分发:
- copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: u=rw,g=r,o=r
将本地的 /srv/myfiles/foo.conf
文件复制到所有服务器的 /etc/foo.conf
上。
变量替换
每台服务器上的配置经常可能只有一些细微的区别,对此,Ansible 集成了 Jinja2,一个模板引擎,我们把配置文件写成模板,其中蕴含一些变量,之后为每台机器设置不同的变量值,这样 Jinja2 会自动将变量替换为相应的值,同时还能支持 if
、for loop
等控制流操作。
例如一个简单的例子,如果某个路径每台机器都不同,你可以把这个路径字符串赋值给一个变量 foo_path
,然后在 Playbook 中写:
template: src=foo.cfg.j2 dest={{ foo_path }}/foo.cfg
两个花括号之间的 foo_path
就会被进行变量替换,你在不同的机器上设置不同的值,最终就会得到不同的路径。
相关资源
本文只是一个抛砖引玉,Ansible 功能非常丰富强大,读者应该查阅相关手册,一步步递进学习就好,需要什么就现用现查。
Ansible 英文文档:官方,写的很好。
Ansible 中文权威指南:官方文档的中文翻译,但个人觉得翻译有些生硬,如果英语水平可以还是建议看英文。