Ansible playbook簡介與配置
Ansible playbook簡介
playbook是ansible用於配置,部署,和管理被控節點的劇本。
通過playbook的詳細描述,執行其中的一系列tasks,可以讓遠端主機達到預期的狀態。playbook就像Ansible控制器給被控節點列出的的一系列to-do-list,而被控節點必須要完成。
也可以這麼理解,playbook 字面意思,即劇本,現實中由演員按照劇本表演,在Ansible中,這次由計算機進行表演,由計算機安裝,部署應用,提供對外服務,以及組織計算機處理各種各樣的事情。
Ansible playbook使用場景
執行一些簡單的任務,使用ad-hoc命令可以方便的解決問題,但是有時一個設施過於複雜,需要大量的操作時候,執行的ad-hoc命令是不適合的,這時最好使用playbook。
就像執行shell命令與寫shell指令碼一樣,也可以理解為批處理任務,不過playbook有自己的語法格式。
使用playbook你可以方便的重用這些程式碼,可以移植到不同的機器上面,像函式一樣,最大化的利用程式碼。在你使用Ansible的過程中,你也會發現,你所處理的大部分操作都是編寫playbook。可以把常見的應用都編寫成playbook,之後管理伺服器會變得十分簡單。
Ansible playbook格式
playbook格式介紹
playbook由YMAL語言編寫。YAML( /ˈjæməl/ )參考了其他多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822,Clark Evans在2001年5月在首次發表了這種語言,另外Ingy döt Net與Oren Ben-Kiki也是這語言的共同設計者。
YMAL格式是類似於JSON的檔案格式,便於人理解和閱讀,同時便於書寫。首先學習瞭解一下YMAL的格式,對我們後面書寫playbook很有幫助。以下為playbook常用到的YMAL格式。
檔案的第一行應該以 ”—” (三個連字元)開始,表明YMAL檔案的開始。
在同一行中,#之後的內容表示註釋,類似於shell,python和ruby。
YMAL中的列表元素以”-”開頭然後緊跟著一個空格,後面為元素內容。就像這樣:
- apple - banana - orange等價於JSON的這種格式
[ “apple”, “banana”, “orange” ]
同一個列表中的元素應該保持相同的縮排。否則會被當做錯誤處理。
playbook中hosts,variables,roles,tasks等物件的表示方法都是鍵值中間以”:”分隔表示,”:”後面還要增加一個空格。
house:
family: { name: Doe, parents: [John, Jane], children: [Paul, Mark, Simone] }
address: { number: 34, street: Main Street, city: Nowheretown, zipcode: 12345 }
由上圖可知,在mysql.yml中,主要由三個部分組成:
hosts部分:使用hosts指示使用哪個主機或主機組來執行下面的tasks,每個playbook都必須指定hosts,hosts也可以使用萬用字元格式。主機或主機組在inventory清單中指定,可以使用系統預設的 /etc/ansible/hosts,也可以自己編輯,在執行的時候加上-i選項,指定清單的位置即可。在執行清單檔案的時候,–list-hosts選項會顯示那些主機將會參與執行task的過程中。
remote_user:指定遠端主機中的哪個使用者來登入遠端系統,在遠端系統執行task的使用者,可以任意指定,也可以使用sudo,但是使用者必須要有執行相應task的許可權。
tasks:指定遠端主機將要執行的一系列動作。tasks的核心為ansible的模組,前面已經提到模組的用法。tasks包含name和要執行的模組,name是可選的,只是為了便於使用者閱讀,不過還是建議加上去,模組是必須的,同時也要給予模組相應的引數。
ansible-playbook執行playbook檔案
使用ansible-playbook執行playbook檔案,得到如下輸出資訊,輸出內容為JSON格式。並且由不同顏色組成,便於識別。一般而言
| 綠色代表執行成功,系統保持原樣
| 黃色代表系統代表系統狀態發生改變
| 紅色代表執行失敗,顯示錯誤輸出。
執行有三個步驟:1、收集facts 2、執行tasks 3、報告結果
[[email protected] ~]# ansible-playbook mariadb.yml
---------------------------1、收集facts------------------------------------------
PLAY [webservers] **************************************************************
TASK [setup] *******************************************************************
ok: [172.17.254.165]
ok: [172.17.254.180]
---------------------------2、執行tasks------------------------------------------
TASK [Install mariadb-server package] ******************************************
changed: [172.17.254.165]
changed: [172.17.254.180]
TASK [Starting mysqld service] *************************************************
changed: [172.17.254.165]
changed: [172.17.254.180]
---------------------------3、報告結果-------------------------------------------
PLAY RECAP *********************************************************************
172.17.254.165 : ok=3 changed=2 unreachable=0 failed=0
172.17.254.180 : ok=3 changed=2 unreachable=0 failed=0
Playbook的核心元素及基礎元件
Playbook的核心元素:
Hosts:主機;
Tasks:任務列表;
Variables 變數;
Templates:包含了模板語法的文字檔案;
Handlers:由特定條件觸發的任務;
Playbooks配置檔案的基礎元件:
hosts:
Hosts:執行指定任務的目標主機;
remoute_user: 在遠端主機上執行任務的使用者;
sudo_user:
tasks:任務列表
模組,模組引數;
格式:
(1) action: module arguments
(2) module: arguments
注意:shell和command模組後面直接跟命令,而非key=value類的引數列表;
(1) 某任務的狀態在執行後為changed時,可通過“notify”通知給相應的handlers;
(2) 任務可以通過“tags“打標籤,而後可在ansible-playbook命令上使用-t指定進行呼叫;
handlers:
任務,在特定條件下觸發;
接收到其它任務的通知時被觸發;
tasks:
– name: TASK_NAME
module: arguments
notify: HANDLER_NAME
handlers:
– name: HANDLER_NAME
module: arguments
示例:
[[email protected] ~]# vim mariadb.yml
---
- hosts: webservers
remote_user: root
tasks:
- name: Install mariadb-server package
yum: name=mariadb-server state=present
- name: copy my.cnf
copy: src=/etc/my.cnf dest=/etc/ backup=yes
notify: start
tags: startmariadb
- name: Stopping mysqld service
service: name=mariadb state=stopped
tags: stopmariadb
handlers:
- name: start
service: name=mariadb state=started
variables:
(1) facts:可直接呼叫;
注意:可使用setup模組直接獲取目標主機的facters;
(2) 使用者自定義變數:
(a) ansible-playbook命令的命令列中的
-e VARS, --extra-vars=VARS
(b) 在playbook中定義變數的方法:
vars:
- var1: value1
- - var2: value2
(3) 通過roles傳遞變數;
(4) Host Inventory
(a) 使用者自定義變數
(i) 向不同的主機傳遞不同的變數;
IP/HOSTNAME varaiable=value var2=value2
(ii) 向組中的主機傳遞相同的變數;
[groupname:vars]
variable=value
eg:
[web]
172.17.251.188
172.17.250.209
[web:vars]
rpmname=samba
執行playbook的方式:
(1) 測試
ansible-playbook --check 只檢測可能會發生的改變,但不真正執行操作;
ansible-playbook --list-hosts 列出執行任務的主機;
(2) 直接執行
templates:模板
文字檔案,巢狀有指令碼(使用模板程式語言編寫)
Jinja2:Jinja2是python的一種模板語言,以Django的模板語言為原本。
Jinja2檔案的建立可以直接將自己建立好的文字檔案的字尾改成以“.j2”結尾的即可!
下面用到的nginx.conf.j2檔案就是將nginx.conf檔案修改好後將其重新命名為nginx.conf.j2的!
支援:
字串:使用單引號或雙引號;
數字:整數,浮點數;
列表:[item1, item2, ...]
元組:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布林型:true/false
算術運算:
+, -, *, /, //, %, **
比較操作:
==, !=, >, >=, <, <=
邏輯運算:
and, or, not
示例:
[root@CentOS7-master ~]# vim nginx.yml
---
- hosts: webservers
remote_user: root
vars:
- rpmname: nginx
nginxport: 8888
tasks:
- name: yum install {{ rpmname }}
yum: name={{ rpmname }} state=present
- name: copy {{ rpmname }}.conf
template: src=/tmp/{{ rpmname }}.conf.j2 dest=/etc/nginx/{{ rpmname }}.c
onf backup=yes
notify: reload
tags: reload{{ rpmname }}
- name: start service
service: name={{ rpmname }} state=started
tags: start{{ rpmname }}
handlers:
- name: reload
service: name={{ rpmname }} state=restarted
模板配置檔案 :
[root@CentOS7-master ~]# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.j2
[root@CentOS7-master ~]# vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }};
listen {{ http_port }};
Ansible playbook條件測試
when語句:在task中使用,jinja2的語法格式
tasks:
- name: install conf file to centos7
template: src=files/nginx.conf.c7.j2
when: ansible_distribution_major_version == "7"
- name: install conf file to centos6
template: src=files/nginx.conf.c6.j2
when: ansible_distribution_major_version == "6"
迴圈:迭代,需要重複執行的任務
對迭代項的引用,固定變數名為”item“;而後,要在task中使用with_items給定要迭代的元素列表。
- name: install some packages
yum: name={{ item }} state=present
with_items:
- nginx
- memcached
- php-fpm
- name: add some groups
group: name={{ item }} state=present
with_items:
- group11
- group12
- group13
- name: add some users
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user11', group: 'group11' }
- { name: 'user12', group: 'group12' }
- { name: 'user13', group: 'group13' }