ansible special topics

一、加速模式運行playbook

accelerate

對於使用ansible 1.5 及以後版本的用戶,加速模式只在如下狀況下有用處:html

(A) 管理紅帽企業版 Linux 6 或者更早的那些依然使用 paramiko 的版本 python

(B) 像在文檔中描述的那樣:沒法在 TTYs 中使用 sudo.web

#只需在你的 play 中添加 accelerate: true 便可使用加速模式: ---

- hosts: all accelerate: true tasks: - name: some task command: echo {{ item }} with_items: - foo - bar - baz #若是你但願改變 Ansible 用於加速模式的端口,你只需添加 accelerated_port 選項: ---

- hosts: all accelerate: true # default port is 5099 accelerate_port: 10000 #accelerate_port 選項也一樣能經過指定環境變量 ACCELERATE_PORT 或者在你的 ansible.cfg 中配置: [accelerate] accelerate_port = 5099

二、異步操做和輪詢

async
poll

async_status

默認狀況下playbook中的任務執行時會一直保持鏈接,直到該任務在每一個節點都執行完畢.有時這是沒必要要的,好比有些操做運行時間比SSH超時時間還要長.docker

解決該問題最簡單的方式是一塊兒執行它們,而後輪詢直到任務執行完畢.shell

你也能夠對執行時間很是長(有可能遭遇超時)的操做使用異步模式.json

爲了異步啓動一個任務,能夠指定其最大超時時間以及輪詢其狀態的頻率.vim

若是你沒有爲 poll 指定值,那麼默認的輪詢頻率是10秒鐘:安全

---

- hosts: all remote_user: root tasks: - name: simulate long running op (15 sec), wait for up to 45 sec, poll every 5 sec command: /bin/sleep 15 async: 45 poll: 5

async 並無默認值,若是你沒有指定 async 關鍵字,那麼任務會以同步的方式運行,這是Ansible的默認行爲.服務器

另外,若是你不須要等待任務執行完畢,你能夠指定 poll 值爲0而啓用 「啓動並忽略」app

---

- hosts: all remote_user: root tasks: - name: simulate long running op, allow to run for 45 sec, fire and forget command: /bin/sleep 15 async: 45 poll: 0

對於要求排它鎖的操做,若是你須要在其以後對同一資源執行其它任務,那麼你不該該對該操做使用」啓動並忽略」.好比yum事務.

--forks 參數值過大會更快的觸發異步任務.也會加快輪詢的效率.

 

當你想對 「啓動並忽略」 作個變種,改成」啓動並忽略,稍後再檢查」,你可使用如下方式執行任務:

--- # Requires ansible 1.8+
- name: 'YUM - fire and forget task'
  yum: name=docker-io state=installed async: 1000 poll: 0 register: yum_sleeper - name: 'YUM - check on fire and forget task' async_status: jid={{ yum_sleeper.ansible_job_id }} register: job_result until: job_result.finished retries: 30

若是 async: 值過小,可能會致使 「稍後檢查」 任務執行失敗,由於 async_status:: 的臨時狀態文件還未被寫入信息,而」稍後檢查」任務就試圖讀取此文件.

三、檢查模式運行playbook(dry run)

--check 
--diff
--limit

當以 --check 參數來運行 ansible-playbook 時,將不會對遠程的系統做出任何更改.

相對的,任何帶有檢測功能的模塊(這幾乎包含了全部的主要核心模塊,但這不要求全部的模塊都需支持.) 只要支持 ‘檢測模式’ 將會報告它們會作出什麼改變而不是直接進行改變.其餘不支持檢測模式的模塊將既不響應也不提出相應的報告.

檢測模式只是一種模擬.若是你的playbook是以先前命令的執行結果做爲條件的話,那它可能對你就沒有什麼大用處了. 可是對於基於一次一節點的基礎配置管理的使用情形來講是頗有用.

Example: ansible-playbook foo.yml --check

 

有時候你甚至會想在檢測模式中執行一個任務.爲了達到這樣的效果, 你須要在相應的任務上使用 always_run 子句.跟 when 子句同樣,它的值是一個 Jinja2 表達式. 在一個簡單的例子中,布爾值也會表達爲一個適當的 YAML 值.

Example: tasks: - name: this task is run even in check mode command: /something/to/run --even-in-check-mode always_run: yes

 

友情提示,帶有 when 子句的任務會返回false,該任務將會被跳過,即便它還被添加了會返回true的 always_run 子句.

