記得自己當初最早使用Ansible的時候,網上搜到的中文資料的都是零零散散的,後來只能硬着頭皮看官方的英文文檔。發現好多事情都沒有什麼捷徑可走,最好的資料還是官方的文檔。最近又抽時間按照官方文檔對Ansible做了一個較爲系統的學習與研究,主要是爲了整理一份較爲完善的學習筆記供自己以後查閱,哎,年紀大了,記性不好了,寫文檔才能把有些細節記下來。
Playbooks可以稱爲是Ansible的配置,部署,編排語言。在Playbooks中,你可以定義遠程節點要執行的某組動作。如:希望遠程節點要先安裝httpd,創建一個vhost,最後啓動httpd。
Playbooks使用了YAML格式,具有較少的語法格式。其特意的避免將自己設計爲一門語言或者腳本,而是一個純粹的配置和過程模型。
每個playbooks都有一個或者多個play組成。
play簡單來說就是一些主機節點要執行一些任務。最基本的,一個任務也就是調用一個Ansible模塊。
通過爲Playbooks編寫多個play ,可以協調多主機的部署。如,按照一定的步驟在webservers組內的所有主機上執行操作,然後按照一定的步驟在databaseserver組內的主機上執行,然後再有其他更多的命令在webservers組內主機上執行,等等。
下邊是個只包含一個play的playbooks:
[root@web1 ~]# cat /etc/ansible/http.yml --- - hosts: webservers vars: http_port: 80 #定義變量 max_clients: 200 #定義變量 remote_user: root tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=/etc/ansible/httpd.j2 dest=/etc/httpd.conf notify: - restart apache - name: ensure apache is running (and enable it at boot) service: name=httpd state=started enabled=yes handlers: - name: restart apache service: name=httpd state=restarted [root@web1 ~]# ansible-playbook /etc/ansible/http.yml PLAY [webservers] ************************************************************* GATHERING FACTS *************************************************************** ok: [192.168.1.65] TASK: [ensure apache is at the latest version] ******************************** changed: [192.168.1.65] TASK: [write the apache config file] ****************************************** changed: [192.168.1.65] TASK: [ensure apache is running (and enable it at boot)] ********************** changed: [192.168.1.65] NOTIFIED: [restart apache] **************************************************** changed: [192.168.1.65] PLAY RECAP ******************************************************************** 192.168.1.65 : ok=5 changed=4 unreachable=0 failed=0
上邊的playbooks只定義了對webservers組內的主機所執行的一系列任務。
在模板httpd.j2中會引用上邊定義的兩個變量,如` max_clients `
notify表示當配置文件發生變化時會觸發restart apache動作 handlers定義一些要
被觸發的動作。
playbooks也可以包含多個play ,如下邊的示例,在同一個playbooks中既可以對web servers組操作,也可以對datavase servers組操作:
--- - hosts: webservers remote_user: root tasks: - name: ensure apache is at the latest version yum: pkg=httpd state=latest - name: write the apache config file template: src=/srv/httpd.j2 dest=/etc/httpd.conf - hosts: databases remote_user: root tasks: - name: ensure postgresql is at the latest version yum: name=postgresql state=latest - name: ensure that postgresql is started service: name=postgresql state=running
play就像任務一樣按照在playbooks中的定義順序從上到下依次執行。
Playbooks中的主機和用戶
Playbooks中的每個play ,都需要指定一個遠程主機節點(或一組節點主機)和要以哪個遠程用戶執行任務。
hosts指定主機組的列表,或者是一個主機的匹配正則表達式。多個主機組或者多個匹配模式之間以冒號隔開,如,one*.com:dbservers。remote_user指定一個用戶賬戶。
--- - hosts: webservers remote_user: root
遠程用戶也可以在每個任務中指定:
--- - hosts: webservers remote_user: root tasks: - name: test connection ping: remote_user: yourname
也可以以其他用戶的身份來執行任務(sudo):
--- - hosts: webservers remote_user: yourname sudo: yes
示例:
[root@web1 ~]# cat /etc/ansible/sudo.yml --- - hosts: webservers remote_user: liuzhenwei sudo: yes tasks: - name: create file as root file: path=/tmp/testfile2 state=touch [root@web1 ~]# ansible-playbook /etc/ansible/sudo.yml -K -k SSH password: SUDO password[defaults to SSH password]: PLAY [webservers] ************************************************************* GATHERING FACTS *************************************************************** ok: [192.168.1.65] TASK: [create file as root] *************************************************** changed: [192.168.1.65] PLAY RECAP ******************************************************************** 192.168.1.65 : ok=2 changed=1 unreachable=0 failed=0 #遠程節點 [root@db2 ~]# ll /tmp/testfile2 -rw-r--r--. 1 root root 0 Jul 27 15:01 /tmp/testfile2
也可以爲每個任務指定是否使用sudo,而不是應用於整個play中:
--- - hosts: webservers remote_user: yourname tasks: - service: name=nginx state=started become: yes become_method: sudo
也可以先以自己的賬戶登錄,然後切換爲其他非root用戶:
--- - hosts: webservers remote_user: yourname become: yes become_user: postgres
示例:
[root@web1 ~]# cat /etc/ansible/become.yml --- - hosts: webservers remote_user: liuzhenwei become: yes become_user: tom tasks: - name: touch file file: path=/tmp/sufile state=touch [root@web1 ~]# ansible-playbook /etc/ansible/become.yml -k --ask-become-pass SSH password: SU password[defaults to SSH password]: PLAY [webservers] ************************************************************* GATHERING FACTS *************************************************************** ok: [192.168.1.65] TASK: [touch file] ************************************************************ changed: [192.168.1.65] PLAY RECAP ******************************************************************** 192.168.1.65 : ok=2 changed=1 unreachable=0 failed=0 #遠程節點 [root@db2 ~]# ll /tmp/sufile -rw-r--r--. 1 tom tom 0 Jul 27 15:21 /tmp/sufile
-k,--ask-become-pass表示需要命令提示用戶輸入遠程用戶及su用戶的密碼。
也可以使用su來提升用戶權限:
--- - hosts: webservers remote_user: yourname become: yes become_method: su
示例:
[root@web1 ~]# cat /etc/ansible/become.yml --- - hosts: webservers remote_user: liuzhenwei become: yes become_method: su tasks: - name: touch file file: path=/tmp/sufiles state=touch [root@web1 ~]# ansible-playbook /etc/ansible/become.yml -k --ask-su-pass SSH password: SU password[defaults to SSH password]: PLAY [webservers] ************************************************************* GATHERING FACTS *************************************************************** ok: [192.168.1.65] TASK: [touch file] ************************************************************ changed: [192.168.1.65] PLAY RECAP ******************************************************************** 192.168.1.65 : ok=2 changed=1 unreachable=0 failed=0 #遠程節點 [root@db2 ~]# ll /tmp/sufiles -rw-rw-r--. 1 root root 0 Jul 27 15:23 /tmp/sufiles
注意-k,--ask-su-pass表示需要命令提示用戶輸入遠程用戶及su用戶的密碼。
任務列表
每個play都包含了一個任務列表,任務是按照順序執行的,且每個任務會都在指定的所有遠程節點上執行,然後再執行下一個任務。
playbooks從上到下執行,如果某個主機的某個任務執行失敗則退出。
每個任務實際上都是執行了一個模塊,並且爲該模塊指定了特定的參數。文件上邊定義的變量,可以用在模塊的參數內。
模塊都是等冪的,意思就是當你再次運行的 時候,他們只做他們必須要做的操作(改變某些文件狀態等),以使系統達到所需的狀態。這樣的話,當
你重複運行多次相同的playbooks時,也是非常安全的。
每個任務都應該有一個名稱,這個名稱會在運行playbook的時候輸出,如果沒有指定名稱,那麼對主機做的操作行爲將會被用來輸出到屏幕上。
任務可以以這種格式來定義: module:options。
下邊是一個簡單的任務示例:
tasks: - name: make sure apache is running service: name=httpd state=running
command和shell模塊只需要一個參數列表既可:
tasks: - name: disable selinux command: /sbin/setenforce 0
command和shell會關注它的返回碼,如果有一個自定義的腳本或者命令,成功執行後的退出碼爲非0值,可以進行以下操作:
tasks: - name: run this command and ignore the result shell: /usr/bin/somecommand || /bin/true
或者:
tasks: - name: run this command and ignore the result shell: /usr/bin/somecommand ignore_errors: True
如果參數較多的話也可以將其換行書寫:
tasks: - name: Copy ansible inventory file to client copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts owner=root group=root mode=0644
同樣也可以在tasks中引用變量:
tasks: - name: create a virtual host file for {{ vhost }} template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}
這些變量都會在vars中定義。關於變量和某些常用模塊的使用方法後續也會介紹。
Handlers:當某些操作發生改變時觸發執行的任務
正如前面提到的,Ansible模塊都是冪等的,而且當在遠程主機上做了改變之後也可以傳遞change這個事件。Playbooks有一個基本的事件系統來對‘改
變’做出響應。
notify中指定的行爲會在每個任務的最後觸發,如果在多個不同的任務裏指定了相同的觸發事件,那麼只會觸發一次。
例如,多個任務都表明需要重啓Apache,因爲他們都修改了配置文件。但是Apache只會重啓一次,這樣就避免了一些不必要的重啓動作。
下邊的例子,表名當文件內容發生變化的時候,重啓兩個服務:
- name: template configuration file template: src=template.j2 dest=/etc/foo.conf notify: - restart memcached - restart apache
notify中的任務稱爲handlers。
handlers也是一個任務列表,與普通tasks不同的是hanlders下邊的每個操作行爲都需要指定一個全局唯一的名稱。如果沒有任務操作觸發該
hanlders,那麼它將不會運行。如論有多少個操作都觸發了同一個handlers,在所有的任務執行完成後,也只會觸發執行一次該handlders。
handlers定義格式如下:
handlers: - name: restart memcached service: name=memcached state=restarted - name: restart apache service: name=apache state=restarted
示例:
[root@web1 ~]# cat /etc/ansible/notify.yml --- - hosts: webservers remote_user: root vars: http_port: 8083 max_clients: 220 tasks: - name: template config file template: src=/etc/ansible/httpd.j2 dest=/etc/httpd.conf notify: - restart apache handlers: - name: restart apache service: name=httpd state=restarted [root@web1 ~]# ansible-playbook /etc/ansible/notify.yml PLAY [webservers] ************************************************************* GATHERING FACTS *************************************************************** ok: [192.168.1.65] TASK: [template config file] ************************************************** changed: [192.168.1.65] NOTIFIED: [restart apache] **************************************************** changed: [192.168.1.65] PLAY RECAP ******************************************************************** 192.168.1.65 : ok=3 changed=2 unreachable=0 failed=0
vars是定義的變量內容,varname:value的形式,在該playbooks中和在template指定的模板文件中都可以引用變量,關於template模塊和變量在其他文檔中會詳細說明。
notify hanlders都會按照書寫的循序運行。
hanlders名稱必須是全局唯一。
如果有兩個handlers定義了相同的名稱,只會有一個handlers會運行。
其實上邊已經無形中說明了playbooks的執行方法,使用ansible-playbook命令:
ansible-playbook playbook.yml -f 10
-f|--forks 指定使用的併發進程數。
OK,關於playbooks的簡單使用就介紹到這裏,這基本上就可以做很多平時運維中的自動化工作了,playbooks高效的組織了ansible對遠程節點所執行的操作。而且playbooks還有其他很多特性及語法可以更好地組織自動化操作,並且可以很方便的複用某些操作,不需要在不同的地方重複定義同一個操作行爲,這些抽時間都會整理上來的。