讀一本書最好的時機是什麼時候?是你剛買的時候,趁著新鮮勁,先了解這本書,繼而馬上閱讀完這本書。如果錯過了最好的時機閱讀一本書,那什麼時候是合適的時機,是你需要這方面的資料或者知識的時候。
最近我一直在研究 Ansible 自動化運維工具。入手請參考 Ansible 上手指南。主要是為了實現自己在遠端主機進行相關操作的任務,以此為切入點進行學習。
在實現了自己的任務後,我準備繼續研究下 Ansible 的其他用法。下面就是我的個人總結。
體會:
- 文件內容很多,不可能全部掌握,使用 2/8 法則,看看同事們口中的主要內容有哪些
- 實踐型的內容,還是需要自己寫寫程式碼,執行,看看效果。當你跑通了你自己寫的程式碼,有可能你就學會了這個知識點
- 快速入手的方法是:如果你急切需要解決問題,那就問有經驗的人。如果你不是很急,先嚐試瞭解下內容,不懂再問別人。反覆提出你的疑問。
- 提問題不要覺得不好意思,時間很珍貴的。
下面的總結主要以例子為主:
- 第一稿:拋棄所有參考資料,憑藉實踐的經驗總結
- 第二稿:彌補不明白的地方
- 第三稿:對著參考文獻修正不對的地方,釋出
大綱:
- ansible.cfg 配置檔案
- 變數
- 判斷
- 迴圈
- 常用模組
- debug
- copy
- file
- shell
- command
- stat
- unarchive
- ping
- template
- user
- group
- service
- get_url
- include
- role
- 目錄結構
- 依賴
- 執行順序
Ansible 是使用Python 編寫,基於模組化的工作方式,真正處理動作都是這些模組。Ansible 提供整體的框架。
1、安裝
pip install ansible
複製程式碼
或者根據Linux 的版本進行安裝
apt-get install ansible
複製程式碼
管理主機要求是Linux, 節點主機需要帶 Python 及相應的庫。
一般是管理主機和節點主機都是Linux。
2、基本使用
命令列方式執行:
命令列方式適合操作簡單的動作。
ansible all -m ping
複製程式碼
playbook 執行:
playbook 適合複雜的處理動作。
ansible-playbook example.yml
複製程式碼
檢視支援的模組:
ansible-doc -l
複製程式碼
檢視某模組用法及支援的引數:
ansible-doc -s ping
複製程式碼
3、配置檔案
安裝完成之後,預設目錄下有兩個檔案:
/etc/ansible/hosts
/etc/ansible/ansible.cfg
複製程式碼
hosts 檔案定義節點主機的IP 及以下配置資訊。
ansible.cfg 檔案定義全域性配置檔案,配置項很多, 一般預設就可以完成你的日常任務了。
但是除預設的生成的 ansible.cfg 檔案之外,你可以在自己的專案中建立這樣一個同名ansible.cfg 檔案。
ansible 讀取配置檔案的順序是:
- ANSIBLE_CONFG 環境變數中定義
- ansible.cfg 當前目錄
- */ansible.cfg 當前使用者home/username/ansible.cfg
- /etc/ansible/ansible.cfg 預設生成的檔案路徑
怎麼理解這個讀取配置檔案的資訊呢?
舉個例子:
# 當前專案結構
ansible:
---playbooks
---example
---leanr-ansible/example.yml
---ansible.cfg
複製程式碼
你在這個目錄下執行:ansible 命令
- 那麼首先檢視環境變數有沒有設定,沒有那就讀取當前目錄下的ansible.cfg 配置資訊;
- 如果當前目錄沒有設定,那麼就搜尋home 目錄下有沒有配置資訊。
- 否則讀取預設生成的配置資訊。
4、常用模組
操作動作舉例
這裡為舉例只明白這些模組的使用場景,故意執行多步操作。
- 拷貝管理節點
/home/ubuntu/zartclient
下的zartcli
和zartcli.ini
檔案至節點主機/home/ubuntu/zartclient
下 - 在上一步的基礎之上,拷貝
/home/ubuntu/zartclient/zartcli
至/usr/bin/zartcli
- 在節點主機上使用剛才拷貝的檔案,執行下載命令:
zartcli -o=download -i=admin -m=bin -n=op-cli -v=v0.0.3 -p=/home/ubuntu/download
下載至/home/ubuntu/download
目錄 - 在節點主機上解壓下載的檔案至
/paasdata/data
目錄下 - 在節點主機上拷貝解壓之後的檔案至 /etc/opcli 目錄下
- 在節點主機上拷貝
op-cli
至/usr/bin
- 在節點主機上
op-cli task list
執行命令 - 在節點主機上
op-cli node list
執行命令
快閱讀時代,估計沒人想認真看這些動作。畫個流程圖吧。
把每一步動作認為是一個任務 task.
第一步:先檢查是否存在對應的檔案,是則拷貝
模組:stat, copy, debug, file
- 判斷遠端節點主機是否存在對應的資料夾
- 不存在則建立
- 拷貝本地檔案至遠端節點主機的對應的目錄下
- name: is /home/ubuntu/zartclient exists
stat:
path: /home/ubuntu/zartclient
register: result
- name: show result
debug:
msg: "{{result}}"
- name: create dest path in remote
file:
path: "{{ dest-path }}"
state: direstory
with_items:
- "/home/ubuntu/zartclient"
when: not result.stat.exists
- name: copy file to remote
copy:
src: "{{item.src}}"
dest: "{{item.dest}}"
with_items:
- { src: "/home/ubuntu/zartclient/zartcli" dest: "/home/ubuntu/zartclient"}
- { src: "/home/ubuntu/zartclient/zartcli.ini" dest: "/home/ubuntu/zartclient"}
- name: copy zartcli into /usr/bin
copy:
src: "{{item.src}}"
dest: "{{item.dest}}"
with_items:
- { src: "/home/ubuntu/zartclient/zartcli", dest: "/usr/bin"}
複製程式碼
可以看出,處理相應的動作,有相應的模組,模組帶引數,完成任務。
{{ }}
裡面表示變數- with_items: 是一個列表,表示迴圈獲取變數
- register : 表示把執行的動作結果賦值給一個變數,是一個map, 可以根據鍵值,獲取內容
- when: 表示判斷, 根據結果的布林值進行操作
第二步:先查詢是否存在檔案,存在則執行下載命令
第一步拷貝的檔案是一個客戶端,主要是對檔案的上傳、下載、查詢等。
模組:shell 、 command
- name: is /home/ubuntu/download exists
stat:
path: "{{item}}"
with_items:
- "/home/ubunt/download"
register: result
- name: create /home/ubuntu/download
file:
path: "{{item}}"
state: direstroy
with_items:
- "home/ubuntu/download"
when: not result.stat.exists
- name: query op-cli
command: "{{tools}} -o={{operate}} -i={{tenants}} -m={{type}} -n={{name}} \
-v={{version}}"
vars:
tools: zartcli
operate: query
tenants: admin
type: bin
name: op-cli
version: v0.0.3
register: result
- name: download op-cli
command: "{{tools}} -o={{operate}} -i={{tenants}} -m={{type}} -n={{name}} \
-v={{version}} -p={{path}}"
vars:
tools: zartcli
operate: query
tenants: admin
type: bin
name: op-cli
version: v0.0.3
path: /home/ubuntu/download
複製程式碼
- item 是個關鍵字,表示變數
- item[0] 可以表示變數是一個列表,這裡表示列表的第一個值
- item.src 可以表示變數是一個map, 這裡表示map的src 的值
- vars 表示模組中可以填充自定義的變數名稱對應的值
第三步:解壓下載的檔案
第二步下載的檔案內是一個 tar 包,需要將其解壓至指定目錄
模組:unarchive, file
- name: create /paasdata/data
file:
path: "/paasdata/data"
state: direstory
- name: untar file
unarchive:
src: "{{src-path}}"
dest: "{{dest-path}}"
remote_src: yes
vars:
src-path: "/home/ubuntu/download/admin_op_cli_v0.0.3/op-cli.tar.gz"
dest-path: "/paasdata/data"
複製程式碼
- yes 和 true 沒區別
- remote_src: yes 表示解壓的檔案在節點主機上操作
第四步:拷貝檔案
- name: create /etc/opcli
file:
path: "/etc/opcli"
state: directory
- name: copy /paadata/data/conf||op-cli
copy:
src: "{{item.src}}"
dest: "{{item.dest}}"
with_items:
- { src: "/paasdata/data/conf/common.yml" dest: "/etc/opcli/conf"}
- { src: "/paasdata/data/op-cli" dest: "/usr/bin"}
複製程式碼
第五步:執行查詢命令
- name: op-cli task list || op-cli node list
command: "{{item[0]}} {{item[1]}} list"
with_nested:
- [ "op-cli" ]
- ["task", "node", "nodepool"]
複製程式碼
- with_nested: 巢狀迴圈
上文相當於:op-cli task list, op-cli node list, op-cli nodepool list
上文借用一些迴圈,把之前規劃的 八 個動作改成了 五個動作, 即 五 個動作內的每一個又包含幾個動作。
新手容易把上面的所有的動作都處理在一個檔案內:但是其實存在更好的處理方法。
# main.yml
---
- hosts: 10.62.60.21
romote_user: root
tasks:
- name: one # 第一步
- name: two # 第二步
- name: three # 第三步
- name: four # 第四步
- name: five # 第五步
- name: six # 第六步
...
複製程式碼
5、 include_tasks
假如你希望寫的task 能夠進行復用,就相當於程式設計領域裡的抽象出函式一樣。ansible 提供這樣的機制。即將上文一個很大的檔案拆分成獨立的檔案。使用 include_tasks 方法將檔案匯入。
比如:上文的五步動作分別單獨寫檔案
- zartclient.yml
- download.yml
- untarfile.yml
- copyfile.yml
- executecommand.yml
playbook 入口: mail.yml
則main.yml 如下:
---
- hosts: 10.62.60.21
root_usr: root
tasks:
- include_tasks: zartclient.yml
- include_tasks: download.yml
- include_tasks: untarfile.yml
- include_tasks: copyfile.yml
- include_tasks: executecommand.yml
複製程式碼
即將各個處理動作獨立出去。隨時複用。
6、roles
看上去 include_tasks 方式就是對ansible-playbook 的一種比較好的組織方式了。
ansible 提供了一種更好的組織方式:roles
Roles 基於一個已知的檔案結構,去自動的載入某些 vars_files,tasks 以及 handlers。基於 roles 對內容進行分組,使得我們可以容易地與其他使用者分享 roles。 這樣的組織方式使得複用更為簡便。每個相對獨立的處理動作獨立出來,可以適用於更復雜的場景。
一個role 的檔案大概包括這些:
- tasks 檔案:主要編寫某個獨立模組的處理動作
- handlers 檔案:
- vars 檔案: 主要編寫某個獨立模組的變數
- meta 檔案:主要編寫依賴關係,即一個獨立模組引用另一個role
- defaults 檔案:預設的變數檔案
- templates 檔案: 模板檔案
- files 檔案
注意資料夾下可以有多個字尾名為yml
的檔案,但一定要有main.yml
檔案
上文的處理動作,使用 roles 重新組織如下:
目錄:
├─ansible
│ ├─playbook
│ └─roles
│ ├─download-bin
│ │ ├─tasks
│ │ └─vars
│ └─op-cli
│ ├─meta
│ ├─tasks
│ └─vars
複製程式碼
這裡以上文的處理動作:下載檔案獨立成一個 download-bin role 為例,講述如何編寫 role.
tasks/deploy.yml
- name: download bin by zartcli
command: "{{zartcli_cli_path}}/zartcli -o=download -i={{tenant_id}} -m={{bin_type}} \
-n={{bin_name}} -v={{bin_version}} -p={{download_path}}"
複製程式碼
tasks/main.yml
---
- include_tasks: download.yml
vars:
zartcli_cli_path: "{{zartcli_clipath}}"
tenant_id: "{{tenantid}}"
bin_name: "{{binname}}"
bin_version: "{{binversion}}"
download_path: "{{downloadpath}}"
bin_type: "{{bintype}}"
複製程式碼
vars/main.yml
---
zartcli_clipath: "/home/cloud/zartclient"
tenantid: "admin"
binname: "op-cli"
binversion: "v0.0.3"
downloadpath: "/home/cloud/zartclidownload"
bintype: "bin"
複製程式碼
task/main.yml 是這個role 的入口。匯入download.yml,下載所需要的變數全部置放在 var/main.yml 檔案中。
別的role 需要複用這個模組:
op-cli/meta/main.yml
dependencies:
- role: download-bin
複製程式碼
這樣 op-cli role 也有download 動作。
roles 適用於組織較為複雜的專案,將各個模組獨立處理,又可以相互複用。使用 include_tasks 存在模組的複用性變低、變數需要重複定義等缺點。
上文 op-cli role 複用download-bin,無需再次定義變數。
再一個值得注意的是:一般playbook 的執行順序和task 的定義順序一致。
使用 roles 後,playbook 中 roles 先執行,再按tasks 的定義順序執行。
如果需要最先執行某個task , 或者最後執行某個task, 可以使用pre_tasks
和 post_tasks
。
pre_tasks
最先執行post-tasks
最後執行
再一個使用roles 需要配置 ansible.cfg
roles_path = 目錄
# 即roles 所在的檔案目錄
複製程式碼
7、參考文獻
這些原理性的東西,用文字不是很好講,以後遇到文字難以表達出來,我錄個視訊實際操作下。這樣讀者可能更好理解。