日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ansible基础-playbooks

發(fā)布時(shí)間:2025/7/25 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ansible基础-playbooks 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?1. playbooks介紹

如果說ansible的modules是工具,inventory配置文件是原材料,那么playbook就是一封說明書,這里會(huì)記錄任務(wù)是如何如何執(zhí)行的,當(dāng)然如果你愿意,這里也可以定義一些變量、連接參數(shù)等等。

playbook可以由單個(gè)或者多個(gè)play組成。

單個(gè)play示例:

--- - hosts: webserversvars:http_port: 80max_clients: 200remote_user: roottasks:- name: ensure apache is at the latest versionyum:name: httpdstate: latest- name: write the apache config filetemplate:src: /srv/httpd.j2dest: /etc/httpd.confnotify:- restart apache- name: ensure apache is runningservice:name: httpdstate: started

上面的示例中所有的任務(wù)作用于webservers所包含的主機(jī),通過root用戶連接到目的主機(jī),對(duì)apache服務(wù)進(jìn)行了安裝、配置、啟動(dòng)等操作,當(dāng)配置文件有更改時(shí),會(huì)觸發(fā)hanlders里的重啟apache操作,vars里定義的“http_port”和 “ max_clients”將會(huì)在模版文件“/srv/httpd.j2”中遵循Jinja2語法被使用到。

playbooks是使用yaml語法格式,所以看起來比較通俗易懂。通過上面的示例可以看出一個(gè)play可以包含如下內(nèi)容:

  • hosts:主機(jī)組,后面定義的task將作用于該主機(jī)組的所有主機(jī)
  • vars:變量定義,在后面的task中可以引用
  • remote-user:連接參數(shù),例如remote-user,become,become-user等等,這些參數(shù)將會(huì)覆蓋ansible.cfg配置文件里的參數(shù)
  • tasks:任務(wù),可以看作很多modules的集合,這些modules可以使用vars定義的變量
  • handlers:觸發(fā)才會(huì)執(zhí)行的task,很多情況下,當(dāng)其他task被執(zhí)行并且狀態(tài)有改變后,我們希望會(huì)觸發(fā)一些任務(wù),那些被觸發(fā)的任務(wù)可以寫在這里

一個(gè)playbooks也可以編寫多個(gè)play,示例如下:

--- - hosts: webserversremote_user: roottasks:- name: ensure apache is at the latest versionyum:name: httpdstate: latest- name: write the apache config filetemplate:src: /srv/httpd.j2dest: /etc/httpd.conf - hosts: databasesremote_user: roottasks:- name: ensure postgresql is at the latest versionyum:name: postgresqlstate: latest- name: ensure that postgresql is startedservice:name: postgresqlstate: started?

上面的示例中,第一個(gè)play通過root用戶連接到webservers主機(jī)組,進(jìn)行了apache服務(wù)的安裝和配置操作;第二個(gè)play通過root用戶鏈接到databases主機(jī)組,進(jìn)行了數(shù)據(jù)庫的安裝和啟動(dòng)操作。

2.可重復(fù)利用的playbooks

上一章節(jié)中我們說到,一個(gè)playbooks可以放置多個(gè)play,一個(gè)play里面可以有多個(gè)tasks(modules),但是,當(dāng)要管理的資源越來越多時(shí),我們發(fā)現(xiàn)將所有play都寫在一個(gè)yml文件里會(huì)很臃腫,不好維護(hù)。

此時(shí)我們可以通過“import_playbook”方法引用其他的playbooks文件;

此時(shí)我們可以通過“import_playbook”方法引用其他的playbooks文件;使用“import_tasks”、“include_tasks”、“import_role”、“include_role”、“roles”引用其他的tasks文件。

import_playbook

比較簡單,直接上示例,文件main.yml:

- import_playbook: webservers.yml - import_playbook: databases.yml

上述示例中使用import_playbook將webservers.yml和databases.yml文件里的play引用到main.yml,和直接將兩個(gè)文件里的內(nèi)容直接粘過來是一樣的效果,執(zhí)行順序自然也會(huì)按照play定義的順序執(zhí)行。

import_tasks和include_tasks

可以參考筆者之前寫的文章?ansible中include_tasks和import_tasks

import_role和include_role

ansible2.3引入了include_role,ansible 2.4版本后,新增了import_role,通過這兩個(gè)方法可以在tasks里面導(dǎo)入role,示例如下:

