Linux中國

使用 Ansible 讓你的系統管理自動化

你是否想精進你的系統管理能力和 Linux 技能?也許你的本地區域網上跑了一些東西,而你又想讓生活更輕鬆一點--那該怎麼辦呢?在本文中,我會向你演示如何設置工具來簡化管理多台機器。

遠程管理工具有很多,SaltStack、Puppet、Chef,以及 Ansible 都是很流行的選擇。在本文中,我將重點放在 Ansible 上並會解釋它是如何幫到你的,不管你是有 5 台還是 1000 台虛擬機。

讓我們從多機(不管這些機器是虛擬的還是物理的)的基本管理開始。我假設你知道要做什麼,有基礎的 Linux 管理技能(至少要有能找出執行每個任務具體步驟的能力)。我會向你演示如何使用這一工具,而是否使用它由你自己決定。

什麼是 Ansible?

Ansible 的網站上將之解釋為 「一個超級簡單的 IT 自動化引擎,可以自動進行雲供給、配置管理、應用部署、服務內部編排,以及其他很多 IT 需求。」 通過在一個集中的位置定義好伺服器集合,Ansible 可以在多個伺服器上執行相同的任務。

如果你對 Bash 的 for 循環很熟悉,你會發現 Ansible 操作跟這很類似。區別在於 Ansible 是 幕等的 idempotent 。通俗來說就是 Ansible 一般只有在確實會發生改變時才執行所請求的動作。比如,假設你執行一個 Bash 的 for 循環來為多個機器創建用戶,像這樣子:

for server in serverA serverB serverC; do ssh ${server} "useradd myuser"; done

這會在 serverA、serverB,以及 serverC 上創建 myuser 用戶;然而不管這個用戶是否存在,每次運行這個 for 循環時都會執行 useradd 命令。一個幕等的系統會首先檢查用戶是否存在,只有在不存在的情況下才會去創建它。當然,這個例子很簡單,但是幕等工具的好處將會隨著時間的推移變得越發明顯。

Ansible 是如何工作的?

Ansible 會將 Ansible playbooks 轉換成通過 SSH 運行的命令,這在管理類 UNIX 環境時有很多優勢:

  1. 絕大多數類 UNIX 機器默認都開了 SSH。
  2. 依賴 SSH 意味著遠程主機不需要有代理。
  3. 大多數情況下都無需安裝額外的軟體,Ansible 需要 2.6 或更新版本的 Python。而絕大多數 Linux 發行版默認都安裝了這一版本(或者更新版本)的 Python。
  4. Ansible 無需主節點。他可以在任何安裝有 Ansible 並能通過 SSH 訪問的主機上運行。
  5. 雖然可以在 cron 中運行 Ansible,但默認情況下,Ansible 只會在你明確要求的情況下運行。

配置 SSH 密鑰認證

使用 Ansible 的一種常用方法是配置無需密碼的 SSH 密鑰登錄以方便管理。(可以使用 Ansible Vault 來為密碼等敏感信息提供保護,但這不在本文的討論範圍之內)。現在只需要使用下面命令來生成一個 SSH 密鑰,如示例 1 所示。

[09:44 user ~]$ ssh-keygen
Generating public/private rsa key pair。
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Created directory '/home/user/.ssh'。
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa。
Your public key has been saved in /home/user/.ssh/id_rsa.pub。
The key fingerprint is:
SHA256:TpMyzf4qGqXmx3aqZijVv7vO9zGnVXsh6dPbXAZ+LUQ user@user-fedora
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|                 |
|              E  |
|       o .   .。|
|   .  + S    o+。|
|  . .o * .  .+ooo|
| . .+o  o o oo+。*|
|。.ooo* o。*  .*+|
| . o+*BO.o+    .o|
+----[SHA256]-----+

示例 1 :生成一個 SSH 密鑰

在示例 1 中,直接按下回車鍵來接受默認值。任何非特權用戶都能生成 SSH 密鑰,也能安裝到遠程系統中任何用戶的 SSH 的 authorized_keys 文件中。生成密鑰後,還需要將之拷貝到遠程主機上去,運行下面命令:

ssh-copy-id root@servera

