ansible之playbook入門

playbook適合複雜的環境部署。其實用的語法是yaml。

playbook由一個或多個plays組成,它的內容是以plays爲元素的列表。在play中,主機被定義爲角色,play的內容被稱爲task,一個task是對ansible模塊的一次調用。

舉栗子

---
- 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=/srv/httpd.j2 dest=/etc/httpd.conf
    notify:
    - restart apache
  - name: ensure apache is running
    service: name=httpd state=started
  handlers:
    - name: restart apache
      service: name=httpd state=restarted

這是一個playbook,只包含一個play。

主機與用戶

每個play都可以指定主機,執行者身份,和操作內容。

  • hosts 行的內容是一個或多個組或主機的 patterns,以逗號爲分隔符,詳見 Patterns 章節:
---
- hosts: webservers
  remote_user: root
  • 再者,在每一個 task 中,可以定義自己的遠程用戶:
---
- hosts: webservers
  remote_user: root
  tasks:
    - name: test connection
      ping:
      remote_user: yourname
  • 也支持用su身份執行命令:
---
- hosts: webservers
  remote_user: yourname
  become:yes
  become_method: su
  • 同樣的,你可以僅在一個 task 中,使用 sudo 執行命令,而不是在整個 play 中使用 sudo:
---
- hosts: webservers
  remote_user: yourname
  tasks:
    - service: name=nginx state=started
      become: yes
      become_method: sudo
  • 你也可以登陸後,sudo 到不同的用戶身份,而不是使用 root:
---
- hosts: webservers
  remote_user: yourname
  become: yes
  become_user: username

如果需要指定sudo的密碼,請使用–ask-become-pass運行ansible-playbook,或者使用舊的sudo語法–ask-sudo-pass(-K)。如果程序卡死,可能是在權限切換部分卡住,執行Ctrl+C打斷,檢查身份認證的語法再執行。

task list

每個play包含一個task的列表,task按照與主機匹配的模式順序執行,然後進行下一個task。重要的是要明白,在一個play中,所有的主機都獲得了相同的,play的目的是把主機映射到task上。

格式

如果要聲明一個 task,以前有一種格式: “action: module options” (可能在一些老的 playbooks 中還能見到).現在推薦使用更常見的格式:”module: options”

  • 下面是一種基本的 task 的定義,service moudle 使用 key=value 格式的參數,這也是大多數 module 使用的參數格式:
tasks:
  - name: make sure apache is running
    service: name=httpd state=running
  • 比較特別的兩個 modudle 是 command 和 shell ,它們不使用 key=value 格式的參數,而是這樣:
tasks:
  - name: disable selinux
    command: /sbin/setenforce 0
  • 使用 command module 和 shell module 時,我們需要關心返回碼信息,如果有一條命令,它的成功執行的返回碼不是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
  • 如果 action 行看起來太長,你可以使用 space(空格) 或者 indent(縮進) 隔開連續的一行:
tasks:
  - name: Copy ansible inventory file to client
    copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
            owner=root group=root mode=0644
  • 在 action 行中可以使用變量.假設在 ‘vars’ 那裏定義了一個變量 ‘vhost’ ,可以這樣使用它:
tasks:
  - name: create a virtual host file for {{ vhost }}
    template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}

這些變量在 tempates 中也是可用的,稍後會講到.

在一個基礎的 playbook 中,所有的 task 都是在一個 play 中列出,稍後將介紹一種更合理的安排 task 的方式:使用 ‘include:’ 指令.

一些知識

  • playbook從上到下執行,如果某個host執行task失敗,則會把其從playbook的rotation中去除;如果發生執行失敗的情況,則修改playbooks,重新執行。

  • 每個 task 的目標在於執行一個 moudle, 通常是帶有特定的參數來執行.在參數中可以使用變量(variables)。

  • modules 具有”冪等”性,意思是如果你再一次地執行 moudle,moudle 只會執行必要的改動,只會改變需要改變的地方.所以重複多次執行 playbook 也很安全。

  • 對於 command module 和 shell module,重複執行 playbook,實際上是重複運行同樣的命令.如果執行的命令類似於 ‘chmod’ 或者 ‘setsebool’ 這種命令,這沒有任何問題.也可以使用一個叫做 ‘creates’ 的 flag 使得這兩個 module 變得具有”冪等”特性 (不是必要的)。

  • 每一個 task 必須有一個名稱 name,這樣在運行 playbook 時,從其輸出的任務執行信息中可以很好的辨別出是屬於哪一個 task 的. 如果沒有定義 name,‘action’ 的值將會用作輸出信息中標記特定的 task.

Handlers: 在發生改變時執行的操作

模塊具有冪等性,當遠端發生改變時,重複執行playbook可以恢復改動,因爲playbook本身識別這種改動,並且有一個系統來響應這種改動。

notify這個動作在每個task末尾被觸發,而且就算被多個task觸發,也只生效一次。比如說,多個resources表示配置文件改動而需要重啓Apache,但是最終Apache只會重啓一次。

下面是重啓兩個服務的例子,但是隻有文件更改了纔會生效:

- name: template configuration file
  template: src=template.j2 dest=/etc/foo.conf
  notify:
     - restart memcached
     - restart apache

noitfy下面的列出來的即是handlers

handlers是由全局唯一名稱引用的task列表,與常規task完全沒有任何區別,並由notifier進行notify,如果沒有被notify,handlers將不會執行。在所有task運行完一遍之後,不管有多少個notify,handles只會運行一次。

handlers示例:

handlers:
    - name: restart memcached
      service: name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted

從ansible2.2開始,處理程序也可以“listen”通用topic,task可以notify該topic:

handlers:
    - name: restart memcached
      service: name=memcached state=restarted
      listen: "restart web services"
    - name: restart apache
      service: name=apache state=restarted
      listen: "restart web services"

tasks:
    - name: restart everything
      command: echo "this task will restart the web services"
      notify: "restart web services"

這將很容易調用多個handlers,也使其名稱和handlers分離,從而容易在playbook和roles之間共享handlers。

在介紹role之前,要注意幾點:
- 在pre_tasks, tasks, post_tasks 中調用handlers之後,在notify之後就自動刷新handlers。
- 在roles中notify handlers,則在這個task末尾,下一個task之前刷新handlers。

還可以手動刷新handles:

tasks:
   - shell: some tasks go here
   - meta: flush_handlers
   - shell: some other tasks

在上述例子中,任何在等待的handlers將會在meta時提早執行。

發佈了49 篇原創文章 · 獲贊 12 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章