IT 自動化工具 Ansible 入門指南

Ansible 是一個非常簡單的 IT 自動化引擎,可以完成諸如云端資源調配、配置管理、應用部署、服務協調等眾多 IT 自動化任務。它不需要在受控端安裝配置額外的 agent 軟件,因此部署流程非常簡單。
Ansible 的運行機制也并不復雜,它通過 SSH 協議向遠程節點推送特定的“小程序”(Ansible modules)并運行,一旦運行完成則將其移除。
同時 Ansible 提供了一種非常簡單易懂的語言(YAML)用于編寫自動化代碼。

一、簡介

Ansible 通常會被描述為一個配置管理工具,類似于 ChefPuppetSalt 等。
通過配置管理工具,我們可以確保服務器主機處于某種期望的狀態,比如指定的軟件包已安裝,配置文件中包含正確的值,運行著特定的服務等。
與其他配置管理工具一樣,Ansible 也加入了自己的 DSL(領域專用語言)用來描述服務器的狀態,即后面會介紹到的用于編寫 Playbook 的 YAML 語言。

Ansible 也可以用于部署任務,比如通過源代碼生成可執行程序或靜態資源并發布到服務器,然后開啟遠程主機上的對應服務。類似的開源部署工具如 Fabric 等。

還有一種需求叫做流程編排,通常會涉及到多個遠程服務器,用于確保各類型的任務以特定順序執行。比如在開啟 Web 服務器之前確保數據庫服務處于已經運行的狀態。
Ansible 從設計之初即關注多個服務器狀態下任務的執行,它有一個非常簡單的模塊用于控制動作的順序。

此外,Ansible 還提供眾多的模塊用來與常見的云服務進行交互,包括 Amazon EC2、Azure、Digital Ocean、Linode 以及任何支持 OpenStack API 的云端服務。

一個簡單的 Ansible 運行實例如下圖:


在三個服務器上運行 Playbook

二、Ansible 安裝

絕大部分 Linux 發行版的軟件鏡像中都默認包含了 Ansible 的安裝包, 可以直接通過對應的包管理器進行安裝。如 Ubuntu 系統:
$ sudo apt-get install ansible

Ansible 是基于 Python 語言開發的,因此也可以通過 Python 的包管理器進行安裝,命令如下:
$ pip install ansible

我用 VirtualBox 軟件搭建了兩臺 Ubuntu 19.04 虛擬機,配置了內部網絡(Internal)的聯網方式。
server1 IP 地址為 192.168.1.101,用于安裝 Ansible 環境。
server2 IP 地址為 192.168.1.102,作為遠程主機進行測試。兩者可以相互 ping 通。

SSH 的密鑰認證

為了使得每次運行 Ansible 任務時,不需要重復輸入遠程主機的認證信息,這里先配置好 SSH 連接的無密碼認證(即 RSA 密鑰認證)。命令如下:

$ # 生成 SSH 密鑰文件
$ ssh-keygen
$ # 復制公鑰文件到遠程主機(需要輸入密碼)
$ ssh-copy-id remoteuser@remoteserver

運行成功后,使用 $ ssh remoteuser@remoteserver 命令進行測試,如可以自動登錄,則配置完成。

PS:被控制的遠程主機不需要安裝任何客戶端軟件,但是必須確保已安裝 Python 且 sshd 服務處于運行狀態。如兩者未正確安裝,可運行以下命令:

$ sudo apt-get install python
$ sudo apt-get install openssh-server
主機清單(Inventory)

Ansible 通過一個主機清單文件(hosts)存放被管理的服務器的列表。
創建 playbooks 目錄作為存放 ansible 腳本和配置文件的項目文件夾,進入該目錄并編輯如下 hosts 文件:

server2 ansible_ssh_host=192.168.1.102 ansible_ssh_user=skitar ansible_ssh_private_key_file=~/.ssh/id_rsa

通過 hosts 中定義的服務器別名和連接信息訪問遠程主機并執行 ping 模塊:
$ ansible server2 -i hosts -m ping

輸出內容如下:

server2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

如看到類似上面的輸出則 Ansible 環境配置完成。

PS:Ansible 主機清單的配置文件默認為 /etc/ansible/hosts。如需使用其他位置的主機清單文件,可以通過 -i 選項手動指定,或者修改 ansible.cfg 配置文件的 inventory 項。

ansible.cfg

ansible.cfg 文件中包含了 Ansible 工具的一些默認配置,該文件通常位于以下位置:

  • 當前目錄(./ansible.cfg)
  • Home 目錄(~/.ansible.cfg)
  • /etc/ansible/ansible.cfg

