在管理機器上安裝ansible工具html
yum install ansiblenode
將須要管理的主機加入absible,的主機管理清單配置文件/etc/ansible/hostspython
格式:inventory文件遵循INI文件風格,中括號中的字符爲組名。 能夠將同一個主機同時歸併到多個不一樣的組中;此外,當如若 目標主機使用了非默認的SSH端口,還能夠在主機名稱以後 使用冒號加端口號來標明mysql
1)不分組方式 #不推薦這樣使用linux
192.168.136.5:2222 #冒號後面的2222表示端口號nginx
192.168.136.6git
2)分組方式github
[web] # web表示組名,分組之後能夠直接經過組名來進行管理組裏面的主機web
192.168.136.5正則表達式
192.168.136.6
[opt]
192.168.136.[7:10] #這表示範圍,從192.168.136.7到192.168.136.10之間的全部主機
[webservers]
www1.magedu.com
www2.magedu.com
ansible管理主機通常最好是先基於key驗證以後管理起來會比較方便
步驟:
1)生成公私鑰對
ssh-keygen
2)將公鑰複製到全部主機
能夠編寫腳本:完成這一步
也能夠用ssh-copy-id <主機ip>便可
ansible 配置文件
Ansible 配置文件/etc/ansible/ansible.cfg (通常保持默認)
[defaults]
#inventory = /etc/ansible/hosts # 主機列表配置文件
#library = /usr/share/my_modules/ # 庫文件存放目錄
#remote_tmp = $HOME/.ansible/tmp #臨時py命令文件存放在遠程主 機目錄
#local_tmp = $HOME/.ansible/tmp # 本機的臨時命令執行目錄
#forks = 5 # 默認併發數
#sudo_user = root # 默認sudo 用戶
#ask_sudo_pass = True #每次執行ansible命令是否詢問ssh密碼
#ask_pass = True
#remote_port = 22
#host_key_checking = False # 檢查對應服務器的host_key,建議取消 註釋
#log_path = /var/log/ansible.log #會把你執行的命令生成日誌計入在/var/log/ansible.log文件中,建議把這一項啓用起來,
ansible
功能介紹 |
基於模塊化,遠程管理主機,而且是基於ssh方式鏈接主機的方式,安全性高 |
格式 |
<host-pattern> [-m module_name] [-a args] |
特色 |
1)模塊化:調用特定的模塊,完成特定任務 2)有Paramiko,PyYAML,Jinja2(模板語言)三個關鍵模塊 3)支持自定義模塊 4)基於Python語言實現 5)部署簡單,基於python和SSH(默認已安裝),agentless 6)安全,基於OpenSSH 7)支持playbook編排任務 8)冪等性:一個任務執行1遍和執行n遍效果同樣,不因重複執行帶來意外狀況 9)無需代理不依賴PKI(無需ssl) 10)可以使用任何編程語言寫模塊 11)YAML格式,編排任務,支持豐富的數據結構 12)較強大的多層解決方案 |
ansable系列命令 |
ansible ansible-doc ansible-playbook ansible-vault ansible-console ansible-galaxy ansible-pull |
ansible-doc 查看模 塊幫助用法 |
ansible-doc –l 列出全部模塊 ansible-doc ping 查看指定模塊幫助用法 ansible-doc –s ping 查看指定模塊幫助用法 |
ansible命令執行過程
1. 加載本身的配置文件 默認/etc/ansible/ansible.cfg
2. 加載本身對應的模塊文件,如command
3. 經過ansible將模塊或命令生成對應的臨時py文件,並將該 文 件傳輸至遠程服務器的對應執行用戶 $HOME/.ansible/tmp/ansible-tmp-數字/XXX.PY文件
4. 給文件+x執行
5. 執行並返回結果
6. 刪除臨時py文件,sleep 0退出
執行狀態:
綠色:執行成功而且不須要作改變的操做
黃色:執行成功而且對目標主機作變動
紅色:執行失敗
選項 |
說明 |
--version |
顯示版本 |
-m module |
指定模塊,默認爲command |
-v |
詳細過程 –vv -vvv更詳細 |
--list-hosts |
顯示主機列表,可簡寫—list |
--ask-pass |
提示鏈接密碼,默認Key驗證 |
-C, --check |
檢查,並不執行 |
-T --timeout=TIMEOUT |
執行命令的超時時間,默認10s |
-u --user=REMOTE_USER |
執行遠程執行的用戶 |
-b --become |
代替舊版的sudo 切換 |
模塊介紹
模塊名成 |
功能介紹及經常使用參數 |
ping |
一個簡單的測試模塊,這個模塊老是在成功的接觸中返回「乒乓」。這是不合理的 可是它對於驗證登陸的能力和可用的python來講是有用的。 配置。這不是ICMP ping,這只是一個簡單的測試模塊。對於Windows目標,使用 (win_ping)模塊。 用法: anisble 主機 -m ping |
command |
命令的模塊接受命令名,後面是空格分隔的參數列表。給定的 命令將在全部選定的節點上執行。它不會經過shell進行處理,因此變量 「$ HOME」和操做,好比「<「」、「」>「」,「」|「」、「」;「和」不會起做用(使用shell模塊 若是您須要這些特性)。 常見選項: 1),chdir <切換目錄> 格式: ansible 主機組 -m command -a ‘chdir=/app/ ls -al /app ’ 2),creates <判斷若是文件不存在就執行後面的命令> 格式: ansible 主機組 -m command -a ‘creates=/etc/fstab ls -al /app’ 3),removes <判斷若是文件存在就執行後面的命令> 格式: ansible 主機組 -m command -a 'removes=/etc/fstab ls-al /app/' |
shell |
shell的模塊接受命令名,後面是空格分隔的參數列表。這幾乎是 與命令模塊徹底同樣,可是在遠程節點上經過shell(/bin/sh')運行命令 支持 特殊符號$ HOME」和操做,好比「<「」、「」>「」,「」|「」、「」;「 在執行命令是儘可能使用單引號, 其餘用法基本跟command模塊相同 |
script |
腳本的模塊接受腳本名稱,發送到遠程主機上執行, 格式:ansible 主機組 -m script -a ‘/app/f1 .sh ’ |
copy |
copy'模塊將一個文件從本地或遠程機器複製到遠程機器上的一個位置。使用com fetch模塊將文件從遠程位置複製到本地框。若是你須要變量插值 在複製的文件中,使用模板模塊。 注意:copy模塊複製文件若是目錄不存在會自動建立目錄 經常使用參數: content:<把自定義內容複製到遠程主機文件中> 格式 : content=「df -h \nls\n\hostname dest=/app/f1.sh」 src:<本機源文件> dest:<指定複製到目標主機的某個目錄或者覆蓋某個文件> backup:<文件複製到遠程主機若是文件已存在能夠將源文件作備份,再覆蓋> 格式: backup=yes /no yes表示作備份,no表示不作備份 directory_mode :<複製整個目錄> mode:<更改複製過去的文件權限> 格式: mode=644...... owner:<更改複製過去的文件屬主> 格式:owner=wang 格式:ansible 主機組 -m copy -a ‘src=/etc/fstab dest=/app/ backup=yes mode=644 owner=wang’ |
fetch |
這個模塊的工做方式相似於複製,但反過來。它用於從遠程機器獲取文件 將它們存儲在本地目錄下 經常使用參數: src:<指定遠程主機的文件> dest:<指定本地主機的目錄> 格式:ansible 主機組 -m fetch -a ‘src=/etc/fstab best=/app/’ |
file |
支持在被控主機建立空文件,建立軟鏈接,刪除文件等做 經常使用選項: 建立空文件:path=<指定建立文件路徑> 通常配合state=touch使用 建立軟鏈接:src=<指定原始文件路徑> 通常配合path=<建立到那個目錄>,state=link<鏈接> 建立目錄:path=<指定路徑> 通常配合state=directory使用 刪除文件: path=<指定文件路徑> 通常配合state=absent使用 設置文件權限:mode<設置文件權限> owner<設置文件屬組> 格式: 建立文件 ansible 主機組 -m file -a ‘path=/app/testfile state=touch’ 建立軟鏈接 absible 主機組 -m file -a ‘src=/app/testfile path=/tmp/testfile-link stare=link’ 建立目錄 absible 主機住 -m file -a 'path=/app/dir1 state=directory' 刪除文件 ansible 主機組 -m file -a ‘path=/app/testfile state=absent’e |
hostname |
更改被控主機端的主機名 格式: ansible 主機 -m hostname -a 'name=名字' |
cron |
建立計劃任務 minute<分鐘> day <天> hour<小時> weekday<周> month<月> job<執行的操做> 注意:命令須要寫全路徑 name<計劃任務的名字> disabled=yes <yes表示禁用計劃任務,no表示啓用計劃任務> start=absent <表示刪除計劃任務> 例子: ansible 主機組 -m cron -a 'minute=*/5 hour=12 weekday=0,6 job="/usr/sbin/wall is jobs " name="test job"' 此命令原理: 建立一個名爲test job計劃任務 每週六週天,凌晨12點沒5分鐘執行一次wall廣播 is job 禁用,啓用計劃任務 ansible 主機組 -m cron -a 'disabled=yes/on job="執行的操做" name="計劃任務名字"' 刪除計劃任務 ansible 主機組 -m cron -a 'start=adsent job="執行的操做" name="計劃任務名字"' |
yum |
管理軟件包模塊 安裝軟件包 name=包名 start=absent 卸載包 start=latest 裝最新版 updata_cache=yes 更新yum緩存 |
service |
管理服務狀態模塊 經常使用選項 name=<指定包名> state=<指定運行狀態> 如:stopped<中止>,started<啓動>,restarted<重啓服務>, reloaded<重讀配置文件> , enabled=yes 表示把服務設置爲開機自動重啓 格式: 設置服務開機自動啓動而且啓動 ansible 主機組 -m service -a 'name=httpd state=started enabled=yes' |
user |
建立管理用戶 經常使用選項: name=<指定用戶名> comment=<描述信息> uid=<指定uid> home=<指定家目錄路徑> group=<指定 主組> groups=<指定輔助組> system=yes<yes表示建立的是系統用戶> shell=<指定shell類型> remove=yes <yes表示把家目錄等等相關數據全刪除> 例子: 建立普通用戶 ansible 主機組 -m user -a 'name="test" uid=2000 home=/app/test group=wang groups=root,bin ' 建立系統用戶 <注意:默認建立系統用戶會建立家目錄> ansible 主機組 -m user -a 'name=sys system=yes shell=nologin' 刪除用戶並把家目錄刪除 ansible 主機組 -m user -a 'name="test" state=absent remove=yes’ |
group |
管理組 name=<指定組名> state=<指定操做> 例子 建立組 ansible 主機組 -m group -a 'name=group1 ' 刪除組 ansible 主機組 -m group -a 'name=group1 state=absent' |
setup |
顯示全部被控主機的,全部主機信息,例如:IP,主機名,版本,等等信息 經常使用選項 filter="*信息*"<做用用來匹配想要查看的信息> 例子: ansible 主機組 -m setup -a 'filter="*hostname*"' 注意匹配時須要把匹配的值放在雙星」*「號裏面 |
匹配主機列表的方式:
All :表示全部Inventory中的全部主機
ansible all –m ping
* :通配符
ansible 「*」 -m ping #匹配全部主機執行ping模塊操做
ansible 192.168.1.* -m ping #匹配192.168.1.這個網段的全部主機,執行平模塊操做
ansible 「*srvs」 -m ping #匹配主機組名後面srvs的主機組執行ping模塊操做
或關係:
ansible 「websrvs:appsrvs」 -m ping #這表示匹配兩個主機組裏面的全部主機
ansible 「192.168.1.10:192.168.1.20」 -m ping #這是隻針對兩臺主機執行ping模塊操做
邏輯與
ansible 「websrvs:&dbsrvs」 –m ping 在websrvs組而且在dbsrvs組中的主機,才執行ping模塊操做
邏輯非
ansible 'websrvs:!dbsrvs' –m ping #在websrvs組,但不在dbsrvs組中的主機 ,執行平模塊中操做
綜合邏輯
ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' –m ping #匹配在websrvszu或者在dbsrvs組,而且在appsrvs組,但不在ftpsrvszu裏的主機,纔會執行ping模塊操做
正則表達式
ansible 「~(web|db).*\.magedu\.com」 –m ping #匹配以帶有web關鍵字後面跟任意字符.magedu.com的主機組,或者帶有db關鍵字後面跟任意字符.magedu.com的主機組,執行ping模塊操做
ansible系列命令
Ansible-vault
功能:管理加密解密yml文件
ansible-vault [create|decrypt|edit|encrypt|rekey|view]
ansible-vault encrypt hello.yml 加密
ansible-vault decrypt hello.yml 解密
ansible-vault view hello.yml 查看
ansible-vault edit hello.yml 編輯加密文件
ansible-vault rekey hello.yml 修改口令
ansible-vault create new.yml 建立新文件
Ansible-console:2.0+新增,可交互執行命令,支持tab
root@test (2)[f:10] $ 執行用戶@當前操做的主機組 (當前組的主機數量)[f:併發數]$
設置併發數: forks n 例如: forks 10
切換組: cd 主機組 例如: cd web
列出當前組主機列表: list
列出全部的內置命令: ?或help
示例:
root@all (2)[f:5]$ list
root@all (2)[f:5]$ cd appsrvs
root@appsrvs (2)[f:5]$ list
root@appsrvs (2)[f:5]$ yum name=httpd state=present
root@appsrvs (2)[f:5]$ service name=httpd state=started
經常使用選項示例:
查看主機組名裏包括多少臺主機
anisble 主機分組名 --list-host
#普通用戶與root用戶配置
[root@localhost python]# cat /etc/ansible/hosts
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - Comments begin with the '#' character
# - Blank lines are ignored
# - Groups of hosts are delimited by [header] elements
# - You can enter hostnames or ip addresses
# - A hostname/ip can be a member of multiple groups
# Ex 1: Ungrouped hosts, specify before any group headers.
## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10
10.60.32.149
# Ex 2: A collection of hosts belonging to the 'webservers' group
## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110
# If you have multiple hosts following a pattern you can specify
# them like this:
## www[001:006].example.com
# Ex 3: A collection of database servers in the 'dbservers' group
## [dbservers]
##
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57
# Here's another example of host ranges, this time there are no
# leading 0s:
## db-[99:101]-node.example.com
[docker]
10.60.32.149
[k8s]
10.60.36.220
10.60.36.210
[k8s:vars]
ansible_ssh_user=www
ansible_ssh_port=22
ansible_sudo_pass=123456
1、什麼是playbooks
playbooks是ansible的腳本、如同shell腳本同樣,它是控制遠程主機的一系列命令的集合,經過YAML語言編寫。執行一些簡單的任務,咱們可使用ad-hoc命令就能夠解決,對於一些較複雜的任務,ad-hoc就不能勝任了,這時候playbooks就派上用場了,在playbooks中能夠編排有序的執行過程,甚至能夠在多組機器間來回有序的執行特定的步驟,而且能夠同步或異步發起任務。
2、YAML語法
一、文件開始符
1
|
---
|
二、數組
1
2
3
|
- name
- hosts
- user
|
三、字典
1
2
|
name: restart apache
service: name=httpd state=restarted
|
字典與字典的嵌套:
1
2
3
|
vars:
http_port: 80
max_clients: 200
|
字典與數組的嵌套:
1
2
3
4
5
6
7
8
9
|
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
|
此外,Ansible 使用 "{{ var }}"來引用變量.,若是一個值以 "{" 開頭, YAML 將認爲它是一個字典, 因此咱們必須引用它, 像這樣:foo: "{{ variable }}"
3、playbooks的基本用法
最基本的playbook分爲四部分:
定義主機和用戶
1
2
|
hosts
users
|
定義 playbook 執行須要的變量
1
|
variable
|
定義任務
1
|
tasks
|
定義響應事件
1
|
handlers
|
簡單示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
---
- name: Install apache
hosts: webservers
user: root
gather_facts:
false
vars:
http_port: 80
max_clients: 200
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
|
說明:
name參數對此playbook實現的功能的概述,執行時會輸出name變量值。
hosts參數指定了在哪些主機上執行playbook
user參數指定在遠程主機上使用什麼用戶執行任務
gather_facts參數指定了下面任務執行前,是否先執行setup模塊獲取遠程主機相關信息,這些信息在task中能夠做爲變量使用
vars參數指定了變量
task參數指定了任務,這裏有3個任務。name參數是對具體任務的描述,在執行過程當中會輸出
handlers參數指定一個響應事件,當template: src=/srv/httpd.j2 dest=/etc/httpd.conf這個任務執行狀態是changed時纔會觸發。
一、主機和用戶
key | 含 義 |
hosts | 爲主機的IP,或者主機組名,或者關鍵字all |
user | 在遠程以哪一個用戶身份執行。 |
become | 切換成其它用戶身份執行,值爲yes或者no |
become_method | 與became一塊兒用,指能夠爲‘sudo’/’su’/’pbrun’/’pfexec’/’doas’ |
become_user | 與bacome一塊兒用,能夠是root或者其它用戶名 |
通常用法:
1
2
3
|
---
- hosts: webserver, [all]
user: root
|
還能夠在每一個 task 中,定義遠程執行用戶
1
2
3
4
5
6
7
|
---
- hosts: webserver
user: root
tasks:
- name:
test
connection
ping
:
remote_user: root
|
也支持 sudo 方法,在 task中一樣支持,在sudo須要密碼時,能夠加上選項 –ask-sudo-pass
1
2
3
4
5
6
7
8
|
---
- hosts: all
user:
test
sudo
:
yes
task:
- service: name=nginx state=started
sudo
:
yes
sudo_user: root
|
二、任務列表
tasks 是從上到下順序執行,若是中間發生錯誤,整個 playbook 便會中斷。
每個 task 是對module的一次調用,一般會帶有特定參數,參數可使用變量。
每個 task 有一個 name 屬性,name 值會在命令行中輸出,以提示用戶,若是沒有定義,aciton 的值會做爲輸出信息來標記task。
語法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
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
//
或者使用 yaml 的字典做爲參數
tasks:
- name: copy ansible inventory
file
to client
copy:
src:
/etc/ansible/hosts
dest:
/etc/ansible/hosts
owner: root
group: root
mode: 0644
//
大部分的模塊都是使用 `key-value` 這種格式的,其中有兩個比較特殊, command 和 shell 模塊。
tasks:
- name: disable selinux
command
:
/sbin/setenforce
0
tasks:
- name: run this
command
and ignore the result
shell:
/usr/bin/command
|| /bin/true
tasks:
- name: run some
command
and ignore the reslut
shell:
/usr/bin/somecommadn
ignore_error: True
|
執行狀態:
task中每一個action會調用一個module,在module中會去檢查當前系統狀態是否須要從新執行。
若是本次執行了,那麼action會獲得返回值changed
若是不須要執行,那麼action獲得返回值ok
三、響應事件
每一個主流的編程語言都會有event機制,那麼handler就是playbook的event。
Handlers裏面的每個handler,也是對module的一次調用。而handlers與tasks不一樣,tasks會默認的按定義順序執行每個task,handlers則不會,它須要在tasks中被調用,纔有可能被執行。Tasks中的任務都是有狀態的,changed或者ok。 在Ansible中,只在task的執行狀態爲changed的時候,纔會執行該task調用的handler,這也是handler與普通的event機制不一樣的地方。
什麼狀況下使用handlers呢?
若是你在tasks中修改了apache的配置文件。須要重起apache。此外還安裝了apache的插件。那麼還須要重起apache。像這樣的應該場景中,重啓apache就能夠設計成一個handler。
特性:
一個handler最多隻執行一次
在全部的任務裏表執行以後執行,若是有多個task notify同一個handler,那麼只執行一次。
在下面的例子裏apache只執行一次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
---
- 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"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//
示例代碼
---
- 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的定義順序執行
andlers是按照在handlers中定義個順序執行的,而不是安裝notify的順序執行的。
下面的例子定義的順序是1>2>3,notify的順序是3>2>1,實際執行順序:1>2>3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
---
- 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中經常使用變量的幾種狀況:
用戶自定義的變量
用戶能夠在Playbook中,經過vars關鍵字自定義變量,使用時用{{ }}引用以來便可。
示例:
1
2
3
4
5
6
7
8
|
---
- hosts: web
vars:
http_port: 80
remote_user: root
tasks:
- name: insert firewalld rule
for
httpd
firewalld: port={{ http_port }}
/tcp
permanent= true state=enabled immediate= yes
|
把變量放在單獨的文件中
當變量比較多的時候,或者變量須要在多個playbook中重用的時候,能夠把變量放到一個單獨的文件中。經過關鍵字var_files把文件中定義的變量引入playbook中,使用變量的方法和在本文件中定義的變量相同。
1
2
3
4
5
6
7
8
9
10
|
- hosts: web
remote_user: root
vars_files:
- vars
/server_vars
.yml
tasks:
- name: insert firewalld rule
for
httpd
firewalld: port={{ http_port }}
/tcp
permanent= true state=enabled immediate= yes
#cat vars/server_vars.yml
http_port: 80
|
定義複雜的變量
當變量的值不是簡單的字符串或者數字,而是一個字典,語法以下
1
2
3
|
foo:
field1: one
field2: two
|
訪問複雜變量中的子屬性,能夠利用中括號或者點號:
1
2
3
|
foo[
'field1'
]
或
foo.field1
|
系統變量(facts)
ansible會經過module setup來收集主機的系統信息,這些收集到的系統信息叫作facts,這些facts信息能夠直接以變量的形式使用。
有哪些facts變量能夠引用呢?在命令行上經過調用setup module命令能夠查看:
1
|
$ ansible all -m setup -u root
|
系統變量在playbook中能夠直接使用:
1
2
3
4
5
6
7
8
9
10
11
12
|
---
- 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變量,能夠經過下面的兩種方式的任意一種訪問複雜的變量中的子屬性:
中括號:
1
|
{{ ansible_ens3[
"ipv4"
][
"address"
] }}
|
點號:
1
|
{{ ansible_ens3.ipv4.address }}
|
關係facts變量,一旦關閉以後就不用調用了。關閉方法:
1
2
|
- hosts: webserver
gather_facts: no
|
註冊變量
把task的執行結果也能夠做爲一個變量值。這個時候就須要用到「註冊變量」,將執行結果註冊到一個變量中,待後面的action使用。
1
2
3
4
5
6
7
8
9
|
---
- hosts: web
tasks:
- shell:
ls
register: result
ignore_errors: True
- shell:
echo
"{{ result.stdout }}"
when: result.rc == 5
- debug: msg=
"{{ result.stdout }}"
|
註冊變量常常和debug module一塊兒使用,這樣能夠獲得更多action的輸出信息,幫助用戶調試。
命令行中傳遞的變量
爲了使Playbook更靈活、通用性更強,容許用戶在執行的時候傳入變量的值,這個時候就須要用到「額外變量」。
定義命令行變量
在test.yml文件裏,hosts和user都定義爲變量,須要從命令行傳遞變量值。
1
2
3
4
5
|
---
- hosts:
'{{ hosts }}'
remote_user:
'{{ user }}'
tasks:
...
|
在命令行裏面傳值得的方法:
1
|
ansible-playbook testyml --extra-vars
"hosts=web user=root"
|
還能夠用json格式傳遞參數:
1
|
ansible-playbook
test
.yml --extra-vars
"{'hosts':'vm-rhel7-1', 'user':'root'}"
|
還能夠將參數放在文件裏面:
1
|
ansible-playbook
test
.yml --extra-vars
"@vars.json"
|
五、如何執行playbook
語法:
1
|
$ ansible-playbook deploy.yml
|
查看輸出的細節
1
|
$ ansible-playbook playbook.yml --verbose
|
查看該腳本影響哪些hosts
1
|
$ ansible-playbook playbook.yml --list-hosts
|
並行執行腳本
1
|
$ ansible-playbook playbook.yml -f 10
|
4、playbooks的高級用法
一、邏輯控制
when: 條件判斷語句,相似於變成語言中的if
主機爲Debian Linux馬上關機:
1
2
3
4
|
tasks:
- name:
"shutdown Debian flavored systems"
command
:
/sbin/shutdown
-t now
when: ansible_os_family ==
"Debian"
|
根據action的執行結果,來決定接下來執行的action
1
2
3
4
5
6
7
8
9
10
|
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」還能夠轉換返回值的類型:
1
2
3
4
5
|
---
- 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
|
條件表達式
基本:
1
2
3
|
tasks:
- shell:
echo
"This certainly is epic!"
when: epic
|
否認:
1
2
3
|
tasks:
- shell:
echo
"This certainly isn't epic!"
when: not epic
|
變量定義:
1
2
3
4
5
|
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
|
數值表達:
1
2
3
4
|
tasks:
-
command
:
echo
{{ item }}
with_items: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
|
與Include一塊兒用:
1
2
|
- include: tasks
/sometasks
.yml
when:
"'reticulating splines' in output"
|
與Role一塊兒用:
1
2
3
|
- hosts: webservers
roles:
- { role: debian_stock_config, when: ansible_os_family ==
'Debian'
}
|
loop: 循環語句,相似於編程語言的中的while
標準循環
爲了保持簡潔,重複的任務能夠用如下簡寫的方式:
1
2
3
4
|
- name: add several
users
user: name={{ item }} state=present
groups
=wheel
with_items:
- testuser1
|
若是你在變量文件中或者 'vars' 區域定義了一組YAML列表,你也能夠這樣作:
1
2
3
4
5
6
|
vars:
somelist: [
"testuser1"
,
"testuser2"
]
tasks:
-name: add several user
user: name={{ item }} state=present
groups
=wheel
with_items:
"{{somelist}}"
|
使用 'with_items' 用於迭代的條目類型不只僅支持簡單的字符串列表.若是你有一個哈希列表,那麼你能夠用如下方式來引用子項:
1
2
3
4
5
|
- name: add several
users
user: name={{ item.name }} state=present
groups
={{ item.
groups
}}
with_items:
- { name:
'testuser1'
,
groups
:
'wheel'
}
- { name:
'testuser2'
,
groups
:
'root'
}
|
注意:若是同時使用 when 和 with_items (或其它循環聲明),when聲明會爲每一個條目單獨執行。
嵌套循環:
1
2
3
4
5
6
7
8
9
10
11
|
- 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'
]
|
對字典使用循環:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
---
vars:
users
:
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 能夠以非遞歸的方式來模式匹配單個目錄中的文件.以下面所示:
1
2
3
4
5
6
7
|
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: 把幾個tasks組成一塊代碼,便於針對一組操做的異常處理等操做。
多個action組裝成塊,能夠根據不一樣條件執行一段語句 :
1
2
3
4
5
6
7
8
9
10
11
|
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
|
組裝成塊處理異常更方便:
1
2
3
4
5
6
7
8
9
10
11
|
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"
|
二、重用playbook
Playbook支持兩種重用機制,一種是重用靜態Playbook腳本,另一種是相似於編程語言中函數的機制。
include語句 - 重用靜態的Playbook腳本,使用起來簡單、直接。
Include語句的功能,基本的代碼重用機制。主要重用tasks。同時Include可將tasks分割成多個文件,避免Playbook過於臃腫,使用戶更關注於總體的架構,而不是實現的細節上。
普通用法
像其它語言的Include語句同樣,直接Include:
1
2
3
4
5
6
7
8
|
---
# 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
|
高級用法-使用參數
include文件中還能夠定義參數
被include的文件tasks/firewall_httpd_default.yml中,使用{{ port }}定義了一個名字爲port的參數。
1
2
3
|
---
- name: insert firewalld rule
for
httpd
firewalld: port={{ port }}
/tcp
permanent= true state=enabled immediate= yes
|
傳參數的各類方法
在執行的playbook傳參數,能夠加在行尾,使用空格分隔:
1
2
3
4
|
tasks:
- include: tasks
/firewall
.yml port=80
- include: tasks
/firewall
.yml port=3260
- include: tasks
/firewall
.yml port=423
|
還可使用yml的字典傳參數:
1
2
3
4
5
6
7
|
tasks:
- include: wordpress.yml
vars:
wp_user: timmy
ssh_keys:
- keys
/one
.txt
- keys
/two
.txt
|
還能夠把一條task簡寫成成一個類JSON的形式傳參數:
1
|
- { include: wordpress.yml, wp_user: timmy, ssh_keys: [
'keys/one.txt'
,
'keys/two.txt'
] }
|
固然在playbook中已經定義了的參數,就不須要再顯示傳入值了,能夠直接寫成下面的:
1
2
3
4
5
6
7
|
---
- hosts: lb
vars:
port: 3206
remote_user: root
tasks:
- include: tasks
/firewall
.yml
|
role語言 - Playbook的"函數機制",使用方法稍複雜、功能強大。是Playbook腳本的共享平臺ansible galaxy主要的分享方式
Role是比include更強大靈活的代碼重用和分享機制。Include相似於編程語言中的include,是重用單個文件的,功能有限。
而Role相似於編程語言中的「Package」,能夠重用一組文件造成完整的功能。例如安裝和配置apache,須要tasks實現安裝包和拷貝模版等,httpd.conf和index.html的模版文件,和handler文件實現重起功能。這些文件均可以放在一個role裏面,供不一樣的playbook文件重用。
Ansible很是提倡在playbook中使用role,而且提供了一個分享role的平臺Ansible Galaxy, https://galaxy.ansible.com/, 在galaxy上能夠找到別人寫好的role。
在ansible中,經過遵循特定的目錄結構,就能夠實現對role的定義:
下面的目錄結構定義了一個role:名字爲myrole。在site.yml,調用了這個role。
role的目錄結構:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
site.yml
roles/
├── myrole
├── tasks
│ └── main.yml
├── handlers
│ └── main.yml
├── defaults
│ └── main.yml
├── vars
│ └── main.yml
├── files
├── templates
├── README.md
├── meta
│ └── main.yml
└── tests
├── inventory
└──
test
.yml
|
site.yml中調用role
1
2
3
4
|
---
- hosts: webservers
roles:
- myrole
|
ansible並不要求role包含上述全部的目錄及文件,根據role的功能須要加入對應的目錄和文件。下面是每一個目錄和文件的功能。
若是 roles/x/tasks/main.yml 存在, 其中列出的 tasks 將被添加到 play 中,因此這個文件也能夠視做role的入口文件,想看role作了什麼操做,能夠今後文件看起。
若是 roles/x/handlers/main.yml 存在, 其中列出的 handlers 將被添加到 play 中
若是 roles/x/vars/main.yml 存在, 其中列出的 variables 將被添加到 play 中
若是 roles/x/meta/main.yml 存在, 其中列出的 「角色依賴」 將被添加到 roles 列表中
roles/x/tasks/main.yml中全部tasks,能夠引用 roles/x/{files,templates,tasks}中的文件,不須要指明文件的路徑。
在寫role的時候,通常都要包含role入口文件roles/x/tasks/main.yml,其它的文件和目錄,能夠根據需求選擇加入。
參數在role中是如何定義的呢
定義一個帶參數的role,名字是myrole,那麼目錄結構爲:
1
2
3
4
5
|
main.yml
roles
role_with_var
tasks
main.yml
|
在roles/myrole/tasks/main.yml中,使用{{ }}定義的變量就能夠了
1
2
3
|
---
- name: use param
debug: msg=
"{{ param }}"
|
使用帶參數的role
那麼在main.yml就能夠用以下的方法使用myrole
1
2
3
4
5
|
---
- hosts: webservers
roles:
- { role: myrole, param:
'Call some_role for the 1st time'
}
- { role: myrole, param:
'Call some_role for the 2nd time'
}
|
或者寫成YAML字典格式:
1
2
3
4
5
6
7
|
---
- hosts: webservers
roles:
- role: myrole
param:
'Call some_role for the 1st time'
- role: myrole
param:
'Call some_role for the 2nd time'
|
role指定默認的參數
指定默認參數後,若是在調用時傳參數了,那麼就使用傳入的參數值.若是調用的時候沒有傳參數,那麼就使用默認的參數值.
指定默認參數很簡單,以上面的role_with_var爲例
1
2
3
4
5
6
7
|
main.yml
roles:
myrole
tasks
main.yml
defaults
main.yml
|
在roles/myrole/defaults/main.yml中,使用yml的字典定義語法定義param的值,以下:
param: "I am the default value"
這樣在main.yml中,下面兩種調用方法均可以
1
2
3
4
5
|
---
- hosts: webservers
roles:
- role_with_var
- { role: role_with_var, param:
'I am the value from external'
}
|
role與條件語句when一塊兒執行,下面的例子中,my_role只有在RedHat系列的server上才執行。
1
2
3
4
5
6
7
8
9
10
11
|
---
- hosts: webservers
roles:
- { role: my_role, when:
"ansible_os_family == 'RedHat'"
}
一樣也能夠寫成YAML字典格式
---
- hosts: webservers
roles:
- role: my_role
when:
"ansible_os_family == 'RedHat'"
roles和tasks的執行順序
|
若是一個playbook同時出現role和tasks,他們的調用順序以下:
pre_tasks > role > tasks > post_tasks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
---
- hosts: lb
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'
執行的結果爲:
PLAY [lb] **********************************************************************
TASK [setup] *******************************************************************
ok: [rhel7u3]
TASK [pre] *********************************************************************
changed: [rhel7u3]
TASK [some_role : some role] ***************************************************
ok: [rhel7u3] => {
"msg"
:
"Im some role"
}
TASK [task] ********************************************************************
changed: [rhel7u3]
TASK [post] ********************************************************************
changed: [rhel7u3]
PLAY RECAP *********************************************************************
rhel7u3 : ok=5 changed=3 unreachable=0 failed=0
|
三、tags的用法
若是playbook文件比較大,在執行的時候只是想執行部分功能,這個時候沒有有解決方案呢?Playbook提供了tags便籤能夠實現部分運行。
tags的基本用法
例如,文件example.yml如何所示,標記了兩個tag:packages和configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
tasks:
- yum: name={{ item }} state=installed
with_items:
- httpd
tags:
- packages
- name: copy httpd.conf
template: src=templates
/httpd
.conf.j2 dest=
/etc/httpd/conf/httpd
.conf
tags:
- configuration
- name: copy index.html
template: src=templates
/index
.html.j2 dest=
/var/www/html/index
.html
tags:
- configuration
|
那麼咱們在執行的時候,若是不加任何tag參數,那麼會執行全部的tasks
1
|
$ ansible-playbook example.yml
|
指定執行安裝部分的tasks,則能夠利用關鍵字tags
1
|
$ ansible-playbook example.yml --tags
"packages"
|
指定不執行packages部分的task,則能夠利用關鍵字skip-tags
1
|
$ ansible-playbook example.yml --skip-tags
"configuration"
|
特殊的Tags:「always」
tags的名字是用戶自定義的,可是若是你把tags的名字定義爲「always」,那麼就有點特別了。只要在執行playbook時,沒有明確指定不執行always tag,那麼它就會被執行。
在下面的例子中,即便你只指定執行packages,那麼always也會被執行。
1
2
3
4
5
6
7
8
9
10
11
12
|
tasks:
- debug: msg=
"Always print this debug message"
tags:
- always
- yum: name= state=installed
with_items:
- httpd
tags:
- packages
- template: src=templates
/httpd
.conf.j2 dest=
/etc/httpd/conf/httpd
.conf
tags:
- configuration
|
指定運行packages時,仍是會執行always tag對應的tasks
1
2
3
4
5
6
7
8
9
10
11
|
$ ansible-playbook tags_always.yml --tags
"packages"
「tagged」,「untagged」和「all」
tasks:
- debug: msg=
"I am not tagged"
tags:
- tag1
- debug: msg=
"I am not tagged"
分別指定--tags爲「tagged」,「untagged」和「all」試下效果吧:
$ ansible-playbook tags_tagged_untagged_all.yml --tags tagged
$ ansible-playbook tags_tagged_untagged_all.yml --tags untagged
$ ansible-playbook tags_tagged_untagged_all.yml --tags all
|
在include中和role中使用tags
include語句指定執行的tags的語法:
1
2
|
- include: foo.yml
tags: [web,foo]
|
調用role中的tags的語法爲:
1
2
|
roles:
- { role: webserver, port: 5000, tags: [
'web'
,
'foo'
] }
|
四、playbook文件加密
ansible-vault命令能夠對配置文件進行基於密碼的加密,防止敏感信息泄漏。
加密已存在文件
1
|
$ ansible-vault encrypt site.yml
|
加密並建立文件
1
|
$ ansible-vault create filename
|
執行加密後的playbook
1
|
$ ansible-playbook site.yml --ask-vault-pass
|
解密
1
|
$ ansible-vault decrypt site.yml
|
5、編譯安裝nginx的playbook的實例
playbooks目錄結構:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
$ tree playbooks
playbooks
├── group_vars
├── roles
│ └── nginx
│ ├── files
│ │ ├── nginx-1.8.0.
tar
.gz
│ │ └── pcre-8.33.
tar
.gz
│ ├── handlers
│ │ └── main.yml
│ ├── tasks
│ │ └── main.yml
│ └── templates
│ └── default.conf
└── site.yml
|
yml文件內內容以下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
$
cat
playbooks /site .yml
---
- name: Install Nginx
hosts:
test
user: admin
roles:
- nginx
$
cat
playbooks /roles/nginx/tasks/main .yml
---
- name: Copy nginx software
copy: src=nginx-1.8.0.
tar
.gz dest=
/app/admin/soft/nginx-1
.8.0.
tar
.gz
- name: Copy pcre software
copy: src=pcre-8.33.
tar
.gz dest=
/app/admin/soft/pcre-8
.33.
tar
.gz
- name: Install Pcre
shell:
cd
/app/admin/soft ; tar zxf pcre-8.33. tar .gz; cd pcre-8.33;. /configure ; make ; make install
sudo
:
yes
- name: Install Nginx
shell:
cd
/app/admin/soft ; tar zxf nginx-1.8.0. tar .gz; cd nginx-1.8.0;. /configure --user=admin --group=app --prefix= /app/admin/nginx --with-http_stub_status_module --with-http_ssl_module; make ; make install
- name: Copy nginx configuration
template: src=default.conf dest=
/app/admin/nginx/conf/nginx
.conf
notify: restart nginx
[admin@wts-vm-01 ~]$
cat
playbooks /roles/nginx/handlers/main .yml
---
- name: restart nginx
shell:
/app/admin/nginx/sbin/nginx
sudo
:
yes
|
6、其它官方例子Ansible官方提供了一些比較經常使用的、通過測試的Playbook例子:https://github.com/ansible/ansible-examplesPlaybook分享平臺:https://galaxy.ansible.com/