--- - hosts: webserverstasks:- debug:msg: "before we run our role"- import_role:name: example- include_role:name: example- debug:msg: "after we ran our role"

從上面的示例可以看出,在tasks中使用import_role和include_role方法導(dǎo)入了role example,role里面的task會(huì)按順序執(zhí)行。

?當(dāng)然我們也可以引用的同時(shí)定義變量:

--- - hosts: webserversroles:- common- role: foo_app_instancevars:dir: '/opt/a'app_port: 5000- role: foo_app_instancevars:dir: '/opt/b'app_port: 5001

也可以給role打tag:

--- - hosts: webserverstasks:- import_role:name: footags:- bar- baz

使用條件語句(后面有詳細(xì)寫when語句用法):

--- - hosts: webserverstasks:- include_role:name: some_rolewhen: "ansible_os_family == 'RedHat'"

roles

除了使用import_role和include_role導(dǎo)入role,我們也可以直接使用roles方法來導(dǎo)入,示例如下:

--- - hosts: webservers roles: - common - webservers ###OR - hosts: webservers roles: - role: '/path/to/my/roles/common'?

和import和include方法相比,roles方法是僅僅可以導(dǎo)入role類型的playbook,而上述兩個(gè)方法可以在其他tasks中穿插一些role類型的playbook。

在生產(chǎn)中,roles是比較常用的所以后面的章節(jié)會(huì)有對(duì)roles的單獨(dú)講解,這里就不在展開了。

通過以上的總結(jié),我們可以看出,在ansible里,如果我們想復(fù)用其他文件的playbooks,可以使用include、import、roles三種方法,據(jù)我所知也只有這三種方法。?

2.1 動(dòng)態(tài)和靜態(tài)

至此,我們知道了可以使用import*和include*導(dǎo)入其他的playbooks,那么這兩者的區(qū)別是什么呢?

在ansible 2.4版本中引入了dynamic和static的概念,在這之前只能使用include來導(dǎo)入其他的tasks文件,現(xiàn)在include也能用,但官方在考慮在未來版本廢棄掉。

靜態(tài)指所有import*的方法,動(dòng)態(tài)指include*的方法。

關(guān)于動(dòng)態(tài)和靜態(tài)的兩點(diǎn)區(qū)別,總結(jié)如下:

  • import_tasks(Static)方法會(huì)在playbooks解析階段將父task變量和子task變量全部讀取并加載
  • include_tasks(Dynamic)方法則是在執(zhí)行play之前才會(huì)加載自己變量
  • include_tasks方法調(diào)用的文件名稱可以加變量
  • import_tasks方法調(diào)用的文件名稱不可以有變量

具體介紹可以參考筆者之前寫的文章ansible中include_tasks和import_tasks

3.playbooks變量

3.1定義變量

ansible中可以定義變量的地方可以有很多,在這里主要寫下playbooks里面的變量定義,其他部分的變量會(huì)在后續(xù)的“ansible基礎(chǔ)-變量”詳細(xì)闡述。?

變量的定義通常使用YAML語法格式,示例如下:

--- vars:field1: one 字典變量: --- foo:field1: onefield2: two

play中定義全局變量

--- - hosts: webserversvars:http_port: 80

上面示例中 http_port參數(shù)可以在這個(gè)play中的tasks、playbooks、roles中引用。

tasks中定義變量

當(dāng)然,我們也可以在某個(gè)task中定義局部變量,這個(gè)變量只能在本task內(nèi)使用,示例如下:

--- - hosts: node1gather_facts: falsetasks:- name: Use var debugvars:- name: weimeng- age: 26debug:var: name,age

include和import中定義變量

include_role定義變量只在被引用的role中生效:

- hosts: node1gather_facts: falsetasks:- include_role:name: role_Avars:age: 24

include_tasks定義變量只在被引用的task中生效:

tasks: - import_tasks: wordpress.ymlvars:wp_user: timmy - import_tasks: wordpress.ymlvars:wp_user: alice - import_tasks: wordpress.ymlvars:wp_user: bob

roles中定義變量

playbook引用role也可以直接定義變量,示例如下:

--- - hosts: webserversroles:- role: bartags: ["foo"]# using YAML shorthand, this is equivalent to the above- { role: foo, tags: ["bar", "baz"] }

注冊變量

