摘 要
Ansible是新出現的自動化運維工具,基於Python開發,主要使用Paramiko、PyYaml和JinJa2三個關鍵模塊,部署簡單。Ansible集合了衆多運維工具的優點,實現了批量系統配置、批量程序部署、批量運行命令等功能。
本文將按照個人學習Ansible的過程,由淺入深逐漸向讀者介紹ansible的概念,playbook常用模塊以及編寫腳本時的文檔結構,從而爲後續各部門SaaS化軟件需提供的自動安裝部署腳本打下工作基礎。
關鍵詞:ansible playbook 自動運維
1 引言
在互聯網迅猛發展的同時,運維這個工種也從默默無聞的後臺走向公衆視野,被更多的人所知曉。一個公司擁有幾十臺上百臺機器早已不是稀奇事,巨型公司數以萬計的機器都不在話下,在沿用老一套辦法一臺臺的人工修改配置已然不現實,這該怎麼辦呢?相信此時你已然明白運維自動化具體是什麼了。簡單來講,運維自動化就是將日常重複性的工作通過規則設定使其遵循預先既定規則,在指定的範圍時間內自動化運行,但整個過程無需人工參與。而Ansible正是幫助運維人員實現自動化的工具之一。
1)Ansible主要架構如下圖所示:
- INVENTORY: Ansible管理主機的清單,默認位置/etc/anaible/hosts。
- PLAYBOOKS:任務劇本(任務集),編排定義Ansible任務集的配置文件,由Ansible順序依次執行,通常是YML格式文件。
- ANSIBLE:組合INVENTORY、 API、 MODULES、PLUGINS的綠框,可以理解爲ansible命令工具,這一部分是核心執行工具。
- MODULES: Ansible執行命令的功能模塊,多數爲內置的核心模塊,也可自定義,ansible-doc –l 可查看模塊。
- PLUGINS:模塊功能的補充,如連接類型插件、循環插件、變量插件、過濾插件等,該功能不常用。
- HOST:運維操作的目標主機。
2)Ansible執行流程如下圖所示
3)注意事項
- 主控端Python版本需要2.6或以上。
- 被控端Python版本小於2.4需要安裝python-simplejson。
- 被控端如開啓SELinux需要安裝libselinux-python。
- windows不能做爲主控端。
4)Ansible特性
- 模塊化:調用特定的模塊,完成特定任務,可使用任何編程語言寫模塊。
- 部署簡單安全,基於python和OpenSSH,無需在受控主機上安裝客戶端。
- 冪等性:一個任務執行1遍和執行n遍效果一樣,不因重複執行帶來意外情況。
2 Ansible入門
下文所有操作運行環境如下,其他環境可能會略有出入。
主機 | CentOS Linux release 7.4.1708 (Core) |
Python | 2.7.5 |
Ansible | 2.5.3 |
2.1 yum安裝
//安裝eple源
1)yum install epel-release
//安裝Ansible
2)yum install ansible
2.2 Ansible中常用基本概念
在使用Ansible的過程首先需要了解四個基本,其中前兩個屬於基礎文件的定義,後兩個是基本命令的定義:
1)ansible.cfg
Ansible的配置文件,與其他軟件一樣,通過該文件對Ansible運行過程中涉及的一些參數進行設置,常用設置主要包括ssh的配置以及plugin的定義。使用時Ansible通常會在當前目錄下查找是否存在ansible.cfg文件,如果不存在則會到用戶根目錄下查找默認的. ansible.cfg文件。可以運行ansible --version命令查看當前使用的配置文件路徑。
2)hosts
Ansible的主機清單(INVENTORY)文件,主要以分組的形式羅列受控主機連接信息。內容如下圖所示:
以[ ]形式描述分組名稱,下面是隸屬於該組的主機列表,可以是具體的IP地址,也可以是相應訪問域名。同時也可以把一個組作爲另一個組的子成員以children作爲標識。運行時可以通過-i參數來指定hosts文件所在位置,如果沒有指定將使用默認文件/etc/anaible/hosts。
3)ad-hoc 命令
Ansible提供兩種方式去完成任務,一種是 ad-hoc 命令,敲入一些命令去比較快的完成一些事情,而不需要將這些執行的命令特別保存下來,例如停電維護時需要預先關閉所有受控主機。ad-hoc使用ansible命令執行。
4)playbook命令
Ansible提供的另一種完成任務的方式就是playbook命令。playbooks 是一種簡單的配置管理系統與多機器部署系統的基礎。與現有的其他系統有不同之處,且非常適合於複雜應用的部署。Playbook使用ansible-playbook命令執行。
3 Ad-hoc介紹
我們首先通過簡單的ad-hoc示例來熟悉下ansible的基本操作。在這過程中也會涉及到ansible使用ssh進行通信的一些特性。
3.1 Ad-hoc中的Hello World
運維管理中最常用的就是ping命令,用來測試與目標主機的通道是否正常,在ad-hoc中可以使用如下命令實現這一操作。命令中通過-i參數指定主機清單位置,可根據實際情況更換自己的路徑信息,被控主機組名一定要存在於主機清單內。-k參數在執行過程中要求用戶填寫密碼,效果如下圖所示。
3.2 ad-hoc命令語法
從上面的“Hello World”示例中,我們對ad-hoc的執行有了一個初步的認識,命令的詳細語法如下所示:
ansible <host-pattern> [-m module_name] [options]
--version 顯示版本
-a 模塊參數(如果有)
-m module 指定模塊,默認爲command
-v 詳細過程 –vv -vvv更詳細
--list-hosts 顯示主機列表,可簡寫--list
-k --ask-pass 提示連接密碼,默認Key驗證
-K --ask-become-pass 提示使用sudo密碼
-C --check 檢查,並不執行
-T --timeout=TIMEOUT 執行命令的超時時間,默認10s
-u --user=REMOTE_USER 執行遠程執行的用戶
-U SUDO_USER, --sudo-user 指定sudu用戶
-b --become 代替舊版的sudo 切換
-i 指定主機清單文件位置
3.3 Ansible常用模塊
ad-hoc命令中的-m用來指定運行的模塊,其中最重要的模塊就是command/shell模塊,用來在被控主機端執行命令腳本,而command和shell模塊主要區別就是command模塊中的命令不能帶有特殊字符,shell模塊可以。
ad-hoc還將一些shell命令整合爲具體模塊,用戶可以通過調用模塊的方式更加快捷的實現操作目標。這些模塊主要有:
- command/shell模塊,
- ping模塊,測試主機是否是通的。
- file模塊,主要用於遠程主機上的文件操作。
- copy模塊,複製文件到遠程主機。
- service模塊,用於管理服務 。
- yum模塊,使用yum包管理器來管理軟件包。
- user模塊與group模塊,用來管理用戶和用戶組。
- setup模塊,獲取主機信息。
- cron模塊,用於管理計劃任務。
例如下面的命令實現在tomcat分組的被控主機內建立/data/test文件夾,並設置用戶組是vh,所有者是vh,操作權限是755。
ansible tomcat -m file -a "dest=/data/test mode=755 owner=vh group=vh state=directory" –i source/tomcat/9.0/hosts
4 Playbook介紹
在 playbook中可以編排有序的執行過程,甚至於做到在多組機器間,來回有序的執行特別指定的步驟,並且可以同步或異步的發起任務。簡單來說,可以把playbook看做是軟件當中的宏,按照預定的內容完成一系列操作。
4.1 Playbook目錄結構
playbook的典型目錄結構如下圖所示,其中各自文件主要作用是:
- ansible.cfg:ansible配置文件,如果用戶的操作有些個性配置可以在文件中聲明,這樣會取代系統默認的ansible配置。需要注意的是必須將工作路徑切換到ansible.cfg文件所在目錄纔會生效。ansible.cfg文件命名不可變。
- hosts:主機清單,羅列本次操作所涉及的被控主機,通過-i參數引入。hosts文件命名不可變。
- roles:角色目錄,playbook的工作任務以角色進行劃分,每個角色會按照任務列表執行相關操作。roles文件命名不可變。
- tomcat.yml:playbook的入口文件,根據擴展名可以看出該文件以yml格式編寫,在文件內規定了操作的指引信息。文件名稱可自定義。
4.2 Playbook命令語法
playbook命令的詳細語法如下:
ansible-playbook [options] playbook.yml [playbook2 ...]
-u REMOTE_USER, --user=REMOTE_USER # ssh 連接的用戶名
-k, --ask-pass #ssh登錄認證密碼
-s, --sudo #sudo 到root用戶,相當於Linux系統下的sudo命令
-U SUDO_USER, --sudo-user=SUDO_USER #sudo 到對應的用戶
-K, --ask-sudo-pass #用戶的密碼(—sudo時使用)
-T TIMEOUT, --timeout=TIMEOUT # ssh 連接超時,默認 10 秒
-C, --check # 指定該參數後,執行 playbook 文件不會真正去執行,而是模擬執行一遍,然後輸出本次執行會對遠程主機造成的修改
-e EXTRA_VARS, --extra-vars=EXTRA_VARS # 設置額外的變量如:key=value 形式 或者 YAML or JSON,以空格分隔變量,或用多個-e -f FORKS, --forks=FORKS # 進程併發處理,默認 5
-i INVENTORY, --inventory-file=INVENTORY # 指定 hosts 文件路徑,默認 default=/etc/ansible/hosts
-l SUBSET, --limit=SUBSET # 指定一個 pattern,對- hosts:匹配到的主機再過濾一次 --list-hosts # 只打印有哪些主機會執行這個 playbook 文件,不是實際執行該 playbook --list-tasks # 列出該 playbook 中會被執行的 task --private-key=PRIVATE_KEY_FILE # 私鑰路徑 --step # 同一時間只執行一個 task,每個 task 執行前都會提示確認一遍 --syntax-check # 只檢測 playbook 文件語法是否有問題,不會執行該 playbook
-t TAGS, --tags=TAGS #當 play 和 task 的 tag 爲該參數指定的值時才執行,多個 tag 以逗號分隔 --skip-tags=SKIP_TAGS # 當 play 和 task 的 tag 不匹配該參數指定的值時,才執行
-v, --verbose #輸出更詳細的執行過程信息,-vvv可得到所有執行過程信息。
4.3 Playbook常用模塊
爲了方便用戶使用,playbook內置了許多功能模塊,比較常用的模塊主要有:
1)file模塊
參數名 | 是否必須 | 默認值 | 選項值 | 說明 |
follow | no | no | yes/no | 如果原來的文件是link,拷貝後依舊是link |
force | no | no | yes/no | 強制執行,沒說的 |
group | no | 設定一個羣組擁有拷貝到遠程節點的文件權限 | ||
mode | no | 等同於chmod,參數可以爲“u+rwx or u=rw,g=r,o=r” | ||
owner | no | 設定一個用戶擁有拷貝到遠程節點的文件權限 | ||
path | yes | 目標路徑,也可以用dest,name代替 | ||
src | yes | 待拷貝文件/文件夾的原始位置。 | ||
state | no | file | file/link/directory/hard/touch/absent | file代表拷貝後是文件;link代表最終是個軟鏈接;directory代表文件夾;hard代表硬鏈接;touch代表生成一個空文件;absent代表刪除 |
2)copy模塊
參數名 | 是否必須 | 默認值 | 選項值 | 說明 |
src | no | 用於定位ansible執行的機器上的文件,需要絕對路徑。如果拷貝的是文件夾,那麼文件夾會整體拷貝,如果結尾是”/”,那麼只有文件夾內的東西被考過去。一切的感覺很像rsync | ||
content | no | 用來替代src,用於將指定文件的內容,拷貝到遠程文件內 | ||
dest | yes | 用於定位遠程節點上的文件,需要絕對路徑。如果src指向的是文件夾,這個參數也必須是指向文件夾 | ||
backup | no | no | yes/no | 備份遠程節點上的原始文件,在拷貝之前。如果發生什麼意外,原始文件還能使用。 |
directory_mode | no | 這個參數只能用於拷貝文件夾時候,這個設定後,文件夾內新建的文件會被拷貝。而老舊的不會被拷貝 | ||
follow | no | no | yes/no | 當拷貝的文件夾內有link存在的時候,那麼拷貝過去的也會有link |
force | no | yes | yes/no | 默認爲yes,會覆蓋遠程的內容不一樣的文件(可能文件名一樣)。如果是no,就不會拷貝文件,如果遠程有這個文件 |
group | no | 設定一個羣組擁有拷貝到遠程節點的文件權限 | ||
mode | no | 等同於chmod,參數可以爲“u+rwx or u=rw,g=r,o=r” | ||
owner | no | 設定一個用戶擁有拷貝到遠程節點的文件權限 |
3)template模塊
參數名 | 是否必須 | 默認值 | 選項值 | 說明 |
backup | no | no | yes/no | 建立個包括timestamp在內的文件備份,以備不時之需. |
dest | yes | 遠程節點上的絕對路徑,用於放置template文件。 | ||
group | no | 設置遠程節點上的的template文件的所屬用戶組 | ||
mode | no | 設置遠程節點上的template文件權限。類似Linux中chmod的用法 | ||
owner | no | 設置遠程節點上的template文件所屬用戶 | ||
src | yes | 本地Jinjia2模版的template文件位置。 |
4)shell 模塊
參數名 | 是否必須 | 默認值 | 選項值 | 參數說明 | ||
chdir | no | 運行command命令前先cd到這個目錄 | ||||
creates | no | 如果這個參數對應的文件存在,就不運行command | ||||
executable | no | 將shell切換爲command執行,這裏的所有命令需要使用絕對路徑 | ||||
removes | no | 如果這個參數對應的文件不存在,就不運行command | ||||
5)Yum模塊
參數名 | 是否必須 | 默認值 | 選項值 | 參數說明 |
conf_file | no | 設定遠程yum執行時所依賴的yum配置文件 | ||
disable_gpg_check | no | no | yes/no | 在安裝包前檢查包,只會影響state參數爲present或者latest的時候 |
list | no | 只能由ansible調用,不支持playbook,這個幹啥的大家都懂 | ||
name | yes | 你需要安裝的包的名字,也能如此使用name=python=2.7安裝python2.7 | ||
state | no | present | present/latest/absent | 用於描述安裝包最終狀態,present/latest用於安裝包,absent用於remove安裝包 |
update_cache | no | no | yes/no | 用於安裝包前執行更新list,只會影響state參數爲present/latest的時候 |
6)service模塊
參數名 | 是否必須 | 默認值 | 選項值 | 說明 |
enabled | no | yes/no | 啓動os後啓動對應service的選項。使用service模塊的時候,enabled和state至少要有一個被定義 | |
name | yes | 需要進行操作的service名字 | ||
state | no | stared/stoped/restarted/reloaded | service最終操作後的狀態。 |
7)unarchive模塊
參數名 | 是否必須 | 默認值 | 選項值 | 說明 |
copy | no | yes | yes/no | 在解壓文件之前,是否先將文件複製到遠程主機,默認爲yes。若爲no,則要求目標主機上壓縮包必須存在。 |
creates | yes | 指定一個文件名,當該文件存在時,則解壓指令不執行 | ||
dest | yes | 遠程主機上的一個路徑,即文件解壓的路徑 | ||
grop | no | 解壓後的目錄或文件的屬組 | ||
list_files | no | no | yes/no | 如果爲yes,則會列出壓縮包裏的文件,默認爲no,2.0版本新增的選項 |
mode | no | 解壓後文件的權限 | ||
src | no | 如果copy爲yes,則需要指定壓縮文件的源路徑 | ||
owner | no | 解壓後文件或目錄的屬主 |
4.4 編寫Playbook
在編寫playbooke實現運維管理的時候,最主要的就是定義好入口文件,並依照操作順序利用功能模塊編寫任務列表。整個過程可以這樣理解:運維管理就是一場表演,入口文件就是導演,它規定了演員是誰、出演什麼角色、到哪表演;任務列表就是角色的劇本,每一條任務就是一句臺詞。當所有人按照劇本表演完成整場演出也就順理完成。
1)導演的職責
編寫入口文件的內容相對固定,以tomcat.yml舉例來看:
- 第2行表明是註釋,用戶可自行描述,需要注意的是註釋中不能有中文。
- 第3行聲明的被控主機的組名,在引入的hosts文件裏需有對應的定義,導演就是通過這裏規定了演員的表演場所。
- 第4行聲明的是以root用戶身份去被控主機執行操作,導演就是通過這裏規定了誰是演員。
- 第5行聲明的是主控機是否需要收集被控主機的系統變量,最常用的就是獲知當前正在操作的受控主機IP地址。
- 第6、7行聲明的是參與本次操作的角色信息。每個角色對應roles目錄裏面的一個子目錄。導演就是通過這裏規定了演員擔任的角色。
2)劇本的作用
playbook的具體操作邏輯都是由角色來實現的,在規範中對於角色目錄下的內容都有明確定義,最常見的就是files、tasks、templates、vars四個文件夾,其中tasks就是存放劇本的位置,其他文件夾都是表演中使用的道具。
- files:文件夾內存放第三方文件,這裏的文件不經過任何變化直接複製到被控主機。通常files目錄用來存放程序的安裝包文件,由copy模塊操作。
- tasks:文件夾內存放以yml格式定義任務列表,playbook執行後會按入口文件定義的順序依次執行角色文件夾內main.yml文件。
- templates:文件夾內存放模板文件,模板文件以JinJa2格式編寫的,執行時會將相應變量替換成真正內容後,再複製到被控主機。通常templates目錄用來存放軟件的配置文件、輔助文件,對需要動態調整的內容以參數替換形成模板,由template模塊操作。
- vars:文件夾內存放以yml格式定義參數文件,playbook查找參數時會默認搜索vars目錄下main.yml文件。
任務列表由一條條任務組成,每條任務都可以看做是一條ad-hoc(shell命令),不過任務中可以搭配循環、條件、異常處理等邏輯控制,實現更加複雜的操作。任務列表格式如下圖所示:name定義任務的描述信息,下一行指出執行任務使用的模塊。模塊的參數值可指定爲參數文件裏面定義的變量,用兩層{}包裹起來,需要注意的是爲了跟YAML語法中字典的定義進行區分,引入變量的{{}}需要用英文狀態的雙引號包起來,爲了簡便也可整行參數直接用雙引號包起來。
5 總結
本文主要通過介紹ansible框架、基本概念、ad-hoc及playbook的使用,讓讀者對ansible工具有了初步認識,明確編寫playbook腳本時需要關注的內容,以及各部分所起到的作用,對於運維中的操作可以快速找到相對應的模塊實現具體操作。讀者也可以從參考文獻1處的網址下載ansible示例,通過學習以及動手改造可以使你更快的掌握ansible工具。由於篇幅限制本文對於如何免密登錄ssh、如何避免自動化執行過程中的交互動作以及playbook的循環、邏輯控制等沒有展開詳談,這些內容會在下一篇內容中進行闡述,幫助讀者更加全面瞭解ansible的作用。
參考文獻
[1] ansible示例 https://github.com/ansible/ansible-examples
[2] ansible中文權威指南 http://ansible.com.cn/docs/intro.html
[3] YAML 語言教程 http://www.ruanyifeng.com/blog/2016/07/yaml.html
[4] Ansible安裝與配置 https://blog.csdn.net/xyang81/article/details/51568227