讀一本書最好的時機(jī)是什么時候唠倦?是你剛買的時候称鳞,趁著新鮮勁,先了解這本書稠鼻,繼而馬上閱讀完這本書冈止。如果錯過了最好的時機(jī)閱讀一本書,那什么時候是合適的時機(jī)候齿,是你需要這方面的資料或者知識的時候熙暴。
最近我一直在研究 Ansible 自動化運維工具。入手請參考 Ansible 上手指南慌盯。主要是為了實現(xiàn)自己在遠(yuǎn)程主機(jī)進(jìn)行相關(guān)操作的任務(wù)周霉,以此為切入點進(jìn)行學(xué)習(xí)。
在實現(xiàn)了自己的任務(wù)后亚皂,我準(zhǔn)備繼續(xù)研究下 Ansible 的其他用法俱箱。下面就是我的個人總結(jié)。
體會:
- 文檔內(nèi)容很多灭必,不可能全部掌握狞谱,使用 2/8 法則乃摹,看看同事們口中的主要內(nèi)容有哪些
- 實踐型的內(nèi)容,還是需要自己寫寫代碼跟衅,運行孵睬,看看效果掰读。當(dāng)你跑通了你自己寫的代碼蹈集,有可能你就學(xué)會了這個知識點
- 快速入手的方法是:如果你急切需要解決問題食寡,那就問有經(jīng)驗的人。如果你不是很急善榛,先嘗試了解下內(nèi)容移盆,不懂再問別人咒循。反復(fù)提出你的疑問叙甸。
- 提問題不要覺得不好意思裆蒸,時間很珍貴的僚祷。
下面的總結(jié)主要以例子為主:
- 第一稿:拋棄所有參考資料贮缕,憑借實踐的經(jīng)驗總結(jié)
- 第二稿:彌補不明白的地方
- 第三稿:對著參考文獻(xiàn)修正不對的地方感昼,發(fā)布
大綱:
- ansible.cfg 配置文件
- 變量
- 判斷
- 循環(huán)
- 常用模塊
- debug
- copy
- file
- shell
- command
- stat
- unarchive
- ping
- template
- user
- group
- service
- get_url
- include
- role
- 目錄結(jié)構(gòu)
- 依賴
- 執(zhí)行順序
Ansible 是使用Python 編寫,基于模塊化的工作方式烂琴,真正處理動作都是這些模塊蜕乡。Ansible 提供整體的框架号醉。
1畔派、安裝
pip install ansible
或者根據(jù)Linux 的版本進(jìn)行
apt-get install ansible
管理主機(jī)要求是Linux, 節(jié)點主機(jī)需要帶 Python 及相應(yīng)的庫解藻。
一般是管理主機(jī)和節(jié)點主機(jī)都是Linux纽窟。
2、基本使用
命令行方式運行:
命令行方式適合操作簡單的動作配紫。
ansible all -m ping
playbook 運行:
playbook 適合復(fù)雜的處理動作午阵。
ansible-playbook example.yml
查看支持的模塊:
ansible-doc -l
查看某模塊用法及支持的參數(shù):
ansible-doc -s ping
3底桂、配置文件
安裝完成之后籽懦,默認(rèn)目錄下有兩個文件:
/etc/ansible/hosts
/etc/ansible/ansible.cfg
hosts 文件定義節(jié)點主機(jī)的IP 及以下配置信息猫十。
ansible.cfg 文件定義全局配置文件拖云,配置項很多, 一般默認(rèn)就可以完成你的日常任務(wù)了宙项。
但是除默認(rèn)的生成的 ansible.cfg 文件之外乏苦,你可以在自己的項目中創(chuàng)建這樣一個同名ansible.cfg 文件。
ansible 讀取配置文件的順序是:
- ANSIBLE_CONFG 環(huán)境變量中定義
- ansible.cfg 當(dāng)前目錄
- */ansible.cfg 當(dāng)前用戶home/username/ansible.cfg
- /etc/ansible/ansible.cfg 默認(rèn)生成的文件路徑
怎么理解這個讀取配置文件的信息呢汇荐?
舉個例子:
# 當(dāng)前項目結(jié)構(gòu)
ansible:
---playbooks
---example
---leanr-ansible/example.yml
---ansible.cfg
你在這個目錄下執(zhí)行:ansible 命令
- 那么首先查看環(huán)境變量有沒有設(shè)置,沒有那就讀取當(dāng)前目錄下的ansible.cfg 配置信息掀淘;
- 如果當(dāng)前目錄沒有設(shè)置旬蟋,那么就搜索home 目錄下有沒有配置信息。
- 否則讀取默認(rèn)生成的配置信息倾贰。
4匆浙、常用模塊
操作動作舉例
這里為舉例只明白這些模塊的使用場景首尼,故意執(zhí)行多步操作言秸。
- 拷貝管理節(jié)點
/home/ubuntu/zartclient
下的zartcli
和zartcli.ini
文件至節(jié)點主機(jī)/home/ubuntu/zartclient
下 - 在上一步的基礎(chǔ)之上埋嵌,拷貝
/home/ubuntu/zartclient/zartcli
至/usr/bin/zartcli
- 在節(jié)點主機(jī)上使用剛才拷貝的文件,執(zhí)行下載命令:
zartcli -o=download -i=admin -m=bin -n=op-cli -v=v0.0.3 -p=/home/ubuntu/download
下載至/home/ubuntu/download
目錄 - 在節(jié)點主機(jī)上解壓下載的文件至
/paasdata/data
目錄下 - 在節(jié)點主機(jī)上拷貝解壓之后的文件至 /etc/opcli 目錄下
- 在節(jié)點主機(jī)上拷貝
op-cli
至/usr/bin
- 在節(jié)點主機(jī)上
op-cli task list
執(zhí)行命令 - 在節(jié)點主機(jī)上
op-cli node list
執(zhí)行命令
快閱讀時代俱恶,估計沒人想認(rèn)真看這些動作雹嗦。畫個流程圖吧。
把每一步動作認(rèn)為是一個任務(wù) task.
第一步:先檢查是否存在對應(yīng)的文件合是,是則拷貝
模塊:stat, copy, debug, file
- 判斷遠(yuǎn)端節(jié)點主機(jī)是否存在對應(yīng)的文件夾
- 不存在則創(chuàng)建
- 拷貝本地文件至遠(yuǎn)程節(jié)點主機(jī)的對應(yīng)的目錄下
- 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"}
可以看出了罪,處理相應(yīng)的動作,有相應(yīng)的模塊聪全,模塊帶參數(shù)泊藕,完成任務(wù)。
-
{{ }}
里面表示變量 - with_items: 是一個列表难礼,表示循環(huán)獲取變量
- register : 表示把執(zhí)行的動作結(jié)果賦值給一個變量娃圆,是一個map, 可以根據(jù)鍵值,獲取內(nèi)容
- when: 表示判斷蛾茉, 根據(jù)結(jié)果的布爾值進(jìn)行操作
第二步:先查詢是否存在文件讼呢,存在則執(zhí)行下載命令
第一步拷貝的文件是一個客戶端,主要是對文件的上傳谦炬、下載悦屏、查詢等节沦。
模塊: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 是個關(guān)鍵字础爬,表示變量
- item[0] 可以表示變量是一個列表甫贯,這里表示列表的第一個值
- item.src 可以表示變量是一個map, 這里表示map的src 的值
- vars 表示模塊中可以填充自定義的變量名稱對應(yīng)的值
第三步:解壓下載的文件
第二步下載的文件內(nèi)是一個 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 沒區(qū)別
- remote_src: yes 表示解壓的文件在節(jié)點主機(jī)上操作
第四步:拷貝文件
- 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"}
第五步:執(zhí)行查詢命令
- name: op-cli task list || op-cli node list
command: "{{item[0]}} {{item[1]}} list"
with_nested:
- [ "op-cli" ]
- ["task", "node", "nodepool"]
- with_nested: 嵌套循環(huán)
上文相當(dāng)于:op-cli task list, op-cli node list, op-cli nodepool list
上文借用一些循環(huán)看蚜,把之前規(guī)劃的 八 個動作改成了 五個動作叫搁, 即 五 個動作內(nèi)的每一個又包含幾個動作。
新手容易把上面的所有的動作都處理在一個文件內(nèi):但是其實存在更好的處理方法失乾。
# 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 能夠進(jìn)行復(fù)用纬乍,就相當(dāng)于編程領(lǐng)域里的抽象出函數(shù)一樣碱茁。ansible 提供這樣的機(jī)制。即將上文一個很大的文件拆分成獨立的文件仿贬。使用 include_tasks 方法將文件導(dǎo)入纽竣。
比如:上文的五步動作分別單獨寫文件
- 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
即將各個處理動作獨立出去。隨時復(fù)用茧泪。
6蜓氨、roles
看上去 include_tasks 方式就是對ansible-playbook 的一種比較好的組織方式了。
ansible 提供了一種更好的組織方式:roles
Roles 基于一個已知的文件結(jié)構(gòu)队伟,去自動的加載某些 vars_files穴吹,tasks 以及 handlers∈任辏基于 roles 對內(nèi)容進(jìn)行分組港令,使得我們可以容易地與其他用戶分享 roles。 這樣的組織方式使得復(fù)用更為簡便锈颗。每個相對獨立的處理動作獨立出來顷霹,可以適用于更復(fù)雜的場景。
一個role 的文件大概包括這些:
- tasks 文件:主要編寫某個獨立模塊的處理動作
- handlers 文件:
- vars 文件: 主要編寫某個獨立模塊的變量
- meta 文件:主要編寫依賴關(guān)系击吱,即一個獨立模塊引用另一個role
- defaults 文件:默認(rèn)的變量文件
- 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 的入口朵纷。導(dǎo)入download.yml,下載所需要的變量全部置放在 var/main.yml 文件中。
別的role 需要復(fù)用這個模塊:
op-cli/meta/main.yml
dependencies:
- role: download-bin
這樣 op-cli role 也有download 動作永脓。
roles 適用于組織較為復(fù)雜的項目袍辞,將各個模塊獨立處理,又可以相互復(fù)用憨奸。使用 include_tasks 存在模塊的復(fù)用性變低革屠、變量需要重復(fù)定義等缺點。
上文 op-cli role 復(fù)用download-bin,無需再次定義變量似芝。
再一個值得注意的是:一般playbook 的執(zhí)行順序和task 的定義順序一致那婉。
使用 roles 后,playbook 中 roles 先執(zhí)行党瓮,再按tasks 的定義順序執(zhí)行详炬。
如果需要最先執(zhí)行某個task , 或者最后執(zhí)行某個task, 可以使用pre_tasks
和 post_tasks
寞奸。
-
pre_tasks
最先執(zhí)行 -
post-tasks
最后執(zhí)行
再一個使用roles 需要配置 ansible.cfg
roles_path = 目錄
# 即roles 所在的文件目錄
7呛谜、參考文獻(xiàn)
這些原理性的東西,用文字不是很好講枪萄,以后遇到文字難以表達(dá)出來隐岛,我錄個視頻實際操作下。這樣讀者可能更好理解瓷翻。