ansbile-playbook是一系統ansible命令的集合,其利用yaml 語言編寫,運行過程,ansbile-playbook命令根據自上而下的順序依次執行。同時,playbook開創了很多特性,它可以允許你傳輸某個命令的狀態到后面的指令,如你可以從一台機器的文件中抓取內容並附為變量,然后在另一台機器中使用,這使得你可以實現一些復雜的部署機制,這是ansible命令無法實現的。
playbook通過ansible-playbook命令使用,它的參數和ansible命令類似,如參數-k(–ask-pass) 和 -K (–ask-sudo) 來詢問ssh密碼和sudo密碼,-u指定用戶,這些指令也可以通過規定的單元寫在playbook 。ansible-playbook的簡單使用方法: ansible-playbook example-play.yml 。
一、一個簡單的示例
下面給出一個簡單的ansible-playbook示例,了解下其構成。
- # cat user.yml
- - name: create user
- hosts: all
- user: root
- gather_facts: false
- vars:
- - user: "test"
- tasks:
- - name: create user
- user: name="{{ user }}"
上面的playbook 實現的功能是新增一個用戶:
name參數對該playbook實現的功能做一個概述,后面執行過程中,會打印 name變量的值 ;
hosts參數指定了對哪些主機進行參作;
user參數指定了使用什么用戶登錄遠程主機操作;
gather_facts參數指定了在以下任務部分執行前,是否先執行setup模塊獲取主機相關信息,這在后面的task會使用到setup獲取的信息時用到;
vars參數,指定了變量,這里指字一個user變量,其值為test ,需要注意的是,變量值一定要用引號引住;
task指定了一個任務,其下面的name參數同樣是對任務的描述,在執行過程中會打印出來。user提定了調用user模塊,name是user模塊里的一個參數,而增加的用戶名字調用了上面user變量的值。具體執行結果如下:
- [root@361way playbooks]# ansible-playbook user.yml
- PLAY [create user] ************************************************************
- TASK: [create user ] **********************************************
- changed: [10.212.52.252]
- changed: [10.212.52.14]
- changed: [10.212.52.16]
- PLAY RECAP ********************************************************************
- 10.212.52.14 : ok=1 changed=1 unreachable=0 failed=0
- 10.212.52.16 : ok=1 changed=1 unreachable=0 failed=0
- 10.212.52.252 : ok=1 changed=1 unreachable=0 failed=0
同樣,如果想實現把這個新增的用戶刪除,只需將該playbook文件的最后一行替換為如下行再執行相應的playbook即可:
- user: name="{{ user }}" state=absent remove=yes
二、一鍵修補bash shellcode示例
再給出一個稍微復雜的示例,通過ansible-playbook實現對N台主機同時修補bash shellcode 漏洞。需要注意的是,可能現網主機分布着不同的系統版本。這里假設現網同時存在centos5和6版本,具體playbook內容如下:
- # cat update_bash.yml
- - hosts: all
- remote_user: root
- gather_facts: True
- tasks:
- - name: update bash in redhat 6 version
- yum: name=http://mirrors.aliyun.com/centos/6.6/os/x86_64/Packages/bash-4.1.2-29.el6.x86_64.rpm.rpm state=present
- when: ansible_os_family == "RedHat" and ansible_distribution_version|int >=6
- - name: update bash in redhat 5 version
- yum: name=http://mirrors.hustunique.com/centos/5/updates/x86_64/RPMS/bash-3.2-33.el5.1.x86_64.rpm state=present
- when: ansible_os_family == "RedHat" and ansible_distribution_version|int <=5
上面使用了when語句,同時也開啟了gather_facts setup模塊,這里的ansible_os_family變量和ansible_distribution_version變量就是直接使用的setup模塊獲取的信息。
如果有大量主機,就在運行的時候加上-f然后選擇一個合適的並發主機數量即可,我這里使用了這個,很快的就升級完成bash了。
三、playbook的構成
playbook是由一個或多個“play”組成的列表。play的主要功能在於將事先歸並為一組的主機裝扮成事先通過ansible中的task定義好的角色。從根本上來講所謂task無非是調用ansible的一個module。將多個play組織在一個playbook中即可以讓它們聯同起來按事先編排的機制同唱一台大戲。其主要有以下四部分構成
- playbooks組成:
- Target section: 定義將要執行 playbook 的遠程主機組
- Variable section: 定義 playbook 運行時需要使用的變量
- Task section: 定義將要在遠程主機上執行的任務列表
- Handler section: 定義 task 執行完成以后需要調用的任務
而其對應的目錄層為五個,如下:
- 一般所需的目錄層有:(視情況可變化)
- vars 變量層
- tasks 任務層
- handlers 觸發條件
- files 文件
- template 模板
下面介紹下構成playbook 的四層結構。
1、Hosts和Users
playbook中的每一個play的目的都是為了讓某個或某些主機以某個指定的用戶身份執行任務。
hosts 用於指定要執行指定任務的主機其可以是一個或多個由冒號分隔主機組。
remote_user 則用於指定遠程主機上的執行任務的用戶。
不過remote_user也可用於各task中。也可以通過指定其通過sudo的方式在遠程主機上執行任務其可用於play全局或某任務。
此外甚至可以在sudo時使用sudo_user指定sudo時切換的用戶。
示例:
- - hosts: webnodes
- tasks:
- - name: test ping connection:
- remote_user: test
- sudo: yes
2、任務列表和action
play的主體部分是task list。
task list中的各任務按次序逐個在hosts中指定的所有主機上執行即在所有主機上完成第一個任務后再開始第二個。在運行自下而下某playbook時如果中途發生錯誤所有已執行任務都將回滾因此在更正playbook后重新執行一次即可。
task的目的是使用指定的參數執行模塊而在模塊參數中可以使用變量。模塊執行是冪等的這意味着多次執行是安全的因為其結果均一致。每個task都應該有其name用於playbook的執行結果輸出建議其內容盡可能清晰地描述任務執行步驟。如果未提供name則action的結果將用於輸出。
定義task的可以使用“action: module options”或“module: options”的格式推薦使用后者以實現向后兼容。如果action一行的內容過多也中使用在行首使用幾個空白字符進行換行。
- tasks:
- - name: make sure apache is running
- service: name=httpd state=running
- 在眾多模塊中只有command和shell模塊僅需要給定一個列表而無需使用“key=value”格式例如
- tasks:
- - name: disable selinux
- command: /sbin/setenforce 0 如果命令或腳本的退出碼不為零可以使用如下方式替代
- tasks:
- - name: run this command and ignore the result
- shell: /usr/bin/somecommand || /bin/true
- 或者使用ignore_errors來忽略錯誤信息
- tasks:
- - name: run this command and ignore the result
- shell: /usr/bin/somecommand
- ignore_errors: True
3、handlers
用於當關注的資源發生變化時采取一定的操作。
“notify”這個action可用於在每個play的最后被觸發這樣可以避免多次有改變發生時每次都執行指定的操作取而代之僅在所有的變化發生完成后一次性地執行指定操作。
在notify中列出的操作稱為handler也即notify中調用 handler中定義的操作。
注意:在 notify 中定義內容一定要和tasks中定義的 - name 內容一樣,這樣才能達到觸發的效果,否則會不生效。
- - name: template configuration file
- template: src=template.j2 dest=/etc/foo.conf
- notify:
- - restart memcached
- - restart apache
- handler是task列表這些task與前述的task並沒有本質上的不同。
- handlers:
- - name: restart memcached
- service: name=memcached state=restarted
- - name: restart apache
- service: name=apache state=restarted
4、tags
tags用於讓用戶選擇運行或略過playbook中的部分代碼。ansible具有冪等性因此會自動跳過沒有變化的部分即便如此有些代碼為測試其確實沒有發生變化的時間依然會非常地長。
此時如果確信其沒有變化就可以通過tags跳過此些代碼片斷。
5、示例
下面再給出一個安裝httpd web服務的示例:
- # cat /etc/ansible/playbook/install_web.yml
- - hosts: webservers
- remote_user: root
- gather_fasks: False
- vars:
- packages: httpd
- tasks:
- - name: Install httpd
- yum: name={{ packages }} state=present
- - name: Cofiguration httpd
- copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
- tags: httpd_conf
- notify:
- - restart httpd
- - name: Start httpd
- service: name=httpd state=started enabled=no
- tags: start
- - name:Add centos user
- user: name={{ item }} state=absent
- tags: adduser
- with_items:
- - centos
- - admin
- handlers:
- - name: restart httpd
- service: name=httpd state=restart
注:上面的代碼沒有考慮ubuntu平台,僅僅考慮centos/redhat平台。
