『Ansible 上手指南:2』

wuxiaoshen發表於2018-03-09

Ansible 上手指南 2.png

讀一本書最好的時機是什麼時候?是你剛買的時候,趁著新鮮勁,先了解這本書,繼而馬上閱讀完這本書。如果錯過了最好的時機閱讀一本書,那什麼時候是合適的時機,是你需要這方面的資料或者知識的時候。

最近我一直在研究 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 下的 zartclizartcli.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_taskspost_tasks

  • pre_tasks 最先執行
  • post-tasks 最後執行

再一個使用roles 需要配置 ansible.cfg

roles_path = 目錄
# 即roles 所在的檔案目錄
複製程式碼

7、參考文獻


這些原理性的東西,用文字不是很好講,以後遇到文字難以表達出來,我錄個視訊實際操作下。這樣讀者可能更好理解。

相關文章