在playbook中,我們可以將一個(gè)task的執(zhí)行結(jié)果注冊為一個(gè)變量,供另外一個(gè)task使用。例如:

--- - hosts: webserversroles:- role: bartags: ["foo"]# using YAML shorthand, this is equivalent to the above- { role: foo, tags: ["bar", "baz"] }

將一個(gè)task的結(jié)果注冊為一個(gè)變量,然后通過這個(gè)變量判斷另外一個(gè)task是否執(zhí)行,這是注冊變量很常用的方式。

通過命令行定義變量

在我們執(zhí)行playbook時(shí)可以在命令行中指定自定義變量,例如:

ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo”

在同一個(gè)scope內(nèi),如果與其他地方的變量沖突,命令行指定的參數(shù)優(yōu)先級(jí)最高。

3.2引用變量文件

上面介紹了在playbook中如何定義變量,那么變量能否和task一樣定義在單獨(dú)的yml文件內(nèi),然后使用類似于include_tasks的語句引用過來呢? 答案是肯定的。

在playbook內(nèi)引用變量文件使用的是vars_files:語句,示例如下:

--- - hosts: allremote_user: rootvars:favcolor: bluevars_files:- /vars/external_vars.ymltasks:- name: this is just a placeholdercommand: /bin/echo foo

在變量文件/vars/external_vars.yml中,我們只需要使用YAML語法格式進(jìn)行變量定義即可。

3.3 facts

除了我們自定義的變量,ansible還支持另外一種變量,這個(gè)變量類似于puppet的facter,ansible叫做fact。

ansible的fact會(huì)根據(jù)目的主機(jī)的系統(tǒng)信息生成一個(gè)json格式的變量集合,我們在play中可以直接引用。例如比較常用的變量:ip地址、主機(jī)名、操作系統(tǒng)類型等等。

puppet的facter依賴ruby的一個(gè)安裝包,通過ruby程序收集系統(tǒng)信息,而ansible的fact是通過python程序收集。

我們可以通過setup模塊來獲取目的主機(jī)的fact信息:

ansible hostname -m setup

fact會(huì)在playbook執(zhí)行之前收集信息,默認(rèn)是打開的,我們也可以通過指定gather_fact參數(shù)為false/no/False關(guān)閉fact。在沒有配置fact cache的情況下,如果關(guān)閉fact,playbook的執(zhí)行速度會(huì)有一個(gè)顯著的提升,示例如下:

--- - hosts: whatevergather_facts: no

3.4變量的使用

前面我們介紹了下變量的定義/引用方式和fact變量,那么在playbook中我們?nèi)绾问褂眠@些變量呢?

變量通常會(huì)在模版、條件判斷語句、新的變量定義等處能用到。

使用變量的方法很簡單,只需要將變量寫在兩個(gè)大括號(hào)內(nèi)并且前后都有空格即可,同時(shí)我們必須將這個(gè)大括號(hào)用雙引號(hào)引起來,如果變量穿插在字符串內(nèi)使用,雙引號(hào)也要將字符串部分引起來。

示例如下:

- hosts: app_serversvars:app_path: "{{ base_path }}/22"

如果一個(gè)變量定義比較復(fù)雜,例如列表、字典或fact(json格式),我們可以通過如下方式訪問:

列表變量訪問:

{{ foo[0] }}

字典變量訪問:?

{{ foo[name] }}?

{{ foo.name }}

json格式訪問變量訪問:

{{ansible_eth0["ipv4"]["address"] }}

{{ansible_eth0.ipv4.address }}

這里說一個(gè)小技巧,在我們排錯(cuò)過程中很多情況我們要debug一些變量。此時(shí),可以使用debug模塊輸出變量。

debug模塊有兩種使用方式,vars和msg :

--- - hosts: node1gather_facts: falsevars:- name: weimeng- age: 26tasks:- name: Use var debugdebug:var: name,age- name: Use msg debugdebug:msg: "my name is {{ name }},and my age is {{ age }}"

輸入如下:

? lab-ansible ansible-playbook playbooks/task_vars.yml[WARNING]: Found variable using reserved name: namePLAY [node1] *******************************************************************TASK [Use var debug] *********************************************************** ok: [node1] => {"name,age": "(u'weimeng', 26)" }TASK [Use msg debug] *********************************************************** ok: [node1] => {"msg": "my name is weimeng,and my age is 26" }PLAY RECAP ********************************************************************* node1 : ok=2 changed=0 unreachable=0 failed=0

