上篇文章Ansible 入門指南 - 安裝及 Ad-Hoc 命令使用介紹的額是 Ad-Hoc 命令方式,本文將介紹 Playbook
方式。html
Playbook
譯爲「劇本」,以爲還挺恰當的。mysql
Playbook
譯爲「劇本」,以爲還挺恰當的。那麼 play
那我就譯爲 「場景」吧。playbook 由一個或多個 ‘plays’ 組成.它的內容是一個以 ‘plays’ 爲元素的列表linux
能夠爲 playbook 中的每個 play,個別地選擇操做的目標機器是哪些,以哪一個用戶身份去完成要執行的步驟(called tasks)git
$ ansible-playbook -h Usage: ansible-playbook [options] playbook.yml [playbook2 ...] Runs Ansible playbooks, executing the defined tasks on the targeted hosts.
在指定的目標主機上執行定義好的 tasks
。github
playbook.yml
常包含下面幾個關鍵字:web
hosts
:爲主機的IP,或者主機組名,或者關鍵字allremote_user
: 以哪一個用戶身份執行。vars
: 變量tasks
: playbook的核心,定義順序執行的動做 action
。每一個action
調用一個ansbile module
。action
語法: module: module_parameter=module_value
module
有yum
、copy
、template
等,module
在 ansible 的做用,至關於 bash 腳本中yum
,copy
這樣的命令。name
,這樣在運行 playbook 時,從其輸出的任務執行信息中能夠很好的辨別出是屬於哪個 task 的handers
: 是 playbook 的 event ,默認不會執行,在 action 裏觸發纔會執行。屢次觸發只執行一次。一個簡單的示例:
deploy.yml
的功能爲 web 主機部署 apache, 其中包含如下部署步驟:sql
--- - hosts: centos vars: httpd_port: 8080 max_clients: 200 remote_user: root tasks: - name: ensure apache is at the latest version yum: name=httpd state=present - name: Write the configuration file template: src=templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf notify: - restart apache ignore_errors: False - name: Write the default index.html file template: src=templates/index.html.j2 dest=/var/www/html/index.html ignore_errors: False - name: ensure apache is running service: name=httpd state=started handlers: - name: restart apache service: name=httpd state=restarted
運行ansible-playbook deploy.yml
便可執行。shell
taks
參數實際上是有不一樣寫法的,當參數比較少時,可用key=value
的方式apache
tasks: - name: make sure apache is running service: name=httpd state=running
當tasks
參數比較多時,爲了美觀和不易出錯,用 yml
的字典傳參比較好:編程
tasks: - name: make sure apache is running service: name: httpd state: running
task中每一個action會調用一個module,在module中會去檢查當前系統狀態是否須要從新執行。
action
會獲得返回值 changed
;action
獲得返回值ok
module 的執行狀態的具體判斷規則由各個 module 本身決定和實現的。例如,」copy」 module的判斷方法是比較文件的checksum,代碼以下:
下面這條命令,指定 inventory 文件,列出 hosts 列表,並不會去執行定義的 tasks,觀察 host 是否配置正確頗有用:
ansible-playbook -i inventory/slave_init.yml execute_slave_init.yml --list-hosts
ansible-playbook playbook.yml --verbose
ansible-playbook playbook.yml -f 10
playbook 中使用到了 become
,執行playbook
時能夠加上--ask-become-pass
參數:
ansible-playbook deploy.yml --ask-become-pass
#
表示註釋,從這個字符一直到行尾,都會被解析器忽略---
. 這是 YAML 格式的一部分, 代表一個文件的開始.鍵: 值
的形式組成(這個冒號後面必須是一個空格)foo: "{{ variable }}"
。參考
其實在一個Playbook文件中還能夠有針對兩組server進行不一樣的操做,例如給web安裝http服務器,和給lb安裝mysql放在一個文件中:
--- #安裝apache的play - hosts: web remote_user: root tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest # 安裝mysql server的play - hosts: lb remote_user: root tasks: - name: ensure mysqld is at the latest version yum: pkg=mariadb state=latest
上面例子中針對每一組 server 的全部操做就組成一個 play,通常一個 playbook 中只包含一個 play,play 的內容稱爲 tasks,即任務。
參考:
handlers與tasks不一樣,tasks會默認的按定義順序執行每個task,handlers則不會,它須要在tasks中被調用,纔有可能被執行。
Handlers will only be fired for tasks which report a changed state.
只有當 task 執行狀態顯示是 changed 時,handler 動做纔會被觸發
Tasks中的任務都是有狀態的,changed或者ok。 在Ansible中,只在task的執行狀態爲 changed
的時候,纔會執行該task調用的handler。
在全部的task列表執行以後執行,若是有多個task notify同一個handler,那麼 handlers 也只執行一次。
若是你在tasks中修改了apache的配置文件。須要重起apache。此外還安裝了apache的插件。那麼還須要重起apache。像這樣的應該場景中,重起apache就能夠設計成一個handler.
當一個文件的內容被改動時,重啓兩個 services:
- name: template configuration file template: src=template.j2 dest=/etc/foo.conf notify: - restart memcached - restart apache
notify
下列出的便是 handlers.name
)來引用。handlers: - name: restart memcached service: name=memcached state=restarted - name: restart apache service: name=apache state=restarted
此外,還有個注意點:
handlers
定義的順序是1>2>3
,notify 的順序是3>2>1
,實際執行順序:1>2>3
.總結,Handlers 最佳的應用場景是用來重啓服務,或者觸發系統重啓操做.除此之外不多用到。
參考
playbook 中經常使用的集中變量:
在 playbook 中,經過關鍵字 vars
自定義變量,用 {{}}
引用變量。
經過 vars_files
關鍵字指定了變量文件:
--- - hosts: centos vars: httpd_port: 80 vars_files: - ./vars_servers.yml remote_user: root tasks: - debug: msg: "http_port: {{httpd_port}}" - debug: msg: "x86 passwd: {{x86.password}}" - debug: msg: "arm passwd: {{arm.password}}" # 也能夠用 arm['password'] 表示
專門存放變量的文件:
# vars_servers.yml x86: password: 123 arm: password: 456
ansible 經過 module setup 收集主機的系統信息,這些收集到的系統信息叫作 facts
,這些facts
能夠直接以變量的形式使用。
哪些 facts
變量能夠引用的?經過以下命令行調用setup module
能夠查看:
ansible all -m setup -u root
能夠看到它輸出的變量信息有不少!
複雜的facts
變量的使用能夠用以下兩種形式:
{{ ansible_ens3["ipv4"]["address"] }}
{{ ansible_ens3.ipv4.address }}
ansible_hostname
指定的 host 名稱ansible_default_ipv4.address
主機真實的 ipv4 地址,小網IP--- - hosts: all user: root tasks: - name: echo system shell: echo {{ ansible_os_family }} - name install ntp on Debian linux apt: name=git state=installed when: ansible_os_family == "Debian" - name install ntp on redhat linux yum: name=git state=present when: ansible_os_family == "RedHat"
在 playbook 中,若是不收集系統信息,那麼上面的變量就不能再 playbook 中使用了,可是有時候關閉會加快執行的效率:
- hosts: all gather_facts: no
將某個 task 執行的結果「註冊」爲一個變量。後面的 action 就可使用它
--- - hosts: centos tasks: - name: ls /tmp shell: ls -l /tmp register: result ignore_errors: True - name: echo result when rc==5 shell: echo "{{result}}" when: result.rc == 5 - name: debug show stdout debug: msg: "{{result.stdout}}"
「註冊變量」常常和debug module
一塊兒使用,這樣能夠得到 action 更多的輸出信息,幫助調試。
參考
set_facts
的模塊--- - hosts: "{{hosts}}" remote_user: "{{user}}"" tasks: - debug: msg="{{hosts}}""
命令輸入變量:
ansible-playbook extra_learn.yml --extra-vars "{'hosts':'x86','user':‘’michael'}" # or ansible-playbook extra_learn.yml --extra-vars "hosts=x86 user=michael"
when
:條件判斷,相似編程語言中的 if
loop
:循環,相似編程語言中的 while
block
:將幾個 task
組成一塊代碼,便於針對一組操做進行異常處理等例如,在某個特定版本的系統上裝包,或者只在磁盤空間滿了的文件系統上執行清理操做。這些操做在Playbook中用when語句實現。
主機爲Debian Linux馬上關機
tasks: - name: "shutdown Debian flavored systems" command: /sbin/shutdown -t now when: ansible_os_family == "Debian"
根據action的執行結果,來決定接下來執行的action。
tasks: - command: /bin/false register: result ignore_errors: True - command: /bin/something when: result|failed - command: /bin/something_else when: result|success - command: /bin/still/something_else when: result|skipped
遠程中的系統變量facts變量做爲when的條件,用「|int」還能夠轉換返回值的類型:
--- - hosts: web tasks: - debug: msg="only on Red Hat 7, derivatives, and later" when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6
爲了保持簡潔,重複的任務能夠用如下簡寫的方式:
- name: add several users user: name="{{ item }}" state=present groups=wheel with_items: - michael - qq
若是你在變量文件中或者 ‘vars’ 區域定義了一組YAML列表,你也能夠這樣作:
vars: userlist: ["micahel", "qq"] tasks: -name: add several user user: name: "{{ item }}" state: present groups: wheel with_items: "{{userlist}}"
使用 with_items
用於迭代的條目類型不只僅支持簡單的字符串列表.若是你有一個哈希列表,那麼你能夠用如下方式來引用子項:
- name: add several users user: name="{{ item.name }}" state=present groups="{{ item.groups }}" with_items: - { name: 'michael', groups: 'wheel' } - { name: 'qq', groups: 'root' }
這個例子不只演示了 with_dict
用法,還使用循環安裝了 RPM 包
--- - hosts: centos vars: users: michael: name: michael xiang phone: 123 qq: name: qq huang phone: 456 rpms: - httpd - lrzsz - vim - git tasks: - name: print phone records debug: msg="User {{item.key }} is {{ item.value.name }} {{item.value.phone}}" with_dict: "{{ users }}" - name: install rpms yum: name="{{item}}" state=installed with_items: "{{rpms}}"
with_fileglob
能夠以非遞歸的方式來模式匹配單個目錄中的文件.以下面所示:
tasks: # first ensure our target directory exists - file: dest=/etc/fooapp state=directory # copy each file over that matches the given pattern - copy: src=\{\{ item \}\} dest=/etc/fooapp/ owner=root mode=600 with_fileglob: - /playbooks/files/fooapp/*
參考
多個action組裝成塊,能夠根據不一樣條件執行一段語句 :
tasks: - block: - yum: name=\{\{ item \}\} state=installed with_items: - httpd - memcached - template: src=templates/src.j2 dest=/etc/foo.conf - service: name=bar state=started enabled=True when: ansible_distribution == 'CentOS' become: true become_user: root