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

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

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

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

什麼是 Ansible?瀏覽器

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

若是你對 Bash 的 for 循環很熟悉,你會發現 Ansible 操做跟這很相似。區別在於 Ansible 是幕等的idempotent。通俗來講就是 Ansible 通常只有在確實會發生改變時才執行所請求的動做。好比,假設你執行一個 Bash 的 for 循環來爲多個機器建立用戶,像這樣子:網絡

 
  1. for server in serverA serverB serverC; do ssh ${server} "useradd myuser"; doneapp

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

Ansible 是如何工做的?dom

Ansible 會將 Ansible playbooks 轉換成經過 SSH 運行的命令,這在管理類 UNIX 環境時有不少優點:ssh

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

配置 SSH 密鑰認證

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

 
  1. [09:44 user ~]$ ssh-keygen

  2. Generating public/private rsa key pair

  3. Enter file in which to save the key (/home/user/.ssh/id_rsa):

  4. Created directory '/home/user/.ssh'

  5. Enter passphrase (empty for no passphrase):

  6. Enter same passphrase again:

  7. Your identification has been saved in /home/user/.ssh/id_rsa

  8. Your public key has been saved in /home/user/.ssh/id_rsa.pub

  9. The key fingerprint is:

  10. SHA256:TpMyzf4qGqXmx3aqZijVv7vO9zGnVXsh6dPbXAZ+LUQ user@user-fedora

  11. The key's randomart image is:

  12. +---[RSA 2048]----+

  13. |                 |

  14. |                 |

  15. |              E  |

  16. |       o .   .。|

  17. |   .  + S    o+。|

  18. |  . .o * .  .+ooo|

  19. | . .+o  o o oo+。*|

  20. |。.ooo* o。*  .*+|

  21. | . o+*BO.o+    .o|

  22. +----[SHA256]-----+

示例 1 :生成一個 SSH 密鑰

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

 
  1. ssh-copy-id root@servera

注意:運行 Ansible 自己無需 root 權限;然而若是你使用非 root 用戶,你須要爲要執行的任務配置合適的 sudo 權限。

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

安裝 Ansible

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

 
  1. sudo dnf install ansible -y

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

 
  1. sudo yum install epel-release -y

而後再使用 yum 來安裝 Ansible:

 
  1. sudo yum install ansible -y

對於基於 Ubuntu 的系統,能夠從 PPA 上安裝 Ansible:

 
  1. sudo apt-get install software-properties-common -y

  2. sudo apt-add-repository ppa:ansible/ansible

  3. sudo apt-get update

  4. sudo apt-get install ansible -y

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

 
  1. sudo pip install ansible

對於其餘發行版,請參見 Ansible 安裝文檔 [1]

Ansible Inventory

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

 
  1. [arch]

  2. nextcloud

  3. prometheus

  4. desktop1

  5. desktop2

  6. vm-host15

  7. [fedora]

  8. netflix

  9. [centos]

  10. conan

  11. confluence

  12. 7-repo

  13. vm-server1

  14. gitlab

  15. [ubuntu]

  16. trusty-mirror

  17. nwn

  18. kids-tv

  19. media-centre

  20. nas

  21. [satellite]

  22. satellite

  23. [ocp]

  24. lb00

  25. ocp_dns

  26. master01

  27. app01

  28. infra01

示例 2 : Ansible 主機文件

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

運行命令

將你的 SSH 密鑰拷貝到庫存清單中全部服務器上後,你就能夠開始使用 Ansible 了。Ansible 的一項基本功能就是運行特定命令。語法爲:

 
  1. ansible -a "some command"

例如,假設你想升級全部的 CentOS 服務器,能夠運行:

 
  1. ansible centos -a 'yum update -y'

注意:不是必需要根據服務器操做系統來進行分組的。我下面會提到,Ansible Facts[3] 能夠用來收集這一信息;然而,若使用 Facts 的話,則運行特定命令會變得很複雜,所以,若是你在管理異構環境的話,那麼爲了方便起見,我推薦建立一些根據操做系統來劃分的組。

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

 
  1. ansible all -m ping

這會讓 Ansible 嘗試經過 SSH 登陸庫存清單中的全部服務器。在示例 3 中能夠看到 ping命令的部分輸出結果。

 
  1. nwn | SUCCESS => {

  2.    "changed":false

  3.    "ping":"pong"

  4. }

  5. media-centre | SUCCESS => {

  6.    "changed":false

  7.    "ping":"pong"

  8. }

  9. nas | SUCCESS => {

  10.    "changed":false

  11.    "ping":"pong"

  12. }

  13. kids-tv | SUCCESS => {

  14.    "changed":false

  15.    "ping":"pong"

  16. }

  17. ...

示例 3 :Ansible ping 命令輸出

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

複雜任務使用 Ansible playbooks

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

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

 
  1. ---

  2. - hosts:all

  3.  gather_facts:false

  4.  vars:

  5.    ssh_key:'/root/playbooks/files/laptop_ssh_key'

  6.  tasks:

  7.    - name:copy ssh key

  8.      authorized_key:

  9.        key:"{{ lookup('file',ssh_key) }}"

  10.        user:root

示例 4:Ansible 劇本 「pushsshkeys.yaml」

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

gather_facts: 行指明 Ansible 是否去搜索每一個主機的詳細信息。我稍後會作一次更詳細的檢查。如今爲了節省時間,咱們設置 gather_facts 爲 false

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

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

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

 
  1. ansible-playbook push_ssh_keys.yaml

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

如今 SSH 密鑰已經傳輸到服務器中去了,能夠來作點有趣的事了。

使用 Ansible 收集信息

Ansible 可以收集目標系統的各類信息。若是你的主機數量不少,那它會特別的耗時。按個人經驗,每臺主機大概要花個 1 到 2 秒鐘,甚至更長時間;然而有時收集信息是有好處的。考慮下面這個劇本,它會禁止 root 用戶經過密碼遠程登陸系統:

 
  1. ---

  2. - hosts:all

  3.  gather_facts:true

  4.  vars:

  5.  tasks:

  6.    - name:Enabling ssh-key only root access

  7.      lineinfile:

  8.        dest:/etc/ssh/sshd_config

  9.        regexp:'^PermitRootLogin'

  10.        line:'PermitRootLogin without-password'

  11.      notify:

  12.        - restart_sshd

  13.        - restart_ssh

  14.  handlers:

  15.    - name:restart_sshd

  16.      service:

  17.        name:sshd

  18.        state:restarted

  19.        enabled:true

  20.      when:ansible_distribution == 'RedHat'

  21.    - name:restart_ssh

  22.      service:

  23.        name:ssh

  24.        state:restarted

  25.        enabled:true

  26.      when:ansible_distribution == 'Debian'

示例 5:鎖定 root 的 SSH 訪問

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

 
  1. ansible localhost -m setup |less

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

更近一步

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

相關文章
相關標籤/搜索