通過對(duì)比我們可以看出,“vars”適用于直接debug變量,而“msg”可以摻雜一些字符串,我們可以根據(jù)實(shí)際情況來選擇使用。

本章節(jié)主要介紹了playbook的相關(guān)變量。ansible變量的知識(shí)點(diǎn)還是很多的,所以我計(jì)劃在后邊會(huì)單獨(dú)介紹ansible的變量,這里就點(diǎn)到為止。

4. 條件語句

ansible條件語句不是很多,比較常用的就是when語句和循環(huán)語句。

當(dāng)滿足一定的條件時(shí),我們想要跳過某個(gè)task,這時(shí)候when語句出場了。當(dāng)when語句的參數(shù)為true時(shí),才會(huì)執(zhí)行這個(gè)task,否則反之。

yum模塊的name可以以列表的形式指定多個(gè)安裝包,但是很多其他模塊是不支持列表的,例如file的path,copy的src,等等;或者說我們想迭代的將一個(gè)列表元素傳遞給某個(gè)模塊處理,如果有多少個(gè)元素寫多個(gè)task就很麻煩。此時(shí)我們可以使用ansible的循環(huán)語句loop(ansible 2.5以后),在2.5版本之前可以使用with_,loop類似于舊版本的with_list語句。

?4.1 when語句

ansible的when語句用于判斷是否執(zhí)行這個(gè)task,例如

tasks:- name: "shut down Debian flavored systems"command: /sbin/shutdown -t nowwhen: ansible_os_family == "Debian"# note that Ansible facts and vars like ansible_os_family can be used# directly in conditionals without double curly braces

示例中如果系統(tǒng)的類型是“Debian”才會(huì)執(zhí)行/sbin/shutdown -t now命令。?

條件語句也可以使用“and”和“or”:

tasks:- name: "shut down CentOS 6 and Debian 7 systems"command: /sbin/shutdown -t nowwhen: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6") or(ansible_distribution == "Debian" and ansible_distribution_major_version == "7")

條件也可以寫成列表的形式,這種形式和and語句起到一樣的效果:

tasks:- name: "shut down CentOS 6 systems"command: /sbin/shutdown -t nowwhen:- ansible_distribution == "CentOS"- ansible_distribution_major_version == "6"

register變量條件語句

通過對(duì)某個(gè)task的執(zhí)行結(jié)果是否成功,決定另外一個(gè)task是否要執(zhí)行:

tasks:- command: /bin/falseregister: resultignore_errors: True- command: /bin/somethingwhen: result is failed# In older versions of ansible use ``success``, now both are valid but succeeded uses the correct tense.- command: /bin/something_elsewhen: result is succeeded- command: /bin/still/something_elsewhen: result is skipped

變量是否被定義語句:

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 undefined

4.2 循環(huán)語句

上面說到loop類似于舊版本的with_list語句,也就是說loop會(huì)將列表的元素逐個(gè)傳遞給上面的module,從而達(dá)到重復(fù)執(zhí)行的目的。

最簡單的形式:

--- tasks:- command: echo { item }loop: [ 0, 2, 4, 6, 8, 10 ]

loop與when結(jié)合使用:

--- tasks: - command: echo { item } loop: [ 0, 2, 4, 6, 8, 10 ] when: item > 5

