Try Ansible

Page content

Ansible是用来干什么的

Ansible 可以用来批量管理服务器。
Ansible 的优点是它只需要在主控机上安装一个 Ansible 软件就可以透过 SSH 连线到其他机器上进行控制,不需要特别地在被控制的机器上安装什么软件。

怎么安装Ansible

安装Python

首先需要安装 python3pip3 ,写这个文章的时候最新的 ansible-core 版本是2.14,需要使用 python 3.9-3.11.
对于其他版本具体的 python 版本要求可以在 Ansible 文档的 Control node requirement 找到。
如果机器上还没有屁眼通红,就去装一个(以debian为例)

sudo apt install python3 python3-pip -y

然后康康装上对了没有

root@ifrit:~# python3 --version
Python 3.9.2
root@ifrit:~# pip3 --version
pip 20.3.4 from /usr/lib/python3/dist-packages/pip (python 3.9)
root@ifrit:~# 

安装Ansible

装完 Python3,就可以开始装 Ansbile 了,直接执行下面这行。

python3 -m pip install --user ansible

然后等它搞完。
最后再执行 ansbile --version ,如果有出现 ansible [core 2.14.0] 之类的字样就说明装好了。

安装一些其他可选的软件

下面说的这些软件可装可不装,但推荐安装。

软件包 说明
ansible-lint 用来检查你的 Ansible 配置文件有没有输错的地方
sshpass Ansible 发起 SSH 连线的时候需要使用

装装装,都可以装!

apt install sshpass -y
pip3 install ansible-lint

Ansible 中的一些术语

名词 解释
Control Node 就是正在运行 Ansible 要去控制别人的主机
Managed Node 就是要被 Control Node 控制的主机
Inventory Inventory 文件中记录了每个 Managed node 的名称、IP 地址和 SSH 连线的凭据
Playbook Playbook 文件记录了让各 Managed node 要进行的动作(Plays)和任务(Tasks),使用 Python-like json YAML 编写
Ad hoc Commands 可以理解为指令模式,可以直接在命令行中控制 Managed node 直接个别地执行一些简短的指令,比如 ping 之类的

编辑 Inventory

Inventory 文件中记录了每个 Managed node 的名称、IP 地址和 SSH 连线的凭据。
Inventory 文件中包含如下字段:
ansible_ssh_host 被控主机的IP地址
ansible_ssh_port 被控主机的SSH连接埠
ansible_ssh_user 被控主机的SSH用户名
ansible_ssh_pass 被控主机的SSH密码

下面是一个 Inventory 文件的例子

[myServers] # 这里指定了这些服务器的分组
ifrit      ansible_ssh_host=114.514.191.810 ansible_ssh_port=22 ansible_ssh_user=tdkr ansible_ssh_pass=tdkrYES!114514
dusk       ansible_ssh_host=114.514.191.811 ansible_ssh_port=22 ansible_ssh_user=tdkr ansible_ssh_pass=tdkrYES!114514
honeyberry ansible_ssh_host=114.514.191.812 ansible_ssh_port=22 ansible_ssh_user=tdkr ansible_ssh_pass=tdkrYES!114514
lumen      ansible_ssh_host=114.514.191.813 ansible_ssh_port=22 ansible_ssh_user=tdkr ansible_ssh_pass=tdkrYES!114514

保存为 inventory

使用 Ad-Hoc Commands

来点简单的 Ad-Hoc commands 来试试 Ansible 的威力。
例如显示各个被控主机的 hostname

$ ansible myServers -i inventory -m command -a "hostname"
honeyberry | CHANGED | rc=0 >>
honeyberry.kaf.moe
ifrit | CHANGED | rc=0 >>
ifrit.kaf.moe
dusk | CHANGED | rc=0 >>
dusk.kaf.moe
lumen | CHANGED | rc=0 >>
lumen.kaf.moe

可以看出 hostname 在各个主机上都被执行了,并且结果显示在了一起。

使用 Playbook

如果一个相同的动作需要在不同的装置上执行多次,就可以使用 Playbook。
一个 Playbook 中可以包含多个动作(Play)和任务(Task)。

一个「动作」指的是某种特定的目的,比如说:

  • 「搭建一个 wordpress 博客」
  • 「重启服务器」

一个「任务」指的是达成这个动作所需要的步骤,比如说:

  • 为了「搭建一个 wordpress 博客」,我要:
    • 安装 apache
    • 安装 php
    • etc,
  • 为了「重启服务器」,我要:
    • 执行 reboot 指令

依然以主机名为例,「获取所有主机的主机名」这个动作,包含「获取主机名」和「打印主机名」两个动作。
编写成 Playbook 就是

- name: Print hostname
  hosts: myServers
  tasks:
    # Task 1
    - name: Get hostname
      command: hostname
      register: msg
    # Task 2
    - name: Print them out
      ansible.builtin.debug:
        msg: "{{ msg.stdout }}"

然后我们可以运行一下

root@ifrit:~/ansible# ansible-playbook -i inventory playbook.yaml 

PLAY [Print hostname] *************************************************************************
TASK [Gathering Facts] ************************************************************************
ok: [honeyberry]
ok: [ifrit]
ok: [lumen]

TASK [Get hostname] ***************************************************************************
changed: [honeyberry]
changed: [ifrit]
changed: [lumen]

TASK [Print them out] *************************************************************************
ok: [ifrit] => {
    "msg": "ifrit.kaf.moe"
}
ok: [honeyberry] => {
    "msg": "honeyberry.kaf.moe"
}
ok: [lumen] => {
    "msg": "lumen.kaf.moe"
}

PLAY RECAP ************************************************************************************
honeyberry                 : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ifrit                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
lumen                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

可以看出在 TASK [Print them out] 这一列之下成功显示了各个主机的主机名。