對 ansible-playbook 來講 --diff 選項與 --check (詳情參下)配合使用效果奇佳,不過它也能夠單獨使用.當提供了相應的標識後,當遠程系統上任何模板文件的變化時,ansible-playbook CLI 將會報告文件上任何文本的變化 (或者,若是使用了 --check 參數,將報告會發生的變化.).由於 diff 特性會產生大量的輸出結果,因此它在一次檢測一個主機時使用爲佳,如:

ansible-playbook foo.yml --check --diff --limit foo.example.com

四、滾動更新

serial

因爲設計初衷是做爲多用戶,Anisible很擅長在某一個主機上表明另外一個作事,或者參考遠程主機作一些本地工做.

這個特性對於架設連續實現某些設施或者無縫滾動升級,這裏你可能會提到負載均衡或者監控系統.

更多的特性容許調試事情完成的順序,和設置一批窗口,來肯定多少機器在一次中滾動更新.

默認來講,Anisble 能夠試圖參考某一個play來並行操做全部主機.對於滾動更新案例,你可使用’‘serial’’ 關鍵詞來定義Ansible在一個特定時間同時控制多少主機:

- name: test play hosts: webservers serial: 3

在上面的例子,若是咱們有100臺主機,3 臺主機定義在組’webservers’ 能夠在下面3個主機開始以前徹底完成

這個’‘serial’’ 關鍵詞在Ansible 1.8 之後能夠被定義爲百分數,用來定義每一次操做一個play中百分之多少主機:

- name: test play hosts: websevers serial: "30%"

若是主機數不能被passes數量整除,最後的pass將會包含提醒信息,無論多小的百分比,每一個pass的主機數必定會大於等於1.

默認來講,Ansible 會持續執行,只要在一個組中還有主機沒有宕機.

在有些狀況下,例如以前提到的滾動更新,也許理想的狀況是當一個失敗數上限達到時,主動宕掉這個play.

爲了達到這個目的,在 1.3版本中,你能夠設置最大失敗半分比:

- hosts: webservers max_fail_percentage: 30 serial: 10

在上面的例子中,若是在10個服務器中若是多餘3個,其它的play就會主動宕掉.這個百分比必須被超過,不只僅是相等.

例如若是serial值唄設置爲4,而且你但願任務主動在2個系統失敗時候放棄.那麼這個百分比應該設置爲49而不是50.

五、委任

delegate_to

local_action

若是你想參考其它主機來在一個主機上執行一個任務,咱們就可使用’delegate_to’關鍵詞在你要執行的任務上.

這個對於把節點放在一個負載均衡池裏面活着從裏面移除很是理想. 這個選項也對處理窗口中斷很是有用. 使用’serial’關鍵詞來控制必定數量的主機也是一個好想法:

---

- hosts: webservers serial: 5 tasks: - name: take out of load balancer pool command: /usr/bin/take_out_of_pool {{ inventory_hostname }} delegate_to: 127.0.0.1

  - name: actual steps would go here yum: name=acme-web-stack state=latest - name: add back to load balancer pool command: /usr/bin/add_back_to_pool {{ inventory_hostname }} delegate_to: 127.0.0.1
--- # ... tasks: name: take out of load balancer pool local_action: command /usr/bin/take_out_of_pool {{ inventory_hostname }} # ... name: add back to load balancer pool local_action: command /usr/bin/add_back_to_pool {{ inventory_hostname }}

A common pattern is to use a local action to call ‘rsync’ to recursively copy files to the managed servers. Here is an example:

--- # ... tasks: - name: recursively copy files from management server to target local_action: command rsync -a /path/to/files {{ inventory_hostname }}:/path/to/target/

 

六、本地執行playbook

connection

在本地使用playbook有時候比ssh遠程使用更加有用.能夠經過把playbook放在crontab中,來確保一個系統的配置,能夠頗有用.

在OS installer 中運行一個playbook也頗有用.例如Anaconda kickstart.

要想在本地運行一個play,能夠直接設置」host:」 與 「hosts:127.0.0.1」, 而後使用下面的命令運行:

ansible-playbook playbook.yml --connection=local

或者,一個本地鏈接也能夠做爲一個單獨的playbook play應用在playbook中, 即使playbook中其餘的plays使用默認遠程 鏈接以下:

- hosts: 127.0.0.1 connection: local

七、只運行一次任務

run_once

有時候你有這樣的需求,在一個主機上面只執行一次一個任務.這樣的配置能夠配置」run_once」來實現:

--- # ... tasks: # ... - command: /opt/application/upgrade_db.py run_once: true # ...

這樣能夠添加在」delegat_to」選項對中來定義要執行的主機:

- command: /opt/application/upgrade_db.py run_once: true delegate_to: web01.example.org

當」run_once」 沒有和」delegate_to」一塊兒使用,這個任務將會被清單指定的第一個主機.