在當前目錄下創建 ansible.cfg 文件并輸入以下內容:

[defaults]
inventory = hosts
remote_user = skitar
private_key_file = ~/.ssh/id_rsa
host_key_checking = False

由于部分默認選項已配置,此時的 hosts 文件則可以省略用戶名和密鑰文件等信息,簡化為如下形式:

server2 ansible_ssh_host=192.168.1.102

使用 ansible 命令時也無需再通過 -i hosts 選項手動指定主機清單文件。即之前的 ping 模塊可以這樣調用:
$ ansible server2 -m ping

Ad-Hoc 命令

即通過命令行的形式直接調用 Ansible 模塊。
Ansible 有著功能豐富的內置模塊,可以通過 ansible-doc -l 命令顯示所有的內置模塊,通過 ansible-doc <module> 命令查看指定模塊的介紹以及使用案例。

Ansible 內置的 command 模塊可以用來在遠程主機上執行 Linux 命令。如執行 uptime 命令:

$ ansible server2 -m command -a uptime
server2 | CHANGED | rc=0 >>
 17:45:12 up  5:13,  1 user,  load average: 0.12, 0.08, 0.02

其中 -m 用于指定調用的模塊,-a 用于指定傳遞給該模塊的選項,此處即某個具體的命令。
由于 command 模塊很常用,它其實是不指定任何模塊情況下的默認模塊。所以上面的命令也可以使用如下形式:
$ ansible server2 -a uptime

當遠程主機上執行的命令中包含空格時,需要用引號括起來,示例如下:

$ ansible server2 -a "tail /var/log/syslog"
server2 | CHANGED | rc=0 >>
Jul  8 18:18:18 server2 systemd[6250]: Reached target Paths.
Jul  8 18:18:18 server2 systemd[6250]: Listening on GnuPG cryptographic agent and passphrase cache (access for web browsers).
Jul  8 18:18:18 server2 systemd[6250]: Listening on D-Bus User Message Bus Socket.
Jul  8 18:18:18 server2 systemd[6250]: Reached target Sockets.
Jul  8 18:18:18 server2 systemd[6250]: Reached target Basic System.
Jul  8 18:18:18 server2 systemd[1]: Started User Manager for UID 1000.
Jul  8 18:18:18 server2 systemd[1]: Started Session 47 of user skitar.
Jul  8 18:18:18 server2 systemd[6250]: Reached target Default.
Jul  8 18:18:18 server2 systemd[6250]: Startup finished in 75ms.
Jul  8 18:18:19 server2 python3[6304]: ansible-command Invoked with _raw_params=tail /var/log/syslog warn=True _uses_shell=False stdin_add_newline=True strip_empty_ends=True argv=None chdir=None executable=None creates=None removes=None stdin=None

對于某些需要 root 權限才能執行的操作,則需要加上 --become --ask-become-pass 或者 -b -K 選項通過 sudo 執行。如使用 service 模塊重啟遠程主機上的 nginx 服務:

$ ansible server2 -b -K -m service -a "name=nginx state=restarted"
BECOME password:
server2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "name": "nginx",
    "state": "started",
    "status": {
        "ActiveEnterTimestamp": "Mon 2019-07-08 18:16:58 CST",
        "ActiveEnterTimestampMonotonic": "20685653757",
        "ActiveExitTimestamp": "Mon 2019-07-08 18:16:57 CST",
        "ActiveExitTimestampMonotonic": "20685035019",
        "ActiveState": "active",
...

其他常用的內置模塊還有 apt、copy、user 等。

如通過 apt 模塊管理遠程主機上的軟件包:

$ ansible server2 --b -K -m apt -a "name=nginx state=latest"
BECOME password:
 [WARNING]: Could not find aptitude. Using apt-get instead

server2 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "cache_update_time": 1562598780,
    "cache_updated": false,
    "changed": false
}

通過 copy 模塊復制本地文件到遠程主機:

$ ansible server2 -m copy -a "src=ansible.cfg dest=/home/skitar/ansible.cfg owner=skitar mode=644"
server2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": true,
    "checksum": "2f4f9975ef1875adcc2a299d3962f70630f49965",
    "dest": "/home/skitar/ansible.cfg",
    "gid": 1001,
    "group": "skitar",
    "mode": "0644",
    "owner": "skitar",
    "path": "/home/skitar/ansible.cfg",
    "size": 109,
    "state": "file",
    "uid": 1000
}