注意:運行 Ansible 本身無需 root 許可權;然而如果你使用非 root 用戶,你需要為要執行的任務配置合適的 sudo 許可權。

輸入 servera 的 root 密碼,這條命令會將你的 SSH 密鑰安裝到遠程主機上去。安裝好 SSH 密鑰後,再通過 SSH 登錄遠程主機就不再需要輸入 root 密碼了。

安裝 Ansible

只需要在示例 1 中生成 SSH 密鑰的那台主機上安裝 Ansible。若你使用的是 Fedora,輸入下面命令:

sudo dnf install ansible -y

若運行的是 CentOS,你需要為 EPEL 倉庫配置額外的包:

sudo yum install epel-release -y

然後再使用 yum 來安裝 Ansible:

sudo yum install ansible -y

對於基於 Ubuntu 的系統,可以從 PPA 上安裝 Ansible:

sudo apt-get install software-properties-common -y
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible -y

若你使用的是 macOS,那麼推薦通過 Python PIP 來安裝:

sudo pip install ansible

對於其他發行版,請參見 Ansible 安裝文檔

Ansible Inventory

Ansible 使用一個 INI 風格的文件來追蹤要管理的伺服器,這種文件被稱之為 庫存清單 Inventory 。默認情況下該文件位於 /etc/ansible/hosts。本文中,我使用示例 2 中所示的 Ansible 庫存清單來對所需的主機進行操作(為了簡潔起見已經進行了裁剪):

[arch]
nextcloud
prometheus
desktop1
desktop2
vm-host15

[fedora]
netflix

[centos]
conan
confluence
7-repo
vm-server1
gitlab

[ubuntu]
trusty-mirror
nwn
kids-tv
media-centre
nas

[satellite]
satellite

[ocp]
lb00
ocp_dns
master01
app01
infra01

示例 2 : Ansible 主機文件

每個分組由中括弧和組名標識(像這樣 [group1] ),是應用於一組伺服器的任意組名。一台伺服器可以存在於多個組中,沒有任何問題。在這個案例中,我有根據操作系統進行的分組(archubuntucentosfedora),也有根據伺服器功能進行的分組(ocpsatellite)。Ansible 主機文件可以處理比這複雜的多的情況。詳細內容,請參閱 庫存清單文檔

運行命令

將你的 SSH 密鑰拷貝到庫存清單中所有伺服器上後,你就可以開始使用 Ansible 了。Ansible 的一項基本功能就是運行特定命令。語法為:

ansible -a "some command"

例如,假設你想升級所有的 CentOS 伺服器,可以運行:

ansible centos -a 'yum update -y'

注意:不是必須要根據伺服器操作系統來進行分組的。我下面會提到,Ansible Facts 可以用來收集這一信息;然而,若使用 Facts 的話,則運行特定命令會變得很複雜,因此,如果你在管理異構環境的話,那麼為了方便起見,我推薦創建一些根據操作系統來劃分的組。

這會遍歷 centos 組中的所有伺服器並安裝所有的更新。一個更加有用的命令應該是 Ansible 的 ping 模塊了,可以用來驗證伺服器是否準備好接受命令了:

ansible all -m ping

這會讓 Ansible 嘗試通過 SSH 登錄庫存清單中的所有伺服器。在示例 3 中可以看到 ping 命令的部分輸出結果。

nwn | SUCCESS => {
    "changed":false,
    "ping":"pong"
}
media-centre | SUCCESS => {
    "changed":false,
    "ping":"pong"
}
nas | SUCCESS => {
    "changed":false,
    "ping":"pong"
}
kids-tv | SUCCESS => {
    "changed":false,
    "ping":"pong"
}
...

示例 3 :Ansible ping 命令輸出

運行指定命令的能力有助於完成快速任務(LCTT 譯註:應該指的那種一次性任務),但是如果我想在以後也能以同樣的方式運行同樣的任務那該怎麼辦呢?Ansible playbooks 就是用來做這個的。

複雜任務使用 Ansible playbooks

Ansible 劇本 playbook 就是包含 Ansible 指令的 YAML 格式的文件。我這裡不打算講解類似 Roles 和 Templates 這些比較高深的內容。有興趣的話,請閱讀 Ansible 文檔

