ansible playbook(二)php
運行palybook時 要使用ansible-playbook命令
palybook執行任務的順序是,在第一個主機上完成第一個任務,而後在第二個主機上完成第一個任務
而不是在第一個主機上完成全部任務,而後再在第二個主機上完成全部任務,以任務爲中心,在全部主機上執行
如何構建ansible的playbook
Inventory
Modules
Ad Hoc Commands
PlayBooks
Tasks 任務,及調用某模塊所完成的操做
Variable 變量
Templates 模版
Handlers 處理器,一般指的是在某條件知足時觸發執行的操做
Roles 角色
若是想說清楚的playbooks,還要額外的瞭解一些基礎概念html
Ansible中使用的YAML基礎元素: 變量 Inventory 條件判斷 迭代 基本結構 - hosts: websrvs remote_user: tasks: - name: task1 module_name: - name: task2 module_name: - hosts: dbsrvs
簡單示例1:node
- hosts: websrvs remote_user: root tasks: - name: create nginx group group: name=nginx system=yes gid=208 - name: create nginx user user: name=nginx uid=208 system=yes group=nginx - hosts: dbsrvs remote_user: root tasks: - name: copy file to dbsrvs copy: src=/etc/inittab dest=/tmp/inittab.ansible
簡單實例2:python
- hosts: websrvs remote_user: root tasks: - name: install httpd packege yum: name=httpd state=latest - name: install configuration file for httpd copy: src=conf/httpd.conf dest=/etc/httpd/conf/httpd.conf - name: start httpd service service: enabled=true name=httpd state=started
簡單實例3-handler:
當配置文件發生改變時,應該讓服務重啓。那麼重啓服務就要用handler,當這個服務發生變化時使用notify屬性通知要執行的handler裏定義的任務以下:mysql
- hosts: websrvs remote_user: root tasks: - name: install httpd packege yum: name=httpd state=latest - name: install configuration file for httpd copy: src=conf/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: - restart httpd - name: start httpd service service: enabled=true name=httpd state=started handlers: - name: restart httpd service: name=httpd state=restarted ~
簡單實例4-定義變量:linux
- hosts: websrvs remote_user: root vars: - package: httpd - service: httpd tasks: - name: install httpd packege yum: name={{ package }} state=latest - name: install configuration file for httpd copy: src=conf/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: - restart httpd - name: start httpd service service: enabled=true name={{ service }} state=started handlers: - name: restart httpd service: name={{ service }} state=restarted
簡單示例5-使用facts變量:nginx
- hosts: websrvs remote_user: root tasks: - name: copy file copy: content= "{{ ansible_all_ipv4_addresses }}" dest=/tmp/vars.ans
一樣在inventory 中爲主機 或者主機組定義的變量也能夠經過 {{ 變量名 }}直接調用。web
簡單示例6-條件判斷語句when:sql
- hosts: all remote_user: root vars: - username: user10 tasks: - name: create {{ username }} user user: name= {{username}} when: ansible_fqdn == 'node1.my.com'
簡單示例7-迭代
重複執行同類task時使用
定義循環列表:with_itemsshell
- name: add serveral users user: name={{ item }} state=present groups=wheel with_items: - testuser1 - testuser2 要安裝多個程序包的時候使用很方便,定義yum - apache - php - mysql-server 注意: with_item中的列表值也能夠是字典 - name add serveral users user: name= {{ itesm.name }} state=present groups= {{ item.groups }} with_items: - { name: 'testuser1', groups: 'wheel' } - { name: 'testuser2', groups: 'root' }
比較是用的是,一個tasks下安裝程序包,定義配置文件就能夠用yum,和copy
with_items: - { name: apache, conf: conffiles/httpd.conf } - { name: php, conf: conffiles/php.ini } - { name: mysql-server, conf: conffiles/my.cnf }
模版template 的使用,經常使用於靜態配置文件中定義變量以及條件語句,通常在ansible中模版文件後綴名爲.j2由於使用的是jinjia2模版語言。同時也要安裝python的jinjia2擴展包,對於咱們來將最經常使用的就是變量。
使用舉例:
inventory中定義以下:
[websrvs]
172.16.100.7 http_port=80 maxClients=100
172.16.100.8 http_port=8080 maxClients=200
假若有一個配置文件中關於端口和maxClients配置項更改以下 Server Name {{ ansible_fqdn }} Listen {{ http_port }} maxClients {{ maxClients }} 通常都會建立一個名爲templates/httpd.conf.j2
接着咱們在playbooks就把以前使用copy模塊定義配置文件的地方改用template模塊,以下:
- hosts: websrvs remote_user: root vars: - package: httpd - service: httpd tasks: - name: install httpd packege yum: name={{ package }} state=latest - name: install configuration file for httpd template: src=/root/templates/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: - restart httpd - name: start httpd service service: enabled=true name={{ service }} state=started handlers: - name: restart httpd service: name={{ service }} state=restarted
tags的使用
咱們前面定義的playbook中有多個tasks,若是咱們想單獨運行這個playbook中的某一個task就須要經過tabs來實現。
- hosts: websrvs remote_user: root vars: - package: httpd - service: httpd tasks: - name: install httpd packege yum: name={{ package }} state=latest - name: install configuration file for httpd template: src=/root/templates/httpd.conf dest=/etc/httpd/conf/httpd.conf tags: - conf notify: - restart httpd - name: start httpd service service: enabled=true name={{ service }} state=started handlers: - name: restart httpd service: name={{ service }} state=restarted 使用下面命令,只運行tags爲conf的任務 ansible-playbook apache.yml --tags='conf' 固然能夠--tage='aa,bb,cc'指明多個tag
特殊tags
假若有的任務你想只要運行這個playbook(即便指定--tags)就須要執行這個task,那麼就可使用
tags: always
以上內容就能夠知足咱們對ansible的使用了,接來下了解角色的定義,讓咱們更方便的使用ansible
咱們想讓一批主機完成 一批任務就可使用playbook進行配置執行。那麼咱們想那爲何還要有role角色這個東西的存在。存在的意義是什麼。這裏咱們在playbook已經能夠實現爲一批主機執行一批任務了,爲何還要有role角色這個玩意。 那好咱們來舉個例子,假如一臺服務器上安裝nginx又安裝了php還安裝了mysql。那麼你能夠寫一個playbook的yaml文件,可是咱們如今又有一臺主機想只執行 nginx 和php,那麼你怎麼實現。固然能夠再次更改playbook,爲其添加一個play,但這違背了開發的儘可能不寫重複代碼的宗旨。因此你實現的方式很low。那麼這時候你若是想,事先定義了三個角色,一個nginx,php,mysql 在應用到主機上就完美了,那就是roles。
roles的應用
ansible 自1.2版本引入的新特性,用於層次性、結構化地組織playbook,roles可以根據層次型結構自動裝載變量文件、tasks以及handles等,要使用roles只須要在playbook中使用include指令便可,簡單來說,roles就是經過分別將變量、文件、任務、模塊及處理器放置於單獨的目錄中,並能夠便捷地include他們的一種機制,角色通常用於基於主機的構建服務的場景中,但也能夠適用於構建守護進程等場景中:
一個roles的案例以下所示: site.yml webservers.yml fooservers.yml roles/ common/ files/ templates/ tasks/ handlers/ vars/ meta/ webservers/ files/ templates/ tasks/ handlers/ vars/ meta/ 而在playbook中,也能夠這樣使用roles: ... - hosts: webservers roles: - common - webservers 也能夠向roles傳遞參數,例如: ... - hosts: webservers roles: - common - { role: foo_app_instance, dir: '/opt/a', port: 5000} - { role: foo_app_instance, dir: '/opt/b', port: 5001} 設置也能夠條件式地使用roles, 例如: ... - hosts: webservers roles: - {role: some_role, when: "ansible_os_family == 'redhat'"}
8.1建立role的步驟
(1) 建立以roles命名的目錄;
(2) 在roles目錄中分別建立以各類角色名稱命名的目錄,如 webservers等;
(3) 在每個角色命名的目錄中分別建立 files,handlers,meta, tasks,templates 和vars目錄:用不到的目錄能夠建立爲空目錄,也能夠不建立;
(4) 在playbook文件中,調用各角色
8.2 role內各目錄彙總可用的文件
tasks目錄: 至少應該包含一個名爲main.yml的文件,其定義來此角色的任務列表;此文件可使用include包含其它的位於此目錄中的task文件; files目錄: 存放又copy或script等模塊調用的文件; templates目錄: template模塊會自動在此目錄中尋找jinjia2模版文件; handlers目錄: 此目錄中應當包含一個mian.yml文件,用於定義此角色用到的handler,在handler中使用include包含的其它的handler文件也應該位於此目錄; vars目錄:應當包含一個mian.yml文件,用於定義此角色用到的變量; meta目錄:應當包含一個main.yml文件,用於定義此角色的特殊設定及其依賴關係,ansible 1.3及其之後的版本才支持; default目錄: 爲當前角色設定變量時使用此目錄,應當包含一個main.yml文件
示例:
1.建立roles目錄
mkdir /root/ansible_playbooks/roles
mkidr -pv /root/ansible_playbooks/roles/{webservers, dbservers}/{tasks,files,templates,handlers,vars,meta}
2. 把要用到的文件放到 files目錄下,把要用到的template文件放到 templates目錄下
3. 在tasks目錄中編輯main.yml
vim /root/ansible_playbooks/roles/webservers/tasks/main.yml
- name: install httpd packeg
yum: name=httpd
- name: install configuration file for httpd
template: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
tags:
- conf
notify:
- restart httpd
- name: start httpd service
service: enabled=true name={{ service }} state=started
這裏指定模版文件的時候,就不用指定目錄來,它會本身去找角色目錄下的template目錄下的文件
4. 這裏咱們用到了notify,也就是說咱們須要定義handlers,接下來
vim /root/ansible_playbooks/roles/webservers/handlers/main.yml - name: restart httpd service: name={{ service }} state=restarted 5. 若是想定義變量 vim /root/ansible_playbooks/roles/webservers/vars/main.yml - http_port: 80 - service: httpd - maxclients: 200 6. 這樣咱們就定義了webservers 這個角色,未來咱們想要調用這個角色,須要在roles這個目錄的同級目錄下有site.yml文件 vim site.yml - hosts: websrvs remote_user: root roles: - webservers
至此 咱們ansible-playbook site.yml
爲了體現這個roles的靈活性:
vim site.yml
- hosts: 172.16.100.7
remote_user: root
roles:
- webservers
- hosts: 172.16.100.8 remote_user: root roles: - dbservers - hosts: 172.16.100.9 remote_user: root roles: - webservers - dbservers 4.1 YAML 簡介 YAML是一個可讀性高的用來表達資料序列的格式。YAML在設計時參考了其餘多種語言,包括:XML、C語言、PYTHON、Perl以及電子郵件格式的RFC2882等,Clark Evans 在2001年首次發表了這種語言,另外Ingy dot Net 與 Ben-Kiki 也是這語言的共同設計者。 YAML Ain't Markup Language, 即YAML不是XML,不過,在開發的這種語言是,YAML的意思實際上是: 「Yet Another Markup Language"(還是一種標記語言),其特性:
也是用於在不一樣主機之間共享數據時,可以經過某種特定形式描述數據自己結構的一種數據組織形式。不一樣xml的是,yaml經過使用鍵值對+縮進的形式表示的
YAML 的可讀性好 YAML 和腳本語言的交互性好 YAML 使用實現語言的數據類型 YAML 又一個一直的信息模型 YAML 易於實現 YAML 能夠基於流來處理 YAML 表達能力強,擴展性好 更多的內容及規範參見http://www.yaml.org/ 4.2 YAML 語法 YAML的語法和其餘高階語言相似,而且能夠簡單表達清單、散列表、標量等數據結構,其結構(Structure) 經過空格來展現, 序列(sequence)裏的項用"-"來表明,Map裏的鍵值對用":"分隔。下面是一個事例 name: John Smith age: 41 gender: Male spouse: name: Jane Smith age:37 gender: Female children: - name: Jimmy Smith age :17 gender : Male - name: Jenny Smith age: 13 gender:female YAML 文件擴展名一般爲.yaml, 如 example.yaml. 4.2.1 list 列表的全部元素均使用"-"大頭,例如: # A list of tasty fruits - Apple - Orange - strawberry - mango 4.2.2 dictionay 字典經過key與value進行標示, 例如: --- # An employee record name: Examle Developer job: Developer skill: Elite 也能夠將key:value 放置於{}中進行表示,例如: --- # An employee record {name: Examle Developer, job: Developer, skill: Elite} 5、Ansible基礎元素 5.1 變量 5.1.1 變量命名 變量名僅能由字母、數字和下劃線組成,且只能以字母開頭 5.1.2 facts facts 是由正在通訊的遠程目標主機發回的信息,這些信息被保存在ansible變量中,要獲取指定的遠程主機所支持的全部facts,可以使用以下命令進行: # ansible hostname -m setup 5.1.3 register 把任務的輸出定義爲變量,而後用於其餘任務,示例以下: tasks: - shell: /usr/bin/foo - register: foo_result - ignore_errors:True 5.1.4 經過命令行傳遞變量 在運行playbook的時候也能夠傳遞一些變量供playbook使用:示例以下: ansible-playbook test.yml --extra-vars "hosts=www user=mageedu" 5.1.5 經過role傳遞變量 當給一個主機應用角色的時候能夠傳遞變量, 而後在角色內使用這些變量,示例以下: - hosts: webservers roles: - common - {role: foo_app_instance, dir:'/web/htdocs/a.com', port:8080} 5.2 Inventory ansible 的主要做用在於批量主機操做, 爲了便捷地使用其中的部分主機, 能夠在inventory file 中將其分組命名, 默認的inventory file爲/etc/ansible/hosts. inventory file 能夠有多個,且也能夠經過 Dynamic Inventory來動態生成。 5.2.1 inventory文件格式 inventory 文件遵循INI文件風格, 中括號中的字符爲組名,能夠將同一個主機同時歸到多個不一樣的組中;此外,當如若目標主機使用了非默認的SSH端口,還能夠在主機名稱以後使用冒號來標明。 ntp.mageedu.com [webserver] www1.my.com:2222 www2.my.com [dbserver] db1.my.com db2.my.com db3.my.com 若是主機名遵循類似的命名模式,還可使用列表的方式標識各主機,例如: [webservers] www[01:10].my.com [databases] db-[a:f].my.com 5.2.2主機變量 能夠在inventory中定義主機時爲其添加主機變量以便與在playbook中使用,例如: [webservers] www1.my.com http_port=80 maxRequestsPerChild=808 www1.my.com http_port=8080 maxRequestsPerChild=909 5.2.3組變量 組變量是指賦予給指定組內全部主機上的palybook中可用的變量,例如: [webservers] www1.my.com www2.my.com [webservers:vars] ntp_server=ntp.my.com nfs_server=nfs.my.com 5.2.4 組嵌套 inventory 中,組還能夠包含其餘組,而且也能夠向組中的主機指定變量,不過,這些變量只能在ansible-playbook中使用,而ansible不支持,例如: [apache] http1.my.com http2.my.com [nginx] ngx1.my.com ngx2.my.com [webservers:children] apache nginx [webservers:vars] ntp_server=ntp.my.com 5.2.5 inventory參數 ansible基於ssh鏈接inventory中指定的遠程主機時,還能夠經過參數指定其交互方式;這些參數以下所示: [webservers] 172.16.100.7 ansible_ssh_user=root ansible_ssh_pass=mypasswd ansible_ssh_port=12008 5.3 條件測試 在task後添加when子句便可使用條件測試;when語句支持jinjia2表達式語法,例如: tasks: - name: "shutdown Debian flavored systems" command: /sbin/shutdown -h now when: ansible_os_family == 'Debian' when語句中還可使用jinjia2的大多"filter", 例如要忽略此前某語句的錯誤並基於其結果<failed或者sucess> 運行後面指定的語句,可以使用相似以下形式: tasks: - command: /bin/false register: result ignore_errors; True - command: /bin/something when: result|failed - command: /bin/somethin_else when: result|skipped 此外,when 語句中還可使用facts或playbook中定義的變量 5.4 迭代,其實就表示循環 當有須要重複性執行的任務時,可使用迭代機制,其使用格式爲將須要迭代的內容定義爲item變量引用,並經過with_items 語句來指明迭代的元素列表便可 - 例如: - name: add serveral users user: name={{ item }} state=present groups=wheel with_items: - testuser1 - testuser2 上面語句的功能等同於下面的語句: - name: add user testuser1 user: name=testuser1 state=present groups=wheel - name: add user testuser2 user: name=testuser2 state=present groups=wheel 事實上,with_items中可使用元素還能夠爲hashes, 例如: - name add serveral users user: name= {{ itesm.name }} state=present groups= {{ item.groups }} with_items: - { name: 'testuser1', groups: 'wheel' } - { name: 'testuser2', groups: 'root' } ansible的循環機制還有更多的高級功能, 具體請參見官方文檔(http://docs.ansible.com/playbooks_loops.html)
七. 如何編寫playbook
ansible playbooks
playbook是由一個或多個'play'組成的列表,play的主要功能在於將事先歸併爲一組的主機裝扮成事先經過ansible中的task定義好的角色。從根本上來說,所謂task無非是調用ansible的一個module.將多個play組織在一個palybook中,便可以讓他們聯同起來按事先編排的機制同唱一臺大戲,下面是一個簡單示例。
- hosts: webnodes vars: http_port: 80 max_clients: 256 remote_user:root tasks: - name: ensure apache is at the latest version yum : name=httpd state=latest - name: ensure apache is running service: name=httpd state=started handlers: - name: retart apache service: name=httpd state=restarted
7.1 palybook的基礎組件
7.1.1 Hosts和Users
playbook中的每個play的目的都是爲了讓某個或某些主機以某個指定的用戶身份執行任務。hosts 用於指定要執行任務的主機,其能夠是一個或多個由某好分隔主機組;remote_user 則用於指定遠程主機上的執行任務的用戶,如上圖示例中的
- hosts: webnodes remote_user: root
不過,remote_user也可用於各task中,也能夠經過指定其經過sudo的方式在遠程主機上執行任務,其可用於play全局或某任務,此外,甚至能夠在sudo時使用sudo_user指定sudo時切換的用戶。
- hosts: webnodes
remote_user: ted1
tasks:
- name: test connection
ping:
remote_user: ted2
sudo : yes
7.1.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 sehll: /usr/bin/somecommand|| /bin/true 或者使用ignore_errors來忽略錯誤信息:(即便運行有錯誤,無論他繼續執行其餘tasks) tasks: - name: run this command and ignore the result shell: /usr/bin/somecommand ignore_errors: True
7.1.3 handlers
用於當天關注的資源發生變化時採起必定的操做。
'notify'這個action可用於在每一個play的最後被觸發。 這樣能夠避免屢次由改變發生時每次都執行指定的操做,取而代之,僅在全部的變化發生完成後一次性執行指定操做。在notify中列出的操做成爲handler,也即notify中調用handler中定義的操做。
- 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=mamcached state=restarted
- name: restart apache
service: name=apache state=restarted
示例: - hosts: websrvs remote_user: root tasks: - name: install httpd packege yum: name=httpd state=latest - name: install configuration file for httpd copy: src=conf/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: - restart httpd - name: start httpd service service: enabled=true name=httpd state=started handlers: - name: restart httpd service: name=httpd state=restarted