Ansible 简介

Ansible 是一个开源的基于 OpenSSH 的自动化配置管理工具。可以用它来配置系统、部署软件和编排更高级的 IT 任务,比如持续部署或零停机更新。Ansible 的主要目标是简单和易用,并且它还高度关注安全性和可靠性。基于这样的目标,Ansible 适用于开发人员、系统管理员、发布工程师、IT 经理,以及介于两者之间的所有人。Ansible 适合管理几乎所有的环境,从拥有少数实例的小型环境到有数千个实例的企业环境。

使用 Ansible 无须在被管理的机器上安装代理,所以不存在如何升级远程守护进程的问题,也不存在由于卸载了守护进程而无法管理系统的问题。

Ansible 的主要功能

管理员可以通过 Ansible 在成百上千台计算机上同时执行指令(任务)。
对于管理员来说,经常需要执行下面的任务:

  • 维护现存的比较复杂的服务器时,手动登录的方式很容易遗漏一些操作,或者是执行一些未预期的操作。
  • 手动初始化新的服务器耗时耗力!

对于这两种情况,如果完全通过 shell 脚本实现。脚本会过于复杂,极难维护。当然我们也可以使用同类的工具,比如 Puppet and Chef。这两个工具的特点是:需要学习新的知识栈(其实 Ansible 也是有学习成本的)。

相比 Puppet 和 Chef 使用 Ansible 可以延续之前使用 shell 脚本的工作习惯和方式,因而其学习成本会低一些。下面是 Ansible 的一些优势:

  • 可以逐行的执行 shell 命令。
  • 不需要另外的客户端工具(linux 一般会自带 ssh 工具)。
  • 相同的配置只被执行一次(多次执行同一配置不会出问题)。

Ansible 的工作方式

使用 Ansible 无须在被管理的客户端电脑上安装代理之类的组件。它通过普通的 SSH 进行通信,以便从远程计算机检索信息、发出命令和复制文件。这是 Ansible 简化服务器管理的一种方式。任何公开 SSH 端口的服务器都可以通过 Ansible 进行配置和管理。

Ansible 采用模块化的设计,所以非常容易扩展到各种特定的使用场景。模块可以用任何语言编写,并使用标准 JSON 进行通信。Ansible 的配置文件是用 YAML 格式编写的,因为它使用起来非常简单,并且与主流的标记语言很相似。除了通过命令行工具 Ansible 还可以通过配置脚本(Playbooks)与客户端交互。

安装 Ansible

$ sudo apt-add-repository -y ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install -y ansible

安装完成后检查一下版本:

$ ansible --version

2.7.1 是笔者在写本文时的最新版本。

配置客户端主机的 SSH 秘钥

对于自动化来说,最后是通过秘钥进行认证,这样就不会把用户的密码以明文的方式写在脚本里。下面的命令把安装了 ansible 的主机上当前用户的 SSH 公钥安装到了被管理的客户端 192.168.21.145 和 192.168.21.148 上:

$ ssh-copy-id -i ~/.ssh/id_rsa.pub nick@192.168.21.145
$ ssh-copy-id -i ~/.ssh/id_rsa.pub nick@192.168.21.148

说明:这两台被管理的客户端主机运行的也都是 Ubuntu 16.04。

然后尝试通过下面的命令以不输密码的方式连接到远程主机中:

$ ssh nick@192.168.21.145
$ ssh nick@192.168.21.148

如果能够成功登陆,说明 SSH 的配置已经 OK 了。

配置用户执行 sudo 时不需要密码
在我们执行的自动化操作中,有很大一部分是需要 root 权限的,比如执行更新、安装软件等等。这样的操作会因为在以 sudo 方式执行是提升用户输入密码而失败,比如下面的命令:

$ ansible testservers -b -u nick -a "apt update"

-b 选项默认把用户 nick 提升为 root 权限,但是需要输入用户 nick 的密码,所以自动化执行的命令失败了。当然我们可以同时添加 -K 选项,这是 ansible 会停下来与用户交互,等待用户输入密码:

但这真的不是我想要的结果,我需要的是脚本能够自动化的不需要交互的完成任务!

这个问题的解决方法是把用户设置为执行 sudo 命令时不需要输入密码,让我们在客户机 192.168.21.148 上执行下面的命令:

$ sudo visudo

为用户 nick 添加下面的行:

nick    ALL=(ALL)     NOPASSWD: ALL

该行内容配置用户 nick 在执行 sudo 命令时不需要输入密码,保存后让我们再次执行下面的命令:

$ ansible testservers -b -u nick -a "apt update"

这次终于可以执行 root 权限的命令了!

清单(inventory)