在前一章節,我推薦你使用 ssh-copy-id 命令來傳遞你的 SSH 密鑰;然而,本文關注於如何以一種一致的、可重複性的方式來完成任務。示例 4 演示了一種以冥等的方式,即使 SSH 密鑰已經存在於目標主機上也能保證正確性的實現方法。

- hosts:all
  gather_facts:false
  vars:
    ssh_key:'/root/playbooks/files/laptop_ssh_key'
  tasks:
    - name:copy ssh key
      authorized_key:
        key:"{{ lookup('file',ssh_key) }}"
        user:root

示例 4:Ansible 劇本 「push ssh keys.yaml」

- hosts: 行標識了這個劇本應該在那個主機組上執行。在這個例子中,它會檢查庫存清單里的所有主機。

gather_facts: 行指明 Ansible 是否去搜索每個主機的詳細信息。我稍後會做一次更詳細的檢查。現在為了節省時間,我們設置 gather_factsfalse

vars: 部分,顧名思義,就是用來定義劇本中所用變數的。在示例 4 的這個簡短劇本中其實不是必要的,但是按慣例我們還是設置了一個變數。

最後由 tasks: 標註的這個部分,是存放主體指令的地方。每個任務都有一個 -name:。Ansbile 在運行劇本時會顯示這個名字。

authorized_key: 是劇本所使用 Ansible 模塊的名字。可以通過命令 ansible-doc -a 來查詢 Ansible 模塊的相關信息; 不過通過網路瀏覽器查看 文檔 可能更方便一些。authorized_key 模塊 有很多很好的例子可以參考。要運行示例 4 中的劇本,只要運行 ansible-playbook 命令就行了:

ansible-playbook push_ssh_keys.yaml

如果是第一次添加 SSH 密鑰,SSH 會提示你輸入 root 用戶的密碼。

現在 SSH 密鑰已經傳輸到伺服器中去了,可以來做點有趣的事了。

使用 Ansible 收集信息

Ansible 能夠收集目標系統的各種信息。如果你的主機數量很多,那它會特別的耗時。按我的經驗,每台主機大概要花個 1 到 2 秒鐘,甚至更長時間;然而有時收集信息是有好處的。考慮下面這個劇本,它會禁止 root 用戶通過密碼遠程登錄系統:

- hosts:all
  gather_facts:true
  vars:
  tasks:
    - name:Enabling ssh-key only root access
      lineinfile:
        dest:/etc/ssh/sshd_config
        regexp:'^PermitRootLogin'
        line:'PermitRootLogin without-password'
      notify:
        - restart_sshd
        - restart_ssh

  handlers:
    - name:restart_sshd
      service:
        name:sshd
        state:restarted
        enabled:true
      when:ansible_distribution == 'RedHat'
    - name:restart_ssh
      service:
        name:ssh
        state:restarted
        enabled:true
      when:ansible_distribution == 'Debian'

示例 5:鎖定 root 的 SSH 訪問

在示例 5 中 sshd_config 文件的修改是有條件 的,只有在找到匹配的發行版的情況下才會執行。在這個案例中,基於 Red Hat 的發行版與基於 Debian 的發行版對 SSH 服務的命名是不一樣的,這也是使用條件語句的目的所在。雖然也有其他的方法可以達到相同的效果,但這個例子很好演示了 Ansible 信息的作用。若你想查看 Ansible 默認收集的所有信息,可以在本地運行 setup 模塊:

ansible localhost -m setup |less

Ansible 收集的所有信息都能用來做判斷,就跟示例 4 中 vars: 部分所演示的一樣。所不同的是,Ansible 信息被看成是內置 變數,無需由系統管理員定義。

更近一步

現在可以開始探索 Ansible 並創建自己的基本了。Ansible 是一個富有深度、複雜性和靈活性的工具,只靠一篇文章不可能就把它講透。希望本文能夠激發你的興趣,鼓勵你去探索 Ansible 的功能。在下一篇文章中,我會再聊聊 Copysystemdserviceaptyumvirt,以及 user 模塊。我們可以在劇本中組合使用這些模塊,還可以創建一個簡單的 Git 伺服器來存儲這些所有劇本。

via: https://opensource.com/article/17/7/automate-sysadmin-ansible

作者:Steve Ovens 譯者:lujun9972 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國