一、簡介
ansible是新出現的自動化運維工具,基于Python開發,集合了衆多運維工具(puppet、cfengine、chef、func、fabric)的優點,實作了批量系統配置、批量程式部署、批量運作指令等功能。
ansible是基于子產品工作的,本身沒有批量部署的能力。真正具有批量部署的是ansible所運作的子產品,ansible隻是提供一種架構。主要包括:
(1)、連接配接插件connection plugins:負責和被監控端實作通信;
(2)、host inventory:指定操作的主機,是一個配置檔案裡面定義監控的主機;
(3)、各種子產品核心子產品、command子產品、自定義子產品;
(4)、借助于插件完成記錄日志郵件等功能;
(5)、playbook:劇本執行多個任務時,非必需可以讓節點一次性運作多個任務。
二、安裝Ansible
<code># yum install python-paramiko-1.7.5-2.1.el6.noarch.rpm PyYAML-3.10-3.1.el6.x86_64.rpm python-jinja2-26-2.6-3.el6.noarch.rpm</code>
<code> </code><code>python-crypto2.6-2.6.1-2.el6.x86_64.rpm python-babel-0.9.4-5.1.el6.noarch.rpm</code>
2.1 編譯安裝
<code># yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto</code>
<code># tar xf ansible-1.5.4.tar.gz</code>
<code># cd ansible-1.5.4</code>
<code># python setup.py build</code>
<code># python setup.py install</code>
<code># mkdir /etc/ansible</code>
<code># cp -r examples/* /etc/ansible</code>
2.2 rpm包安裝
<code># yum install ansible-2.2.1.0-1.el6.noarch.rpm</code>
或
<code>yum </code><code>install</code> <code>http:</code><code>//mirrors</code><code>.sohu.com</code><code>/fedora-epel/6/x86_64/epel-release-6-8</code><code>.noarch.rpm</code>
<code>yum </code><code>install</code> <code>anisble</code>
注意:不同版本的ansible的功能差異可能較大。
三、簡單應用
ansible通過ssh實作配置管理、應用部署、任務執行等功能,是以,需要事先配置ansible端能基于密鑰認證的方式聯系各被管理節點。
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
-m module:預設為command
ansible-doc: Show Ansible module documentation
-l, --list List available modules
-s, --snippet Show playbook snippet for specified module(s)
四、YAML
4.1 YAML介紹
YAML是一個可讀性高的用來表達資料序列的格式。YAML參考了其他多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822等。Clark Evans在2001年在首次發表了這種語言,另外Ingy dt Net與Oren Ben-Kiki也是這語言的共同設計者。
YAML Ain't Markup Language,即YAML不是XML。不過,在開發的這種語言時,YAML的意思其實是:"Yet Another Markup Language"(仍是一種标記語言)。其特性:
YAML的可讀性好
YAML和腳本語言的互動性好
YAML使用實作語言的資料類型
YAML有一個一緻的資訊模型
YAML易于實作
YAML可以基于流來處理
YAML表達能力強,擴充性好
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 dictionary
字典通過key與valuef進行辨別,例如:
---
# An employee record
name: Example Developer
job: Developer
skill: Elite
也可以将key:value放置于{}中進行表示,例如:
{name: Example Developer, job: Developer, skill: Elite}
五、Ansible基礎元素
5.1 變量
5.1.1 變量命名
變量名僅能由字母、數字和下劃線組成,且隻能以字母開頭。
5.1.2 facts
facts是由正在通信的遠端目标主機發回的資訊,這些資訊被儲存在ansible變量中。要擷取指定的遠端主機所支援的所有facts,可使用如下指令進行:
<code># ansible hostname -m setup</code>
5.1.3 register
把任務的輸出定義為變量,然後用于其他任務,示例如下:
<code>tasks:</code>
<code> </code><code>- shell: </code><code>/usr/bin/foo</code>
<code> </code><code>register: foo_result</code>
<code> </code><code>ignore_errors: True</code>
5.1.4 通過指令行傳遞變量
在運作playbook的時候也可以傳遞一些變量供playbook使用,示例如下:
<code>ansible-playbook </code><code>test</code><code>.yml --extra-vars </code><code>"hosts=www user=bovin"</code>
5.1.5 通過roles傳遞變量
當給一個主機應用角色的時候可以傳遞變量,然後在角色内使用這些變量,示例如下:
<code>- hosts: webservers</code>
<code> </code><code>roles:</code>
<code> </code><code>- common</code>
<code> </code><code>- { role: foo_app_instance, </code><code>dir</code><code>: </code><code>'/web/htdocs/a.com'</code><code>, port: 8080 }</code>
5.2 Inventory
ansible的主要功用在于批量主機操作,為了便捷地使用其中的部分主機,可以在inventory file中将其分組命名。預設的inventory file為/etc/ansible/hosts。
inventory file可以有多個,且也可以通過Dynamic Inventory來動态生成。
5.2.1 inventory檔案格式
inventory檔案遵循INI檔案風格,中括号中的字元為組名。可以将同一個主機同時歸并到多個不同的組中;此外,當如若目标主機使用了非預設的SSH端口,還可以在主機名稱之後使用冒号加端口号來标明。
<code>mail.example.com</code>
<code>[webservers]</code>
<code>foo.example.com:8888</code>
<code>bar.example.com</code>
<code>[dbservers]</code>
<code>one.example.com</code>
<code>two.example.com</code>
<code>three.example.com</code>
方括号[]中是組名,用于對系統進行分類,便于對不同系統進行個别的管理.
一個系統可以屬于不同的組,比如一台伺服器可以同時屬于 webserver組 和 dbserver組.這時屬于兩個組的變量都可以為這台主機所用.
如果有主機的SSH端口不是标準的22端口,可在主機名之後加上端口号,用冒号分隔.SSH 配置檔案中列出的端口号不會在 paramiko 連接配接中使用,會在 openssh 連接配接中使用.
端口号不是預設設定時,可明确的表示為:
<code>badwolf.example.com:5309</code>
假設你有一些靜态IP位址,希望設定一些别名,但不是在系統的 host 檔案中設定,又或者你是通過隧道在連接配接,那麼可以設定如下:
<code>jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50</code>
在這個例子中,通過 “jumper” 别名,會連接配接 192.168.1.50:5555.記住,這是通過 inventory 檔案的特性功能設定的變量. 一般而言,這不是設定變量(描述你的系統政策的變量)的最好方式.後面會說到這個問題.
如果主機名稱遵循相似的命名模式,還可以使用清單的方式辨別各主機,例如:
<code>www[01:50].example.com</code>
<code>[databases]</code>
<code>db-[a:f].example.com</code>
對于每一個 host,你還可以選擇連接配接類型和連接配接使用者名:
<code>[targets]</code>
<code>localhost ansible_connection=</code><code>local</code>
<code>other1.example.com ansible_connection=</code><code>ssh</code> <code>ansible_ssh_user=mpdehaan</code>
<code>other2.example.com ansible_connection=</code><code>ssh</code> <code>ansible_ssh_user=mdehaan</code>
5.2.2 主機變量
可以在inventory中定義主機時為其添加主機變量以便于在playbook中使用。例如:
<code>host1 http_port=80 maxRequestsPerChild=808</code>
<code>host2 http_port=303 maxRequestsPerChild=909</code>
5.2.3 組變量
組變量是指賦予給指定組内所有主機上的在playbook中可用的變量。例如:
<code>host1</code>
<code>host2</code>
<code>[webserver:vars]</code>
<code>ntp_server=ntp.webservers.example.com</code>
<code>nfs_server=nfs.webservers.example.com</code>
5.2.4 組嵌套
inventory中,組還可以包含其它的組,并且也可以向組中的主機指定變量。不過,這些變量隻能在ansible-playbook中使用,而ansible不支援。例如:
<code>[apache]</code>
<code>httpd1.centos.com</code>
<code>httpd2.centos.com</code>
<code>[nginx]</code>
<code>ngx1.centos.com</code>
<code>ngx2.centos.com</code>
<code>[webservers:children]</code>
<code>apache</code>
<code>nginx</code>
<code>[webservers:vars]</code>
<code>ntp_server=ntp.centos.com</code>
5.2.5 inventory參數
ansible基于ssh連接配接inventory中指定的遠端主機時,還可以通過參數指定其互動方式;這些參數如下所示:
<code>ansible_ssh_host</code>
<code> </code><code>将要連接配接的遠端主機名.與你想要設定的主機的别名不同的話,可通過此變量設定.</code>
<code>ansible_ssh_port</code>
<code> </code><code>ssh</code><code>端口号.如果不是預設的端口号,通過此變量設定.</code>
<code>ansible_ssh_user</code>
<code> </code><code>預設的 </code><code>ssh</code> <code>使用者名</code>
<code>ansible_ssh_pass</code>
<code> </code><code>ssh</code> <code>密碼(這種方式并不安全,我們強烈建議使用 --ask-pass 或 SSH 密鑰)</code>
<code>ansible_sudo_pass</code>
<code> </code><code>sudo</code> <code>密碼(這種方式并不安全,我們強烈建議使用 --ask-</code><code>sudo</code><code>-pass)</code>
<code>ansible_sudo_exe (new </code><code>in</code> <code>version 1.8)</code>
<code> </code><code>sudo</code> <code>指令路徑(适用于1.8及以上版本)</code>
<code>ansible_connection</code>
<code> </code><code>與主機的連接配接類型.比如:</code><code>local</code><code>, </code><code>ssh</code> <code>或者 paramiko. Ansible 1.2 以前預設使用 paramiko.1.2 以後預設使用 </code><code>'smart'</code><code>,</code><code>'smart'</code> <code>方式會根據是否支援 ControlPersist, 來判斷</code><code>'ssh'</code>
<code>方式是否可行.</code>
<code>ansible_ssh_private_key_file</code>
<code> </code><code>ssh</code> <code>使用的私鑰檔案.适用于有多個密鑰,而你不想使用 SSH 代理的情況.</code>
<code>ansible_shell_type</code>
<code> </code><code>目标系統的shell類型.預設情況下,指令的執行使用 </code><code>'sh'</code> <code>文法,可設定為 </code><code>'csh'</code> <code>或 </code><code>'fish'</code><code>.</code>
<code>ansible_python_interpreter</code>
<code> </code><code>目标主機的 python 路徑.适用于的情況: 系統中有多個 Python, 或者指令路徑不是</code><code>"/usr/bin/python"</code><code>,比如 \*BSD, 或者 </code><code>/usr/bin/python</code>
<code> </code><code>不是 2.X 版本的 Python.我們不使用 </code><code>"/usr/bin/env"</code> <code>機制,因為這要求遠端使用者的路徑設定正确,且要求 </code><code>"python"</code> <code>可執行程式名不可為 python以外的名字(實際有可能名為</code>
<code>python26).</code>
<code> </code><code>與 ansible_python_interpreter 的工作方式相同,可設定如 ruby 或 perl 的路徑....</code>
5.3 條件測試
如果需要根據變量、facts或此前任務的執行結果來做為某task執行與否的前提時要用到條件測試。
5.3.1 when語句
在task後添加when子句即可使用條件測試;when語句支援Jinja2表達式文法。例如:
<code>tasks</code>
<code> </code><code>- name: </code><code>"shutdown Debian flavored systems"</code>
<code> </code><code>command</code><code>: </code><code>/sbin/shutdown</code> <code>-h now</code>
<code> </code><code>when: ansible_os_family == </code><code>"Debian"</code>
when語句中還可以使用Jinja2的大多“filter”,例如要忽略此前某語句的錯誤并基于其結果(failed或者sucess)運作後面指定的語句,可使用類似如下形式:
<code> </code><code>- </code><code>command</code><code>: </code><code>/bin/false</code>
<code> </code><code>register: result</code>
<code> </code><code>ignore_errors: True</code>
<code> </code><code>- </code><code>command</code><code>: </code><code>/bin/something</code>
<code> </code><code>when: result|failed</code>
<code> </code><code>- </code><code>command</code><code>: </code><code>/bin/something_else</code>
<code> </code><code>when: result|success</code>
<code> </code><code>- </code><code>command</code><code>: </code><code>/bin/still/something_else</code>
<code> </code><code>when: result|skipped</code>
此外,when語句中還可以使用facts或playbook中定義的變量。
5.4 疊代
當有需要重複性執行的任務時,可以使用疊代機制。其使用格式為将需要疊代的内容定義為item變量引用,并通過with_items語句來指明疊代的元素清單即可。例如:
<code>- name: add several </code><code>users</code>
<code> </code><code>user: name={{ item }} state=present </code><code>groups</code><code>=wheel</code>
<code> </code><code>with_items:</code>
<code> </code><code>- testuser1</code>
<code> </code><code>- testuser2</code>
上面語句的功能等同于下面的語句:
<code>- name: add user testuser1</code>
<code> </code><code>user: name=testuser1 state=present </code><code>groups</code><code>=wheel</code>
<code>- name: add user testuser2</code>
<code> </code><code>user: name=testuser2 state=present </code><code>groups</code><code>=wheel</code>
事實上,with_items中可以使用元素還可為hashes,例如:
<code> </code><code>user: name={{ item.name }} state=present </code><code>groups</code><code>={{ item.</code><code>groups</code> <code>}}</code>
<code> </code><code>- { name: </code><code>'testuser1'</code><code>, </code><code>groups</code><code>: </code><code>'wheel'</code> <code>}</code>
<code> </code><code>- { name: </code><code>'testuser2'</code><code>, </code><code>groups</code><code>: </code><code>'root'</code> <code>}</code>
六、Ansible的基本使用
1.
<code>[root@Centos ansible]</code><code># rpm -ql ansible | head</code>
<code>/etc/ansible</code>
<code>/etc/ansible/ansible</code><code>.cfg --ansible的主配置檔案</code>
<code>/etc/ansible/hosts</code> <code>--ansible的host inventory檔案</code>
<code>/etc/ansible/roles</code>
<code>/usr/bin/ansible</code> <code>--ansible的指令,實作批量部署的指令</code>
<code>/usr/bin/ansible-console</code>
<code>/usr/bin/ansible-doc</code> <code>--ansible子產品相關指令,可以擷取相關幫助</code>
<code>/usr/bin/ansible-galaxy</code>
<code>/usr/bin/ansible-playbook</code> <code>--playbook相關指令</code>
<code>/usr/bin/ansible-pull</code>
2、定義Host Inventory
<code># vim /etc/ansible/hosts </code>
<code>[webserver]</code>
<code>192.168.1.101 ansible_ssh_user=root ansible_ssh_pass=fanshine</code>
<code>192.168.1.102 ansible_ssh_user=root ansible_ssh_pass=fanshine</code>
<code>[dbserver]</code>
<code>192.168.1.110</code>
解釋 :
#ansible_ssh_user=root 是ssh登陸使用者
#ansible_ssh_pass=fanshine是ssh登陸密碼
# 注意每個子產品的用法可以使用 ansible-doc MOD 來檢視例如ansible-doc copy
ansible指令最常用的用法:
<code>ansible <host-pattern> [-f forks] [-m module_name] [-a args]</code>
<code> </code><code>args:</code>
<code> </code><code>key=value</code>
注意:command子產品要執行指令無須為key=value格式,而是直接給出要執行的指令即可;
ansible常用子產品:
<code>command</code>
<code> </code><code>-a </code><code>'COMMAND'</code>
<code>user</code>
<code> </code><code>-a </code><code>'name= state={present|absent} system= uid='</code>
<code>group</code>
<code> </code><code>-a </code><code>'name= gid= state= system='</code>
<code>cron</code>
<code> </code><code>-a </code><code>'name= minute= hour= day= month= weekday= job= user= state='</code>
<code>copy</code>
<code> </code><code>-a </code><code>'dest= src= mode= owner= group='</code>
<code>file</code>
<code> </code><code>-a </code><code>'path= mode= owner= group= state={directory|link|present|absent} src='</code>
<code>ping</code>
<code> </code><code>沒有參數</code>
<code>yum</code>
<code> </code><code>-a </code><code>'name= state={present|latest|absent}'</code>
<code>service</code>
<code> </code><code>-a </code><code>'name= state={started|stopped|restarted} enabled='</code>
<code>shell</code>
<code>script</code>
<code> </code><code>-a </code><code>'/path/to/script'</code>
<code>setup</code>
所支援的子產品可以使用ansible-doc -l來檢視.
Ansible簡單執行個體:
1.使用command子產品,檢視客戶機上的網卡資訊:
<a href="https://s1.51cto.com/wyfs02/M01/95/C1/wKiom1kZZryyQ5SXAABVR6eDP3M482.png-wh_500x0-wm_3-wmp_4-s_1810241519.png" target="_blank"></a>
2使用user子產品進行添加使用者。
<a href="https://s4.51cto.com/wyfs02/M00/95/C2/wKiom1kZaW-RbBJdAAA9FWaje2w962.png-wh_500x0-wm_3-wmp_4-s_1300130808.png" target="_blank"></a>
3.使用copy子產品進行複制。
<a href="https://s3.51cto.com/wyfs02/M01/95/C2/wKiom1kZbqOSxVNFAABmCCzp8K0874.png-wh_500x0-wm_3-wmp_4-s_1117419598.png" target="_blank"></a>
在使用copy子產品,出現以下錯誤:
<code>192.168.1.102 | FAILED! => {</code>
<code> </code><code>"changed"</code><code>: </code><code>false</code><code>, </code>
<code> </code><code>"checksum"</code><code>: </code><code>"8a7d578b4e911043538f101eae8291c428c67605"</code><code>, </code>
<code> </code><code>"failed"</code><code>: </code><code>true</code><code>, </code>
<code> </code><code>"msg"</code><code>: </code><code>"Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"</code>
<code>}</code>
<code>192.168.1.101 | FAILED! => {</code>
錯誤: "msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!"
解決: yum install -y libselinux-python
4.使用commad子產品,安裝軟體或者服務。
<a href="https://s4.51cto.com/wyfs02/M02/95/C2/wKioL1kZa1zAXDKPAABaxH6EN0k073.png-wh_500x0-wm_3-wmp_4-s_3337230063.png" target="_blank"></a>
5、支援管道的指令。raw子產品,類似于shell子產品
6.使用file子產品,建立目錄。
<a href="https://s3.51cto.com/wyfs02/M01/95/C3/wKioL1kZcw7h-9pLAAA5v0kipI4378.png-wh_500x0-wm_3-wmp_4-s_3264867734.png" target="_blank"></a>
7.使用yum子產品進行安裝服務。
<a href="https://s4.51cto.com/wyfs02/M00/95/C5/wKioL1kZfqyDgrbjAABraGkMPhA303.png-wh_500x0-wm_3-wmp_4-s_3281851267.png" target="_blank"></a>
8.使用service子產品,啟動,停止,重新開機服務。
<a href="https://s5.51cto.com/wyfs02/M02/95/C5/wKioL1kZfwCg4uHUAAA3o-e6Ivs435.png-wh_500x0-wm_3-wmp_4-s_2414036044.png" target="_blank"></a>
9.簡單的Ping指令進行各主機檢查。
<a href="https://s5.51cto.com/wyfs02/M00/95/C4/wKioL1kZeOeR0r0gAAAX3NZ7b1M884.png-wh_500x0-wm_3-wmp_4-s_2956511397.png" target="_blank"></a>
10.使用shell子產品,完成更多操作。
<a href="https://s5.51cto.com/wyfs02/M01/95/C4/wKiom1kZeiuySqU7AAAp0p-fBn8315.png-wh_500x0-wm_3-wmp_4-s_888523299.png" target="_blank"></a>
七、ansible playbooks
playbook是由一個或多個“play”組成的清單。play的主要功能在于将事先歸并為一組的主機裝扮成事先通過ansible中的task定義好的角色。從根本上來講,所謂task無非是調用ansible的一個module。将多個play組織在一個playbook中,即可以讓它們聯同起來按事先編排的機制同唱一台大戲。下面是一個簡單示例。
- 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: restart apache
service: name=httpd state=restarted
7.1 playbook基礎元件
7.1.1 Hosts和Users
playbook中的每一個play的目的都是為了讓某個或某些主機以某個指定的使用者身份執行任務。hosts用于指定要執行指定任務的主機,其可以是一個或多個由冒号分隔主機組;remote_user則用于指定遠端主機上的執行任務的使用者。如上面示例中的
-hosts: webnodes
remote_user: root
不過,remote_user也可用于各task中。也可以通過指定其通過sudo的方式在遠端主機上執行任務,其可用于play全局或某任務;此外,甚至可以在sudo時使用sudo_user指定sudo時切換的使用者。
remote_user: centos
- name: test connection
ping:
remote_user: centos
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”格式,例如:
- name: disable selinux
command: /sbin/setenforce 0
如果指令或腳本的退出碼不為零,可以使用如下方式替代:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors來忽略錯誤資訊:
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=memcached state=restarted
service: name=apache state=restarted
案例:
<code>heartbeat.yaml</code>
<code>- hosts: hbhosts</code>
<code> </code><code>remote_user: root</code>
<code> </code><code>tasks:</code>
<code> </code><code>- name: ensure heartbeat latest version</code>
<code> </code><code>yum: name=heartbeat state=present</code>
<code> </code><code>- name: authkeys configure </code><code>file</code>
<code> </code><code>copy: src=</code><code>/root/hb_conf/authkeys</code> <code>dest=</code><code>/etc/ha</code><code>.d</code><code>/authkeys</code>
<code> </code><code>- name: authkeys mode 600</code>
<code> </code><code>file</code><code>: path=</code><code>/etc/ha</code><code>.d</code><code>/authkeys</code> <code>mode=600</code>
<code> </code><code>notify:</code>
<code> </code><code>- restart heartbeat</code>
<code> </code><code>- name: ha.cf configure </code><code>file</code>
<code> </code><code>copy: src=</code><code>/root/hb_conf/ha</code><code>.cf dest=</code><code>/etc/ha</code><code>.d</code><code>/ha</code><code>.cf</code>
<code> </code><code>notify: </code>
<code> </code><code>- restart heartbeat</code>
<code> </code><code>handlers:</code>
<code> </code><code>- name: restart heartbeat</code>
<code> </code><code>service: name=heartbeat state=restarted</code>
八、roles
ansilbe自1.2版本引入的新特性,用于層次性、結構化地組織playbook。roles能夠根據層次型結構自動裝載變量檔案、tasks以及handlers等。要使用roles隻需要在playbook中使用include指令即可。簡單來講,roles就是通過分别将變量、檔案、任務、子產品及處理器放置于單獨的目錄中,并可以便捷地include它們的一種機制。角色一般用于基于主機建構服務的場景中,但也可以是用于建構守護程序等場景中。
一個roles的案例如下所示:
<code>site.yml</code>
<code>webservers.yml</code>
<code>fooservers.yml</code>
<code>roles/</code>
<code> </code><code>common/</code>
<code> </code><code>files/</code>
<code> </code><code>templates/</code>
<code> </code><code>tasks/</code>
<code> </code><code>handlers/</code>
<code> </code><code>vars/</code>
<code> </code><code>meta/</code>
<code> </code><code>webservers/</code>
而在playbook中,可以這樣使用roles:
- hosts: webservers
roles:
- common
- webservers
也可以向roles傳遞參數,例如:
- common
- { role: foo_app_instance, dir: '/opt/a', port: 5000 }
- { role: foo_app_instance, dir: '/opt/b', port: 5001 }
甚至也可以條件式地使用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子產品會自動在此目錄中尋找Jinja2模闆檔案;
handlers目錄:此目錄中應當包含一個main.yml檔案,用于定義此角色用到的各handler;在handler中使用include包含的其它的handler檔案也應該位于此目錄中;
vars目錄:應當包含一個main.yml檔案,用于定義此角色用到的變量;
meta目錄:應當包含一個main.yml檔案,用于定義此角色的特殊設定及其依賴關系;ansible 1.3及其以後的版本才支援;
default目錄:為目前角色設定預設變量時使用此目錄;應當包含一個main.yml檔案;
九、Tags
tags用于讓使用者選擇運作或路過playbook中的部分代碼。ansible具有幂等性,是以會自動跳過沒有變化的部分,即便如此,有些代碼為測試其确實沒有發生變化的時間依然會非常地長。此時,如果确信其沒有變化,就可以通過tags跳過此些代碼片斷。
十、Jinja2相關
10.1 字面量
表達式最簡單的形式就是字面量。字面量表示諸如字元串和數值的 Python 對象。下面 的字面量是可用的:
“Hello World”:
雙引号或單引号中間的一切都是字元串。無論何時你需要在模闆中使用一個字 符串(比如函數調用、過濾器或隻是包含或繼承一個模闆的參數),它們都是 有用的。
42 / 42.23:
直接寫下數值就可以建立整數和浮點數。如果有小數點,則為浮點數,否則為 整數。記住在 Python 裡, 42 和 42.0 是不一樣的。
[‘list’, ‘of’, ‘objects’]:
一對中括号括起來的東西是一個清單。清單用于存儲和疊代序列化的資料。例如 你可以容易地在 for 循環中用清單和元組建立一個連結的清單:
<ul>
{% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
('downloads.html', 'Downloads')] %}
<li><a href="` href `">` caption `</a></li>
{% endfor %}
</ul>
(‘tuple’, ‘of’, ‘values’):
元組與清單類似,隻是你不能修改元組。如果元組中隻有一個項,你需要以逗号 結尾它。元組通常用于表示兩個或更多元素的項。更多細節見上面的例子。
{‘dict’: ‘of’, ‘key’: ‘and’, ‘value’: ‘pairs’}:
Python 中的字典是一種關聯鍵和值的結構。鍵必須是唯一的,并且鍵必須隻有一個 值。字典在模闆中很少使用,罕用于諸如 xmlattr() 過濾器之類。
true / false:
true 永遠是 true ,而 false 始終是 false 。
10.2 算術運算
Jinja 允許你用計算值。這在模闆中很少用到,但是為了完整性允許其存在。支援下面的 運算符:
+
把兩個對象加到一起。通常對象是素質,但是如果兩者是字元串或清單,你可以用這 種方式來銜接它們。無論如何這不是首選的連接配接字元串的方式!連接配接字元串見 ~ 運算符。 {{ 1 + 1 }} 等于 2 。
-
用第一個數減去第二個數。 ` 3 - 2 ` 等于 1 。
/
對兩個數做除法。傳回值會是一個浮點數。 {{ 1 / 2 }} 等于 ` 0`.`5 ` 。
//
對兩個數做除法,傳回整數商。 {{ 20 // 7 }} 等于 2 。
%
計算整數除法的餘數。 {{ 11 % 7 }} 等于 4 。
*
用右邊的數乘左邊的操作數。 {{ 2 * 2 }} 會傳回 4 。也可以用于重 複一個字元串多次。 {{ ‘=’ * 80 }} 會列印 80 個等号的橫條。
**
取左操作數的右操作數次幂。 {{ 2**3 }} 會傳回 8 。
10.3 比較操作符
==
比較兩個對象是否相等。
!=
比較兩個對象是否不等。
>
如果左邊大于右邊,傳回 true 。
>=
如果左邊大于等于右邊,傳回 true 。
<
如果左邊小于右邊,傳回 true 。
<=
如果左邊小于等于右邊,傳回 true 。
10.4 邏輯運算符
對于 if 語句,在 for 過濾或 if 表達式中,它可以用于聯合多個表達式:
and
如果左操作數和右操作數同為真,傳回 true 。
or
如果左操作數和右操作數有一個為真,傳回 true 。
not
對一個表達式取反(見下)。
(expr)
表達式組。
本文轉自 SoulMio 51CTO部落格,原文連結:http://blog.51cto.com/bovin/1925802,如需轉載請自行聯系原作者