Ansible PlayBook语法
PlayBook語法實例
playbook是由一個或多個play組成的列表,play的主要功能在于將事先歸并為一組的主機裝扮成事先通過Ansible中的tasks定義好的角色(play的內容被稱為tasks,即任務),從根本上來講所謂tasks無非是調用Ansible的一個module,將多個play組織在一個playbook中即可以讓它們聯同起來按事先編排的機制一同工作.
下面來看一個基礎的playbook,其中只包含一個tasks任務:
--- - hosts: web_server #指定執行的主機組vars: #聲明了2個變量http_port: 80max_clients: 200remote_user: root #使用root權限執行tasks:- name: ensure apache is at the latest versionyum: pkg=httpd state=latest- name: write the apache config file #將apache配置文件拷貝到指定主機template: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd.confnotify: #當上面拷貝工作完成以后,執行消息發送- restart apache- name: ensure apache is running #設置開機自啟動service: name=httpd state=startedhandlers:- name: restart apache #接收消息,并執行重啟apache服務service: name=httpd state=restarted第一行中,文件開頭為---,這是YAML將文件解釋為正確的文檔的要求,YAML允許多個文檔存在于一個文件中,每個文檔由 --- 符號分割,但Ansible只需要一個文件存在一個文檔即可,因此這里需要存在于文件的開始行第一行.
YAML對空格非常敏感,并使用空格來將不同的信息分組在一起,在整個文件中應該只使用空格而不使用制表符,并且必須使用一致的間距,才能正確讀取文件,相同縮進級別的項目被視為同級元素.
以 - 開頭的項目被視為列表項目.作為散列或字典操作,它具有key:value格式的項,YAML文檔基本上定義了一個分層的樹結構,其中位于左側是包含的元素.YAML文件擴展名通常為.yaml或者.yml,接下來,我們將分別講解 playbook 語言的多個特性.
PlayBook構成部分
◆Hosts(主機)與Users(用戶)◆
我們可以為playbook中的每一個play,個別的選擇操作的目標機器是哪些,以哪個用戶身份去完成要執行的步驟(called tasks)
--- - hosts: web_serversremote_user: roottasks:- name: test connectionremote_user: yournamesudo: yesplaybook中的每一個play的目的都是為了讓某個或某些主機以某個指定的用戶身份執行任務.
| hosts | 指定要執行指定任務的主機 |
| remote_user | 指定遠程主機上的執行任務的用戶,此處的意思是以root身份執行 |
| user | 與remote_user相同 |
| sudo | 如果設置為yes執行該任務組的用戶在執行任務的時候,獲取root權限 |
| sudo_user | 指定使用那個用戶授權執行 |
| connection | 通過什么方式連接到遠程主機,默認為ssh |
| gather_facts | setup模塊默認自動執行 |
◆Tasks 和 Action◆
每一個play包含了一個tasks列表(任務列表),任務列表中的各任務按次序逐個在hosts中指定的所有主機上執行即在所有主機上完成第一個任務后再開始第二個,在自上而下運行某playbook時如果中途發生錯誤,所有已執行任務都將回滾,因此在更正playbook后重新執行即可.
每一個tasks必須有一個名稱name,這樣在運行playbook時,從其輸出的任務執行信息中可以很好的辨別出是屬于哪一個tasks的,如果沒有定義name,action的值將會用作輸出信息中標記特定的tasks.tasks的目的是使用指定的參數執行模塊,而在模塊參數中可以使用變量.模塊執行是冪等的,這意味著多次執行是安全的,因為其結果均一致.
每個tassk都應該有其name用于playbook的執行結果輸出,建議其內容盡可能清晰地描述任務執行步驟,如果未提供name則action的結果將用于輸出.
下面是一種基本的taska的定義,service moudle使用key=value格式的參數,這也是大多數module使用的參數格式:
tasks:- name: make sure apache is runningservice: name=httpd state=running[在眾多模塊中,只有command和shell模塊僅需要給定一個列表而無需使用“key=value”格式如下]tasks:- name: disable selinuxcommand: /sbin/setenforce 0[使用command module和shell module時,我們需要關心返回碼信息,如果有一條命令,它的成功執行的返回碼不是0我們可以這樣做] tasks:- name: run this command and ignore the resultshell: /usr/bin/somecommand || /bin/true[或者使用ignore_errors來忽略錯誤信息] tasks:- name: run this command and ignore the resultshell: /usr/bin/somecommandignore_errors: True[如果action行看起來太長,可以使用space(空格)或者indent(縮進)隔開連續的一行] tasks:- name: Copy ansible inventory file to clientcopy: src=/etc/ansible/hosts dest=/etc/ansible/hosts owner=root group=root mode=0644◆Handlers 發生改變后執行◆
上面我們曾提到過,module具有“冪等”性,所以當遠程主機被人改動時,可以重放playbooks達到恢復的目的.playbooks本身可以識別這種改動,并且有一個基本的event system(事件系統),可以響應這種改動.
當發生改動時notify這個actions會在playbook的每一個tasks結束時被觸發,而且即使有多個不同的tasks通知改動的發生,notify actions只會被觸發一次.這樣可以避免多次有改變發生時每次都執行指定的操作,取而代之僅在所有的變化發生完成后一次性地執行指定操作.
下面一個小例子,當一個文件的內容被改動時,重啟兩個services進程.
- name: template configuration filetemplate: src=template.conf dest=/etc/foo.confnotify:- restart memcached- restart apachehandlers也是一些tasks的列表,通過名字來引用,它們和一般的tasks并沒有什么區別handlers是由通知者進行notify,如果沒有被notify,handlers不會執行.不管有多少個通知者進行了notify,等到play中的所有tasks執行完成之后,handlers也只會被執行一次.
下面是一個 handlers 的示例:
handlers:- name: restart memcachedservice: name=memcached state=restarted- name: restart apacheservice: name=apache state=restartedHandlers最佳的應用場景是用來重啟服務,或者觸發系統重啟操作,除此以外很少用到了.
◆幾個常用小實例◆
1.通過playbook添加用戶,給遠程主機添加用戶lyshark.
--- - name: create userhosts: alluser: rootgather_facts: False #在執行命令前是否去獲取setup信息vars:- user: lysharktasks:- name: create useruser: name={{ user }}2.通過playbook刪除用戶,刪除遠程主機lyshark的賬號.
--- - name: create userhosts: alluser: rootgather_facts: Falsevars:- user: lysharktasks:- name: create useruser: name={{ user }} state=absent remove=yes3.安裝 httpd 服務,將本地準備好的配置文件 copy 過去,并且啟動服務.
--- - hosts: allremote_user: rootgather_facts: Falsetasks:- name: install apache on CentOS 7yum: name=httpd state=present- name: copy httpd confcopy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf- name: start apache serviceservice: name=httpd state=started4.通過playbook 安裝apache修改端口,并帶有vars變量.
--- - hosts: allremote_user: rootgather_facts: Falsevars:src_http_dir: /etc/httpd/confdest_http_dir: /etc/httpd/conftasks:- name: install apache on CentOS 7yum: name=httpd state=present- name: copy httpd confcopy: src={{ src_http_dir }}/httpd.conf dest={{ dest_http_dir }}/httpd.confnotify:- systemctl restart httpd- name: start apache serviceservice: name=httpd state=restartedhandlers: #當httpd.conf文件發生改變時,就觸發handler進行服務重啟.- name: restart apacheservice: name=httpd state=restartedPlayBook常用模塊
Playbook的模塊與在Ansible命令行下使用的模塊有一些不同.這主要是因為在playbook中會使用到一些facts變量和一些通過setup模塊從遠程主機上獲取到的變量,有些模塊沒法在命令行下運行,就是因為它們需要這些變量.而且即使那些可以在命令行下工作的模塊也可以通過playbook的模塊獲取一些更高級的功能.
◆template模塊◆
在實際應用中,我們的配置文件有些地方可能會根據遠程主機的配置的不同而有稍許的不同,template可以使用變量來接收遠程主機上setup收集到的facts信息,針對不同配置的主機,定制配置文件,用法大致與copy模塊相同.
| attributes | 文件或目錄的屬性 |
| backup | 如果原目標文件存在,則先備份目標文件 |
| block_end_string | 標記塊結束的字符串 |
| block_start_string | 標記塊的開始的字符串 |
| dest | 目標文件路徑 |
| follow | 是否遵循目標中的文件鏈接 |
| force | 是否強制覆蓋,默認為yes |
| group | 目標文件或目錄的所屬組 |
| owner | 目標文件或目錄的所屬主 |
| mode | 目標文件的權限 |
| newline_sequence | 指定用于模板文件的換行符序列 |
| src | 源模板文件路徑 |
| trim_blocks | 如果這設置為True,則刪除塊后的第一個換行符 |
| validate | 在復制之前通過命令驗證目標文件,如果驗證通過則復制 |
| variable_end_string | 標記打印語句結束的字符串 |
| variable_start_string | 標記打印語句開頭的字符串 |
◆set_fact模塊◆
set_fact模塊可以自定義facts,這些自定義的facts可以通過template或者變量的方式在playbook中使用,如果你想要獲取一個進程使用的內存的百分比,則必須通過set_fact來進行計算之后得出其值,并將其值在playbook中引用.
[root@localhost ~]# echo "# Configure the buffer pool" >> /etc/my.cnf [root@localhost ~]# echo "innodb_buffer_pool_size = {{ innodb_buffer_pool_size_mb|int }}M" >> /etc/my.cnf [root@localhost ~]# vim set_fact.yml --- - name: Configure Mariadbhosts: alltasks:- name: install Mariadbyum: name=mariadb-server state=installed- name: Calculate InnoDB buffer pool sizeset_fact: innodb_buffer_pool_size_mb={{ ansible_memtotal_mb / 2 }}- name: Configure Mariadbtemplate: src=/etc/my.cnf dest=/etc/my.cnf owner=root group=root mode=0644- name: Start Mariadbservice: name=mariadb state=started enabled=yeshandlers:- name: restart Mariadbservice: name=mariadb state=restarted◆pause模塊◆
在playbook執行的過程中暫停一定時間或者提示用戶進行某些操作,要為每個主機暫停、等待、休眠,可以使用wait_for模塊,如果您想提前暫停而不是設置為過期,或者您需要完全中止劇本運行.
| echo | 控制鍵入時是否顯示鍵盤輸入 |
| minutes | 暫停多少分鐘 |
| seconds | 暫停多少秒 |
| prompt | 打印一串信息提示用戶操作 |
◆wait_for模塊◆
wait_for模塊是在playbook的執行過程中,等待某些操作完成以后再進行后續操作.
| active_connection_states | 被計為活動連接的TCP連接狀態列表 |
| connect_timeout | 在下一個任務執行之前等待連接的超時時間 |
| delay | 等待一個端口或者文件或者連接到指定的狀態 |
| exclude_hosts | 在查找狀態的活動TCP連接時要忽略的主機或IP的列表drained |
| host | wait_for模塊等待的主機的地址,默認為127.0.0.1 |
| msg | 這會覆蓋正常的錯誤消息,使其不符合所需的條件 |
| port | wait_for模塊等待的主機的端口 |
| path | 文件路徑,只有當這個文件存在時,下一任務才開始執行,即等待該文件創建完成 |
| search_regex | 可以用來匹配文件或套接字連接中的字符串,默認為多行正則表達式 |
| sleep | 檢查之間睡眠的秒數,在2.3之前,這被硬編碼為1秒 |
| state | 等待的狀態,狀態有started,stoped,present或started,absent |
| timeout | wait_for的等待的超時時間,默認為300秒 |
◆assemble模塊◆
assemble模塊用于組裝文件,即將多個零散的文件(稱為碎片),合并一個目標文件.
| attributes | 文件或目錄應的屬性 |
| backup | 創建一個備份文件(如果yes),包括時間戳信息 |
| decrypt | 控制使用保管庫對源文件進行自動解密 |
| delimiter | 分隔文件內容的分隔符 |
| dest | 使用所有源文件的連接創建的文件,合并后的大文件路徑 |
| group | 合并后的大文件的所屬組 |
| owner | 合并后的大文件的所屬主 |
| ignore_hidden | 組裝時,是否忽略隱藏文件,默認為no |
| mode | 合并后的大文件的權限,指定文件權限 |
| regexp | 在regex匹配文件名時匯編文件 |
| src | 源文件(即零散文件)的路徑 |
| validate | 與template的validate相同,指定命令驗證文件 |
◆add_host模塊◆
add_host模塊使用變量在清單中創建新的主機組,以便在以后的相同劇本中使用.獲取變量以便我們可以更充分地定義新主機,add_host模塊在playbook執行的過程中,動態的添加主機到指定的主機組中.
[添加主機到webservers組中,主機的變量foo的值為42] - name: add host to group 'just_created' with variable foo=42add_host:name: "{{ ip_from_ec2 }}"groups: just_createdfoo: 42[將主機添加到多個組] - name: add host to multiple groupsadd_host:hostname: "{{ new_ip }}"groups:- group1- group2[向主機添加一個非本地端口的主機] - name: add a host with a non-standard port local to your machinesadd_host: name: "{{ new_ip }}:{{ new_port }}"[添加一個通過隧道到達的主機別名] - name: add a host alias that we reach through a tunnel (Ansible <= 1.9)add_host:hostname: "{{ new_ip }}"ansible_ssh_host: "{{ inventory_hostname }}" ansible_ssh_port: "{{ new_port }}"[添加一個通過隧道到達的主機別名] - name: add a host alias that we reach through a tunnel (Ansible >= 2.0)add_host:hostname: "{{ new_ip }}"ansible_host: "{{ inventory_hostname }}"ansible_port: "{{ new_port }}"◆group_by模塊◆
group_by模塊在playbook執行的過程中,動態的創建主機組.
[創建主機組] - group_by:key: machine_{{ ansible_machine }}[創建類似kvm-host的主機組] - group_by:key: virt_{{ ansible_virtualization_type }}_{{ ansible_virtualization_role }}[創建嵌套主機組] - group_by:key: el{{ ansible_distribution_major_version }}-{{ ansible_architecture }}parents:- el{{ ansible_distribution_major_version }}◆debug模塊◆
debug模塊在執行過程中打印語句,可用于調試變量或表達式中輸出信息.
[為每個主機打印IP地址和網關] - debug:msg: "System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}"- debug:msg: "System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}"when: ansible_default_ipv4.gateway is defined- shell: /usr/bin/uptimeregister: result- debug:var: result [直接將上一條指令的結果作為變量傳遞給var,由debug打印出result的值]verbosity: 2- name: Display all variables/facts known for a hostdebug:var: hostvars[inventory_hostname]verbosity: 4◆fail模塊◆
fail模塊用于終止當前playbook的執行,通常與條件語句組合使用,當滿足條件時,終止當前play的運行,也可以直接由failed_when取代.
[執行失敗錢打印出自定義信息] - fail:msg: "The system may not be provisioned according to the CMDB status."when: cmdb_status != "to-be-staged"PlayBook條件判斷
在有的時候play的結果依賴于變量,fact或者是前一個任務的執行結果,從而需要使用到條件語句.
◆when◆
有的時候在特定的主機需要跳過特定的步驟,例如在安裝包的時候,需要指定主機的操作系統類型,或者是當操作系統的硬盤滿了之后,需要清空文件等,可以使用when語句來做判斷.when關鍵字后面跟著的是python的表達式,在表達式中你能夠使用任何的變量或者fact,當表達式的結果返回的是false,便會跳過本次的任務.
when基本用法
--- - name: Install VIMhosts: all tasks:- name:Install VIM via yumyum: name=vim-enhanced state=installedwhen: ansible_os_family =="RedHat"- name:Install VIM via aptapt: name=vim state=installedwhen: ansible_os_family =="Debian"- name: Unexpected OS familydebug: msg="OS Family {{ ansible_os_family }} is not supported" fail=yeswhen: not ansible_os_family =="RedHat" or ansible_os_family =="Debian"條件語句還有一種用法,它還可以讓你當達到一定的條件的時候暫停下來,等待你的輸入確認.一般情況下,當ansible遭遇到error時,它會直接結束運行.那其實你可以當遭遇到不是預期的情況的時候給使用pause模塊,這樣可以讓用戶自己決定是否繼續運行任務:
- name: pause for unexpected conditionspause: prompt="Unexpected OS"when: ansible_os_family !="RedHat"在when中使用jinja2的語法
tasks:- command: /bin/falseregister: result # 將命令執行的結果傳遞給result變量ignore_errors: True # 忽略錯誤- command: /bin/somethingwhen: result|failed # 如果注冊變量的值 是任務failed則返回true- command: /bin/something_elsewhen: result|success # 如果注冊變量的值是任務success則返回true- command: /bin/still/something_elsewhen: result|skipped # 如果注冊變量的值是任務skipped則返回true- command: /bin/foowhen: result|changed # 如果注冊變量的值是任務changed則返回true - hosts: alluser: rootvars:epic: truetasks: - shell: echo "This certainly is epic!" when: epic- shell: echo "This certainly is not epic!"when: not epic如果變量不存在,則可以通過jinja2的'defined'命令跳過
tasks:- shell: echo "I've got '{{ foo }}' and am not afraid to use it!"when: foo is defined- fail: msg="Bailing out. this play requires 'bar'"when: bar is not definedwhen在循環語句中的使用方法
tasks:- command: echo {{ item }}with_items: [ 0, 2, 4, 6, 8, 10 ]when: item > 56 #在include和roles中使用when: # 在include中使用的示例:- include: tasks/sometasks.ymlwhen: "'reticulating splines' in output" # 在roles中使用的示例:- hosts: webserversroles:- { role: debian_stock_config, when: ansible_os_family == 'Debian' }◆條件導入◆
有些時候,你也許想在一個Playbook中以不同的方式做事,比如說在debian和centos上安裝apache,apache的包名不同,除了when語句,還可以使用下面的示例來解決:
--- - hosts: allremote_user: rootvars_files:- "vars/common.yml"- [ "vars/{{ ansible_os_family }}.yml", "vars/os_defaults.yml" ]tasks:- name: make sure apache is runningservice: name={{ apache }} state=running很多不同的yml文件只是包含鍵和值,如下:
[root@localhost ~]# for vars/CentOS.yml apache: httpd somethingelse: 42如果操作系統是“CentOS”,Ansible導入的第一個文件將是“vars/CentOS.yml”,緊接著是“/var/os_defaults.yml”,如果這個文件不存在.而且在列表中沒有找到,就會報錯.在Debian系統中,最先查看的將是“vars/Debian.yml”而不是“vars/CentOS.yml”,如果沒找到,則尋找默認文件“vars/os_defaults.yml”.
◆with_first_found◆
有些時候,我們想基于不同的操作系統,選擇不同的配置文件,及配置文件的存放路徑,可以借助with_first_found來解決:
- name: template a filetemplate: src={{ item }} dest=/etc/myapp/foo.confwith_first_found:- files:- {{ ansible_distribution }}.conf- default.confpaths:- search_location_one/somedir/- /opt/other_location/somedir/◆failed_when◆
failed_when其實是ansible的一種錯誤處理機制,是由fail模塊使用了when條件語句的組合效果.示例如下:
- name: this command prints FAILED when it failscommand: /usr/bin/example-command -x -y -zregister: command_resultfailed_when: "'FAILED' in command_result.stderr"我們也可以直接通過fail模塊和when條件語句,寫成如下:
- name: this command prints FAILED when it failscommand: /usr/bin/example-command -x -y -zregister: command_resultignore_errors: True- name: fail the play if the previous command did not succeedfail: msg="the command failed"when: "'FAILED' in command_result.stderr"◆changed_when◆
當我們控制一些遠程主機執行某些任務時,當任務在遠程主機上成功執行,狀態發生更改時,會返回changed狀態響應,狀態未發生更改時,會返回OK狀態響應,當任務被跳過時,會返回skipped狀態響應.我們可以通過changed_when來手動更改changed響應狀態,示例如下:
- shell: /usr/bin/billybass --mode="take me to the river"register: bass_resultchanged_when: "bass_result.rc != 2" # 只有該條task執行以后,bass_result.rc的值不為2時,才會返回changed狀態# 永遠不會報告“改變”的狀態 - shell: wall 'beep'changed_when: False # 當changed_when為false時,該條task在執行以后,永遠不會返回changed狀態PlayBook循環語句
在使用Ansible做自動化運維的時候,免不了的要重復執行某些操作,如:添加幾個用戶,創建幾個MySQL用戶并為之賦予權限,操作某個目錄下所有文件等等.好在playbook支持循環語句,可以使得某些需求很容易而且很規范的實現.
◆with_items◆
with_items是playbooks中最基本也是最常用的循環語句.
tasks: - name:Secure config filesfile: path=/etc/{{ item }} mode=0600 owner=root group=rootwith_items:- my.cnf- shadow- fstab# 或with_items:"{{ somelist }}"上面的例子說明在/etc下創建權限級別為0600,屬主屬組都是root三個文件,分別為my.cnf、shadow、fstab.
使用with_items迭代循環的變量可以是個單純的列表,也可以是一個較為復雜的數據結果,如字典類型:
◆with_nested嵌套循環◆
tasks: - name: give users access to multiple databasesmysql_user: name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs=yes password=foowith_nested:- [ 'alice', 'bob' ]- [ 'clientdb', 'employeedb', 'providerdb' ]item[0]是循環的第一個列表的值['alice','bob'].
item[1]是第二個列表的值,表示循環創建alice和bob兩個用戶,并且為其賦予在三個數據庫上的所有權限.
也可以將用戶列表事先賦值給一個變量:
tasks: - name: here, 'users' contains the above list of employeesmysql_user: name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs=yes password=foowith_nested:- "{{users}}"- [ 'clientdb', 'employeedb', 'providerdb' ]◆with_dict◆
with_dict可以遍歷更復雜的數據結構,假如有如下變量內容:
users:alice:name: Alice Appleworthtelephone: 123-456-7890bob:name: Bob Bananaramatelephone: 987-654-3210現在需要輸出每個用戶的用戶名和手機號:
tasks:- name: Print phone recordsdebug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"with_dict: "{{ users }}"◆with_fileglob文件匹配遍歷◆
可以指定一個目錄,使用with_fileglob可以循環這個目錄中的所有文件,示例如下:
tasks: - name:Make key directory file: path=/root/.sshkeys ensure=directory mode=0700 owner=root group=root - name:Upload public keys copy: src={{ item }} dest=/root/.sshkeys mode=0600 owner=root group=root with_fileglob:- keys/*.pub - name:Assemble keys into authorized_keys fileassemble: src=/root/.sshkeys dest=/root/.ssh/authorized_keysmode=0600 owner=root group=root◆with_subelement遍歷子元素◆
假如現在需要遍歷一個用戶列表,并創建每個用戶,而且還需要為每個用戶配置以特定的SSH key登錄,變量文件內容如下:
users:- name: aliceauthorized:- /tmp/alice/onekey.pub- /tmp/alice/twokey.pubmysql:password: mysql-passwordhosts:- "%"- "127.0.0.1"- "::1"- "localhost"privs:- "*.*:SELECT"- "DB1.*:ALL"- name: bobauthorized:- /tmp/bob/id_rsa.pubmysql:password: other-mysql-passwordhosts:- "db1"privs:- "*.*:SELECT"- "DB2.*:ALL"[playbook中定義如下:] - user: name={{ item.name }} state=present generate_ssh_key=yeswith_items: "`users`" - authorized_key: "user={{ item.0.name }} key='{{ lookup('file', item.1) }}'"with_subelements:- users- authorized[也可以遍歷嵌套的子列表:] - name: Setup MySQL usersmysql_user: name={{ item.0.name }} password={{ item.0.mysql.password }} host={{ item.1 }} priv={{ item.0.mysql.privs | join('/') }}with_subelements:- users - mysql.hosts◆with_sequence循環整數序列◆
with_sequence可以生成一個自增的整數序列,可以指定起始值和結束值,也可以指定增長步長. 參數以key=value的形式指定,format指定輸出的格式.數字可以是十進制、十六進制、八進制:
- hosts: alltasks:# create groups- group: name=evens state=present- group: name=odds state=present# create some test users- user: name={{ item }} state=present groups=evenswith_sequence: start=0 end=32 format=testuser%02d# create a series of directories with even numbers for some reason- file: dest=/var/stuff/{{ item }} state=directorywith_sequence: start=4 end=16 stride=2 # stride用于指定步長# a simpler way to use the sequence plugin# create 4 groups- group: name=group{{ item }} state=presentwith_sequence: count=4◆with_random_choice隨機選擇◆
從列表中隨機取一個值:
- debug: msg={{ item }}with_random_choice:- "go through the door"- "drink from the goblet"- "press the red button"- "do nothing"◆do-Util循環◆
重復執行shell模塊,當shell模塊執行的命令輸出內容包含"all systems go"的時候停止,重試5次,延遲時間10秒.retries默認值為3,delay默認值為5,任務的返回值為最后一次循環的返回結果.
- action: shell /usr/bin/fooregister: resultuntil: result.stdout.find("all systems go") != -1retries: 5delay: 10◆循環注冊變量◆
在循環中使用register時,保存的結果中包含results關鍵字,該關鍵字保存模塊執行結果的列表.
---- hosts: alltasks:- shell: echo "{{ item }}"with_items:- one- tworegister: echo變量內容如下:
TASK [command] ******************************************************* skipping: [192.168.10.20] => (item=one) skipping: [192.168.10.20] => (item=two)PLAY RECAP *********************************************************** 192.168.10.20 : ok=1 changed=0 unreachable=0 failed=0遍歷注冊變量的結果:
- name: Fail if return code is not 0fail:msg: "The command ({{ item.cmd }}) did not have a 0 return code"when: item.rc != 0with_items: "`echo`.`results`"◆with_together遍歷數據并行集合◆
- hosts: allremote_user: rootvars:alpha: [ 'a','b','c','d']numbers: [ 1,2,3,4 ]tasks:- debug: msg="{{ item.0 }} and {{ item.1 }}"with_together:- "{{ alpha }}"- "{{ numbers }}"輸出執行結果如下:
ok: [192.168.10.20] => (item=[u'a', 1]) => {"changed": false,"item": ["a",1],"msg": "a and 1" } ok: [192.168.10.20] => (item=[u'b', 2]) => {"changed": false,"item": ["b",2],"msg": "b and 2" } ok: [192.168.10.20] => (item=[u'c', 3]) => {"changed": false,"item": ["c",3],"msg": "c and 3" } ok: [192.168.10.20] => (item=[u'd', 4]) => {"changed": false,"item": ["d",4],"msg": "d and 4" }PlayBook部署實驗
Ansible的PlayBook文件格式為YAML語言,所以希望讀者在編寫PlayBook前對YAML語法有一定的了解,否則在運行PlayBook的時候經常碰到語法錯誤提示,這里我們通過介紹批量部署apache服務為例,介紹一下apache.yaml這個PlayBook的具體應用寫法,如果你對YAML語言沒有了解的話,請自行去百度學習.
1.首先在當前目錄下創建一個目錄,用來保存與apache相關的配置文件和程序,這里要注意的是,我們應該在本機搭建一個環境,調試好后再進行部署,調試環節此處略過.
[root@localhost ~]# mkdir playbook[root@localhost ~]# ll total 0 drwxr-xr-x. 2 root root 6 Dec 2 06:43 playbook[root@localhost playbook]# cp -a /etc/httpd/conf/httpd.conf ./ [root@localhost playbook]# cp -a /var/www/html/index.html ./ [root@localhost playbook]# ls -l total 16 -rw-r--r--. 1 root root 11755 Dec 2 06:46 httpd.conf -rw-r--r--. 1 root root 15 Dec 2 06:44 index.html2.通過編寫一個apache.yaml劇本,來實現批量部署的案例,這里是Yum安裝所以很簡單,首先我們先來看一下這個PlayBook的代碼:
[root@localhost playbook]# cat apache.yaml1 --- #表示該文件是YAML文件,非必需2 - hosts: all #playbook針對的主機,all表示所有3 tasks: #表示一個集合4 - name: Install httpd #說明信息,安裝httpd服務5 yum: name=httpd state=present #通過YUM模塊安裝信息67 - name: Copy httpd.conf #說明信息,復制配置文件8 template: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf owner=root group=root mode=0755910 - name: Copy index.html #說明文件,復制網頁目錄11 template: src=./index.html dest=/var/www/html/index.html owner=root group=root mode=075512 notify: #發送消息,當上一條語句執行完畢后,執行下面的模塊13 - Restart Apache Server1415 handlers: #消息發送到這里,指定主機執行模塊16 - name: Restart Apache Server #與上面的notify內容相對應17 service: name=httpd state=restarted #重啟httpd服務3.當我們配置完成YAML劇本以后,再來配置一個Inventory的hosts主機文件,也就是指定要執行此操作的主機列表,此處我們定義以下主機列表:
[root@localhost playbook]# cat hosts[apache] #指定Apache這個組,組中有成員192.168.10.20/30兩個IP 192.168.10.20 192.168.10.30#[test] #192.168.10.1..100 #也可以這樣指定一個范圍 #192.168.10.1[0:100] #也可以這樣寫[apache:vars] #指定我們使用的Python解釋器路徑 ansible_python_interpreter=/usr/bin/python2.74.接下來我們對apache.yaml使用 --syntax-check 命令參數,檢查一下PlayBook語法是否正確:
[root@localhost playbook]# ansible-playbook apache.yaml --syntax-checkplaybook: apache.yaml5.緊接著使用--list-task參數顯示apache.yaml,PlayBook文件中所有的task名稱如下所示:
[root@localhost playbook]# ansible-playbook apache.yaml --list-taskplaybook: apache.yamlplay #1 (all): all TAGS: []tasks:Install httpd TAGS: []Copy httpd.conf TAGS: []Copy index.html TAGS: []5.緊接著使用--list-hosts參數顯示apache.yaml,PlayBook文件中所有的task名稱如下所示:
[root@localhost playbook]# ansible-playbook apache.yaml --list-hostsplaybook: apache.yamlplay #1 (all): all TAGS: []pattern: [u'all']hosts (2):192.168.10.20192.168.10.306.確認過以后,直接使用下面的命令一鍵部署,我們寫好的PlayBook劇本,此時我們等它一會.
[root@localhost playbook]# ansible-playbook -i hosts apache.yamlPLAY RECAP ****************************************************************************** 192.168.10.20 : ok=5 changed=4 unreachable=0 failed=0 192.168.10.30 : ok=5 changed=4 unreachable=0 failed=0當然playbook還支持交互式地執行 task 我們可以指定 -step 參數即可,apache.yaml 是一個相對簡單的 Playbook 文件,在我們的實際工作中可能會遇到各種復雜的需求,但 Playbook 的靈活性非常強大,下面我們來看幾個常用參數,如下:
--- - hosts: 192168.10.10:192.168.10.100 #指定一個主機執行范圍patternsremote_user: root #指定遠程SSH認證用戶sudo: yes #啟用Sudo操作sudo_user: lyshark #指定Sudo的用戶gather_facts: no #設置facts信息收集accelerate: no #設置accelerate模式accelerate_port: 5099 #設置accelerate端口max_fail_percentage: 30 #設置失敗百分比connection: local #設置遠程連接方式serial: 15 #設置變量Ansible 的 playbook 寫法很豐富,功能很強大,只有掌握了 playbook 每一個參數之后,我們才能寫出強大而且靈活性很高的 Playbook ,這也是我們在工作中接觸和使用最多的地方.
總結
以上是生活随笔為你收集整理的Ansible PlayBook语法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 听说火狐浏览器的图标里没了狐狸,网友们开
- 下一篇: 新概念英语3完美笔记doc版