[TOC]
** 部分內(nèi)容源于網(wǎng)絡(luò)盛险,文檔是個人學(xué)習(xí)筆記與記錄**
什么是ansible?
Ansible is Simple IT Automation——簡單的自動化IT工具汁果,可以實現(xiàn) 批量系統(tǒng)配置、批量程序部署窖剑、批量運行命令等功能麻车,簡而言之汉矿,就是 <span style='color:red'> 分布式集中管理工具</span>, 通俗的講就是批量在遠端服務(wù)器上執(zhí)行命令宿百。其實趁仙,ansible自身不具備部署能力的,只是提供框架垦页,其核心為模塊
ansible架構(gòu)圖
五大部分 | 功能 |
---|---|
connection plugins | 遠程連接插件 |
hosts | 定義管理主機或主機組 |
modules | 包含各個核心模塊及自定義模塊 |
Plugin | 完成模塊功能的補充雀费,如日志插件、郵件插件等 |
Playbook | ansible的任務(wù)配置文件痊焊,將多個任務(wù)定義在劇本中進行管理 |
?
?
?
ansible 的工作流程
?
?
?
安裝ansible
#配置源 ansible默認(rèn)不在yum倉庫中
rpm -iUvh http://ftp.jaist.ac.jp/pub/Linux/Fedora/epel//7/x86_64/e/epel-release-7-9.noarch.rpm
#此源主要是為了安裝PyYAML
wget http://mirrors.163.com/.help/CentOS7-Base-163.repo
mv CentOS7-Base-163.repo /etc/yum.repos.d/
yum -y install ansible
ansible --version
#可查看當(dāng)前ansible版本
配置登錄
ansible 使用ssh登錄盏袄,所以主奴之間要配置密鑰進行認(rèn)證,這樣才能開始正常工作
ssh-keygen -t rsa #回車
#將會生成密鑰/root/.ssh/id_rsa.pub
ssh-copy-id -i root@ipaddress
#公鑰將會被cp到各個ipaddress節(jié)點
#至此 已經(jīng)實現(xiàn)了master與各節(jié)點的連接
定義Ansible的節(jié)點清單
vim /etc/ansible/hosts
[testgroup]-----#服務(wù)器組的名字薄啥,方便統(tǒng)一管理辕羽,劃分和命名要有規(guī)劃
192.168.1.XX----#組內(nèi)節(jié)點的地址
192.168.1.XXX
等等
[websever]
....
[DBserver]
....
簡單的遠程操作
通過執(zhí)行who,查看服務(wù)器登錄信息
ansible testgroup -m command -a 'who' #組
ansible all -m command -a 'who' # 所有
ansible 192.168.1.XX -m command -a 'who' #單個ip
##
192.168.247.152 | SUCCESS | rc=0 >>
root :0 2017-02-15 22:33 (:0)
root pts/0 2017-02-15 22:34 (:0)
root pts/1 2017-02-18 13:08 (192.168.247.1)
root pts/2 2017-03-07 22:52 (:0)
root pts/3 2017-03-07 22:54 (192.168.247.156)
# 以ashin用戶身份ping .134
ansible 192.168.1.134 -m ping -u zili
# 以用戶zili身份使用sudo來ping 組testgroup
# -K是輸入root密碼
ansible v1 -m ping -u zili --sudo -K
定義變量
定義主機變量
[web]
192.168.247.152 http_port=80
............... http_port=303
[mysql]
192.168.247.152
...
#組名以及ip根本自己需求定義
#主機指定變量垄惧,以便后面供palybooks配置使用刁愿。
#定義兩臺web服務(wù)器的apache參數(shù)http_port,可以讓兩臺服務(wù)器產(chǎn)生的apache配置文件httpd.conf差異化
定義組變量
[web]
192.168.247.152
[web:vars]
http_port=80
#組變量的作用域是覆蓋組所有成員到逊,通過定義一個新塊铣口,塊名由組名+ ":vars"組成。
嵌套組
[web]
192.168.247.152
[mysql]
192.168.247.152
...
[nested:children]
web
mysql
[nested:vars]
ntp_server=s1b.time.edu.cn
##
嵌套組定義一個新塊蕾管,塊名由 組名+":chilren" 組成枷踏。
同是嵌套組也可以定義組變量,作用域是嵌套組里的所有組,
嵌套組只能在/usr/bin/ansible-playbook中掰曾,
在/usr/bin/ansible中不起作用旭蠕,下面會介紹playbook
分離主機和組特定數(shù)據(jù)
為更好的規(guī)范定義的主機與組變量,我們實際是不會在hosts里直接寫的var旷坦,將定義的主機名與組變量單獨剝離出來放到指定的文件中掏熬,將采用YAML格式存放
全局的變量放在group_vars/all中,局部變量放在group_vars/x中秒梅,特定的host使用特定的變量可以使用host_vars/x旗芬,子group中的變量會覆蓋上級變量,hosts變量總是覆蓋groups變量
存放位置規(guī)定:"/etc/ansible/group_vars/名"和"/etc/ansible/host_vars/主機名"分別存放指定組名或主機名定義的變量捆蜀,如
/etc/ansible/group\_vars/mysql.yml
/etc/ansible/host\_vars/192.168.11.1.yml
使用變量要用jinja語法去引用
cat mysql.yml
---
ntp_server: s1b.time.edu.cn
database_server: 192.168.247.152
##
規(guī)范變量名字疮丛,是因為,ansible會自動加載這目錄下的變量辆它,
否則無法調(diào)用誊薄,當(dāng)然也有解決不放此目錄的方法
例如
[root@master ansible]# tree
├── create_user.yml
├── group_vars
│ └── t1.yml
├── hosts
[root@master ansible]# cat hosts
[t1]
10.1.27.24
所以
├── group_vars
│ └── t1.yml #他的內(nèi)容就是t1的變量
[root@master ansible]# cat group_vars/t1.yml
---
user: ansibleTest1
[root@master ansible]# cat create_user.yml
# create user
---
- name: create user
hosts: t1
user: root
tasks:
- name: useradd {{ user }} #引用t1變量
user: name="{{ user }}"
返回結(jié)果如下
[root@master ansible]# ansible-playbook create_user.yml
PLAY [create user] ***********************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************
ok: [10.1.27.24]
TASK [useradd ansibleTest1] **************************************************************************************************
changed: [10.1.27.24]
PLAY RECAP *******************************************************************************************************************
10.1.27.24 : ok=2 changed=1 unreachable=0 failed=0
命令參數(shù)
ansible <host-pattern> [options]
-m MODULE_NAME, --module-name=MODULE_NAME 要執(zhí)行的模塊,默認(rèn)為 command
-a MODULE_ARGS, --args=MODULE_ARGS 模塊的參數(shù)
-u REMOTE_USER, --user=REMOTE_USER ssh 連接的用戶名锰茉,默認(rèn)用 root呢蔫,ansible.cfg 中可以配置
-k, --ask-pass 提示輸入 ssh 登錄密碼,當(dāng)使用密碼驗證登錄的時候用
-s, --sudo sudo 運行
-U SUDO_USER, --sudo-user=SUDO_USER sudo 到哪個用戶飒筑,默認(rèn)為 root
-K, --ask-sudo-pass 提示輸入 sudo 密碼片吊,當(dāng)不是 NOPASSWD 模式時使用
-B SECONDS, --background=SECONDS run asynchronously, failing after X seconds(default=N/A)
-P POLL_INTERVAL, --poll=POLL_INTERVAL set the poll interval if using
-B (default=15)
-C, --check 只是測試一下會改變什么內(nèi)容绽昏,不會真正去執(zhí)行
-c CONNECTION 連接類型(default=smart)
-f FORKS, --forks=FORKS fork 多少個進程并發(fā)處理,默認(rèn) 5
-i INVENTORY, --inventory-file=INVENTORY 指定hosts文件路徑默認(rèn) default =/etc/ansible/hosts
-l SUBSET, --limit=SUBSET 指定一個 pattern俏脊,對<host_pattern>已經(jīng)匹配的主機中再過濾一次
--list-hosts 只打印有哪些主機會執(zhí)行這個 playbook 文件:不是實際執(zhí)行該 playbook
-M MODULE_PATH, --module-path=MODULE_PATH 要執(zhí)行的模塊的路徑全谤,默認(rèn)為/usr/share/ansible/
-o, --one-line 壓縮輸出,摘要輸出
--private-key=PRIVATE_KEY_FILE 私鑰路徑
-T TIMEOUT, --timeout=TIMEOUT ssh 連接超時時間联予,默認(rèn) 10 秒
-t TREE, --tree=TREE 日志輸出到該目錄啼县,日志文件名會以主機名命名
-v, --verbose verbose mode (-vvv for more, -vvvv to enable connection debugging)
Pattern
可以直接指定ip或hosts中的組名,同時指定多個組或者多個ip
使用:
分割
ansible group1:group2 -m ping
ansible ip1:ip2 -m ping
#all 或者 * 代表全部
ansible all -m ping
# 感嘆號 ! 表示非
g1:!g2 #表示在g1分組中沸久,但是不在g2中的hosts
# &符號表示交集
g1:&g2 #表示在g1分組中季眷,也在g2中的hosts
#使用下標(biāo)
g1[2] #組的第三個
g1[0:3] #組的前四個
常用模塊
copy模塊
目的:把主控端/root目錄下的a.sh文件拷貝到到指定節(jié)點上
命令:ansible 192.168.247.152 -m copy -a 'src=/root/a.sh dest=/tmp/ owner=root group=root mode=0755'
file模塊
目的:更改指定節(jié)點上/tmp/t.sh的權(quán)限為755,屬主和屬組為root
命令:ansible all -m file -a "dest=/tmp/t.sh mode=755 owner=root group=root"
cron模塊
目的:在指定節(jié)點上定義一個計劃任務(wù)卷胯,每隔3分鐘到主控端更新一次時間
命令:ansible all -m cron -a 'name="custom job" minute=*/3 hour=* day=* month=* weekday=* job="/usr/sbin/ntpdate 192.168.247.152"'
group模塊
目的:在所有節(jié)點上創(chuàng)建一個組名為nolinux子刮,gid為2014的組
命令:ansible all -m group -a 'gid=2014 name=nolinux'
uesr模塊
目的:在所有節(jié)點上創(chuàng)建一個用戶名為nolinux,組為nolinux的用戶
命令:ansible all -m user -a 'name=nolinux groups=nolinux state=present'
刪除用戶
命令:ansible all -m user -a 'name=nolinux state=absent remove=yes'
yum模塊
目的:在指定節(jié)點上安裝 apache 服務(wù)
命令:ansible all -m yum -a "state=present name=httpd"
#state=latest 安裝最新版本
shell模塊
目的:在指定節(jié)點上安裝 apache 服務(wù)
命令:ansible testgroup -m shell -a 'yum -y install httpd'
command模塊
目的:在指定節(jié)點上運行hostname命令
命令:ansible 192.168.247.152 -m command -a 'hostname'
raw模塊
目的:在192.168.247.152節(jié)點上運行ifconfig命令
命令:ansible 192.168.247.152 -m raw-a 'ifconfig|eth0'
script模塊
目的:在指定節(jié)點上執(zhí)行/root/a.sh腳本(該腳本是在ansible主控端)
命令:ansible 10.1.1.113 -m script -a '/root/a.sh'
command,script,shell,raw的區(qū)別
思考:四者有何區(qū)別窑睁?
command模塊 [執(zhí)行遠程命令]
ansible client -m command -a "uname -n" -s
script模塊 [在遠程主機執(zhí)行主控端的shell/python腳本]
ansible client -m script -a "/soft/ntpdate.py" -s
shell模塊 [執(zhí)行遠程主機的shell/python腳本]
ansible client -m shell -a "/soft/file.py" -s
raw模塊 [類似于command模塊挺峡、支持管道傳遞]
ansible client -m raw -a "ifconfig eth0|sed -n 2p|awk '{print \$2}'" -s
service模塊
目的:啟動指定節(jié)點上的 httpd 服務(wù),并讓其開機自啟動
命令:ansible 192.168.247.152 -m service -a 'name=httpd state=restarted enabled=yes'
ping模塊
目的:檢查指定節(jié)點機器是否還能連通
命令:ansible 192.168.247.152 -m ping
get_url
目的:下載百度下的圖標(biāo)文件到節(jié)點的/tmp文件下
命令:ansible testgroup -m get_url -a 'url=https://www.baidu.com/favicon dest=/tmp'
#結(jié)果為error.html担钮,但是證明了模塊是可用的
stat模塊
目的:獲取遠程文件狀態(tài)信息橱赠,包括atime、ctime箫津、mtime狭姨、md5、uid苏遥、gid等信息
ansible web -m stat -a 'path=/etc/sysctl.conf'
template模塊
template使用了Jinja2格式作為文件模版饼拍,進行文檔內(nèi)變量的替換的模塊。它的每次使用都會被ansible標(biāo)記為”changed”狀態(tài)田炭。
模塊參數(shù)
參數(shù)名 | 是否必須 | 默認(rèn)值 | 選項 | 說明 |
---|---|---|---|---|
backup | no | no | yes/no | 建立個包括timestamp在內(nèi)的文件備份师抄,以備不時之需. |
dest | yes | 遠程節(jié)點上的絕對路徑,用于放置template文件教硫。 | ||
group | no | 設(shè)置遠程節(jié)點上的的template文件的所屬用戶組 | ||
mode | no | 設(shè)置遠程節(jié)點上的template文件權(quán)限叨吮。類似Linux中chmod的用法 | ||
owner | no | 設(shè)置遠程節(jié)點上的template文件所屬用戶 | ||
src | yes | 本地Jinjia2模版的template文件位置 |
模塊參數(shù)案例
把/mytemplates/foo.j2文件經(jīng)過填寫參數(shù)后,復(fù)制到遠程節(jié)點的/etc/file.conf瞬矩,文件權(quán)限相關(guān)略過
- template: src=/mytemplates/foo.j2 dest=/etc/file.conf owner=bin group=wheel mode=0644
跟上面一樣的效果挤安,不一樣的文件權(quán)限設(shè)置方式
- template: src=/mytemplates/foo.j2 dest=/etc/file.conf owner=bin group=wheel mode="u=rw,g=r,o=r"
#詳細(xì)說明
roles/templates/server.xml中的template文件關(guān)鍵部分如下:
<user username="{{ admin_username }}" password="{{ admin_password }}" roles="manager-gui" />
#當(dāng)這個文件還沒被template執(zhí)行的時候,本地的admin_username及admin_password 都是變量狀態(tài)丧鸯。
#當(dāng)playbook執(zhí)行完template的時候,遠程的admin_username*及admin_password 會變成變量所對應(yīng)的值嫩絮。
#例
#前面的那個Playbook,如果我們在tomcat-servers設(shè)置了這兩個變量如下:
dmin_username: admin
admin_password: adminsecret
#那么在執(zhí)行這個Playbook前丛肢,對應(yīng)的那個template文件(俗稱模版)围肥,
將在本地保持{{ admin_username }}及{{ admin_password }}的狀態(tài)。
在Ansible調(diào)用template模版執(zhí)行的時候蜂怎,這里將由Jinjia2從”tomcat-servers”讀取對應(yīng)的值穆刻,
然后替換掉模版里的變量,然后把這個替換變量值后的文件拷貝到遠程節(jié)點杠步。
#這個就是template的意義所在氢伟。
更多模塊
ansible-doc -l 查詢
playbook的配置和使用
配置文件后綴名為.yml
官網(wǎng)demo說明
#這個是你選擇的主機
- hosts: webservers
#這個是變量
vars:
http_port: 80
max_clients: 200
#遠端的執(zhí)行權(quán)限
remote_user: root
tasks:
#利用yum模塊來操作
- 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
#觸發(fā)重啟服務(wù)器
notify:
- restart apache
- name: ensure apache is running
service: name=httpd state=started
#這里的restart apache 和上面的觸發(fā)是配對的。這就是handlers的作用幽歼。相當(dāng)于tag
handlers:
- name: restart apache
service: name=httpd state=restarted
#有的系統(tǒng)做了sudo限制朵锣,所以需要在playbook中開啟權(quán)限,如下
- hosts: web
remote_user: vic
tasks:
- service: name=nginx state=started
sudo: yes
腳本實例
#create_user.yml
- name: create user
hosts: testgroup
user: root
##facts可以調(diào)用client的變量來使用甸私,后面變量里會詳細(xì)介紹
gather_facts: false
vars:
- user: "usertest1"
tasks:
- name: create {{ user }}
user: name="{{ user }}"
#返回結(jié)果如下
[root/] ]$ansible-playbook create_user.yml
PLAY [create user] *************************************************************
TASK [create usertest1] ********************************************************
ok: [192.168.247.152]
PLAY RECAP *********************************************************************
192.168.247.152 : ok=1 changed=0 unreachable=0 failed=0
給腳本添加service的調(diào)用
#create_user.yml
- name: create user
hosts: testgroup
user: root
gather_facts: false
vars:
- user: "usertest1"
tasks:
- name: create {{ user }}
user: name={{ user }}
- name: start httpd
service: name=httpd state=startd
#添加了httpd服務(wù)的開啟
#返回結(jié)果如下
PLAY [create user] *************************************************************
TASK [create usertest2] ********************************************************
ok: [192.168.247.152]
#可以注意到 TASK [service]顯示已經(jīng)開啟了
TASK [service] *****************************************************************
changed: [192.168.247.152]
PLAY RECAP *********************************************************************
192.168.247.152 : ok=2 changed=1 unreachable=0 failed=0
給腳本添加copy模塊的調(diào)用
#create_user.yml
- name: create user
hosts: testgroup
user: root
gather_facts: false
vars:
- user: "usertest1"
tasks:
- name: create {{ user }}
user: name={{ user }}
- name: start httpd
service: name=httpd state=startd
#添加了httpd服務(wù)的開啟
- name: Copy file to client
copy: src=/tmp/test.test dest=/tmp/
#添加了copy服務(wù)的開啟
#返回結(jié)果如下
[root/ansible_yml] ]$ansible-playbook create_user.yml
PLAY [create user] ************************************************************
TASK [create usertest2] *******************************************************
ok: [192.168.247.152]
TASK [service] ****************************************************************
ok: [192.168.247.152]
#可以注意到 TASK [copy file to clent]已成功
TASK [copy file to clent] *****************************************************
changed: [192.168.247.152]
PLAY RECAP ********************************************************************
192.168.247.152 : ok=3 changed=1 unreachable=0 failed=0
copy傳送的時候诚些,可能報錯
afewbug | FAILED >> {
"checksum": "4ee72f7427050dcd97068734d35ca7b2c651bc88",
"failed": true,
"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren‘t installed!"
是因為ansible需要libselinux-python包。(被控端需要安裝libselinux-python**)
可以在copy前先調(diào)用yum模塊皇型,安裝libselinux-python
template模板(支持jinja2)
#create_user.yml
- name: create user
hosts: testgroup
user: root
gather_facts: false
vars:
- user: "usertest1"
- temp: temptest
tasks:
- name: create {{ user }}
user: name={{ user }}
- name: start httpd
service: name=httpd state=startd
#添加了httpd服務(wù)的開啟
- name: Copy file to client
copy: src=/tmp/test.test dest=/tmp/
#添加了copy服務(wù)的開啟
- name: template test
template: src=/tmp/temp dest=/tmp/{{temp}} #{{temp}}變量來自vars
#添加了template模板使用
#返回結(jié)果
[root/ansible_yml] ]$ansible-playbook create_user.yml
PLAY [create user] *************************************************************
TASK [create usertest2] ********************************************************
ok: [192.168.247.152]
TASK [start httpd] *************************************************************
ok: [192.168.247.152]
TASK [copy file to clent] ******************************************************
ok: [192.168.247.152]
#可以注意到 返回結(jié)果顯示成功诬烹,去client相關(guān)目錄即可看到文件
TASK [template test] ***********************************************************
changed: [192.168.247.152]
PLAY RECAP *********************************************************************
192.168.247.152 : ok=4 changed=1 unreachable=0 failed=0
##
#template模塊可以引用變量到源文件
/tmp/temp
{{user}}
{{temp}}
#執(zhí)行yml后
[root/ansible_yml] ]$ansible testgroup -m command -a 'cat /tmp/temptest'
192.168.247.152 | SUCCESS | rc=0 >>
##client返回的就是主機源文件中引入的變量
usertest1
temptest
執(zhí)行外部命令的模塊
#create_user.yml
- name: create user
hosts: testgroup
user: root
gather_facts: false
vars:
- user: "usertest1"
- temp: temptest
tasks:
- name: create {{ user }}
user: name={{ user }}
- name: start httpd
service: name=httpd state=startd
#添加了httpd服務(wù)的開啟
- name: Copy file to client
copy: src=/tmp/test.test dest=/tmp/
#添加了copy服務(wù)的開啟
- name: template test
template: src=/tmp/temp dest=/tmp/{{temp}} #{{temp}}變量來自vars
#添加了template模板使用
- name: run shell
shell: /usr/bin/ls /tmp/ || /bin/true
#/bin/true 防中斷
- name: run command
command: mkdir /tmp/command-test
#添加了兩個執(zhí)行外部命令模塊shell和command
#返回結(jié)果如下
[root/ansible_yml] ]$ansible-playbook create_user.yml
PLAY [create user] *************************************************************
TASK [create usertest2] ********************************************************
ok: [192.168.247.152]
TASK [start httpd] *************************************************************
ok: [192.168.247.152]
TASK [copy file to client] *****************************************************
changed: [192.168.247.152]
TASK [template test] ***********************************************************
changed: [192.168.247.152]
TASK [shell~] ******************************************************************
changed: [192.168.247.152]
TASK [run this command] ********************************************************
changed: [192.168.247.152]
[WARNING]: Consider using file module with state=directory rather than running
mkdir
PLAY RECAP *********************************************************************
192.168.247.152 : ok=6 changed=4 unreachable=0 failed=0
###
#1./usr/bin/...||/bin/true 前面失敗的話/bin/true:返回true。防止中斷弃鸦,繼續(xù)執(zhí)行绞吁。類似的判斷還有chenge_when參數(shù)
變量功能
facts
一個常用的組件,可實現(xiàn)對遠程自己系統(tǒng)信息的獲取唬格,比如:主機名家破,IP地址,操作系統(tǒng)西轩,分區(qū)情況员舵,硬件信息等,配合playbook使用藕畔,更加的靈活和個性化定制
ansible ip/group -m setup
可以獲取clients的facts信息
[root~] ]$ansible testgroup -m setup
192.168.247.152 | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"192.168.122.1",
"192.168.247.152"
],
"ansible_all_ipv6_addresses": [
"fe80::20c:29ff:feb5:6e6"
],
"ansible_architecture": "x86_64",
"ansible_bios_date": "07/02/2015",
"ansible_bios_version": "6.00",
......
腳本中開啟Facts功能
#create_user.yml
- name: create user
hosts: testgroup
user: root
gather_facts: false #開啟facts
tasks:
- name: template test
template: src=/tmp/temp dest=/tmp/{{temp}} #{{temp}}變量來自vars
#返回結(jié)果马僻,
[root/ansible_yml] ]$ansible-playbook create_user.yml
PLAY [create user] *************************************************************
TASK [setup] *******************************************************************
ok: [192.168.247.152]
TASK [template test] ***********************************************************
changed: [192.168.247.152]
PLAY RECAP *********************************************************************
192.168.247.152 : ok=2 changed=1 unreachable=0 failed=0
#查看
[root/ansible_yml] ]$ansible testgroup -m raw -a "ls /tmp | grep 192*"
192.168.247.152 | SUCCESS | rc=0 >>
[u'192.168.122.1', u'192.168.247.152']
Shared connection to 192.168.247.152 closed.
#IP地址有兩個所以文件名很奇怪
當(dāng)然,我們也可以在主機的/tmp/temp下調(diào)用facts變量
#修改/tmp/temp文件
test
{{ansible_all_ipv4_addresses}}
#create_user.yml
- name: create user
hosts: testgroup
user: root
gather_facts: false #開啟facts
tasks:
- name: template test
template: src=/tmp/temp dest=/tmp/factstest
#結(jié)果如下
[root/ansible_yml] ]$ansible-playbook create_user.yml
PLAY [create user] *************************************************************
TASK [setup] *******************************************************************
ok: [192.168.247.152]
TASK [template test] ***********************************************************
changed: [192.168.247.152]
PLAY RECAP *********************************************************************
192.168.247.152 : ok=2 changed=1 unreachable=0 failed=0
[root/ansible_yml] ]$ansible testgroup -m raw -a "cat /tmp/factstest"
192.168.247.152 | SUCCESS | rc=0 >>
test
[u'192.168.122.1', u'192.168.247.152']
Shared connection to 192.168.247.152 closed.
自定義變量
如何facts的變量并不能滿足需求的注服,就可以自定義facts模板來實現(xiàn)
另外可以通過本地facts來實現(xiàn)韭邓,只需在client的/etc/ansible/facts.d目錄定義JSON,INI或可執(zhí)行的JSON輸出,后綴名一定要用.fact溶弟,那么這些文件就可以作為本地的facts
在client定義變量女淑,供ansible主機使用
[root@test1 ~]# mkdir /etc/ansible/facts.d -p
[root@test1 ~]# cd /etc/ansible/facts.d/
[root@test1 facts.d]# cat client.fact
[general]
name=zili
ansible主機
[root/ansible_yml] ]$ansible 192.168.247.152 -m setup -a "filter=ansible_local" 192.168.247.152 | SUCCESS => {
"ansible_facts": {
"ansible_local": { #本地facts
"client": { #文件名
"general": { #節(jié)點名
"name": "zili" #key-value
}
}
}
},
"changed": false
}
那么就可以通過如下方式去調(diào)用自定義的facts變量
{{ansible_local.client.general.name}}
[root/ansible_yml] ]$ansible-playbook create_user.yml
PLAY [create user] *************************************************************
TASK [setup] *******************************************************************
ok: [192.168.247.152]
TASK [template test] ***********************************************************
changed: [192.168.247.152]
PLAY RECAP *********************************************************************
192.168.247.152 : ok=2 changed=1 unreachable=0 failed=0
#調(diào)用成功,并可看到client內(nèi)容已變化
[root/ansible_yml] ]$ansible testgroup -m raw -a "cat /tmp/factstest2" 192.168.247.152 | SUCCESS | rc=0 >>
zili #
Shared connection to 192.168.247.152 closed.
在操作主機定義變量辜御,來控制client
思路就是在執(zhí)行playbook的時候?qū)⒈镜氐膄acts推送到client相關(guān)目錄下
- name: create directory for ansible custom facts
file: state=directory recurse=yes path=/etc/ansible/facts.d
- name: install custom facts
copy: src=/etc/ansible/host.fact dest=/etc/ansible/facts.d
- name: re-read facts after adding custom fact
setup: filter=ansible_local
#如此相當(dāng)于批量在client創(chuàng)建了facts變量
#然后就可以主機調(diào)用了!
注冊變量
變量可以將一條命令的返回值進行保存鸭你,然后提供給playbook使用
[root@ansible ansible]# cat user1.yml
- hosts: testgroup
remote_user: root
tasks:
- shell: /usr/bin/foo
register: z #注冊了一個foo\_resul變量,變量值為shell: /usr/bin/foo的運行結(jié)果;
ignore_errors: True #ignore\_errors: True為忽略錯誤
- shell: touch /tmp/LLL #當(dāng)變量注冊完成后,就可以在后面的playbook中使用了
when: z.rc == 5
#當(dāng)條件語句when: z.rc == 5成立時袱巨,shell: touch /tmp/LLL命令才會執(zhí)行
#可以注意到command是skipping的阁谆。因為返回值是127,所以client肯定還是沒有創(chuàng)建LLL的
[root/ansible_yml] ]$ansible-playbook user1.yml
PLAY [testgroup] ***************************************************************
TASK [setup] *******************************************************************
ok: [192.168.247.152]
TASK [command] *****************************************************************
fatal: [192.168.247.152]: FAILED! => {"changed": true, "cmd": "/usr/bin/foo", "delta": "0:00:00.003488", "end": "2017-03-11 13:08:45.996549", "failed": true, "rc": 127, "start": "2017-03-11 13:08:45.993061", "stderr": "/bin/sh: /usr/bin/foo: No such file or directory", "stdout": "", "stdout_lines": [], "warnings": []}
...ignoring
TASK [command] *****************************************************************
skipping: [192.168.247.152]
PLAY RECAP *********************************************************************
192.168.247.152 : ok=2 changed=1 unreachable=0 failed=0
##所以我門修改z.rc的返回值為127在執(zhí)行
#以為返回值是對的愉老,所以執(zhí)行了touch场绿,warning是友情提示,最好用線管模塊進行文件的操作
[root/ansible_yml] ]$ansible-playbook user1.yml
PLAY [testgroup] ***************************************************************
TASK [setup] *******************************************************************
ok: [192.168.247.152]
TASK [command] *****************************************************************
fatal: [192.168.247.152]: FAILED! => {"changed": true, "cmd": "/usr/bin/foo", "delta": "0:00:00.003539", "end": "2017-03-11 13:11:01.955975", "failed": true, "rc": 127, "start": "2017-03-11 13:11:01.952436", "stderr": "/bin/sh: /usr/bin/foo: No such file or directory", "stdout": "", "stdout_lines": [], "warnings": []}
...ignoring
TASK [command] *****************************************************************
changed: [192.168.247.152]
[WARNING]: Consider using file module with state=touch rather than running touch
PLAY RECAP *********************************************************************
192.168.247.152 : ok=3 changed=2 unreachable=0 failed=0
[root/ansible_yml] ]$
語句
條件語句
playbook的執(zhí)行結(jié)果取決于變量嫉入,不管是facts還是tasks結(jié)果賦值的焰盗,而變量的值可以依賴于其他變量,當(dāng)然一會印象ansible的執(zhí)行
有時候我們咒林,想要跳過某些主機的執(zhí)行步驟熬拒,比如,某些client不安裝某個軟件包映九,不清理垃圾等等
就要使用判斷了
when
- name: when
hosts: testgroup
remote_user: root
gather_facts: true
tasks:
- name: shutdown centos
command: /sbin/shutdown -t now
when: ansible_hostname == 'test1'
#when返回bool值梦湘,為true是執(zhí)行,false則不執(zhí)行
when 針對不同分支的二級處理
- name: when
hosts: web
remote_user: root
gather_facts: true
tasks:
- command: /sbin/ip a
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
# when: result|success"的意思為當(dāng)變量result執(zhí)行結(jié)果為成功
#將執(zhí)行/bin/something_else命令件甥,其他同理捌议。
#其中success為Ansible內(nèi)部過濾器方法,返回True代表命令運行成功引有。
循環(huán)語句
- name: whell
hosts: testgroup
remote_user: root
gather_facts: true
tasks:
- name: "add user"
user: name={{ item }} state=present groups=wheel
with_items:
- tiger1
- tiger2
#創(chuàng)建用戶的瓣颅。with_items會自動循環(huán)執(zhí)行上面的語句"user: name={{ item }} state=present groups=wheel",循環(huán)的次數(shù)為with_items的元素個數(shù)譬正。這里有2個元素宫补,分別為tiger1、tiger2曾我,會分別替換{{ item }}項
#等同于
- name: whell
hosts: testgroup
remote_user: root
gather_facts: true
tasks:
- name: "add user tiger1"
user: name=tiger1 state=present groups=wheel
- name: "add user tiger2"
user: name=tiger2 state=present groups=wheel
循環(huán)元素支持列表
#首先定義好列表 list.yml
packages_base:
- [ 'vsftpd', 'vim' ]
packages_apps:
- [[ 'mysql',httpd' ]]
#然后引入使用
- name: whell
hosts: testgroup
remote_user: root
gather_facts: true
var_files:
- /etc/ansible/list.yml
tasks:
- name: "install rpm"
yum: name={{ item }} state=installed
with_flattened: #此語句 用來循環(huán)定義好的列表
- packages_base
- packages_apps
handlers 和 include
當(dāng)多個playbook涉及復(fù)用的任務(wù)列表時粉怕,可以將復(fù)用的內(nèi)容剝離出來,寫到獨立的文件里抒巢,需要的地方include進來即可
除了tasks之外贫贝,還有一個handlers的命令,handlers是在執(zhí)行tasks之后服務(wù)器發(fā)生變化之后可供調(diào)用的handler
- name: write the httpd config file
hosts: testgroup
remote_user: root
gather_facts: true
tasks:
- name: write the httpd.conf to client
template: src=/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: # 如果copy執(zhí)行完之后/etc/httpd/conf/httpd.conf文件發(fā)送了變化蛉谜,則執(zhí)行
- restart httpd # 調(diào)用handler
- include: playbook/tasks/httpd.yml
handlers:
- name: restart httpd #此處的標(biāo)識必須和notify一樣才可以引起觸發(fā)
service: name=httpd state=restarted
#注意上面使用的- include: playbook/tasks/httpd.yml稚晚,看一下這個文件的內(nèi)容
- name: ensure httpd is running
service: name=httpd state=started
notify這個action可用于在每個play的最后被觸發(fā),這樣可以避免多次有改變發(fā)生時每次都執(zhí)行指定的操作型诚,取而代之客燕,僅在所有的變化發(fā)生完成后一次性地執(zhí)行指定操作。
Handlers 是由通知者進行 notify, 如果沒有被 notify,handlers 不會執(zhí)行狰贯。
Handlers 最佳的應(yīng)用場景是用來重啟服務(wù),或者觸發(fā)系統(tǒng)重啟操作.除此以外很少用到了也搓。
roles 使用
前面的所有都在一個文件內(nèi).還有一種方法可以進行更好的組織架構(gòu)
使用roles
[root@master roles]# tree
.
├── test
│ └── tasks
│ └── main.yml
└── test.yml
test.yml為入口文件,每次執(zhí)行它即可.他的內(nèi)容如下
[root@master roles]# cat test.yml
---
- hosts: all
roles:
- role: test
定義了主機/主機組,然后定義了要使用的roles,(也就是roles下的文件夾的名字)
test文件夾下定義了tasks,內(nèi)有 **main.yml** 這個命名是規(guī)定好的.必須是main
main.yml 書寫了tasks的任務(wù).
[root@master roles]# cat test/tasks/main.yml
---
- name: test role ping
ping:
[root@master roles]#
結(jié)果如下:
[root@master roles]# ansible-playbook test.yml
PLAY [all] ************************************************************************************
TASK [Gathering Facts] ************************************************************************
ok: [10.1.27.28]
ok: [10.1.27.24]
TASK [test : test role ping] ******************************************************************
ok: [10.1.27.28]
ok: [10.1.27.24]
PLAY RECAP ************************************************************************************
10.1.27.24 : ok=2 changed=0 unreachable=0 failed=0
10.1.27.28 : ok=2 changed=0 unreachable=0 failed=0
roles有很多結(jié)構(gòu),ansible可以根據(jù)其進行解析.
├── defaults
├── files
├── handlers
├── meta
├── tasks
├── templates
└── vars
如果roles/x/tasks/main.yml
存在,則自動將里面的tasks添加到play中赏廓。
如果roles/x/handlers/main.yml
存在,則自動將里面的handlers添加到play中。
如果roles/x/vars/main.yml
存在, 則自動將其中的variables添加到play中还绘。
如果roles/x/meta/main.yml
存在,則添加role的依賴關(guān)系roles中楚昭。
任何copy
任務(wù)、script
任務(wù)都可以引用roles/x/files
中的文件拍顷,無論是使用絕對或相對路徑都可以。
任何template
任務(wù)都可以引用roles/x/templates
中的文件塘幅,無論絕對或相對路徑昔案。
任何include
任務(wù)都可以引用roles/x/tasks/
中的文件,無論相對或絕對路徑
具體可以參見文檔:http://docs.ansible.com/playbooks_intro.html
(1)files/:存放copy或script模塊等調(diào)用的文件
(2)templates/:templates查找所需要模塊文件的目錄电媳;
(3)tasks/:(必須要有)至少應(yīng)該包含一個名為main.yml的文件踏揣,其他的文件需要在此文件中通過include進行包含;
(4)handlers/:至少應(yīng)該包含一個名為main.yml的文件匾乓,其他的文件需要在此文件中通過include進行包含捞稿;
(5)vars/:定義的是變量,至少應(yīng)該包含一個名為main.yml的文件拼缝,其他的文件需要在此文件中通過include進行包含娱局;
(6)meta/:定義此當(dāng)前角色的特殊設(shè)定及其他依賴關(guān)系,至少應(yīng)該包含一個名為main.yml的文件咧七,其他的文件需要在此文件中通過include進行包含衰齐;
(7)default/:為當(dāng)前角色設(shè)定默認(rèn)變量時使用目錄中的main.yml文件
ansible和saltstack的對比
1、salt要安裝agent , ansible通過ssh連接继阻。
2耻涛、salt在server端要啟進程;ansible不需要瘟檩。
3抹缕、salt與ansible都有模塊,可使用任意語言開發(fā)模塊墨辛。
4卓研、salt與ansible都使用yaml語言格式編寫劇本。
ansible走的是ssh,所以它有認(rèn)證以及加密碼的過程背蟆,使得ansible非常慢鉴分,不適用于大規(guī)模環(huán)境(指上千臺)