在一組被play制定主機.例如 webservers[0], 若是play指定爲 「hosts: webservers」.

這個方法也很相似,雖然比使用條件更加簡單粗暴,以下事例:

- command: /opt/application/upgrade_db.py when: inventory_hostname == webservers[0]

八、配置環境運行,如代理上網

environment

你徹底有可能遇到一些更新包須要經過proxy才能正常獲取,或者甚至一部分包須要經過proxy升級而另一部分包則不須要經過proxy.

或者可能你的某個腳本須要調用某個環境變量才能正常運行.

Ansible 使用 ‘environment’ 關鍵字對於環境部署的配置很是簡單容易,下面是一個使用案例:

- hosts: all remote_user: root tasks: - apt: name=cobbler state=installed environment: http_proxy: http://proxy.example.com:8080

environment 也能夠被存儲在變量中,像以下方式訪問:

- hosts: all remote_user: root # here we make a variable named "proxy_env" that is a dictionary vars: proxy_env: http_proxy: http://proxy.example.com:8080
 tasks: - apt: name=cobbler state=installed environment: proxy_env

雖然上面只展現了 proxy 設置,但其實能夠同時其實支持多個設置. 大部分合合乎邏輯的地方來定義一個環境變量均可以成爲 group_vars 文件,示例以下:

--- # file: group_vars/boston ntp_server: ntp.bos.example.com backup: bak.bos.example.com proxy_env: http_proxy: http://proxy.bos.example.com:8080
  https_proxy: http://proxy.bos.example.com:8080

九、playbook中錯誤處理

ignore_errors

failed_when

fail

change_when

Ansible 一般默認會確保檢測模塊和命令的返回碼.

有時一條命令會返回 0 但那不是報錯.有時命令不會老是報告它 ‘改變’ 了遠程系統.

本節描述了 如何將 Ansible 處理輸出結果和錯誤處理的默認行爲改變成你想要的.

一、忽略錯誤命令

一般狀況下, 當出現失敗時 Ansible 會中止在宿主機上執行.有時候,你會想要繼續執行下去.爲此 你須要像這樣編寫任務:

- name: this will not be counted as a failure command: /bin/false ignore_errors: yes

注意上面的系統僅僅處理那個特定的任務,因此當你在使用一個未定義的變量時, Ansible 仍然會報 錯,須要使用者進行處理.

二、控制對失敗的定義

假設一條命令的錯誤碼毫無心義,只有它的輸出結果能告訴是你什麼出了問題,好比說字符串 「FAILED」 出 如今輸出結果中.

在 Ansible 1.4及以後的版本中提供了以下的方式來指定這樣的特殊行爲:

- name: this command prints FAILED when it fails command: /usr/bin/example-command -x -y -z register: command_result failed_when: "'FAILED' in command_result.stderr"

三、覆寫返回結果

當一個 shell或命令或其餘模塊運行時,它們每每都會在它們認爲其影響機器狀態時報告 「changed」 狀態,

有時你能夠經過返回碼或是輸出結果來知道它們其實並無作出任何更改.
你但願覆寫結果的「changed」 狀態,使它不會出如今輸出的報告或不會觸發其餘處理程序:
tasks: - shell: /usr/bin/billybass --mode="take me to the river" register: bass_result changed_when: "bass_result.rc != 2" # this will never report 'changed' status - shell: wall 'beep' changed_when: False

十、標籤

tags

若是你有一個大型的 playbook,那可以只運行其中特定部分的配置而無需運行整個 playbook 將會頗有用.

plays 和 tasks 都因這個理由而支持 「tags」

tasks: - yum: name={{ item }} state=installed with_items: - httpd - memcached tags: - packages - template: src=templates/src.j2 dest=/etc/foo.conf tags: - configuration

若是你只想運行一個很是大的 playbook 中的 「configuration」 和 「packages」,你能夠這樣作:

ansible-playbook example.yml --tags "configuration,packages"

另外一方面,若是你只想執行 playbook 中某個特定任務 以外 的全部任務,你能夠這樣作:

ansible-playbook example.yml --skip-tags "notification"

你一樣也能夠對 roles 應用 tags:

roles: - { role: webserver, port: 5000, tags: [ 'web', 'foo' ] }

你一樣也能夠對基本的 include 語句使用 tag:

- include: foo.yml tags=web,foo

十一、從指定任務開始運行playbook,分步運行playbook

--start-at

--step

若是你想從指定的任務開始執行playbook,可使用``–start-at``選項:

ansible-playbook playbook.yml --start-at="install packages"

以上命令就會在名爲」install packages」的任務開始執行你的playbook.

咱們也能夠經過``–step``選項來交互式的執行playbook:

ansible-playbook playbook.yml --step

這樣ansible在每一個任務前會自動中止,並詢問是否應該執行該任務.

好比你有個名爲``configure ssh``的任務,playbook執行到這裏會中止並詢問:

Perform task: configure ssh (y/n/c):

「y」回答會執行該任務,」n」回答會跳過該任務,而」c」回答則會繼續執行剩餘的全部任務而再也不詢問你.

十二、vault加密文件

ansible-vault

--ask-vault-pass

--vault-password-file

Ansible 1.5的新版本中, 「Vault」 做爲 ansible 的一項新功能可將例如passwords,keys等敏感數據文件進行加密,

而非存放在明文的 playbooks 或 roles 中. 這些 vault 文件能夠分散存放,也能夠集中存放.

經過`ansible-vault` 來編輯文件,常常用到的命令如 –ask-vault-pass , –vault-password-file .

你能夠在 ansible.cfg 中定義密碼文件所在位置,這個選項就不須要在命令行中指定標誌了.

Vault能夠加密些什麼

vault 能夠加密任何 Ansible 使用的結構化數據文件. 甚至能夠包括:

「group_vars/」 或 「host_vars/」 inventory 變量,

「include_vars」 或 「vars_files」 加載的變量,

經過 ansible-playbook 命令行使用 「-e @file.yml」 或 「-e @file.json」 命令傳輸的變量文件,

role變量,

全部默認的變量均可以被 vault 加密.

由於 Ansible tasks, handlers等都是數據文件, 全部的這些都可以被 vault 加密. 若是你不喜歡你使用的變量被泄漏,你能夠將整個 task 文件部分加密.

不過,這個工做量比較大並且可能給你的同事帶來不便哦 !

建立加密文件

執行以下命令,建立加密文件:

ansible-vault create foo.yml

首先你將被提示輸出密碼, 通過Vault加密過的文件如需查看需同時輸入密碼後才能進行.

提供密碼後, 工具將加載你定義的 $EDITOR 的編輯工具默認是 vim, 一旦你關閉了編輯會話框,生成後的文件將會是加密文件.

默認加密方式是 AES (基於共享密鑰)

編輯加密文件

編輯加密文件,使用 ansible-vault edit . 該命令會先加密文件爲臨時文件並容許你編輯這個文件,當完成編輯後會保存回你所命名的文件並刪除臨時文件:

ansible-vault edit foo.yml

密鑰更新

若是你但願變動密碼,使用以下 命令:

ansible-vault rekey foo.yml bar.yml baz.yml

如上命令能夠同時批量修改多個文件的組織密碼並從新設置新密碼.

加密普通文件

若是你但願加密一個已經存在的文件,使用 ansible-vault encrypt . 該命令也可同時批量操做多個文件:

ansible-vault encrypt foo.yml bar.yml baz.yml=

解密已加密文件

若是不但願繼續加密一個已經加密過的文件,經過 ansible-vault decrypt 你能夠永久解密. 命令將解密並保存到硬盤上,這樣你不用再使用 ansible-vault edit 來編輯文件了:

ansible-vault decrypt foo.yml bar.yml baz.yml

查閱已加密文件

Available since Ansible 1.8

若是你不但願經過編輯的方式來查看文件, ansible-vault view 能夠知足你的須要:

ansible-vault view foo.yml bar.yml baz.yml

在Vault下運行Playbook

執行 vault 加密後的playbook文件,最少須要提交以下兩個標誌之一. 交互式的指定 vault 的密碼文件:

ansible-playbook site.yml --ask-vault-pass

該提示被用來解密(僅在內存中)任何 vault 加密訪問過的文件. 目前這些文件中全部的指令請求將被使用相同的密碼加密.

另外,密碼也能夠定義在一個文件或者一個腳本中,可是須要 Ansible 1.7 以上的版本才能支持.

當使用該功能時,必定要確認密碼文件的權限是安全的,以確保沒有人能夠隨意訪問或者變動密碼文件:

ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt ansible-playbook site.yml --vault-password-file ~/.vault_pass.py

密碼存儲一行一個

若是你使用的是腳本而不是普通文件,確保腳本是可執行的,這樣密碼能夠輸出至標準設備.若是你的腳本須要提示輸入數據,那提示能夠被髮送到標準錯誤.

若是你是從持續集成系統(例如Jenkins)中使用 Ansible 的話上面的這種狀況你會用的到.

(–vault-password-file 參數能夠在 Ansible-Pull(拉取配置而非推送配置) 命令中被使用,儘管這將須要分發keys到對應的節點上,

因此 ,瞭解這些隱性問題後 – vault 更傾向使用 push 方式)

相關文章
相關標籤/搜索