通常loop語句會(huì)結(jié)合各式各樣的filter去使用,例如“ ?loop: “{ { [\'alice\', \'bob\'] |product([\'clientdb\', \'employeedb\', \'providerdb\'])|list }}””,這個(gè)例子和with_nested語句起到一樣的效果。也就是說舊版本的with_ + lookup() 所能實(shí)現(xiàn)的,新版本的loop+filter同樣能實(shí)現(xiàn)。

5. 執(zhí)行順序

一般playbook里的task執(zhí)行順序和python一樣,由上至下,定義的順序即執(zhí)行的順序。同樣的,使用include*和import*導(dǎo)入playbook或tasks也會(huì)安照導(dǎo)入順序執(zhí)行。

5.1 per_tasks和post_tasks

當(dāng)playbook中有使用roles導(dǎo)入task和自定義tasks時(shí),我們會(huì)發(fā)現(xiàn)ansible總會(huì)先執(zhí)行roles導(dǎo)入的task,然后執(zhí)行自定義的tasks,例如:

- hosts: localhostgather_facts: novars:- ff: 1- gg: 2tasks:- debug:var: ffroles:- role: role_B?

輸出結(jié)果:

? lab-ansible ansible-playbook playbooks/roles_vars.ymlPLAY [localhost] ***************************************************************TASK [role_B : debug] ********************************************************** ok: [localhost] => {"a": 2 }TASK [debug] ******************************************************************* ok: [localhost] => {"ff": 1 }PLAY RECAP ********************************************************************* localhost : ok=2 changed=0 unreachable=0 failed=0

從上面示例發(fā)現(xiàn),雖然我們將tasks定義在了前面,但是tasks任務(wù)還是在roles任務(wù)之后執(zhí)行。此時(shí)我們可以使用pre_task和post_task來強(qiáng)制指定執(zhí)行順序,例如:

--- - hosts: localhostgather_facts: novars:- ff: 1- gg: 2pre_tasks:- import_role:name: role_Avars:age: 23roles:- role: role_Btasks:- debug:var: ffpost_tasks:- debug:var: gg

總結(jié)下playbook里任務(wù)的執(zhí)行順序:

  • 使用“pre_tasks:”定義的任務(wù)

  • 使用“roles:”引用的任務(wù)

  • 使用“tasks:”自定義的任務(wù)

  • 使用“post_tasks”定義的任務(wù)

5.2 handlers

在部署應(yīng)用時(shí),通常的步驟是安裝軟件包==>更改配置文件==>初始化數(shù)據(jù)庫==>啟動(dòng)(重啟)服務(wù);升級(jí)的步驟一般是:升級(jí)軟件包==>更改配置文件==>初始化數(shù)據(jù)庫==>重啟服務(wù)。我們發(fā)現(xiàn)不管是新部署還是升級(jí),最后一步都是要重新加載程序的,也就是說當(dāng)我們升級(jí)了軟件或者更改了配置文件都需要重啟一下應(yīng)用。

為了實(shí)現(xiàn)觸發(fā)服務(wù)重啟,ansible使用handlers方法定義重啟的動(dòng)作,handlers并不是每次執(zhí)行playbook都會(huì)觸發(fā),而是某些指定資源狀態(tài)改變時(shí)才會(huì)觸發(fā)指定的handlers(這里使用“資源”一詞借鑒于puppet)。

示例如下:

- name: template configuration filetemplate:src: template.j2dest: /etc/foo.confnotify:- restart memcached- restart apache

上面的示例中,當(dāng)/etc/foo.conf文件內(nèi)容有改動(dòng)時(shí)(返回changed),會(huì)觸發(fā)重啟memcached和apache服務(wù),如果文件內(nèi)容沒有變化時(shí)(返回ok),則不會(huì)觸發(fā)handlers。

ansible執(zhí)行過程中并不會(huì)立即觸發(fā)handlers動(dòng)作,而是以play為單位,一個(gè)play執(zhí)行完后最后才會(huì)觸發(fā)handlers。

這樣設(shè)計(jì)也是很合理的,試想在一個(gè)play內(nèi),如果觸發(fā)一次就執(zhí)行一次handlers,那么除了最后一次的重啟,前面觸發(fā)的重啟都是無用功。

另外需要注意的一點(diǎn)是,handlers觸發(fā)的執(zhí)行順序是按照定義順序執(zhí)行,而不是按照notify指定的順序執(zhí)行。

當(dāng)然如果我們想要立即觸發(fā),也是可以的,在play定義“- meta: flush_handlers”即可。

另外需要注意的一點(diǎn)是,handlers觸發(fā)的執(zhí)行順序是按照定義順序執(zhí)行,而不是按照notify指定的順序執(zhí)行。

6.參考鏈接?

  • https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html#
  • https://docs.ansible.com/ansible/2.6/user_guide/playbooks_variables.html
  • https://docs.ansible.com/ansible/2.6/user_guide/playbooks_reuse.html
  • https://docs.ansible.com/ansible/2.6/user_guide/playbooks_templating.html
  • https://docs.ansible.com/ansible/2.6/user_guide/playbooks_conditionals.html
  • https://docs.ansible.com/ansible/2.6/user_guide/playbooks_loops.html

?

歡迎大家關(guān)注我的公眾號(hào):

轉(zhuǎn)載于:https://www.cnblogs.com/mauricewei/p/10053649.html

總結(jié)

以上是生活随笔為你收集整理的ansible基础-playbooks的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。