通過 user 模塊管理遠程主機上的用戶(需要先通過 openssl 命令生成密碼,因為 user 模塊的 password 參數只接受加密后的值):

$ echo ansible | openssl passwd -1 -stdin
$1$ZyNqkbXH$i.4R0EDQZV.zu8akyJAu10
$ ansible server2 -b -K -m user -a 'name=starky password="$1$ZyNqkbXH$i.4R0EDQZV.zu8akyJAu10" shell=/bin/bash'
BECOME password:
server2 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "append": false,
    "changed": true,
    "comment": "",
    "group": 1002,
    "home": "/home/starky",
    "move_home": false,
    "name": "starky",
    "password": "NOT_LOGGING_PASSWORD",
    "shell": "/bin/bash",
    "state": "present",
    "uid": 1001
}

三、Playbooks

Playbooks 即 Ansible 用于執行自動化配置的腳本文件。它使用非常簡單的 YAML 語言描述期望達到的狀態,YAML 之于 JSON 類似于 Markdown 之于 HTML 。

一個簡單的用于配置 nginx 站點的 playbook 示例(web-notls.yml)如下:

- name: Configure webserver with nginx
  hosts: webservers
  become: True
  tasks:
    - name: install nginx
      apt: name=nginx update_cache=yes

    - name: copy nginx config file
      copy: src=files/nginx.conf dest=/etc/nginx/sites-available/default

    - name: enable configuration
      file: >
        dest=/etc/nginx/sites-enabled/default
        src=/etc/nginx/sites-available/default
        state=link

    - name: copy index.html
      template: src=templates/index.html.j2 dest=/var/www/html/index.html mode=0644

    - name: restart nginx
      service: name=nginx state=restarted

編輯 nginx 配置文件,即 playbook 中 copy 模塊的 src 選項指定的文件(files/nginx.conf),內容如下:

server {
        listen 80 default_server;

        root /var/www/html;
        index index.html;

        server_name 192.168.1.102;

        location / {
                try_files $uri $uri/ =404;
        }
}

編輯 nginx 站點的主頁文件,即 playbook 中 template 模塊的src 選項指定的文件(templates/index.html.j2),內容如下:

<html>
  <head>
    <title>Welcome to ansible</title>
  </head>
  <body>
  <h1>nginx, configured by Ansible</h1>
  <p>If you see this, Ansible successfuly installed nginx.</p>
  <p>Current time is {{ now() }}</p>
  </body>
</html>

此處使用了 Jinjia2 模板引擎,所以可以通過 {{ now() }} 獲取當前系統時間并替換到 HTML 文檔中。

編輯 Inventory (主機清單)即hosts 文件,創建 webservers 主機組

[webservers]
server2 ansible_ssh_host=192.168.1.102

主機組中可以包含一個或多個遠程主機,便于同時管理多個遠程節點。

上述配置完成后,通過 ansible-playbook web-nolts.yml -K 命令運行 playbook,輸出如下:

$ ansible-playbook web-notls.yml -K
BECOME password:

PLAY [Configure webserver with nginx] **********************************************************

TASK [Gathering Facts] *************************************************************************
ok: [server2]

TASK [install nginx] ***************************************************************************
 [WARNING]: Could not find aptitude. Using apt-get instead

ok: [server2]

TASK [copy nginx config file] ******************************************************************
changed: [server2]

TASK [enable configuration] ********************************************************************
ok: [server2]

TASK [copy index.html] *************************************************************************
changed: [server2]

TASK [restart nginx] ***************************************************************************
changed: [server2]

PLAY RECAP *************************************************************************************
server2                    : ok=6    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

注意 ansibe-playbook 命令的 -K 選項(即 --ask-become-pass),由于 playbook 中的部分任務需要 root 權限執行,加上 -K 選項后,執行 playbook 時會出現 BECOME password: 提示用于輸入 sudo 密碼。否則會報錯。

playbook 執行成功后,使用 curl 192.168.1.102 命令訪問 server2 上剛剛配置的 nginx 站點,輸出如下:

$ curl 192.168.1.102
<html>
  <head>
    <title>Welcome to ansible</title>
  </head>
  <body>
  <h1>nginx, configured by Ansible</h1>
  <p>If you see this, Ansible successfuly installed nginx.</p>
  <p>Current time is 2019-07-09 00:28:46.484053</p>
  </body>
</html>

參考資料

Ansible: Up and Running, 2nd Edition

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內容