3.1 Ansible 的配置
3.1.1 可以配置什么
安裝好Ansible后,通過 /etc/ansible/ansible.cfg 文件的內(nèi)容和注釋可以了解到所有可以配置的選項(xiàng)顶捷,下面距離我們常用的配置
#可以配置主機(jī)清單文件 inventory达椰、extra模塊放置的路徑 library翰蠢、遠(yuǎn)程主機(jī)的臨時(shí)目錄 remote_tmp,以及管理節(jié)點(diǎn)上的臨時(shí)目錄 local_tmp
inventory = /etc/ansible/hosts
library = /usr/share/my_modules/
remote_tmp = ~/.ansible/tmp
local_tmp = ~/.ansible/tmp
# 可以配置連接端口號(hào) accelerate_port啰劲、超時(shí)時(shí)間等
accelerate_port = 5099
accelerate_timeout = 30
accelerate_connect_timeout = 5.0
3.1.2 Ansible 配置文件的優(yōu)先級(jí)
優(yōu)先級(jí)從高到低的排序
- ANSIBLE_CONFIG 配置的環(huán)境變量
- 當(dāng)前目錄的ansible.cfg
- 家目錄下的 .ansible.cfg
- /etc/ansible/ansible.cfg
3.2 主機(jī)清單
主機(jī)清單(Host Inventory)梁沧,它告訴Ansible 需要管理哪些主機(jī),以及這些主機(jī)的分類和分組信息的文件蝇裤⊥⒅В可以認(rèn)為這是個(gè)文件版的CMDB系統(tǒng)。
Inventory的默認(rèn)文件為 /etc/ansible/hosts 栓辜,可以通過 /etc/ansible/ansible.cfg 配置文件進(jìn)行修改恋拍。此外,我們還可以通過 -i 參數(shù)來指定主機(jī)清單配置文件
ansible-playbook -i test.ini site.yml
當(dāng)然我們也可以使用 --inventory-file 參數(shù)來進(jìn)行指定藕甩。
3.2.1 遠(yuǎn)程主機(jī)的分組
在inventory文件中施敢,可以通過 "[]" 符號(hào)給主機(jī)做分組。此外狭莱,分組還支持嵌套僵娃,如下。
mail.example.com
#簡(jiǎn)單的分組
[db]
one.example.com
two.example.com
[web]
www[01:50].example.com
#嵌套分組
[linuxserver:children]
db
web
3.2.2 設(shè)置連接參數(shù)
Ansible 可以在Inventory 文件中指定主機(jī)的連接參數(shù)腋妙,包括連接的方法默怨、用戶等。在Inventory中設(shè)置鏈接的參數(shù)如下辉阶,用空格分割多個(gè)參數(shù)
[targets]
localhost ansible_connect=local
other1.example.com ansible_connect=ssh ansible_user=root
other1.example.com ansible_connect=ssh ansible_user=pangcm
其他常用的連接參數(shù)如下
連接參數(shù)的值 | 連接參數(shù)的含義 |
---|---|
ansible_connection | SSH的連接方式先壕,可以指定為 smart、ssh或者paramiko |
ansible_host | Ansible連接的主機(jī)地址谆甜,如果你要在Ansible中給主機(jī)起了一個(gè)不同的別名垃僚,那么需要使用這個(gè)參數(shù) |
ansible_port | SSH端口號(hào),默認(rèn)為22 |
ansible_user | SSH連接時(shí)默認(rèn)的用戶名 |
ansible_ssh_pass | SSH連接時(shí)使用的密碼规辱,不建議用本參數(shù)存儲(chǔ)明文密碼谆棺,盡量使用values對(duì)密碼進(jìn)行加密存儲(chǔ) |
ansible_ssh_private_key_file | 基于key的SSH連接,使用的是private key 文件 |
ansible_ssh_common_args | 通過配置本參數(shù)指定SFTP、SCP和SSH默認(rèn)的額外參數(shù) |
以上的參數(shù)除了能夠在Inventory文件中定義改淑,還可以在playbook中定義或者通過變量的方式傳入碍岔。
3.2.3 變量
Anible 支持在主機(jī)清單文件中指定變量,或者與主機(jī)清單文件同目錄的特定子目錄和文件中定義變量
- 主機(jī)清單文件中的變量
#為單個(gè)主機(jī)指定變量
[app]
host1 http_port=80
host2 http_port=81
#為一個(gè)組指定變量
[app:vars]
http_port=80
- 按目錄結(jié)果存儲(chǔ)的變量
假設(shè)主機(jī)清單文件為 /etc/ansible/hosts朵夏,那么相關(guān)的Host和Group變量可以放在 /etc/ansible/host_vars 和 /etc/ansible/group_vars 下同名目錄中的文件蔼啦,通常使用 yaml 文件。如下:
#host1的變量
/etc/ansible/host_vars/host1.yml
#app組的變量
/etc/ansible/group_vars/app.yml
這時(shí)候yaml文件存放的變量格式為 key:value 的形式仰猖,如下
---
hppt_port: 80
如果你的變量非常多捏肢,多到一個(gè)文件都存不下。那么你可以在同名目錄下分開多個(gè)文件來存放變量饥侵,如下:
#host1的變量
/etc/ansible/host_vars/host/vars1.yml
/etc/ansible/host_vars/host/vars2.yml
3.3 Ansible 的腳本Playbook
3.3.1 Playbook的文件格式 YAML
Playbook是ANsible的腳本語言鸵赫,使用的YAML格式。YAML和JSON類似躏升,是一種數(shù)據(jù)表示格式辩棒,下面介紹一些關(guān)于YAML語言的基本知識(shí)。
# 文件開始符
---
# 數(shù)組list
- element1
- element2
- element3
#字典
key: value
#字典的嵌套
pangcm:
name: pangcm
job: ops
skill: ansible
# 字典和數(shù)組的嵌套
- pangcm1:
name: pangcm1
job: ops
skills:
- ansible
- linux
- python
- pangcm2:
name: pangcm2
job: ops
skills:
- ansible
- linux
- python
需要注意的地方膨疏,變量里面如果有冒號(hào) ":" 時(shí)需要加上引號(hào)一睁,變量以 "{" 開頭時(shí)也要加上引號(hào)
foo: "foo:bar"
foo: "{{ variable }}"
3.3.2 執(zhí)行Playbook的命令
執(zhí)行Playbook需要使用單獨(dú)的命令: ansible-playbook,常用的使用方法如下
# 基本使用方法
ansible-playbook deploy.yaml
# 查看輸出西街
ansible-playbook deploy.yaml -v
# 查看腳本會(huì)影響哪些主機(jī)
ansible-playbook deploy.yaml --list-hosts
# 并行執(zhí)行腳本(默認(rèn)的并發(fā)數(shù)量為5)
ansible-playbook deploy.yaml -f 10
3.3.3 Playbook 的基本語法
最基本的Playbok腳本分為三個(gè)部分:
- 在什么機(jī)器以什么身份執(zhí)行
- hosts
- user
- 執(zhí)行的任務(wù)都有什么
- tasks
- 善后的任務(wù)都有什么
- handlers
下面針對(duì)這上面提到的三個(gè)部分做介紹
- 主機(jī)和用戶
key | 含義 |
---|---|
hosts | 為主機(jī)的IP成肘,或者主機(jī)組名卖局,或者關(guān)鍵字all |
user | 在遠(yuǎn)程以哪個(gè)身份執(zhí)行 |
become | 切換成其他用戶執(zhí)行斧蜕,值為 yes或者no |
become_method | 與become一起使用双霍,值可以為 "sudo/su/pfexec/doas" |
become_user | 與become一起用,默認(rèn)為root批销,也可以是其他用戶名 |
腳本里面使用become時(shí)洒闸,執(zhí)行Playbook必須加參數(shù) --ask-become-pass,提示用戶輸入 "sudo" 的密碼。
ansible-playbook deploy.yaml --ask-become-pass
你也可以在Inventory中定義 ansible_sudo_pass 變量來避免每次都需要手工交互式地輸入sudo密碼均芽。
- 任務(wù)列表
- 任務(wù)(task)是從上到下順序執(zhí)行的丘逸,如果中間發(fā)生錯(cuò)誤,那么整個(gè)Playbook會(huì)中止掀宋。
- 每個(gè)任務(wù)都是對(duì)模塊的一次調(diào)用深纲,只是使用不用的參數(shù)和變量而已。
- 每個(gè)任務(wù)最好有 name 屬性劲妙,這是供人讀的湃鹊,沒有實(shí)際的操作。但是有這樣的輸出镣奋,我們能更好地知道執(zhí)行的情況以及task的用途币呵。
下面是一個(gè)簡(jiǎn)單的示例:
tasks:
# name 是可選的,建議使用
- name: make sure apache is running
service: name=httpd state=running
# 上面的參數(shù)使用的是 key=value的形式侨颈,也可以使用key:value的形式余赢。
- name: copy ansible inventory file to client
copy:
src: /etc/ansible/hosts
dest: /etc/ansible/hosts
mode: 0644
任務(wù)中Action會(huì)調(diào)用一個(gè)模塊芯义,然后在模塊中檢查當(dāng)前系統(tǒng)狀態(tài)是否需要重新執(zhí)行。如果本次執(zhí)行了妻柒,那么Action返回的值為changed扛拨。如果不需要執(zhí)行,那么返回的是ok举塔。
- 響應(yīng)事件handler
什么是handler
每個(gè)主流的編程語言都有Event機(jī)制鬼癣,而handler就是Playbook的Event。Handlers里面每一個(gè)handler都是對(duì)模塊的一次調(diào)用啤贩。但是和task任務(wù)不同待秃,handler只有在它需要在任務(wù)中被調(diào)用的時(shí)候才有可能被執(zhí)行。
前面提到痹屹,任務(wù)表中的任務(wù)都是有狀態(tài)的:changed或者ok章郁。在Ansible中,只有在任務(wù)的執(zhí)行狀態(tài)為changed的時(shí)候志衍,才會(huì)執(zhí)行該任務(wù)調(diào)用的handler暖庄。這也是handller和普通的Event機(jī)制不同的地方。應(yīng)用場(chǎng)景
什么情況下使用handler呢?如果你在任務(wù)中修改了Apache的配置文件楼肪,嘛呢需要重啟Apache培廓。如果你安裝了一個(gè)Apache插件,那么也需要重啟Apache春叫。這時(shí)候肩钠,重啟Apache就可以設(shè)計(jì)成一個(gè)handler。
一個(gè)handler最多只執(zhí)行一次暂殖,并且在所有任務(wù)都執(zhí)行完之后再執(zhí)行价匠。如果有多個(gè)任務(wù)調(diào)用(notify)同一個(gè)handler,那么只執(zhí)行一次呛每。
下面是一個(gè)示例,第一次執(zhí)行的時(shí)候會(huì)觸發(fā)兩個(gè)handler踩窖,第二次執(zhí)行的之后只會(huì)觸發(fā)第二個(gè)handler。
---
- hosts: lb
remote_user: root
vars:
random_number: "{{ 10000 |random }}"
tasks:
- name: Copy the /etc/hosts to /tmp/hosts
copy: src=/etc/hosts dest=/tmp/hosts
notify:
- call by /tmp/hosts
- name: Copy the /etc/hosts to /tmp/hosts.{{ random_number }}
copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number }}
notify:
- call by /tmp/hosts.{{ random_number }}
handlers:
- name: call by /tmp/hosts.{{ random_number }}
debug: msg="call by /tmp/hosts.{{ random_number }} "
- name: call by /tmp/hosts
debug: msg="call first time"
這里需要注意的是handler的執(zhí)行順序是按照定義的順序晨横,而不是任務(wù)調(diào)用的順序洋腮。就是說定義的時(shí)候順序是 1,2,3;但是調(diào)用的時(shí)候是 3,2,1 手形;但是最后執(zhí)行的時(shí)候還是 1,2,3 的順序啥供。
3.3.4 變量
在Playbook中,常用的幾種變量包括以下幾種情況
- 在Playbook中用戶自定義的變量
- 用戶無須自定義叁幢,Ansible會(huì)在執(zhí)行Playbook之前去遠(yuǎn)程主機(jī)搜集關(guān)于遠(yuǎn)程節(jié)點(diǎn)系統(tǒng)的信息變量
- 在文件模版中滤灯,可以直接使用上述兩種變量
- 把任務(wù)的運(yùn)行結(jié)果作為一個(gè)變量來使用,這個(gè)變量叫做注冊(cè)變量
- 為了使Playbook更靈活、通用性更強(qiáng)鳞骤,允許用戶在執(zhí)行Playbook時(shí)傳入變量的值窒百,這時(shí)候需要額外變量。
- 在Playbook中用戶自定義的變量
用戶在Playbook中使用變量時(shí)需要使用 "{{ }}" 引用起來即可豫尽。在Playbook中篙梢,我們可以使用vars關(guān)鍵字來定義變量,也可以使用var_files來引入變量文件美旧。如下所示:
#使用vars來定義變量
- hosts: web
vars:
http_port: 80
tasks:
....
#使用var_files來引入變量文件
- hosts: web
var_files:
- vars/server_vars.yaml
tasks:
....
有時(shí)候我們需要使用變量的值不是簡(jiǎn)單的字符串或者數(shù)字渤滞,而是一個(gè)對(duì)象,這時(shí)候定義的語法如下榴嗅,格式為YAML的字典格式妄呕。
---
- hosts: localhost
vars:
foo:
field1: one
field2: two
tasks:
- name: use vars
debug:
var=foo['field1'] #也可以foo.field1
要注意有些時(shí)候YAML和Ansible Playbook的變量語法不能在一起好好地工作。這通常發(fā)生在冒號(hào)后面的值有 "{" 開頭的變量時(shí)嗽测,如果不加上引號(hào)绪励,就很有可能報(bào)語法錯(cuò)誤。
- 遠(yuǎn)程主機(jī)的系統(tǒng)變量(Facts)
Ansible 會(huì)通過模塊 "setup" 來搜集主機(jī)的系統(tǒng)信息唠粥,這些收集到的系統(tǒng)信息叫做Facts.每個(gè)Playbook在執(zhí)行前都會(huì)默認(rèn)執(zhí)行setup模塊疏魏,所以這些Facts信息可以直接以變量的形式使用。
那么晤愧,我們?cè)趺粗烙心切〧acts變量可以引用呢大莫,我們可以使用setup模塊來查看下:
ansible all -m setup -u root
在Playbook中,我們可以和使用普通變量一樣來使用Facts變量官份。這里需要特別說明的是如何使用Facts中的復(fù)雜變量只厘。答案是可以通過下面兩種方式,如下:
#中括號(hào)
{{ ansible_ens3['ipv4']['address'] }}
#點(diǎn)號(hào)
{{ ansible_ens3.ipv4.address }}
收集Facts信息會(huì)消耗額外的時(shí)間,Ansible 的默認(rèn)配置中要求搜集這些信息贯吓。如果要關(guān)閉懈凹,可以通過關(guān)鍵字 gather_facts來關(guān)閉蜀变。如下
- hosts: db
gather_facts: no
- 文件模版中使用的變量
template模塊在Ansible中十分常用悄谐,而他在使用的時(shí)候有沒有顯示指定template文件中的值,所以有時(shí)候用戶對(duì)template中使用的變量感到困惑库北,所以這里再重新強(qiáng)調(diào)下它的變量的使用爬舰。
template能直接使用再Playbook中定義的變量,也可以使用Facts變量寒瓦,所有再Playbook中可以訪問的變量情屹,都可以再template文件中使用。通常template文件我們都是使用 j2作為后綴杂腰,因?yàn)檫@是使用jinja2的文件格式垃你,里面的變量需要使用 "{{}}" 括起來。
- 把運(yùn)行結(jié)果當(dāng)作變量使用-注冊(cè)變量
這時(shí)候就需要使用注冊(cè)變量了,把執(zhí)行的結(jié)果注冊(cè)到變量中惜颇,給后面的任務(wù)使用皆刺。把執(zhí)行結(jié)果注冊(cè)到變量中的關(guān)鍵字是register,使用方法如下:
---
- hosts: web
tasks:
- name: exec shell
shell: ls
register: result
ignore_errors: True
- name: echo result
shell: echo "{{ result.stdout }}"
when: result.rc == 5
- name: debug result
debug: msg="{{ result.stdout }}"
注冊(cè)變量經(jīng)常和debug模塊一起使用凌摄,這樣可以得到更多的關(guān)于執(zhí)行錯(cuò)誤的信息羡蛾,以幫助用戶調(diào)試。
- 用命令行傳遞參數(shù)
為了使Playbook更靈活锨亏、通用性更強(qiáng)痴怨,允許用戶在執(zhí)行的時(shí)候傳入變量的值,這時(shí)候就需要用到 "額外變量"器予。
使用命令行傳遞參數(shù)可以使用 --extra-vars 也可以使用簡(jiǎn)寫 -e 浪藻。如下所示:
#在命令行中傳值的方法
ansible-playbook test_var.yaml -e "host=web user=root"
#還可以使用json格式傳遞參數(shù)
ansible-playbook test_var.yaml -e "{'host':'web','user':'root'}"
#還可以將參數(shù)放在文件里面
ansible-playbook test_var.yaml -e "@vars.json"
上面的例子可以下面的playbook。
---
- hosts: localhost
tasks:
- name: show vars
debug: msg="host is {{ host }}, user is {{ user }}"
3.3.5 Playbook 也有邏輯控制語句
- when: 條件判斷語句乾翔,類似編程語言中的if珠移。
- loop: 循環(huán)語句,類似于編程語言中的while末融。
- block: 把幾個(gè)任務(wù)組在一個(gè)代碼塊钧惧,以便針對(duì)一組操作的異常進(jìn)行處理等操作。
- 條件判斷語句when
有時(shí)候用戶很有可能需要滿足特定條件才去執(zhí)行特定的步驟勾习,如在某一特定的版本的系統(tǒng)上安裝軟件包浓瞪。如下:
tasks:
#遠(yuǎn)程主機(jī)如果是debian,立刻關(guān)機(jī)
- name: "shutdown Debian systems"
command: /sbin/shutdown -t now
when: ansible_os_family == "Debian"
#根據(jù)Action的執(zhí)行結(jié)果巧婶,來決定是否執(zhí)行任務(wù)
- name: result is false
command: /bin/false
register: result
ignore_errors: True
- name: exec shell
shell: /bin/something
when: result | failed
- name: exec other shell
shell: /bin/something_else
when: result | success
#還可以使用 |int 對(duì)返回值的類型做轉(zhuǎn)換,如下
- name: "只有在rhel7或者更新的版本上執(zhí)行任務(wù)"
debug: "msg=hello pcm"
when: ansible_os_family == "RedHat" and ansible_lsb.major_release | int >= 6
除了上面的用法外乾颁,我們還可以使用條件表達(dá)式
---
- hosts: localhost
vars:
epic: true
tasks:
- name: "使用布爾表達(dá)式"
shell: echo "This is epic"
when: epic
- name: "布爾表達(dá)式前面可以加上not"
shell: echo "This is epic"
when: not epic
- name: "還可以判斷變量有沒有定義"
shell: echo "This is epic"
when: epic is not defined
- name: "還可以比較數(shù)值大小"
shell: echo "This is epic"
when: epic > 5
when除了能夠用在task上,我們還會(huì)和Include或者Role一起來使用艺栈。
---
#當(dāng)deploy為真時(shí)英岭,執(zhí)行deploy.yaml這個(gè)playbook。
- include: tasks/deploy.yaml
when: deploy
---
- hosts: web
#當(dāng)update為真時(shí)湿右,執(zhí)行名為update的role
roles:
- { role: update, when: update}
- 循環(huán)語句 loop
"with_items" 可以用迭代list類型的變量诅妹,不僅支持簡(jiǎn)單的字符串列表,還可以支持哈希列表毅人,如下:
#最簡(jiǎn)單的列表模式
- name: add serveral user
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
#如果在vars中定義了列表變量吭狡,還能這么操作
vars:
users: ['user1','user2']
tasks:
- name: add serveral user
user: name={{ item }} state=present groups=wheel
with_items: "{{ users }}"
#哈希列表這么用,可以使用具體的子項(xiàng)(字典列表)
- name: add serveral user
user: name={{ item.user }} state=present groups={{ item.group }}
with_items:
- {user: 'user1', group:'group1'}
- {user: 'user2', group:'group2'}
如果同事使用when和with_items(或其他循環(huán)聲明),那么when聲明會(huì)為每個(gè)條目單獨(dú)判斷一次
Ansible的循環(huán)和編程語言的一樣丈莺,也能嵌套循環(huán)
下面嵌套的是列表
---
- hosts: localhost
tasks:
#使用with_nested,和python一樣划煮,可以使用 []來訪問內(nèi)層循環(huán),也可以使用點(diǎn)號(hào) "." 來訪問缔俄。
- name: debug loop
debug: msg="username is {{ item[0] }},password is {{ item[1] }}"
with_nested:
- ['pcm1', 'pcm2']
- ['passwd1', 'passwd2', 'passwd3']
上面playbook執(zhí)行的結(jié)果如下:
TASK [debug loop] ***************************************************************************************************************************************************************************
ok: [localhost] => (item=[u'pcm1', u'passwd1']) => {
"msg": "username is pcm1,password is passwd1"
}
ok: [localhost] => (item=[u'pcm1', u'passwd2']) => {
"msg": "username is pcm1,password is passwd2"
}
ok: [localhost] => (item=[u'pcm1', u'passwd3']) => {
"msg": "username is pcm1,password is passwd3"
}
ok: [localhost] => (item=[u'pcm2', u'passwd1']) => {
"msg": "username is pcm2,password is passwd1"
}
ok: [localhost] => (item=[u'pcm2', u'passwd2']) => {
"msg": "username is pcm2,password is passwd2"
}
ok: [localhost] => (item=[u'pcm2', u'passwd3']) => {
"msg": "username is pcm2,password is passwd3"
}
---
- hosts: localhost
tasks:
#使用with_dict,和python一樣弛秋,可以使用 []來訪問內(nèi)層循環(huán)器躏,也可以使用點(diǎn)號(hào) "." 來訪問。
- name: debug loop
debug: msg="username is {{ item[0] }},password is {{ item[1] }}"
with_nested:
- ['pcm1', 'pcm2']
- ['passwd1', 'passwd2', 'passwd3']
下面嵌套的是哈希表
---
- hosts: localhost
vars:
user:
- user1:
name: pcm1
age: 18
- user2:
name: pcm2
age: 20
tasks:
- name: print mans
debug: msg="User {{ item.key }} is {{ item.value.name }},age is {{ item.value.age }}"
with_dict: "{{ users }}"
對(duì)文件蟹略,我們也可以使用循環(huán)
tasks:
- name: "首先確認(rèn)文件是存在的"
file: dest=/etc/fooapp state=directory
- name: "復(fù)制文件到遠(yuǎn)程目錄上"
copy: "src={{ item }} dest=/etc/fooapp/ mode=600"
with_fileglob:
- /playbooks/files/fooapp/*
- 代碼塊 block
多個(gè)action組成塊后邀桑,可以根據(jù)不同條件執(zhí)行一段語句。好比編程語言中的函數(shù)科乎。
---
- hosts: localhost
vars:
flag: true
tasks:
- block:
- name: action1
debug: msg="hello world"
- name: action2
debug: msg="hello ansible"
when: flag
block除了能和when組合在一起之外壁畸,還可以和rescue和always一起組合。效果可以類比python中的 try茅茂、except捏萍、finally 。如下:
---
- hosts: localhost
tasks:
- block:
- debug:
msg: 'I execute normally'
- command: /bin/false
- debug:
msg: 'I never execute, due to the above task failing'
rescue:
- debug:
msg: 'I caught an error'
- command: /bin/false
- debug:
msg: 'I also never execute'
always:
- debug:
msg: "This always executes"
3.3.6 重用 Playbook
Playbook支持兩種重用機(jī)制空闲,一種是重用單個(gè)靜態(tài)Playbook嗯見令杈,另外一種是重用特定功能的文件夾,類似于Python等編程語言中的包(Package)碴倾。
- include語句: 重用單個(gè)Playbook腳本逗噩,使用起來簡(jiǎn)單、直接
- role語句: 重用實(shí)現(xiàn)特定功能的Playbook文件夾跌榔,使用方法稍復(fù)雜异雁,功能強(qiáng)大。role是Ansible更為推薦的重用和分享Playbook的方式僧须。
1. include語句
include語句是基本的代碼重用機(jī)制纲刀,主要重用任務(wù),同時(shí)担平,include還可以將任務(wù)分割成多個(gè)文件示绊,避免Playbook過于臃腫。
include的使用方法很簡(jiǎn)單暂论,直接使用即可面褐,如下:
#假設(shè)該文件名為main.yaml,下面調(diào)用deploy.yml的Playbook。
---
- hosts: localhost
tasks:
- include: deploy.yml
下面是deploy.yml的內(nèi)容取胎,只需要寫上各個(gè)action即可展哭。
- name: action1
debug: msg=action1
- name: action2
debug: msg=action2
如果我們想要引用Playbook的時(shí)候傳入?yún)?shù)應(yīng)該怎么操作呢?
#直接在行尾加上參數(shù)即可扼菠,用空格分割
- hosts: localhost
tasks:
- include: deploy.yml port=80
#也可以傳入一個(gè)字典作為變量
- include: deploy.yml
vars:
user: pangcm
port: 80
#上面的字典也可以寫成一串json
- { include: deploy.yml,user:pangcm,port=80 }
如果你在Playbook中已經(jīng)定義了參數(shù)摄杂,那么就不需要傳入了,直接在被調(diào)用的Playbook中使用即可循榆。
---
- hosts: localhost
vars:
port: 80
tasks:
- include: deploy.yml
這里要注意 include 的位置,這是在tasks下的墨坚,也就是相當(dāng)于一個(gè)大的action秧饮。如果放在和tasks同級(jí)映挂,也就是全局include。我們不推薦這么做盗尸,因?yàn)樗恢С智度雐nclude柑船,而且很多的Playbook也無法使用,
---
- hosts: localhost
tasks:
...
- include: deploy.yml
include是場(chǎng)景不大的情況下還是挺好用的泼各,但是如果引用多了這將很難管理鞍时,維護(hù)成本會(huì)變得很多。所以在使用更加靈活的重用機(jī)制時(shí)扣蜻,建議使用下面的role.
2. role-Playbook 的 "Package"
Ansible好比編程語言中的include逆巍,role好比編程語言中的package。通常一個(gè)role由一組文件組成莽使,形成一個(gè)完整的功能锐极。如一個(gè)部署nginx的role,里面會(huì)包含若干playbook和文件芳肌。
Ansibe十分提倡在Playbook中使用role灵再,并且提供了一個(gè)分享role的平臺(tái) ANsible Galaxy。在Galaxy上可以找到別人寫好的role亿笤。
- role的目錄結(jié)構(gòu)
在Ansible中翎迁,通過遵循特定的目錄結(jié)構(gòu),就可以實(shí)現(xiàn)對(duì)role的定義净薛,具體遵循的目錄結(jié)構(gòu)是什么樣子的呢鸳兽?如下:
[root@xxx-test roles]# tree
.
├── deploy.yml
└── install-nginx
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
上面定義了一個(gè)名為install-nginx的role,用來安裝nginx罕拂。Playbook文件中的deploy.yml調(diào)用這個(gè)role揍异。上面的文件不要求全部擁有,看自己的實(shí)際需求爆班。(以上目錄我使用的是ansible-galaxy init install-nginx
創(chuàng)建的衷掷。)
下面解析下role目錄的功能:
- defaults: 存放變量文件,存放在這里的變量?jī)?yōu)先級(jí)最低
- files: 存放普通文件柿菩,通常給copy模塊使用
- handlers: 存放handler文件
- meta: 存放描述依賴關(guān)系role的文件
- tasks: 存放任務(wù)文件
- templates: 存放模版文件
- tests: 存放測(cè)試文件戚嗅,用來測(cè)試整個(gè)role能否正常運(yùn)行
- vars: 存放變量文件,優(yōu)先級(jí)比defaults的高
role的子目錄里面通常有main.yml文件枢舶,這是role的入口文件懦胞。整個(gè)role的入口文件為 tasks/main.yml。
此外凉泄,我們?cè)谑褂孟旅娴膸讉€(gè)模塊的時(shí)候躏尉,調(diào)用的文件不需要路徑,直接使用文件名稱即可:
- copy 或者script 使用 files 下的文件
- template 使用templates下的文件
- include 使用 tasks 下的文件。
- 在role中使用變量
在role中使用變量非常簡(jiǎn)單扮饶,直接使用 "{{}}" 括起來就可以使用了诚卸。我們先看下默認(rèn)變量怎么使用避咆,在 install-nginx/defaults/main.yml 文件中定義一個(gè)默認(rèn)變量哩罪,然后輸出滩愁。
var: "I am defalut vars"
在 install-nginx/tasks/main.yml 文件抖仅,也就是我們的role的入口文件中使用這個(gè)變量匾寝,直接輸出括堤。
---
- name: use var
debug: msg="{{ var }}"
最后碌秸,我們?cè)?role的同級(jí)目錄的文件 deploy.yml 中調(diào)用這個(gè)role:
---
- hosts: localhost
roles:
- install-nginx
最后調(diào)用這個(gè)playbook,看到輸出了這個(gè)默認(rèn)變量悄窃。
[root@xxx-test roles]# ansible-playbook deploy.yml
PLAY [localhost] ****************************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************
ok: [localhost]
TASK [install-nginx : use var] **************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "I am defalut vars"
}
PLAY RECAP **********************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
接下來讥电,我們看下使用普通的變量看下,在 install-nginx/vars/main.yml 文件中定義個(gè)和defaults下同名變量广匙,默認(rèn)變量應(yīng)該會(huì)被替換:
var: "I am a var vars dir"
執(zhí)行結(jié)果如下,可以看到確實(shí)被替換了:
TASK [install-nginx : use var] *************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "I am a var vars dir"
}
除此之外允趟,我們還可以在調(diào)用role的時(shí)候傳入變量參數(shù),如下:
---
- hosts: localhost
roles:
- { role: install-nginx,var: "I am a var in role" }
執(zhí)行結(jié)果如下,可以看到這里傳入的變量參數(shù)優(yōu)先級(jí)高于在role里面定義的鸦致。
TASK [install-nginx : use var] *************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "I am a var in role"
}
此外潮剪,role還能使用在Inventory中定義的變量,執(zhí)行Playbook時(shí)傳入的變量等等分唾。更多變量?jī)?yōu)先級(jí)的介紹后面會(huì)具體說明的抗碰。
- role和條件when一起執(zhí)行,和include一樣,role也經(jīng)常和when搭檔使用
---
#只有在RedHat系列的主機(jī)上才會(huì)執(zhí)行操作
- hosts: localhost
roles:
- { role: install-nginx, when: "ansible_os_family == 'RedHat'" }
- role和任務(wù)的執(zhí)行順序
如果一個(gè)Playbook中同時(shí)出現(xiàn)role和任務(wù)绽乔,那么他們的調(diào)用順序是怎樣的呢弧蝇?
答案是: pre_tasks > role > tasks >post_tasks.
3.3.7 用標(biāo)簽,實(shí)現(xiàn)執(zhí)行Playbook中的部分任務(wù)
如果Playbook文件比較大折砸,并且在執(zhí)行的時(shí)候只是想執(zhí)行部分功能看疗,那么這個(gè)時(shí)候有沒有解決方案呢?答案就是使用標(biāo)簽(tags)了.
下面我們有個(gè)playbook睦授,并且打上了幾個(gè)tag两芳。
---
- hosts: localhost
tasks:
- name: "我是標(biāo)簽1"
debug: msg="first tag"
tags: first
- name: "我是標(biāo)簽2"
debug: msg="second tag"
tags: second
- name: "可以打多個(gè)標(biāo)簽,和前面的有同名的也沒事去枷,符合的就執(zhí)行"
debug: msg="third tag"
tags:
- first
- second
執(zhí)行的時(shí)候如果我們不加上任何參數(shù)怖辆,那么所有的標(biāo)簽對(duì)應(yīng)的任務(wù)都會(huì)執(zhí)行。如果我們要執(zhí)行某個(gè)標(biāo)簽的任務(wù)删顶,可以使用"-t" 參數(shù)指定:
ansible-playbook deploy.yml -t first
如果要跳過某些標(biāo)簽的任務(wù)竖螃,可以使用 "--skip-tags" 參數(shù)
ansible-playbook deploy.yml --skip-tags first
標(biāo)簽的名字是用戶自定義的,但是如果把標(biāo)簽的名字定義為always逗余,那么就有點(diǎn)特別了特咆。只要在執(zhí)行Playbook的時(shí)候,如果沒有明確指定不執(zhí)行always標(biāo)簽猎荠,那么always標(biāo)簽對(duì)應(yīng)的任務(wù)就始終會(huì)被執(zhí)行坚弱。
在指定執(zhí)行某個(gè)標(biāo)簽的時(shí)候蜀备,我們可以使用 "tagged" "untagged" 和 "all" 來分別標(biāo)志只執(zhí)行有標(biāo)簽的任務(wù)关摇、只執(zhí)行沒有標(biāo)簽的任務(wù)和執(zhí)行全部任務(wù)荒叶。如下:
ansible-playbook deploy.yml -t tagged
標(biāo)簽除了能夠在action中使用外,還能在include和role中使用標(biāo)簽输虱。如下:
---
#include中使用
- include: foo.yml
tags: [web,foo]
#role中使用
roles:
- {role: webserver, port: 5000, tags: [web,foo]}
3.4 更多的Ansible模塊
3.4.1 模塊的分類
在Ansible模塊文檔上查看單個(gè)模塊的時(shí)候些楣,每一個(gè)模塊文檔的底部都會(huì)表示,這是"COre Module",還是"Extra Module"宪睹。
比如愁茁,yum就是一個(gè)Core模塊,而archive就是一個(gè)Extra模塊亭病。
- Core模塊(核心模塊)
- 不需要額外下載和配置鹅很,安裝Ansible后就可以直接使用的
- 比較常用的模塊
- 經(jīng)過嚴(yán)格測(cè)試的模塊
- Extra模塊(額外模塊)
- 需要進(jìn)行下載和額外配置才能使用
- 次常用的模塊
- 還有可能存在bug的模塊
3.4.2 Extra模塊的使用方法
大概流程為下載Extra模塊,修改配置文件或者環(huán)境變量罪帖。具體方法自行百度促煮。
3.4.3 命令行查看模塊的用法
通過命令 ansible-doc,可以查看模塊的用法,如下:
ansible-doc yum
3.5 最佳使用方法
3.5.1 寫Playbook的原則
Ansible為了降低Playbook的維護(hù)成本整袁,提高Playbook的可維護(hù)性菠齿,提倡以下兩個(gè)原則:
- 鼓勵(lì)文件重用,盡量使用include和role避免重復(fù)代碼坐昙。
- 盡量把大的文件分成小的文件
3.5.2 參考別人的Playbook
官方提供了一些比較常用的绳匀、經(jīng)過測(cè)試的Playbook的例子
https://github.com/ansible/ansible-examples
此外,ansible還提供了一個(gè)Playbook的分享平臺(tái)炸客,平臺(tái)上的例子是Ansible用戶自己上傳的
https://galaxy.ansible.com/