清单是 ansible 的一个配置文件,在清单中我们可以指定被管理的客户端机器。Ansible 默认的清单文件为 /etc/ansible/hosts,当然我们也可以通过 -i 选项指定其它的清单文件,比如下面的例子:

$ ansible myservers -i /etc/ansible/myhosts -b -u nick -a "apt update"

在清单文件中,我们可以指定 ansible 命令操作的主机对象。对于单个的主机,可以在清单中写主机域名,也可以直接写 IP 地址:

如果要同时对对个主机进行操作,可以把它们定义在一个组中:

在执行 ansible 命令时,指定清单中定义的主机名称或者组名就可以了。比如我们在 /etc/ansible/hosts 文件中定义了一个名称为 testservers 的组,它包含了两个主机:

然后通过下面的命令分别在这两台主机上执行 df -h 命令:

$ ansible testservers -u nick -a "df -h"

从输出的结果可以看出 df -h 命令在两台目标主机上都执行了。

模块

Ansible 把类似的操作封装到模块中,这样就可以通过插件的方式对 Ansible 进行扩展了。每个模块都能接收参数,几乎所有的模块都接受键值对(key=value)参数,这些参数通过空格进行分隔。也有一些模块不接收参数,只需在命令行输入相关的命令就能调用。如果要执行单个命令,可以使用 command 模块:

$ ansible testservers -m command -u nick -a "df -h"
$ ansible webservers -m command -a "/sbin/reboot -t now"

因为 command 是 ansible 执行命令是使用的默认模块,所以我们可以在命令行中省略它:

$ ansible testservers -u nick -a "df -h"
$ ansible testservers -b -u nick -a "/sbin/reboot -t now"

这样的写法本质上和前面的写法是一样的。

如果要执行其它模块中的命令就需要通过 -m 选项显式的指定模块的名称,比如执行 service 模块中的命令:

$ ansible testservers -m service -a "name=httpd state=started"

如果要把文件从本机拷贝到客户端主机上去,就需要使用 copy 模块:

$ ansible testservers -m copy -u nick  -a "src=./app.js dest=./myapp/app.js"

Ansible 默认内置了很多好用的模块,你可以从其官方文档中的模块部分了解更多模块相关的内容。

playbook

如果 Ansible 的功能仅仅是能够执行当个的命令和脚本就显得太弱了。Ansible 的 laybook 功能支持把命令以 yaml 的格式写在配置文件中,然后一次性执行配置文件中的所有命令(这一点类似于 chef 中的 cookbook)。比如我们可以把前面演示的 df -h 命令以配置文件的方式写在 playbook 中:

---
- hosts: testservers
  become:
true
  become_user: root
  tasks:
   
- name: check disk
      command:
df -h

把上面的代码保存在文件 playbook.yml 中,当然你可以根据自己的喜好命名这个文件。其中 hosts 表示对哪些主机进行操作,become 就是我们在命令行上用过的 -b 选项,这里我们通过 become_user: root 显式的指定把当前用户的权限提升为 root 用户权限来执行命令。下面的 tasks 则是对任务的定义,name 是独一无二的一个任务名(如果有多个同名的 task,只执行第一个),接着是 task 中的命令,这里我们还是简单的执行 df -h 命令。然后执行下面的命令,注意这次执行的是 ansible-playbook 命令,并且需要指定编辑好的 playbook 的文件名称作为参数:

$ ansible-playbook -u nick playbook.yml

这样一个简单的 playbook 就可以正常工作了,当然实际的生产环境中你可能会把 playbook 编写的非常复杂!

跳过首次 ssh 连接时的确认提示

这是一个在自动化的过程中经常碰到的问题,所以有必要提一下。如果你不是通过 ssh-copy-id 命令把公钥添加到目标机器上的(多数的环境都不是这么做的),在首次执行 ansible 命令时需要用户确认连接的安全性:

这是非常悲催的,因为我们要实现的目标是自动化的执行命令,而不需要进行交互式的操作。
这个问题的解决方案是配置 ansible,跳过这一步的检查。具体的做法是在配置文件 /etc/ansible/ansible.cfg 中找到行 host_key_checking = False,并去掉行头的注释字符:

然后再执行 ansible 命令就不会提示用户进行交互式验证了。

总结

Ansible 是一个强大的自动化工具,并以其简介的用法,对开发者(系统运维工程师)友好的特点在自动化的流程中占据了一席之地。在这个 devops 已经成为主流的时代,如果能够熟练的使用 ansible ,相信必定会让你的 devops 实践如虎添翼。

猜你喜欢

转载自www.linuxidc.com/Linux/2018-12/155789.htm