自動化運維工具Ansible之Playbooks基礎應用

記得自己當初最早使用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:dbserversremote_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還有其他很多特性及語法可以更好地組織自動化操作,並且可以很方便的複用某些操作,不需要在不同的地方重複定義同一個操作行爲,這些抽時間都會整理上來的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章