Ansible進階
本章的目的是讓你能夠上手寫ansible的指令碼,並且能夠看懂一些高階一點的ansible playbook指令碼。
深入介紹一下幾個主題
- Ansible的配置
- Ansible的主機目錄管理(Host Inventory)
- Ansible Playbook的進階語法
- 配置Extra Modules
ansible的配置
ansible的配置
可以配置什麼?
從基本的,主機目錄檔案"inventory",extra module放置路徑"library",管理節點上臨時檔案的位置"remote_tmp",遠端主機的臨時檔案位置"local_tmp"
inventory = /etc/ansible/hosts
library = /usr/share/my_modules/
remote_tmp = $HOME/.ansible/tmp
local_tmp = $HOME/.ansible/tmp
到高階的,連線埠號"accelerate_port",超時時間等。
accelerate_port = 5099
accelerate_timeout = 30
accelerate_connect_timeout = 5.0
看一個完整的anbile配置檔案例子,就能基本瞭解到ansible都能配置什麼了:
https://raw.githubusercontent.com/ansible/ansible/devel/examples/ansible.cfg
對ansible配置檔案裡面的關鍵字不能完整理解,還可以參考關鍵詞解釋列表:
http://docs.ansible.com/ansible/intro_configuration.html#explanation-of-values-by-section
anbile配置檔案的優先順序
ansible的預設配置檔案是/etc/ansible/ansible.cfg。其實ansible會按照下面的順序查詢配置檔案,並使用第一個發現的配置檔案。
* ANSIBLE_CONFIG (an environment variable)
* ansible.cfg (in the current directory)
* .ansible.cfg (in the home directory)
* /etc/ansible/ansible.cfg
Ansible1.5以前的版本順序為:
* ansible.cfg (in the current directory)
* ANSIBLE_CONFIG (an environment variable)
* .ansible.cfg (in the home directory)
* /etc/ansible/ansible.cfg
主機目錄(Host Inventory)
什麼叫主機目錄管理,告訴ansible需要管理哪些server,和server的分類和分組資訊。可以根據你自己的需要根據地域分類,也可以按照功能的不同分類。
主機目錄的配置檔案
預設檔案
/etc/ansible/hosts
修改主機目錄的配置檔案
/etc/ansible/ansible.cfg
...
inventory = /etc/ansible/hosts
...
命令列中傳遞主機目錄配置檔案
$ ansible-playbook -i hosts site.yml
或者引數--inventory-file
$ ansible-playbook --inventory-file hosts site.yml
遠端主機的分組
遠端主機的分組
簡單的分組[]內是組名 mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
[webservers]
www[01:50].example.com
[databases]
db-[a:f].example.com
分組的子組[usa:children]
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children]
atlanta
raleigh
[usa:children]
southeast
northeast
southwest
northwest
指定連線的引數
指定連線的引數
引數
指定Server的連線引數,其中包括連線方法,使用者等。
[targets]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_user=mpdehaan
other2.example.com ansible_connection=ssh ansible_user=mdehaan
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
可以指定的引數在文件中 http://docs.ansible.com/ansible/intro_inventory.html#list-of-behavioral-inventory-parameters
變數
為一個組指定變數
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
按目錄結構儲存變數
按目錄結構儲存變數
假設inventory檔案為/etc/ansible/hosts,那麼相關的hosts和group變數可以放在下面的目錄結構下
/etc/ansible/group_vars/raleigh # can optionally end in '.yml', '.yaml', or '.json'
/etc/ansible/group_vars/webservers
/etc/ansible/host_vars/foosball
/etc/ansible/group_vars/raleigh 檔案內容可以為
ntp_server: acme.example.org
database_server: storage.example.org
如果對應的名字為目錄名,ansible會讀取這個目錄下面所有檔案的內容
/etc/ansible/group_vars/raleigh/db_settings
/etc/ansible/group_vars/raleigh/cluster_settings
group_vars/ 和 host_vars/ 目錄可放在 inventory 目錄下,或是 playbook 目錄下. 如果兩個目錄下都存在,那麼 playbook 目錄下的配置會覆蓋 inventory 目錄的配置.
Ansible的指令碼Playbook
Playbook
YML
ansible的指令碼語言,yaml格式. 請參考YAML語法結構章節
別人的Playbook
能夠學會快速用別人的成果,高效的分享自己的成果,才是好碼農,才是能早下班的好碼農。在你動手從頭開始寫一個Playbook之前,不如先參考一下別人的成果吧。
官方例子
Ansible官方提供了一些比較常用的,經過測試的Playbook例子:
https://github.com/ansible/ansible-examples
Playbook分享平臺
此外,Ansible還提供了Playbook的分享平臺,上面的例子是Ansible使用者自己上傳的。你如果在沒有思路的情況下參考下吧,不過一定要再重新嚴謹的測試下。
https://galaxy.ansible.com/
Playbook基本語法
Playbook基本語法
本節列舉了寫第一個Playbook,你必須瞭解基本語法。
隨著你面臨的機器越多,配屬的需求越複雜,你可能需要了解後面介紹的一些稍微複雜邏輯語句。
執行Playbook語法
bash
$ ansible-playbook deploy.yml
檢視輸出的細節
ansible-playbook playbook.yml --list-hosts
檢視該指令碼影響哪些hosts
ansible-playbook playbook.yml --list-hosts
並行執行指令碼
ansible-playbook playbook.yml -f 10
完整的playbook指令碼示例
最基本的playbook指令碼分為三個部分:
- 在什麼機器上以什麼身份執行
- hosts
- users
- ...
- 執行的任務是都有什麼
- tasks
- 善後的任務都有什麼
- handlers
deploy.yml檔案
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
Playbook中定義主機和使用者
主機和使用者
| key | 含義 |
| -- | -- |
| hosts | 為主機的IP,或者主機組名,或者關鍵字all |
|user | 在遠端以哪個使用者身份執行。 |
| become | 切換成其它使用者身份執行,值為yes或者no |
| become_method | 與became一起用,指可以為‘sudo’/’su’/’pbrun’/’pfexec’/’doas’ |
| become_user | 與bacome_user一起用,可以是root或者其它使用者名稱 |
指令碼里用became的時候,執行的playbook的時候可以加引數--ask-become-pass
ansible-playbook deploy.yml --ask-become-pass
Tasks任務列表
Tasks任務列表
- tasks是從上到下順序執行,如果中間發生錯誤,那麼整個playbook會中止。你可以改修檔案後,再重新執行。
- 每一個task的對module的一次呼叫。使用不同的引數和變數而已。
- 每一個task必須有一個name屬性,這個是供人讀的,然後會在命令列裡面輸出,提示使用者執行情況。
語法
task的基本寫法
tasks:
- name: make sure apache is running
service: name=httpd state=running
引數太長可以分隔到多行
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
或者用yml的字典作為引數
tasks:
- name: Copy ansible inventory file to client
copy:
src: /etc/ansible/hosts
dest: /etc/ansible/hosts
owner: root
group: root
mode: 0644
TASK的執行狀態
task中每個action會呼叫一個module,在module中會去檢查當前系統狀態是否需要重新執行. 具體的判斷規則由各個module自己實現.
- 如果執行那麼action會得到返回值changed;
- 如果不需要執行,那麼action得到返回值ok
"copy" module的判斷方法是比較檔案的checksum,程式碼如下:
https://github.com/ansible/ansible-modules-core/blob/devel/files/copy.py
狀態示例
以一個copy檔案的task為例子:
tasks:
- name: Copy the /etc/hosts
copy: src=/etc/hosts dest=/etc/hosts
第一次執行,它的結果是這個樣子的:
TASK的狀態是changed
第二次執行是下面這個樣子的:
TASK的狀態是ok,由於第一次執行copy_hosts.yml的時候,已經拷貝過檔案,那麼ansible目標檔案的狀態避免重複執行.
下面我更改vm-rhel7-1的/etc/hosts, 再次執行看看:
響應事件(handler)
響應事件Handler
什麼是handler?
每個主流的程式語言都會有event機制,那麼handler就是playbook的event。
Handlers裡面的每一個handler,也是對module的一次呼叫。而handler與tasks不同的是,handlers不會預設的按順序執行。
Tasks中的任務都是有狀態的,changed或者ok。 Ansible提供了一種機制,只在task的執行狀態為changed的時候,才會觸發執行,這就是handler。
應用場景
什麼情況下使用handlers呢?
如果你在tasks中修改了apache的配置檔案。需要重起apache。此外還安裝了apache的外掛。那麼還需要重起apache。像這樣的應該場景中,重起apache就可以設計成一個handler.
一個handler最多隻執行一次
在所有的任務裡表執行之後執行,如果有多個task notify同一個handler,那麼只執行一次。
在下面的例子裡apache只執行一次
https://github.com/ansible-book/ansible-first-book-examples/blob/master/handlers_state.yml
---
- hosts: lb
remote_user: root
vars:
random_number1: "{{ 10000 | random }}"
random_number2: "{{ 10000000000 | random }}"
tasks:
- name: Copy the /etc/hosts to /tmp/hosts.{{ random_number1 }}
copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number1 }}
notify:
- call in every action
- name: Copy the /etc/hosts to /tmp/hosts.{{ random_number2 }}
copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number2 }}
notify:
- call in every action
handlers:
- name: call in every action
debug: msg="call in every action, but execute only one time"
action是Changed ,才會執行handler
只有當TASKS種的action的執行狀態是changed時,才會觸發notify handler的執行。
下面的指令碼執行兩次,執行結果是不同的:
第一次執行是,tasks的狀態都是changed,會觸發兩個handler
第二次執行是,
- 第一個task的狀態是OK,那麼不會觸發handlers"call by /tmp/hosts",
- 第二個task的狀態是changed,觸發了handler"call by /tmp/hosts.random_number"
測試程式碼見:
https://github.com/shijingjing1221/ansible-first-book-examples/blob/master/handlers_execution_time.yml
---
- 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
debug: msg="call first time"
- name: call by /tmp/hosts.random_number
debug: msg="call by /tmp/hosts.random_number"
按Handler的定義順序執行
handlers是按照在handlers中定義個順序執行的,而不是安裝notify的順序執行的。
下面的例子定義的順序是1>2>3,notify的順序是3>2>1,實際執行順序:1>2>3.
---
- hosts: lb
remote_user: root
gather_facts: no
vars:
random_number1: "{{ 10000 | random }}"
random_number2: "{{ 10000000000 | random }}"
tasks:
- name: Copy the /etc/hosts to /tmp/hosts.{{ random_number1 }}
copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number1 }}
notify:
- define the 3nd handler
- name: Copy the /etc/hosts to /tmp/hosts.{{ random_number2 }}
copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number2 }}
notify:
- define the 2nd handler
- define the 1nd handler
handlers:
- name: define the 1nd handler
debug: msg="define the 1nd handler"
- name: define the 2nd handler
debug: msg="define the 2nd handler"
- name: define the 3nd handler
debug: msg="define the 3nd handler"
重用playbook(include語句)
Include語句
Include語句的功能,基本的程式碼重用機制。主要重用tasks。
普通用法
像其它語言的Include語句一樣,直接Include:
---
# possibly saved as tasks/firewall_httpd_default.yml
- name: insert firewalld rule for httpd
firewalld: port=80/tcp permanent=true state=enabled immediate=yes
main.yml檔案中呼叫include的方法:
tasks:
- include: tasks/firewall_httpd_default.yml
高階用法-加引數
加引數
tasks:
- include: tasks/firewall.yml port=80
- include: tasks/firewall.yml port=3260
- include: tasks/firewall.yml port=423
還可以這樣加:
tasks:
- include: wordpress.yml
vars:
wp_user: timmy
ssh_keys:
- keys/one.txt
- keys/two.txt
還可以簡寫成:
tasks:
- { include: wordpress.yml, wp_user: timmy, ssh_keys: [ 'keys/one.txt', 'keys/two.txt' ] }
在handlers裡面加include
handlers:
- include: handlers/handlers.yml
在全域性加include時,tasks和handlers不能有include
- name: this is a play at the top level of a file
hosts: all
remote_user: root
tasks:
- name: say hi
tags: foo
shell: echo "hi..."
- include: load_balancers.yml
- include: webservers.yml
- include: dbservers.yml
include裡面的handlers在外面呼叫不了
不知道為什麼有一處文件裡面寫可以呼叫。文件下面兩個地方提到include裡面的handlers,但是兩處是矛盾的:
- hander的文件寫不能呼叫 http://docs.ansible.com/ansible/playbooks_intro.html
- include的文件寫能呼叫 http://docs.ansible.com/ansible/playbooks_roles.html#task-include-files-and-encouraging-reuse
通過下面的例子實測後,是不能呼叫include裡面的handler的。
---
- hosts: lb
user: root
gather_facts: no
vars:
random_number: "{{ 10000 | random }}"
tasks:
- name: Copy the /etc/hosts to /tmp/hosts.{{ random_number }}
copy: src=/etc/hosts dest=/tmp/hosts.{{ random_number }}
notify:
- restart apache
- restart apache in handlers
handlers:
- include: handlers/handlers.yml
- name: restart apache
debug: msg="This is the handler restart apache"
ansible的“函式"(role語句)
Role語句
比include更強大的程式碼重用機制。一個role可以包含vars_files, tasks, and handlers等等. 通常一個role定義瞭如何完成一個特定的功能,比如安裝Webservers可以寫成一個role, 安裝Database可以寫成一個role.
Ansible提供了一個分享role的平臺, https://galaxy.ansible.com/, 在galaxy上可以找到別人寫好的role.
Role的目錄結構
在ansible中,通過遵循特定的目錄結構,就可以實現對role的定義.
下面的目錄結構定義了兩個role,一個是common,另外一個是webservers. 在site.yml,呼叫了這兩個role.
role的目錄結構
site.yml
roles/
common/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/
webservers/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/
site.yml中的使用
---
- hosts: webservers
roles:
- common
- webservers
帶引數的Role
定義帶引數的role
定義一個帶引數的role,名字是role_with_var,那麼目錄結構為
main.yml
roles
role_with_var
tasks
main.yml
在roles/rolw_with_var/tasks/main.yml中,直接使用定義的變數就可以了
---
- name: use param
debug: msg="{{ param }}"
使用帶引數的role
那麼在main.yml就可以用如下的方法使用role_with_var
---
- hosts: webservers
roles:
- { role: role_with_var, param: 'Call some_role for the 1st time' }
- { role: role_with_var, param: 'Call some_role for the 2nd time' }
指定預設的引數
指定預設引數後,如果在呼叫時傳引數了,那麼就使用傳入的引數值.如果呼叫的時候沒有傳引數,那麼就使用預設的引數值.
指定預設引數很簡單,以上面的role_with_var為例
main.yml
roles:
role_with_var
tasks
main.yml
vars
main.yml
在roles/role_with_var/vars/main.yml中,使用yml的字典定義語法定義param的值,如下:
param: "I am the default value"
這樣在main.yml中,下面兩種呼叫方法都可以
---
- hosts: webservers
roles:
- role_with_var
- { role: role_with_var, param: 'I am the value from external' }
更多的例子在https://github.com/shijingjing1221/ansible-first-book-examples/blob/master/role_vars.yml 中
與條件語句一起執行
下面的例子中,some_role只有在RedHat系列的server上才執行.
---
- hosts: webservers
roles:
- { role: some_role, when: "ansible_os_family == 'RedHat'" }
執行順序
pre_tasks > role > tasks > post_tasks
---
- hosts: vm-rhel7-1
user: root
pre_tasks:
- name: pre
shell: echo 'hello'
roles:
- { role: some_role }
tasks:
- name: task
shell: echo 'still busy'
post_tasks:
- name: post
shell: echo 'goodbye'
看例子!!!
條件語句when
條件語句When
類似於程式語言的if
When語句
有時候使用者有可能需滿足特定條件才執行某一個特定的步驟。在某一個特定版本的系統上裝包,或者只在磁碟空間滿了的檔案系統上執行清理操作一樣。這些操作在Ansible上,使用when
語句都非常簡單.
主機為Debian Linux立刻關機
tasks:
- name: "shutdown Debian flavored systems"
command: /sbin/shutdown -t now
when: ansible_os_family == "Debian"
根據action的執行結果,來決定接下來執行的action。
tasks:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|success
- command: /bin/still/something_else
when: result|skipped
遠端中的系統變數facts變數作為when的跳進,用“|int”還可以轉換返回值的型別:
---
- hosts: web
tasks:
- debug: msg="only on Red Hat 7, derivatives, and later"
when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6
條件表示式
vars:
epic: true
基本款
tasks:
- shell: echo "This certainly is epic!"
when: epic
否定款:
tasks:
- shell: echo "This certainly isn't epic!"
when: not epic
變數定義款
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 defined
數值表達款
tasks:
- command: echo {{ item }}
with_items: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
與Include一起用
- include: tasks/sometasks.yml
when: "'reticulating splines' in output"
與Role一起用
- hosts: webservers
roles:
- { role: debian_stock_config, when: ansible_os_family == 'Debian' }
迴圈語句loop
Loop迴圈
標準迴圈
為了保持簡潔,重複的任務可以用以下簡寫的方式:
- name: add several users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
如果你在變數檔案中或者 ‘vars’ 區域定義了一組YAML列表,你也可以這樣做:
vars:
somelist: ["testuser1", "testuser2"]
tasks:
-name: add several user
user: name={{ item }} state=present groups=wheel
with_items: "{{somelist}}"
使用 ‘with_items’ 用於迭代的條目型別不僅僅支援簡單的字串列表.如果你有一個雜湊列表,那麼你可以用以下方式來引用子項:
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
請note如果同時使用 when 和 with_items (或其它迴圈宣告),when
宣告會為每個條目單獨執行.請參見 the_when_statement 示例.
巢狀迴圈
迴圈也可以巢狀:
- name: give users access to multiple databases
mysql_user: name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs=yes password=foo
with_nested:
- [ 'alice', 'bob' ]
- [ 'clientdb', 'employeedb', 'providerd']
或者
- name: give users access to multiple databases
mysql_user: name={{ item.0 }} priv={{ item.1 }}.*:ALL append_privs=yes password=foo
with_nested:
- [ 'alice', 'bob' ]
- [ 'clientdb', 'employeedb', 'providerd']
對雜湊表使用迴圈
---
vars:
alice:
name: Alice Appleworth
telephone: 123-456-7890
bob:
name: Bob Bananarama
telephone: 987-654-3210
tasks:
- name: Print phone records
debug: msg="User {{ item.key }} is {{ item.value.name }} ({{ item.value.telephone }})"
with_dict: "{{users}}"
對檔案列表使用迴圈
with_fileglob 可以以非遞迴的方式來模式匹配單個目錄中的檔案.如下面所示:
tasks:
# first ensure our target directory exists
- file: dest=/etc/fooapp state=directory
# copy each file over that matches the given pattern
- copy: src={{ item }} dest=/etc/fooapp/ owner=root mode=600
with_fileglob:
- /playbooks/files/fooapp/*
塊語句block
Block塊
多個action組裝成塊,可以根據不同條件執行一段語句 :
tasks:
- block:
- yum: name={{ item }} state=installed
with_items:
- httpd
- memcached
- template: src=templates/src.j2 dest=/etc/foo.conf
- service: name=bar state=started enabled=True
when: ansible_distribution == 'CentOS'
become: true
become_user: root
組裝成塊處理異常更方便:
tasks:
- block:
- debug: msg='i execute normally'
- command: /bin/false
- debug: msg='i never execute, cause ERROR!'
rescue:
- debug: msg='I caught an error'
- command: /bin/false
- debug: msg='I also never execute :-('
always:
- debug: msg="this always executes"
變數
變數
定義
使用yml格式定義
foo:
field1: one
field2: two
使用變數
使用Python的template語言Jinja2的語法引用:利用中括號和點號來訪問子屬性
foo['field1']
foo.field1
Playbook中使用的變數
Playbook中使用的變數
在Playbook中使用,需要用{{ }}引用以來即可:
- hosts: webservers
vars:
apache_config: labs.conf
tasks:
- name: deploy haproxy config
template: src={{ apache_config }} dest=/etc/httpd/conf.d/{{ apache_config }}
在Playbook中使用變數檔案定義變數
- hosts: webservers
vars_files:
- vars/server_vars.yml
tasks:
- name: deploy haproxy config
template: src={{ apache_config }} dest=/etc/httpd/conf.d/{{ apache_config }}
變數檔案vars/server_vars.yml的內容為:
apache_config: labs.conf
YAML的陷阱
YAML的陷阱是YAML和Ansible Playbook的變數語法不能在一起好好工作了。這裡特指冒號後面的值不能以{ 開頭。
下面的程式碼會報錯:
- hosts: app_servers
vars:
app_path: {{ base_path }}/22
解決辦法:要在{ 開始的值加上引號:
- hosts: app_servers
vars:
app_path: "{{ base_path }}/22"
主機的系統變數(facts)
主機的系統變數(facts)
ansible會通過module setup來收集主機的系統資訊,這些收集到的系統資訊叫做facts,這些facts資訊可以直接以變數的形式使用。
哪些facts變數可以引用呢?在命令列上通過呼叫setup module命令可以檢視
$ ansible all -m setup -u root
怎樣在playbook中使用facts變數呢,答案是直接使用:
---
- hosts: all
user: root
tasks:
- name: echo system
shell: echo {{ ansible_os_family }}
- name install ntp on Debian linux
apt: name=git state=installed
when: ansible_os_family == "Debian"
- name install ntp on redhat linux
yum: name=git state=present
when: ansible_os_family == "RedHat"
使用複雜facts變數
一般在系統中收集到如下的資訊,複雜的、多層級的facts變數如何使用呢?
...
"ansible_ens3": {
"active": true,
"device": "ens3",
"ipv4": {
"address": "10.66.192.234",
"netmask": "255.255.254.0",
"network": "10.66.192.0"
},
"ipv6": [
{
"address": "2620:52:0:42c0:5054:ff:fef2:e2a3",
"prefix": "64",
"scope": "global"
},
{
"address": "fe80::5054:ff:fef2:e2a3",
"prefix": "64",
"scope": "link"
}
],
"macaddress": "52:54:00:f2:e2:a3",
"module": "8139cp",
"mtu": 1500,
"promisc": false,
"type": "ether"
},
...
那麼可以通過下面的兩種方式訪問複雜的變數中的子屬性:
中括號:
{{ ansible_ens3["ipv4"]["address"] }}
點號:
{{ ansible_ens3.ipv4.address }}
關閉facts
在Playbook中,如果寫gather_facts來控制是否收集遠端系統的資訊.如果不收集系統資訊,那麼上面的變數就不能在該playybook中使用了.
- hosts: whatever
gather_facts: no
把執行結果當做變數使用
把執行結果當做變數使用-註冊變數
把task的執行結果當作是一個變數的值也是可以的。這個時候就需要用到註冊變數,將執行結果註冊到一個變數中,待後面的action使用:
---
- hosts: web
tasks:
- shell: ls
register: result
ignore_errors: True
- shell: echo "{{ result.stdout }}"
when: result.rc == 5
- debug: msg="{{ result.stdout }}"
檔案模板中使用的變數
檔案模板中使用的變數
檔案模板即template。Ansible使用的檔案是python的一個j2的模板。
template變數的定義
在playbook中定義的變數,可以直接在template中使用。
下面的playbook指令碼中使用了template module來拷貝檔案index.html.j2,並且替換了index.html.j2中的變數為playbook中定義變數值。
---
- hosts: web
vars:
http_port: 80
defined_name: "Hello My name is Jingjng"
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: Write the configuration file
template: src=templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify:
- restart apache
- name: Write the default index.html file
template: src=templates/index2.html.j2 dest=/var/www/html/index.html
- name: ensure apache is running
service: name=httpd state=started
- name: insert firewalld rule for httpd
firewalld: port={{ http_port }}/tcp permanent=true state=enabled immediate=yes
handlers:
- name: restart apache
service: name=httpd state=restarted
template變數的使用
在template index.html.j2中可以直接使用系統變數和使用者自定義的變數
系統變數 {{ ansible_hostname }} , {{ ansible_default_ipv4.address }}
使用者自定義的變數 {{ defined_name }}
index.html.j2檔案:
<html>
<title>#46 Demo</title>
<!--
http://stackoverflow.com/questions/22223270/vertically-and-horizontally-center-a-div-with-css
http://css-tricks.com/centering-in-the-unknown/
http://jsfiddle.net/6PaXB/
-->
<style>.block {text-align: center;margin-bottom:10px;}.block:before {content: '';display: inline-block;height: 100%;vertical-align: middle;margin-right: -0.25em;}.centered {display: inline-block;vertical-align: middle;width: 300px;}</style>
<body>
<div class="block" style="height: 99%;">
<div class="centered">
<h1>#46 Demo {{ defined_name }}</h1>
<p>Served by {{ ansible_hostname }} ({{ ansible_default_ipv4.address }}).</p>
</div>
</div>
</body>
</html>
用命令列傳遞引數
用命令列傳遞引數
定義命令列變數
在release.yml檔案裡,hosts和user都定義為變數,需要從命令列傳遞變數值。
---
- hosts: '{{ hosts }}'
remote_user: '{{ user }}'
tasks:
- ...
使用命令列變數
在命令列裡面傳值得的方法:
ansible-playbook e33_var_in_command.yml --extra-vars "hosts=web user=root"
還可以用json格式傳遞引數:
ansible-playbook e33_var_in_command.yml --extra-vars "{'hosts':'vm-rhel7-1', 'user':'root'}"
還可以將引數放在檔案裡面:
ansible-playbook e33_var_in_command.yml --extra-vars "@vars.json"
更多的Ansible模組
更多的Ansible模組
- 介紹兩類Modules: Core Module和Extra module
- Extra module的配置和使用方法
- 通過命令列檢視modules的用法
Modules的分類
Modules的分類
你Ansible Module文件上檢視單個Module的時候,每一個Module文件的底部都會標識, 這是一個"Core Module", 或者這是一個"Extra Module".
比如, yum就是一個core module, yum_repository就是一個extra module,
Core Module
- 不需要格外下載和配置就可以直接使用的.
- 比較常用的module
- 經過嚴格測試的.
Extra module
- 進行下載和格外的配置才能使用
- 次常用的
- 還有可能存在bug的
Extra module的使用方法
Extra module的使用方法
使用Exra module需要進行下面的配置,就可以在命令列或者是playbook中使用了。配置後extra module使用方法和core module的使用方法是一樣的。
1 下載ansible module extra專案
git clone https://github.com/ansible/ansible-modules-extras.git
我的一下在/home/jshi/software/目錄下了,後面會用到。
2 修改配置檔案或者環境變數
方法1 - 改ansible預設配置檔案/etc/ansible/ansible.cfg
修改ansible配置檔案/etc/ansible/ansible.cfg, 新增一行
library = /home/jshi/software/ansible-modules-extras/
方法2 - 改ansible當前目錄下配置檔案ansible.cfg
改ansible playbook當前的目錄下的配置檔案ansible.cfg,那麼只對當前目錄的playbook生效。對所有其它目錄,包括父目錄和子目錄的playbook都不生效。
library/ansible-modules-extras
ansible.cfg
use_extra_module.yml
subfolder/use_extra_module_will_throw_error.yml
在當前目錄的ansible.cfg中,可以使用相對路徑:
library = library/ansible-modules-extras/
方法3 - 該環境變數
export ANSIBLE_LIBRARY=/project/demo/demoansible/library/ansible-module-extras
如果需要在重啟後生效,那麼放在~/.bashrc中宣告ANSIBLE_LIBRARY變數:
$ echo >>~/.bashrc <<EOF
export ANSIBLE_LIBRARY=/project/demo/demoansible/library/ansible-module-extras
EOF
$ source ~/.bashrc
命令列檢視module的用法
命令列檢視module的用法
類似bash命令的man,ansible也可以通過命令列檢視module的用法。命令是ansible-doc,語法如下:
ansible-doc module_name
core module可以在任何目錄下執行。例如檢視yum的用法:
ansible-doc yum
extra module必須在配置了extra module的目錄下檢視用法(行為當前目錄下的playbook是一致的):
ansible-doc yum_repository
相關文章
- Ansible 進階 | 動態 Inventory
- ansible高階應用ansible-vault
- ansible高階操作 serial滾動更新
- 02 . Ansible高階用法(運維開發篇)運維
- 進擊的 Ansible(二):如何快速搞定生產環境 Ansible 專案佈局?
- CSS高階進階CSS
- 高階前端進階(五)前端
- 高階前端進階(七)前端
- 高階前端進階(三)前端
- React 進階之高階元件React元件
- Redux 進階Redux
- ElasticSearch 進階Elasticsearch
- HBase進階
- SQL進階SQL
- JavaScript進階JavaScript
- css進階CSS
- Mongodb進階MongoDB
- Masonry進階
- vue進階Vue
- protobuf進階
- 06進階
- Typescript 高階語法進階TypeScript
- React 進階(三) 高階元件React元件
- 高階前端進階系列 - webview前端WebView
- ansible
- Java小白進階筆記(5)-進階物件導向Java筆記物件
- SQLMAP進階使用SQL
- 進階筆記筆記
- sqlmap 進階 (一)SQL
- RocketMQ進階技巧MQ
- Sanic 路由進階路由
- React 進階一React
- 微服務進階微服務
- Typescript進階之路TypeScript
- Redux進階(一)Redux
- CSS進階 --- BFCCSS
- Flutter redux 進階FlutterRedux
- Python進階Python