ansible筆記

ansible筆記html

 

 

 

若是某個主機執行失敗了,會生成retry文件,而後用--limit參數來從新執行便可java

to retry, use: ansible  --limit @xxx.retrynode

 

 

解決:
一大堆腳本,並且服務器上腳本不是最新
預估停機執行時間python


注意:
任務重複執行問題
安全:密碼和密鑰,ansible管理機權限
ansible沒有回滾操做mysql

 

 

ansible屬於非登陸shelllinux

 

ansible執行過程大致過程以下圖,其中暖色調的表明已經模塊化nginx

 

 

 

 

https://www.jianshu.com/p/575ced3a08fagit

特色github

無客戶端
無服務器端
基於模塊,用任意語言開發模塊
yaml訂製playbook
基於ssh工做
實現多級指揮web

鏈接插件,鏈接被管理端
核心模塊
自定義模塊
插件完成模塊功能補充
playbooks定義任務
主機清單

 

架構圖

f

管理端支持local(鏈接管理機即本身鏈接本身的時候) 、ssh、zeromq 三種方式鏈接被管理端,默認使用基於ssh的鏈接---這部分對應基本架構圖中的鏈接模塊;

 


ansible安裝

主控機
管理節點操做
yum install -y epel-release
yum install -y ansible

 

 

任務執行模式

ansible系統由控制主機對被管節點的操做方式有兩種ad_hoc和playbook

ad_hoc單命令模式 能夠對多臺主機執行單個命令
ansible all -a "/bin/echo hello"

playbook模式
playbook經過多個tasks的集合完成一類功能如web的安裝部署,數據庫服務器的批量備份等



ansible提供了10個命令
ansible
ansible-doc
ansible-vault
ansible-pull
ansible-config
ansible-galaxy
ansible-playbook
ansible-connection
ansible-inventory
ansible-console

 

 

 

一、ansible

ansible命令管理主機
在官方文檔中命令行的名字是:Ad-Hoc Commands


ansible是指令核心部分,其主要用於執行ad-hoc命令,即單條命令。默認後面須要跟主機和選項部分,默認不指定模塊時,使用的是command模塊。如:
[root@localhost ~]# ansible 127.0.0.1 -a 'date'
-m:後面接調用模塊的名字
-a:後面接調用模塊的參數
ansible all -m shell -a "sh /tmp/kel.sh >>/tmp/kel.log"
參數:
-a 'Arguments', --args='Arguments' 命令行參數
-m NAME, --module-name=NAME 執行模塊的名字,默認使用 command 模塊,因此若是是隻執行單一命令能夠不用 -m參數
-M MODULE_PATH, --module-path=MODULE_PATH 要執行的模塊的路徑,默認爲/usr/share/ansible/
-i PATH, --inventory=PATH 指定主機文件、主機目錄、可執行文件的路徑,默認爲/etc/ansible/hosts.
-u Username, --user=Username 執行用戶,使用這個遠程用戶名而不是當前用戶
-U --sud-user=SUDO_User sudo到哪一個用戶,默認爲 root
-k --ask-pass 登陸密碼,提示輸入SSH密碼而不是基於密鑰的驗證
-K --ask-sudo-pass 提示密碼使用sudo -s --sudo sudo運行
-s --snippet 指定模塊顯示playbook片斷
-S --su 用 su 命令
-f --forks=NUM 並行任務數。NUM被指定爲一個整數,默認是5。 #ansible testhosts -a "/sbin/reboot" -f 10 重啓testhosts組的全部機器,每次重啓10臺
--private-key=PRIVATE_KEY_FILE 私鑰路徑,使用這個文件來驗證鏈接
-vvv --verbose 查看詳細的報錯信息,相似/usr/local/mysql/bin/mysqlbinlog  -vv
all 針對hosts 定義的全部主機執行
-o --one-line 壓縮輸出,摘要輸出.嘗試一切都在一行上輸出。
-t Directory, --tree=Directory 執行過程當中的日誌保存到這個目錄
-B 後臺運行超時時間,ansible all  -m ping  -B 3600 -P 0
-T Seconds, --timeout=Seconds 時間,單位秒s
-P NUM, --poll=NUM 調查背景工做每隔數秒,調查後臺程序時間。須要- b
-c Connection, --connection=Connection 鏈接類型使用。可能的選項是paramiko(SSH),SSH和地方。
--version  ansible版本號
-C, --check 只是測試一下,不會真正去執行
-l SUBSET, --limit=SUBSET 進一步限制所選主機/組模式 --limit=192.168.0.15 只對這個ip執行或--limit=kvm 只對這個kvm組執行 ,除了kvm組不執行,其餘組都執行ansible all -l kvm -m shell -a "sh /tmp/kel.sh >>/tmp/kel.log"

ansible --version
ansible 2.4.2.0
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.6/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) [GCC 4.4.7 20120313 (Red Hat 4.4.7-17)]

 

查後臺任務id
ansible all  -m ping  -B 3600 -P 0
ansible_job_id:"123"
xxx

#查看後臺任務id爲123的任務狀態
ansible all  -m async_status -a "jid='123'"

 

 

二、ansible-doc
查看模塊信息
-l:列出全部已安裝的模塊
-s :查看具體某模塊的用法,若是是extra模塊,必須cd到extra模塊目錄下面再執行,ansible-doc -s command


三、ansible-galaxy
ansible-galaxy 指令用於方便的從https://galaxy.ansible.com/ 站點下載官方收錄的playbooks,咱們能夠形象的理解其相似於centos下的yum、python下的pip。

ansible-galaxy install aeriscloud.docker
這個安裝了一個aeriscloud.docker組件,前面aeriscloud是galaxy上建立該模塊的用戶名,後面對應的是其模塊。


初始化一個role的目錄結構
ansible-galaxy init role_name

 

列出已安裝的roles
ansible-galaxy list

查看已安裝的roles信息
ansible-galaxy info bennojoy.mysql

 

卸載roles
ansible-galaxy remove bennojoy.mysql


安裝一個role
參數-p 指定role下載的目錄。
若是沒有指定-p , 那麼role 會被自動下載到環境變量ANSIBLE_ROLES_PATH 定義的目錄下,
或者默認目錄/etc/ansible/roles 下。
ansible-galaxy -p /tmp/roles install bennojoy.nginx

 

安裝多個role
將全部依賴的role放在一個role.txt裏面,-r參數指定role列表文件role.txt,相似pip install -r requirements.txt

ansible-galaxy -p /tmp/roles install  -r /tmp/role.txt  
cat role.txt
bennojoy.nginx
bennojoy.mysql
bennojoy.mongodb

或者
ansible-galaxy -p /tmp/roles install -r requirements.yml
cat requirements.yml 
# from galaxy
- src: yatesr.timezone

# from GitHub
- src: https://github.com/bennojoy/nginx

# from GitHub , overriding the name and specifying a  specific tag
- src: https://github.com/bennojoy/nginx
  version: master
  name: nginx role

# from a webserver , where the role is packaged in a tar.gz
- src: https://some.webserver.example.com/files/master.tar.gz
  name: http-role

 


四、ansible-playbook
該指令是使用最多的指令,其經過讀取playbook 文件後,執行相應的動做
--tags=TAGS 只執行指定標籤的任務 例子:ansible-playbook test.yml --tags=copy 只執行標籤爲copy的那個任務
--list-hosts 只打印有哪些主機會執行這個 playbook 文件,不是實際執行該 playbook 文件
--list-tasks 列出全部將被執行的任務
--syntax-check 對playbook執行語法檢查,但不執行它
--skip-tags=SKIP_TAGS 只運行任務不匹配這些值的標籤的playbook --skip-tags=copy_start
-e EXTRA_VARS, --extra-vars=EXTRA_VARS 額外的變量設置爲鍵=值或YAML / JSON
--syntax-check 檢查yaml文件的語法
--verbose 查看輸出細節
--step  每執行一個任務後中止,等待用戶確認
-f 用多少個線程執行playbook任務,好比用10個線程 ansible-playbook -f 10 ngxin.yml

#ansible-playbook update.yml --extra-vars "hosts=vipers user=admin" 傳遞{{hosts}}、{{user}}變量,hosts能夠是 ip或組名


 


五、ansible-pull
Ansible的另外一種工做模式,pull模式,ansible默認使用push模式
支持直接從git下載playbook執行,須要遵循其規定的目錄格式,用處不是特別大,能夠不關注



六、ansible-vault
ansible-vault主要應用於配置文件中含有敏感信息,又不但願他能被人看到,vault能夠幫你加密/解密這個配置文件,屬高級用法。
主要對於playbooks裏好比涉及到配置密碼或其餘變量時,能夠經過該指令加密,這樣咱們經過cat看到的會是一個密碼串類的文件,編輯的時候須要輸入事先設定的密碼才能打開。
這種playbook文件在執行時,須要加上 –ask-vault-pass參數,一樣須要輸入密碼後才能正常執行。具體該部分能夠參查官方博客。

[root@node1 ansible]# ansible-vault encrypt db_hosts
New Vault password:
Confirm New Vault password:
Encryption successful
[root@node1 ansible]# ansible -i db_hosts localhost -m ping
ERROR! Decryption failed
Decryption failed
[root@node1 ansible]# ansible -i db_hosts --ask-vault-pass localhost -m ping
Vault password:
localhost | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

[root@node1 ansible]# cat db_hosts
$ANSIBLE_VAULT;1.1;AES256
61663966666265363465653064386666326234353433346163633838366532366236313032303636
6437313333333936396164663031633566613233343161650a333163333732616130343762636135
30303864663138643661393234336433313465623830333832663165393964353961323261373130
3135626236626435640a396338616563646532623966333337366365636665663563666432333539
61663632633130623733316232353836663366623136636432616332376266383263356264303765
6133616235363066356164653232326139643862653464623037

 



 


 

ansible核心模塊

 

 

Ansible 對遠程服務器的操做實際是經過模塊完成的。其工做原理以下
一、將模塊拷貝到遠程服務器
二、執行模塊定義的操做,完成對服務器的修改
三、在遠程服務器中刪除模塊

全部模塊官方文檔:http://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html

 


ping模塊
ping一下你的遠程主機,嘗試ssh登陸遠程節點並檢查python版本,若是鏈接成功,返回pong,不須要任何參數
調試和測試類模塊



setup模塊
獲取遠程機器的facts數據,也就是機器配置
參數
filter:只返回符合過濾規則的facts數據

# 顯示全部機器的facts數據並存儲在/tmp/facts目錄下
# ansible all -m setup --tree /tmp/facts

# 只顯示內存相關內容
# ansible all -m setup -a 'filter=ansible_*_mb'

# 只顯示和facter有關的內容.
# ansible all -m setup -a 'filter=facter_*'

# 只顯示網卡信息
# ansible all -m setup -a 'filter=ansible_eth[0-2]'



debug模塊
參數
msg:定義打印的字符串
var:定義須要打印的變量
regester:定義注入變量

# Example that prints the loopback address and gateway for each host
- debug:
msg: "System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}"

- debug:
msg: "System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}"
when: ansible_default_ipv4.gateway is defined

- shell: /usr/bin/uptime
register: result #將執行結果注入result變量

- debug:
var: result #打印result的內容
verbosity: 2

- name: Display all variables/facts known for a host
debug:
var: hostvars[inventory_hostname]
verbosity: 4

 

 

 

script模塊
在遠程節點上執行主控機上的腳步,其功能至關於scp + shell 的組合,腳本執行完成之後會在遠程服務器上刪除腳本文件
參數
chdir:在執行腳步以前先cd到這個目錄

- script: /some/local/script.sh --some-arguments 1234

# Run a script that creates a file, but only if the file is not yet created
- script: /some/local/create_file.sh --some-arguments 1234
  args:
    creates: /the/created/file.txt

# Run a script that removes a file, but only if the file is not yet removed
- script: /some/local/remove_file.sh --some-arguments 1234
  args:
    removes: /the/removed/file.txt

 

 

 

copy模塊
複製前會比較遠程文件的checksum,若是相同則不復制,返回ok,若是不一樣才複製,返回changed
參數
mode:能夠是數字形式也能夠是符號形式,0644 ,01777,u+rwx , u=rw,g=r,o=r
owner:屬主
group:屬組
backup:默認no,先備份目標節點的源文件再複製,若是拷貝過程失敗,則源文件還能使用,而不是對目標文件備份一份!
validate:默認none,驗證複製後的文件,%s指代複製後的文件
dest:目標文件,必須是絕對路徑
src:源文件,能夠是絕對路徑,也能夠是相對路徑,/tmp/表示拷貝文件夾裏內容,/tmp表示把文件夾也拷貝過去
force:默認yes,當目標文件跟源文件不同時會強制覆蓋目標文件,若是同樣,不會執行復制,別名thirsty,也就是thirsty等於force
follow:默認no,當拷貝的文件夾內有link存在的時候,那麼拷貝過去的也會有link

- name: example copying file with owner and permissions
copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: 0644

- name: The same example as above, but using a symbolic mode equivalent to 0644
copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: u=rw,g=r,o=r

- name: Another symbolic mode example, adding some permissions and removing others
copy:
src: /srv/myfiles/foo.conf
dest: /etc/foo.conf
owner: foo
group: foo
mode: u+rw,g-wx,o-rwx

- name: Copy a new "ntp.conf file into place, backing up the original if it differs from the copied version
copy:
src: /mine/ntp.conf
dest: /etc/ntp.conf
owner: root
group: root
mode: 0644
backup: yes

- name: Copy a new "sudoers" file into place, after passing validation with visudo
copy:
src: /mine/sudoers
dest: /etc/sudoers
validate: /usr/sbin/visudo -cf %s

- name: Copy a "sudoers" file on the remote machine for editing
copy:
src: /etc/sudoers
dest: /etc/sudoers.edit
remote_src: yes
validate: /usr/sbin/visudo -cf %s

- name: Copy using the 'content' for inline data
copy:
content: '# This file was moved to /etc/other.conf'
dest: /etc/mine.conf'

 

 

template模塊
在複製的同時根據實際狀況修改部份內容,這時不能用copy模塊,要用template模塊
template模塊使用的是python的jinja2模板引擎,這裏不須要了解jinja2,只須要知道變量的表示法
{{}}就能夠了
template模塊一樣具有copy模塊的權限設置,文件備份,驗證功能

參數
mode:能夠是數字形式也能夠是符號形式,0644 ,01777,u+rwx , u=rw,g=r,o=r
owner:屬主
group:屬組
backup:默認no,先備份目標節點的源文件再複製
validate:默認none,驗證複製後的文件,%s指代複製後的文件
dest:目標文件
src:源文件
force:默認yes,當目標文件跟源文件不同時會強制覆蓋目標文件,若是同樣,不會執行復制
follow:默認no,當拷貝的文件夾內有link存在的時候,那麼拷貝過去的也會有link

 
roles/templates/server.xml中的template文件關鍵部分以下:
<?xml version="1.0" encoding="utf-8"?>

<code class="language-shell hljs handlebars">
<user username="{{ admin_username }}" password="{{ admin_password }}" roles="manager-gui"/>
</code>
當這個文件還沒被template執行的時候,本地的admin_username及admin_password 都是變量狀態。
當playbook執行完template的時候,遠程的admin_username*及admin_password 會變成變量所對應的值。
麼在執行這個Playbook前,對應的那個template文件(俗稱模版),將在本地保持{{ admin_username }}及{{ admin_password }}的狀態。在Ansible調用template模版執行的時候,這裏將由Jinjia2從」tomcat-servers」讀取對應的值,而後替換掉模版裏的變量,
而後把這個替換變量值後的文件拷貝到遠程節點。

 




 

file模塊
用來設置遠程主機上的文件,軟連接symlinks,文件夾權限,也能夠建立和刪除文件夾,文件
參數
path:目標路徑,別名dest,,name,也就是dest,,name等於path
recurse:遞歸設置文件屬性,當state爲directory時候
mode:能夠是數字形式也能夠是符號形式,0644 ,01777,u+rwx , u=rw,g=r,o=r
owner:屬主
group:屬組
src:源連接,只能應用於state=link 、 state=hard的狀況
force:默認yes,當目標文件跟源文件不同時會強制覆蓋目標文件,若是同樣,不會執行復制
follow:默認no,當拷貝的文件夾內有link存在的時候,那麼拷貝過去的也會有link
state:默認file,file/link/directory/hard/touch/absent
file表明拷是文件;
link表明是個軟連接;
directory表明文件夾;
hard表明硬連接;
touch表明生成一個空文件;
absent表明刪除

#改變文件權限,數字權限必須以0開頭
- file:
path: /etc/foo.conf
owner: foo
group: foo
mode: 0644
#建立軟連接,這裏的src和dest參數含義和copy模塊不同,file模塊裏所操做的文件都是遠程節點上的文件
- file:
src: /file/to/link/to
dest: /path/to/symlink
owner: foo
group: foo
state: link


# 建立一個新文件 touch命令
- file:
path: /etc/foo.conf
state: touch
mode: "u=rw,g=r,o=r"

# touch the same file, but add/remove some permissions
- file:
path: /etc/foo.conf
state: touch
mode: "u+rw,g-wx,o-rwx"

# 建立一個文件夾
- file:
path: /etc/some_directory
state: directory
mode: 0755

 



user模塊/group模塊
user 模塊請求的是useradd , userdel , usermod 三個命令
group 模塊請求的是groupadd,groupdel, groupmod 三個命令

參數
group:主屬組
groups:多個附加屬組,用逗號分隔
home:家目錄
createhome:默認yes,是否建立家目錄
name:用戶名或羣組名,必須,別名user,也就是user等於name
password:密碼,必須是加密過的密碼,python -c "from passlib.hash import sha512_crypt; import getpass; print(sha512_crypt.using(rounds=5000).hash(getpass.getpass()))"
remove:把家目錄也刪除,前提state爲absent,至關於userdel -r
shell:設置用戶的登陸shell
uid:設置uid
gid:設置gid
state:建立或刪除用戶/羣組,取值包括present 和absent
generate_ssh_key:是否生成密鑰
ssh_key_bits:sshkey的位數,最好設置爲2048
ssh_key_file:默認.ssh/id_rsa,
ssh_key_type:默認rsa, 可選dsa,rsa
ssh_key_passphrase:sshkey的密碼
expires :用戶過時時間,過時時間爲時間戳

- name: 添加用戶johnd,設置uid爲1040,組爲admin
user:
name: johnd
comment: John Doe
uid: 1040
group: admin

- name: 添加用戶james,設組爲admins,developers
user:
name: james
shell: /bin/bash
groups: admins,developers
append: yes

- name: 刪除用戶johnd
user:
name: johnd
state: absent
remove: yes

- name: 建立密鑰是 2048位 SSH key 的用戶jsmith,保存位置在~jsmith/.ssh/id_rsa
user:
name: jsmith
generate_ssh_key: yes
ssh_key_bits: 2048
ssh_key_file: .ssh/id_rsa

- name: 建立用戶james18,設置過時時間爲2015/1/28 8:3:7
user:
name: james18
shell: /bin/zsh
groups: developers
expires: 1422403387


#建立羣組
ansible test -m group -a "name=ansible state=present gid=l234" -become


#刪除羣組
ansible test -m group -a "name=ansible state=absent" -become

 

 

 

yum模塊
管理yum包,fedora從版本22開始使用dnf代替yum,若是用fedora22推薦用dnf模塊來進行安裝包

參數
conf_file:yum的配置文件
disable_gpg_check:默認no, 只有state 爲present 或 latest.才能指定disable_gpg_check
list:至關於yum list <package>
name:包名, 能夠是'*' 表示yum -y update 更新全部包 或 rpm 文件的url路徑或本地路徑 ,同時 state=present ,別名pkg,也就是pkg等於name
state:用於描述安裝包最終狀態,present/latest/installed用於安裝包,removed/absent用於remove安裝包
update_cache:默認no,用於安裝包前執行更新list,只會影響state參數爲present/latest的時候

- name: 安裝最新版本的Apache,若是已經安裝了老版本,那麼會更新到最新版本
yum:
name: httpd
state: latest

- name: 刪除 Apache 包
yum:
name: httpd
state: absent

- name: 從testing repo 安裝Apache
yum:
name: httpd
enablerepo: testing
state: present

- name: 安裝指定版本的 Apache
yum:
name: httpd-2.2.29-1.4.amzn1
state: present

- name: 更新全部包
yum:
name: '*'
state: latest

- name: 更新全部包 除外 kernel & foo
yum:
name: '*'
state: latest
exclude: kernel*,foo*

- name: 從url中安裝nginx rpm 包
yum:
name: http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
state: present

- name: 從本地文件中安裝 nginx rpm 包
yum:
name: /usr/local/src/nginx-release-centos-6-0.el6.ngx.noarch.rpm
state: present

- name: 安裝一組包 group install 'Development tools'
yum:
name: "@Development tools"
state: present

- name: 安裝一組包 group install 'Gnome desktop'
yum:
name: "@^gnome-desktop-environment"
state: present

- name: yum list 出ansible相關的包並注入 register result ,以後用 debug 模塊打印
yum:
list: ansible
register: result

- name: 使用多個倉庫來安裝包
yum:
name: sos
enablerepo: "epel,ol7_latest"

- name: 從多個禁用倉庫安裝包
yum:
name: sos
disablerepo: "epel,ol7_latest"

 



 

service模塊
管理遠程節點上的服務,好比httpd,sshd,nfs,crond等

參數
arguments:給命令行提供一些選項,別名: args,也就是args等於arguments
enabled:是否開機啓動
name:必選項,服務名稱
state:對當前服務執行啓動,中止、重啓、從新加載等操做(started,stopped,restarted,reloaded)
pattern:定義一個模式,若是經過status指令來查看服務的狀態時,沒有響應,就會經過ps指令在進程中根據該模式進行查找,若是匹配到,則認爲該服務依然在運行

- name: 開啓服務
service:
name: httpd
state: started

- name: 關服務
service:
name: httpd
state: stopped

- name: 重啓服務
service:
name: httpd
state: restarted

- name: 重載服務
service:
name: httpd
state: reloaded

- name: 設置開機啓動服務
service:
name: httpd
enabled: yes

- name: 啓動foo服務,根據/usr/bin/foo
service:
name: foo
pattern: /usr/bin/foo
state: started

- name: 重啓網絡服務的eth0網卡
service:
name: network
state: restarted
args: eth0

ansible all -m service -a 'name=network state=restarted args=eth0'

 

 

 

firewalld模塊
爲某服務和端口添加firewalld規則,firewalld中有正在運行的規則和永久的規則,firewalld都支持
firewalld模塊要求遠程節點上的firewalld版本在0.2.11以上

參數
permanent:默認None,是否保存設置即便重啓機器
interface,默認None,從zone裏增刪網卡
port:端口,形式端口/協議 ,端口範圍 端口-端口/協議
rich_rule:複雜的firewalld規則
service:服務名,爲服務添加firewall規則
source:ip來源
state:狀態,enabled、disabled、present、absent
zone:work、drop、internal、external、trusted、home、dmz、public、block

#爲https服務添加firewall規則
- firewalld:
service: https
permanent: true
state: enabled
#區域dmz
- firewalld:
zone: dmz
service: http
permanent: true
state: enabled

#爲端口號8081/tcp,範圍161-162/udp添加firewall規則
- firewalld:
port: 8081/tcp
permanent: true
state: disabled

- firewalld:
port: 161-162/udp
permanent: true
state: enabled

#其餘複雜規則
- firewalld:
rich_rule: 'rule service name="ftp" audit limit value="1/m" accept'
permanent: true
state: enabled

- firewalld:
source: 192.0.2.0/24
zone: internal
state: enabled

- firewalld:
zone: trusted
interface: eth2
permanent: true
state: enabled

- firewalld:
masquerade: yes
state: enabled
permanent: true
zone: dmz

- firewalld:
zone: custom
state: present
permanent: true

 

 

 

shell模塊/raw模塊
在遠程節點經過/bin/sh執行命令,若是一個操做能夠經過模塊yum,copy實現,那麼建議不要用shell或command這樣的通用命令模塊
由於通用命令模塊不會根據具體操做的特色進行狀態status判斷,因此當沒有必要再從新執行的時候,他仍是會從新執行一次
shell/raw 模塊至關於使用SSH 直接執行Linux 命令,不會進入到Ansible 的模塊子系統中,也能夠執行遠程機器的shell腳本,不過shell腳本須要絕對路徑

shell:在節點執行shell命令,支持$HOME、<、>、|、;、&  ,不支持傳入參數

參數
chdir:默認None,運行shell以前cd到某個目錄
creates:默認None,建立一個文件,若是這個文件存在則不運行shell
removes:默認None,刪除一個文件,若是這個文件不存在則不運行shell
executable:默認None,指定用哪一種shell來執行命令,給出shell的絕對路徑,好比/bin/bash

- name: 執行shell命令,把標準輸出重定向到文件
shell: somescript.sh >> somelog.txt

- name: 改變工做目錄在執行shell命令前
shell: somescript.sh >> somelog.txt
args:
chdir: somedir/


- name: somelog.txt不存在並改變工做目錄
shell: somescript.sh >> somelog.txt
args:
chdir: somedir/
creates: somelog.txt

- name: bash處理重定向
shell: cat < /tmp/*txt
args:
executable: /bin/bash

- name: 使用模板變量 (always use quote filter to avoid injection)
shell: cat {{ myfile|quote }}


- name: Run expect to wait for a successful PXE boot via out-of-band CIMC
shell: |
set timeout 300
spawn ssh admin@{{ cimc_host }}

expect "password:"
send "{{ cimc_password }}\n"

expect "\n{{ cimc_name }}"
send "connect host\n"

expect "pxeboot.n12"
send "\n"

exit 0
args:
executable: /usr/bin/expect
delegate_to: localhost

 

 

 

 

command模塊
在遠程節點執行命令,不支持家目錄,重定向,管道 $HOME、<、>、|、;、&
和shell模塊相似,但有一個和shell模塊不一樣,command模塊多了一個傳入參數的方式

參數
chdir:默認None,運行shell以前cd到某個目錄
creates:默認None,建立一個文件,若是這個文件存在則不運行shell
removes:默認None,刪除一個文件,若是這個文件不存在則不運行shell

- name: 返回執行結果到變量 registered var
command: cat /etc/motd
register: mymotd

- name: command模塊多了一個傳入參數的方式
command: /usr/bin/make_database.sh arg1 arg2 creates=/path/to/database


- name: This command will change the working directory to somedir/ and will only run when /path/to/database doesn't exist.
command: /usr/bin/make_database.sh arg1 arg2
args:
chdir: somedir/
creates: /path/to/database

- name: safely use templated variable to run command. Always use the quote filter to avoid injection issues.
command: cat {{ myfile|quote }}
register: myoutput

 

 

 

cron模塊
管理cron.d 目錄 crontab 文件
參數
cron_file:若是指定該選項,則用該文件替換遠程主機上的cron.d目錄下的用戶任務計劃,與user參數一塊兒用
backup:默認no,對遠程主機上的原任務計劃內容修改以前作備份,萬一出故障還原回來,而不是備份任務計劃
job:要執行的任務,依賴於state=present  別名value ,也就是job等於value  
user:默認root,操做哪一個用戶的crontab
disabled:禁用job,默認no,job狀態必須是state=present
name:該任務的描述(必須項)
minute:分鐘(0-59,*,*/2,……),不寫默認爲*
hour:小時(0-23,*,*/2,……),不寫默認爲*
day:日(1-31,*,*/2,……),不寫默認爲*,別名dom ,也就是day等於dom
month:月(1-12,*,*/2,……),不寫默認爲*
weekday:周(0-7,*,……),不寫默認爲*,別名dow,也就是weekday等於dow
special_time:指定何時執行,參數:reboot/yearly/annually/monthly/weekly/daily/hourly
state:狀態,參數:present:建立任務 、absent:刪除任務

# 5點和2點運行 一個ls命令"0 5,2 * * ls -alh > /dev/null"
- cron:
    name: "check dirs"
    minute: "0"
    hour: "5,2"
    job: "ls -alh > /dev/null"

# 移除名叫an old job的做業
- cron:
    name: "an old job"
    state: absent

# 建立一個做業 "@reboot /some/job.sh"
- cron:
    name: "a job for reboot"
    special_time: reboot
    job: "/some/job.sh"

# 建一個環境變量 "PATH=/opt/bin"
- cron:
    name: PATH
    env: yes
    value: /opt/bin

# Creates an entry like "APP_HOME=/srv/app" and insert it after PATH
# declaration
- cron:
    name: APP_HOME
    env: yes
    value: /srv/app
    insertafter: PATH

# 建一個cron文件存放在 /etc/cron.d
- cron:
    name: yum autoupdate
    weekday: 2
    minute: 0
    hour: 12
    user: root
    job: "YUMINTERACTIVE: 0 /usr/sbin/yum-autoupdate"
    cron_file: ansible_yum-autoupdate

# 刪除一個cron文件 /etc/cron.d
- cron:
    name: "yum autoupdate"
    cron_file: ansible_yum-autoupdate
    state: absent

# 刪除 "APP_HOME" 環境變量
- cron:
    name: APP_HOME
    env: yes
    state: absent

 

 

 

 

unarchive模塊
unarchive模塊用於解壓文件,其做用相似於Linux 下的tar 命令。
默認狀況下,unarchive的做用是將主控機的壓縮包拷貝到遠程服務器,而後進行解壓。
遠程機器須要已經安裝gtar/unzip

參數:
remote_src: 默認no,表示在解壓文件以前,先將控制節點上的文件複製到遠程主機中,而後再進行解壓,即便遠程主機已經有這個壓縮文件也不檢查,yes表示解壓遠程主機上的文件,即便遠程主機無這個文件
src: 必須,指定壓縮文件的路徑,該選項的取值取決於remote_src 的取值, 若是remote_src:取值爲yes ,則src 指定的是遠程服務器中壓縮包的地址,若是remote_src取值爲no, 則src 指向的是控制節點中的路徑;
dest: 必須,該選項指定的是遠程服務器上的絕對路徑,表示壓縮文件解壓的路徑
list_files:默認no ,若是該選項取值爲yes ,也會解壓文件,而且在ansible 的返回值中列出壓縮包裏的文件
exclude: 解壓文件時排除exclude 選項指定的文件或目錄列表;
keep_newer:默認False ,若是該選項取值爲True ,那麼,當目標地址中存在同名的文件,而且文件比壓縮包中的文件更新時,不進行覆蓋;
owner: 文件或目錄解壓之後的全部者
group:文件或目錄解壓之後所屬的羣組
mode: 文件或目錄解壓之後的權限

- name: Extract foo.tgz into /var/lib/foo
  unarchive:
    src: foo.tgz
    dest: /var/lib/foo

- name: Unarchive a file that is already on the remote machine
  unarchive:
    src: /tmp/foo.zip
    dest: /usr/local/bin
    remote_src: yes

- name: Unarchive a file that needs to be downloaded (added in 2.0)
  unarchive:
    src: https://example.com/example.zip
    dest: /usr/local/bin
    remote_src: yes

 

 

 

stat模塊
stat 模塊用於獲取遠程服務器上的文件信息,其做用相似於Linux 下的stat 命令。
stat模塊能夠獲取atime 、ctime 、mtime 、checksum 、size 、uid 、gid 等信息

參數:
path: 指定文件或目錄的路徑

# Obtain the stats of /etc/foo.conf, and check that the file still belongs
# to 'root'. Fail otherwise.
- stat:
    path: /etc/foo.conf
  register: st
- fail:
    msg: "Whoops! file ownership has changed"
  when: st.stat.pw_name != 'root'

# Determine if a path exists and is a symlink. Note that if the path does
# not exist, and we test sym.stat.islnk, it will fail with an error. So
# therefore, we must test whether it is defined.
# Run this to understand the structure, the skipped ones do not pass the
# check performed by 'when'
- stat:
    path: /path/to/something
  register: sym

- debug:
    msg: "islnk isn't defined (path doesn't exist)"
  when: sym.stat.islnk is not defined

- debug:
    msg: "islnk is defined (path must exist)"
  when: sym.stat.islnk is defined

- debug:
    msg: "Path exists and is a symlink"
  when: sym.stat.islnk is defined and sym.stat.islnk

- debug:
    msg: "Path exists and isn't a symlink"
  when: sym.stat.islnk is defined and sym.stat.islnk == False


# Determine if a path exists and is a directory.  Note that we need to test
# both that p.stat.isdir actually exists, and also that it's set to true.
- stat:
    path: /path/to/something
  register: p
- debug:
    msg: "Path exists and is a directory"
  when: p.stat.isdir is defined and p.stat.isdir

# Don't do md5 checksum
- stat:
    path: /path/to/myhugefile
    get_md5: no

# Use sha256 to calculate checksum
- stat:
    path: /path/to/something
    checksum_algorithm: sha256

 

 

 

mount 模塊
在遠程服務器上掛載磁盤,當進行掛盤操做時,若是掛載點指定的路徑不存在,將建立該路徑

參數
state:能夠取值爲present, absent, mounted, unmounted , 其中, mounted 與unmounted 用來處理磁盤的掛載和卸載, 而且會正確配置fstab 文件, preset 與absent 只會設置fstab 文件, 不會去操做磁盤
fstype:指定文件系統類型, 當state 取值爲present 或mounted 時,該選項爲必填選項
src:掛載的設備
path: 掛載點的路徑

# Before 2.3, option 'name' was used instead of 'path'
- name: Mount DVD read-only
  mount:
    path: /mnt/dvd
    src: /dev/sr0
    fstype: iso9660
    opts: ro,noauto
    state: present

- name: Mount up device by label
  mount:
    path: /srv/disk
    src: LABEL=SOME_LABEL
    fstype: ext4
    state: present

- name: Mount up device by UUID
  mount:
    path: /home
    src: UUID=b3e48f45-f933-4c8e-a700-22a159ec9077
    fstype: xfs
    opts: noatime
    state: present
    

 

 

 

synchronize模塊
synchronize 模塊是對rsync 命令的封裝,以便對常見的rsync 任務進行處理
注意:主控機和遠程主機都須要安裝rsync,rsync daemon必須在主控機和遠程主機都運行
synchronize模塊不必定能徹底代替rsync命令
    
參數
src : 須要同步到遠程服務器的文件或目錄
dest :遠程服務器保存數據的路徑
archive :默認yes ,至關於同時開啓recursive 、links 、perms 、times 、owner 、group 、-D 等選項
compress :默認yes ,表示在文件同步過程當中是否啓用壓縮
delete :默認no ,當取值爲yes 時,表示刪除dest 中存在而src 中不存在的文件
過濾:    (.rsync-filter )files to the source directory,排除同步rsync-filter 文件裏面指定的文件

- name: Synchronization of src on the control machine to dest on the remote hosts
  synchronize:
    src: some/relative/path
    dest: /some/absolute/path

- name: Synchronization using rsync protocol (push)
  synchronize:
    src: some/relative/path/
    dest: rsync://somehost.com/path/

- name: Synchronization using rsync protocol (pull)
  synchronize:
    mode: pull
    src: rsync://somehost.com/path/
    dest: /some/absolute/path/

- name:  Synchronization using rsync protocol on delegate host (push)
  synchronize:
    src: /some/absolute/path/
    dest: rsync://somehost.com/path/
  delegate_to: delegate.host

- name: Synchronization using rsync protocol on delegate host (pull)
  synchronize:
    mode: pull
    src: rsync://somehost.com/path/
    dest: /some/absolute/path/
  delegate_to: delegate.host

- name: Synchronization without any --archive options enabled
  synchronize:
    src: some/relative/path
    dest: /some/absolute/path
    archive: no

- name: Synchronization with --archive options enabled except for --recursive
  synchronize:
    src: some/relative/path
    dest: /some/absolute/path
    recursive: no

- name: Synchronization with --archive options enabled except for --times, with --checksum option enabled
  synchronize:
    src: some/relative/path
    dest: /some/absolute/path
    checksum: yes
    times: no

- name: Synchronization without --archive options enabled except use --links
  synchronize:
    src: some/relative/path
    dest: /some/absolute/path
    archive: no
    links: yes

- name: Synchronization of two paths both on the control machine
  synchronize:
    src: some/relative/path
    dest: /some/absolute/path
  delegate_to: localhost

- name: Synchronization of src on the inventory host to the dest on the localhost in pull mode
  synchronize:
    mode: pull
    src: some/relative/path
    dest: /some/absolute/path

- name: Synchronization of src on delegate host to dest on the current inventory host.
  synchronize:
    src: /first/absolute/path
    dest: /second/absolute/path
  delegate_to: delegate.host

- name: Synchronize two directories on one remote host.
  synchronize:
    src: /first/absolute/path
    dest: /second/absolute/path
  delegate_to: "{{ inventory_hostname }}"

- name: Synchronize and delete files in dest on the remote host that are not found in src of localhost.
  synchronize:
    src: some/relative/path
    dest: /some/absolute/path
    delete: yes
    recursive: yes

# This specific command is granted su privileges on the destination
- name: Synchronize using an alternate rsync command
  synchronize:
    src: some/relative/path
    dest: /some/absolute/path
    rsync_path: "su -c rsync"

# Example .rsync-filter file in the source directory
# - var       # exclude any path whose last part is 'var'
# - /var      # exclude any path starting with 'var' starting at the source directory
# + /var/conf # include /var/conf even though it was previously excluded

- name: Synchronize passing in extra rsync options
  synchronize:
    src: /tmp/helloworld
    dest: /var/www/helloworld
    rsync_opts:
      - "--no-motd"
      - "--exclude=.git"

# Hardlink files if they didn't change
- name: Use hardlinks when synchronizing filesystems
  synchronize:
    src: /tmp/path_a/foo.txt
    dest: /tmp/path_b/foo.txt
    link_dest: /tmp/path_a/

 

 

 

get_url模塊
相似於wget和curl的功能,能夠進行下載以及webapi交互等操做
支持HTTP, HTTPS, FTP
參數:
backup:默認no,建立一個包括時間戳信息的備份文件,這樣你能夠獲得原始文件,若是你不正確地弄錯了
checksum:
若是將校驗和傳遞給此參數,則將在下載目標文件的摘要後計算摘要,以確保其完整性。格式:<algorithm>:<checksum>,例如:checksum =「sha256:D98291AC [...] B6DC7B97」若是你擔憂可移植性,只有sha1算法可用於全部平臺和python版本。能夠安裝第三方hashlib庫以訪問其餘算法。此外,若是將校驗和傳遞給此參數,而且文件位於dest位置下,則將計算destination_checksum,若是校驗和等於destination_checksum,則將跳過文件下載(除非force爲true)
dest:目標文件,必須
force:默認no,當目標文件跟源文件不同時會強制覆蓋目標文件,若是同樣,不會執行復制,別名thirsty,也就是thirsty等於force
mode:能夠是數字形式也能夠是符號形式,0644 ,01777,u+rwx , u=rw,g=r,o=r
owner:屬主
group:屬組
timeout:默認10秒,單位秒 超時請求
url:HTTP, HTTPS, FTP形式URL
url_username:用於HTTP基本認證的用戶名。對於容許空密碼的站點,能夠在不使用url_password的狀況下使用此參數。
url_password:用於HTTP基本認證的密碼。若是未指定url_username參數,則不會使用url_password參數。
use_proxy:默認yes,若是no,它將不使用代理,即便在目標主機上的環境變量中定義了一個代理。
validate_certs:默認yes,若是no,SSL證書將不會驗證。這隻應在使用自簽名證書的我的控制站點上使用。
tmp_dest:臨時文件下載到的絕對路徑。默認爲TMPDIR,TEMP或TMP env變量或特定於平臺的值

- name: 下載文件 foo.conf
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    mode: 0440


- name: 下載並校驗文件(sha256)
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    checksum: sha256:b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c

- name: D下載並校驗文件 (md5)
  get_url:
    url: http://example.com/path/file.conf
    dest: /etc/foo.conf
    checksum: md5:66dffb5228a211e61d6d7ef4a86f5758

- name: 用ftp下載一個文件
  get_url:
    url: file:///tmp/afile.txt
    dest: /tmp/afilecopy.txt

 

 

fetch模塊
從遠程機器拷貝文件到控制機
參數
dest:必選項,必須是一個目錄,假如目錄是/backup/,文件名是/etc/profile,機器是192.168.3.6,那麼保存的路徑是/backup/192.168.3.6/etc/profile
flat:若是dest是/backup/而不是/backup,那麼就會修改默認行爲,那麼保存的路徑是/backup/profile
src :必選項,遠程機器的文件位置,必須是一個文件,不能是目錄,後續可能會支持目錄
validate_checksum:默認yes,驗證源文件和目標文件的校驗和

# 存儲文件在目標路徑/tmp/fetched/192.168.3.6/tmp/somefile
- fetch:
    src: /tmp/somefile
    dest: /tmp/fetched

# 直接定義一個路徑
- fetch:
    src: /tmp/somefile
    dest: /tmp/prefix-{{ inventory_hostname }}
    flat: yes

# 定義一個目標路徑
- fetch:
    src: /tmp/uniquefile
    dest: /tmp/special/
    flat: yes

# 存儲在針對playbook的相對路徑
- fetch:
    src: /tmp/uniquefile
    dest: special/prefix-{{ inventory_hostname }}
    flat: yes

 

 

core模塊和extra模塊
在ansible文檔上查看單個模塊會顯示是core模塊仍是extra模塊
yum就是一個core模塊,archive就是一個extra模塊


core模塊
不須要額外下載和配置,安裝ansible後就能夠直接使用


extra模塊
須要進行下載和額外配置才能使用
額外的模塊託管在Github上的,ansible-modules-extras <http://github.com/ansible/ansible-modules-extras>
使用方法
一、下載extra模塊
cd /tmp/
git clone   https://github.com/ansible/ansible-modules-extras.git

二、修改配置文件
/etc/ansible/ansible.cfg
#library = /tmp/ansible-modules-extras/



 


ansible配置文件 ansible.cfg
注意:修改了配置文件不須要重啓ansible,由於ansible不是服務端,沒有後臺運行,修改了配置文件立刻生效

 

ansible.cfg提供的是默認配置,在inventory文件裏或playbook裏沒有定義的配置,ansible.cfg提供默認配置,例如sudo_user這個選項      



module_set_locale  設置本地的環境變量  
inventory      = /etc/ansible/hosts     這個一個靜態的ini格式的文件,指定主機文件、主機目錄、可執行文件的路徑,默認爲/etc/ansible/hosts.
#library        = /usr/share/my_modules/   Ansible默認搜尋extra模塊的位置  
remote_tmp     = $HOME/.ansible/tmp   Ansible 經過遠程傳輸模塊到遠程主機,而後遠程執行,執行後在清理現場,因此你看不到遠程主機有python腳本或模塊存在  
pattern        = *    若是沒有提供「hosts」節點,這是playbook要通訊的默認主機組.默認值是對全部主機通訊  
forks          = 5    在與主機通訊時的默認並行進程數 ,默認是5
poll_interval  = 15    當具體的poll interval 沒有定義時,多少時間回查一下這些任務的狀態, 默認值是15秒  
sudo_user      = root   sudo使用的默認用戶 ,默認是root  
#ask_sudo_pass = True   用來控制Ansible playbook 在執行sudo以前是否詢問sudo密碼.默認爲False
#ask_pass      = True    控制Ansible playbook 是否會自動默認彈出密碼,默認爲False,若是改成true,ansible命令就不須要用-k選項
transport      = smart   通訊機制.默認 值爲’smart’。若是本地系統支持   ControlPersist技術的話,將會使用(基於OpenSSH)‘ssh’,若是不支持講使用‘paramiko’.其餘傳輸選項包括‘local’, ‘chroot’,’jail’等等  
#remote_port    = 22    遠程SSH端口。 默認是22  
module_lang    = C   模塊和系統之間通訊的計算機語言,默認是C語言  
gathering = implicit   控制默認facts收集(遠程系統變量). 默認值爲’implicit’, 每一次play,facts都會被收集
#roles_path    = /etc/ansible/roles   roles 路徑指的是’roles/’下的目錄,用於playbook搜索Ansible roles
#host_key_checking = False    檢查主機密鑰
sudo_exe = sudo     若是在其餘遠程主機上使用另外一種方式執sudo操做.可使用該參數進行更換
#what flags to pass to sudo   傳遞sudo以外的參數
#sudo_flags = -H

#SSH timeout    SSH超時時間
timeout = 10
#remote_user = root   使用/usr/bin/ansible-playbook連接的默認用戶名,若是不指定,會使用當前登陸的用戶名
#log_path = /var/log/ansible.log     日誌文件存放路徑
#module_name = command     ansible命令執行默認的模塊
#executable = /bin/sh     在sudo環境下產生一個shell交互接口. 用戶只在/bin/bash的或者sudo限制的一些場景中須要修改
#jinja2_extensions = jinja2.ext.do,jinja2.ext.i18n      容許開啓Jinja2拓展模塊
#private_key_file = /root/.ssh/id_rsa        私鑰文件存儲位置
ansible_managed = Ansible managed: {file} modified on %Y-%m-%d %H:%M:%S by {uid} on {host}   這個設置能夠告知用戶,Ansible修改了一個文件,而且手動寫入的內容可能已經被覆蓋.
#display_skipped_hosts = True     顯示任何跳過任務的狀態 ,默認是顯示
#error_on_undefined_vars = False      若是所引用的變量名稱錯誤的話, 將會致使ansible在執行步驟上失敗
#system_warnings = True    容許禁用系統運行ansible相關的潛在問題警告
#deprecation_warnings = True     容許在ansible-playbook輸出結果中禁用「不建議使用」警告
#command_warnings = False    當shell和命令行模塊被默認模塊簡化時,Ansible 將默認發出警告
#nocows = 1    默認ansible能夠調用一些cowsay的特性   開啓/禁用:0/1
#nocolor = 1  輸出帶上顏色區別, 開啓/關閉:0/1


 

 

 

在線查看ansible.cfg文件
https://raw.githubusercontent.com/ansible/ansible/devel/examples/ansible.cfg

ansible配置文件解釋列表
http://docs.ansible.com/ansible/latest/installation_guide/_config.html
http://docs.ansible.com/ansible/latest/installation_guide/intro_configuration.html


ansible會按照下面順序查找配置文件
ANSIBLE_CONFIG (environment variable if set)
ansible.cfg (in the current directory)
~/.ansible.cfg (in the home directory)
/etc/ansible/ansible.cfg

 


 

inventory配置

 

 

指定inventory配置文件
一、在/etc/ansible/ansible.cfg中修改
inventory = /etc/ansible/hosts

二、命令行中傳遞inventory配置文件
利用參數-i傳遞主機清單配置文件
ansible-playbook -i /etc/ansible/hosts  site.yml

 

 

靜態inventory

一組類似的 hostname , 可簡寫以下,通常建議使用ip,而不使用主機名或域名,須要反解析:
[webservers]
www[01:50].example.com


數字的簡寫模式中,01:50 也可寫爲 1:50,意義相同.你還能夠定義字母範圍的簡寫模式:
[databases]
db-[a:f].example.com

 

inventory變量

主機變量
分配變量給主機很容易作到,這些變量定義後可在 playbooks 中使用:
[atlanta]
host1 http_port=80 maxRequestsPerChild=808   #maxRequestsPerChild 稱爲主機變量
host2 http_port=303 maxRequestsPerChild=909


組變量
也能夠定義屬於整個組的變量,這樣就不用單獨一臺一臺主機定義變量:
[atlanta]
host1
host2

[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com

[docker] #定義了一組叫docker
172.16.1.11 #組下面的主機
172.16.1.12
#172.11.11.11 # ansible_ssh_pass='123456'

[docker:vars] #針對docker組使用inventroy內置變量定義了ssh登錄密碼,中括號裏寫組名:vars
ansible_ssh_pass='123456'

[kvm] 
172.16.1.13
172.16.1.14

[docker:children] #組的繼承,docker下面包含一個kvm組,kvm組裏會繼承docker組全部變量ansible_ssh_pass
kvm

 

 


按目錄結構定義變量

經過/etc/ansible/ 定義文件表示變量

建立:/etc/ansible/host_vars/
建立:/etc/ansible/group_vars/

host_vars目錄下文件名,要和/etc/ansible/hosts文件裏的host名一致,而且是yaml格式文件
group_vars目錄下文件名,要和/etc/ansible/hosts文件裏的group名一致,而且是yaml格式文件
host_vars目錄下目錄名,ansible會讀取目錄下全部文件內容,而且是yaml格式文件
group_vars目錄下目錄名,ansible會讀取目錄下全部文件內容,而且是yaml格式文件

 

好比
主機變量
/etc/ansible/hosts
client_105 #主機名


/etc/ansible/host_vars/client_105.yml
---
client_105_key: 105

 

組變量
/etc/ansible/hosts
[kvm]
192.168.3.6


/etc/ansible/group_vars/kvm.yml
---
ntp_server: ntp.atlanta.example.com


目錄下
/etc/ansible/host_vars/client_105/1.yml
/etc/ansible/host_vars/client_105/2.yml
/etc/ansible/host_vars/client_105/x.yml

/etc/ansible/group_vars/kvm/1.yml
/etc/ansible/group_vars/kvm/2.yml
/etc/ansible/group_vars/kvm/x.yml

 

 

 

Inventory行爲參數(behavioral inventory parameters )
覆蓋Ansible 默認配置時
ansible_ssh_host
將要鏈接的遠程主機名.與你想要設定的主機的別名不一樣的話,可經過此變量設置.

ansible_ssh_port
ssh端口號.若是不是默認的端口號,經過此變量設置.

ansible_ssh_user
默認的 ssh 用戶名

ansible_ssh_pass
ssh 密碼(這種方式並不安全,咱們強烈建議使用ansible命令行中 -k 參數 或 SSH 密鑰)

ansible_sudo_pass
sudo 密碼(這種方式並不安全,咱們強烈建議使用 -K)

ansible_sudo_exe (new in version 1.8)
sudo 命令路徑(適用於1.8及以上版本)

ansible_become
強制使用sudo提權

ansible_become_method
使用哪一種提權方法,例如sudo

ansible_become_user
sudo用戶,切換到哪一個用戶執行命令

ansible_become_pass
sudo用戶密碼

ansible_connection
與主機的鏈接類型.好比:local, ssh ,winrm, paramiko. Ansible 1.3 之前默認使用 paramiko.1.3 之後默認使用 'smart','smart' 方式會根據是否支持 ControlPersist, 來判斷'ssh' 方式是否可行.從Ansible 1.3 版本開始, Ansible 默認使用Open SSH實現各服務器間通訊

ansible_ssh_private_key_file
ssh 使用的私鑰文件.適用於有多個密鑰,而你不想使用 SSH 代理的狀況.

ansible_shell_type
目標系統的shell類型.默認狀況下,命令的執行使用 'bash' 語法,可設置爲 'csh' 或 'fish'.

ansible_python_interpreter
目標主機的 python 路徑.適用於的狀況: 系統中有多個 Python, 或者命令路徑不是"/usr/bin/python",好比 \*BSD, 或者 /usr/bin/python
不是 2.X 版本的 Python.咱們不使用 "/usr/bin/env" 機制,由於這要求遠程用戶的路徑設置正確,且要求 "python" 可執行程序名不可爲 python之外的名字(實際有可能名爲python26).
與 ansible_python_interpreter 的工做方式相同,可設定如 ruby 或 perl 的路徑

 

 

多個inventory列表
配置支持多個inventory
首先須要修改ansible.cfg中inventory 的定義改爲一個目錄
inventory = /etc/ansible/inventory   #/etc/ansible/inventory 是一個目錄


而後咱們在目錄裏面放入多個hosts文件
[root@ceshi2 ansible]# tree inventory
inventory
├── docker
└── kvm

cat docker
[docker] 
172.16.1.11 
172.16.1.12
#172.11.11.11 # ansible_ssh_pass='123456'

[docker:vars] 
ansible_ssh_pass='123456'


cat kvm
[kvm] 
172.16.1.13
172.16.1.14

ansible all  -i  /etc/ansible/inventory  -a 'uptime'  # -i能夠指定目錄

 

 

 

 

動態inventory

動態inventory的意思是全部的變量能夠從外部獲取,也就是說咱們能夠從CMDB以及zabbix系統拉取全部的主機信息而後使用ansible進行管理。
引用inventory只須要把ansible.cfg文件中的inventory定義值改爲一個執行腳本便可。

inventory = /etc/ansible/inventory.py   #/etc/ansible/inventory.py 是一個py文件

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Author : huazai
# @Time : 2017/11/27 14:11
# @File : inventory.py
# @Description :

import json
host1ip = ['192.168.1.15']
host2ip = ['192.168.1.110']
group = 'test11'    # 給一個組名
group2 = 'test22'
hostdata = {group:{"hosts":host1ip},group2:{"hosts":host2ip}}
print json.dumps(hostdata,indent=4)


ansible -i inventory.py test11  -a 'uptime' -k
SSH password:
192.168.1.15 | SUCCESS | rc=0 >>
 07:25:27 up  3:56,  3 users,  load average: 0.00, 0.00, 0.00
192.168.1.110 | SUCCESS | rc=0 >>
 07:25:27 up 7 min,  3 users,  load average: 0.00, 0.02, 0.00

 

按照Ansible 的約定,咱們須要寫一個動態腳原本獲取服務器的列表。這個腳本必須支持 --list 選項和--host 選項。
--list 選項以json 的格式返回以組名爲key ,服務器列表爲value 的數據。
--host 返回一個字典,該字典中包含了這個服務器的詳細信息。

python hosts.py --list
{
    "webservers":[
     "foo.example.com",
     "bar.example.com"
    ],
    "dbservers ": [
     "one.example.com",
     "two.example.com",
     "three.example.com"
    ]
}


python hosts.py  --host=foo.example.com
{
    "ansible_user":"lmx",
    "ansible_port":2099
}

 

表結構

mysql > show create table hosts\G
Create Table: CREATE TABLE 'hosts'(
`id`int(11) NOT NULL AUTO_INCREMENT,
`host` varchar(15) DEFAULT NULL ,
`groupname` varchar(15) DEFAULT NULL ,
`username` varchar(15) DEFAULT NULL ,
`port` int(11) DEFAULT  '22',
PRIMARY KEY ('id')
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4


id 是表的主鍵,
host 是服務器的ip 地址或主機名稱 
groupname 是Ansible 中的組名
username  SSH 鏈接的用戶名
port SSH 鏈接的端口號

 

hosts.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Author : huazai
# @Time : 2018/5/31 9:47
# @File : dd.py
# @Description :


from __future__ import  print_function
import argparse
import json
from collections import  defaultdict
from contextlib import  contextmanager

import pymysql


def to_json(in_dict):
    return json.dumps(in_dict,sort_keys=True,indent=2)


@contextmanager
def get_conn(**kwargs):
    conn=pymysql.connect(**kwargs)
    try:
        yield  conn   #關鍵是yield 和contextmanager
    finally:
        conn.close()


def parse_args():
    parse=argparse.ArgumentParser(description='openstack inventory module')
    group=parse.add_mutually_exclusive_group(required=True)
    group.add_argument('--list',action='store_true',help='list active servers')
    group.add_argument('--host',help='list details about the specific host')
    return parse.parse_args()


def list_all_hosts(conn):
    hosts=defaultdict(list)

    with conn as cur:   #上下文管理
        cur.execute('select * from hosts')
        rows=cur.fetchall()
        for row in rows:
            no,host,group,user,port = row
            hosts[group].append(host)
    return  hosts




def get_host_detail(conn,host):
    details = {}
    with conn as cur:
        cur.execute("select * from hosts where host='{0}'".format(host))
        rows = cur.fetchall()
        if rows:
            no,host,group,user,port=rows[0]
            details.update(ansible_user=user,ansible_port=port)

    return details


def main():
    parser=parse_args()
    with get_conn(host='127.0.0.1',user='abc',passwd='abc',db='test') as conn:
        if parser.list:
            hosts=list_all_hosts(conn)
            print(to_json(hosts))
        else:
            details = get_host_detail(conn,parser.host)
            print (to_json(details))

if __name__=='__main__':
    main()

 

ansible test -i hosts.py  -m ping

 

 

主機分組切片

- command: /opt/application/migrate_db.py
  when: inventory_hostname == webservers[0]

 


playbook劇本

 

playbook選項

https://github.com/lorin/ansible-quickref

 

注意:
yaml文件裏  等於號 等價於 冒號,  mode=600  等價於   mode: 600

 

 

playbook劇本主要三部分
一、在什麼機器以什麼身份執行,hosts,users,sudo,sudo_user
二、執行的任務是什麼,tasks
三、善後的任務有什麼,handlers


YAML語法
一、文件開始符
---

二、數組list,橫線後面有空格
- element1
- element2
- element3

三、字典 hash or dictionary,冒號後面有空格
key: value

四、複雜的字典
字典嵌套
languages:
ruby: Elite
python: Elite
dotnet: Lame
字典和數組的嵌套
- languages:
ruby: Elite
python: Elite
dotnet:
- lisp
- fortran
- erlang

五、注意
變量裏有冒號:時要加引號
foo: "somebody i a colon here: so i did"
變量覺得"{"開頭時要加引號
foo: "{{ variable }}"

 

 

 

 

YAML 的語法規則以下
---:聲明這是一個yaml文件,非必須
YAML 中的字段大小寫敏感
YAML 與Python 同樣,使用縮進表示層級關係
YAML 的縮進不容許使用Tab 鍵,只容許使用空格,且空格的數目不重要,只要相同層級的元素左側對齊便可
"#"表示註釋,從這個字符一直到行尾都會被解析器忽略
hosts:被控主機ip,或主機組,或all
remote_user:以某個用戶身份執行
vars:變量
tasks:playbook核心,定義順序執行的動做action,每一個action調用一個ansible模塊
action語法
name:每一個action最好有name屬性,這是供人類讀的,寫name是個好習慣,playbook執行時會顯示對應的name
module:module_parameter=module_value
handers:playbook的event處理操做,有且僅有在action觸發時纔會執行,但屢次觸發只執行一次,並按照聲明順序執行
參數:傳入到模塊執行的參數,好比,copy模塊須要src,dest,owner,group,mode等參數



YAML 支持三種格式的數據,分別是:
對象:鍵值對的集合,又稱爲映射,相似於Python 中的字典
數組: 一組按次序排列的值,又稱爲序列(sequence), 相似於Python 中的列表
純量(scalars): 單個的、不可再分的值,如字符串、布爾值與數字

 

安裝PyYAML模塊
pip install PyYAML

#讀取yaml文件
import yaml
with open('data.yaml') as f:
    print (yaml.load(f))
['Apple','Orange','Strawberry','Mango']

 



YAML 中可使用多種方式指定布爾值。例如,下面的YAML 格式都是合法的:
create_key: yes
needs_agent:no
needs_agent:NO
knows_oop: True
likes_emacs: TRUE
uses_cvs: false

轉換爲Python 代碼之後,對變量的取值進行了格式化
{'create_key': True ,
'know_oop': True,
'likes_emacs': True ,
'needs_agent': False,
'uses_cvs': False}

 

注意:當playbook使用vars.yml外部變量文件的時候,變量文件裏面的yes、no要加單引號不然會當成布爾值

cat  vars.yml
---
redis_settings:
 appendonly: 'no' #no和yes須要使用加單引號的字符串,不然會當成布爾值

 

 



雙引號引用字符串
若是字符串中包含特殊字符,須要使用雙引號包含起來。
例如,下面的例子中,字符串包含冒號
冒號對於YAML 來講是一個特殊字符,所以,須要使用雙引號包含起來。
foo: "somebody said I should put a colon here: so I did"


若是字符串的內容比較長,可使用">"來摺疊換行。也就是說,接下來縮進的內容都是這個字符串的一部分。

that: >
  Foo
  Bar

 

 

針對每一組主機的一個action組成一個play,通常一個playbook中只包含一個play
tasks中每一個action都是對模塊的調用,在每一個action中
冒號前是模塊的名字
冒號後是模塊的參數

web.yml
- hosts: test \\主機組,在/etc/ansible/hosts定義
remote_user: root \\遠端執行任務的用戶
tasks: \\任務
-name: install httpd \\任務描述
command: yum -y install httpd \\調用ansible的command模塊安裝httpd
-name: provide httpd.conf \\任務描述
copy:src="/root/httpd.conf" dest="/etc/httpd/conf/httpd.conf" \\調用ansible的copy模塊,httpd安裝完成後將事先準備好的httpd.conf文件複製到/etc/httpd/conf目錄下
tags: conf \\給此任務打標記,可單獨執行標記的任務
notify: \\文件內容變動通知
- server restart \\通知到指定的任務
- name: server start \\任務描述
service: name=httpd state=started enabled=true \\調用ansible的service模塊的屬性定義安裝完成httpd之後httpd服務的管理
handlers: \\定義接受關注的資源變化後執行的動做
- name: server restart \\任務描述
service: name=httpd state=restarted \\當關注的資源發生變化後調用service模塊,採起的響應的動做

 

 

例子
heartbeat.yaml
    - hosts: hbhosts
    remote_user: root
    tasks:
        - name: ensure heartbeat latest version
          yum: name=heartbeat state=present
        - name: authkeys configure file
          copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/authkeys
        - name: authkeys mode 600
          file: path=/etc/ha.d/authkeys mode=600
          notify:
            - restart heartbeat
        - name: ha.cf configure file
          copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/ha.cf
          notify:
            - restart heartbeat
    handlers:
        - name: restart heartbeat
            service: name=heartbeat state=restarted

 或

例子
heartbeat.yaml
---
- hosts: hbhosts
  remote_user: root
  become: yes
  become_method: sudo
  tasks:
      - name: ensure heartbeat latest version
        yum: name=heartbeat state=present
      - name: authkeys configure file
        copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/authkeys
      - name: authkeys mode 600
        file: path=/etc/ha.d/authkeys mode=600
        notify:
          - restart heartbeat
      - name: ha.cf configure file
        copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/ha.cf
        notify:
          - restart heartbeat
  handlers:
      - name: restart heartbeat
          service: name=heartbeat state=restarted

 

 參數的寫法


key=value
file: path=/etc/ha.d/authkeys mode=600 owner=root
或
多行
file: path=/etc/ha.d/authkeys mode=600 owner=root 或
yaml字典格式
file: path: /etc/ha.d/authkeys mode: 600 owner: root

 

 


handler
每一個編程語言都有event機制,handler就是playbook的event
handlers裏面每一個handler都是對模塊的一次調用
只有在action的狀態爲changed時纔會執行該action的handler

 
testhandler.yaml
    - hosts: lb
    remote_user: root
    vars:
        random_number: "{{ 1000 | random }}"
    tasks:
        - name: copy the /etc/hosts to /tmp/hosts.{{ 1000 | random }}
          copy: src=/etc/hosts dest=/tmp/hosts.{{ 1000 | random }}
          notify:   #由於文件名是隨機數,源和目標永遠都不同,因此永遠都會執行這個handler
            - call by /tmp/hosts.random_number
        - name: copy the /etc/hosts to /tmp/hosts
          copy: src=/etc/hosts dest=/tmp/hosts
          notify:
            - call by /tmp/hosts


    handlers:
        - name: call by /tmp/hosts
            debug: msg="call by /tmp/hosts"
        - name: call by /tmp/hosts.random_number
            debug: msg="call by /tmp/hosts.random_number"

notify裏的名字跟handlers裏的name一一對應
call by /tmp/hosts -》call by /tmp/hosts
call by /tmp/hosts.random_number -》 call by /tmp/hosts.random_number

handler按必定順序執行,即便call by /tmp/hosts.random_number先觸發,handler依然先執行call by /tmp/hosts

 handler 只會在全部task 執行完後執行。而且,即使一個handler 被觸發屢次,它也只會執行一次。handler 並非在被觸發時當即執行,而是按照action中定義的順序執行。
通常狀況下, handler 都位於action的最後,即在全部任務執行完成之後再執行。
Ansible 官方文檔提到handler 的惟一用途,就是重啓服務與服務器

 

 

serial選項
串行執行,serial指定串行值
不管webservers 組中有多少服務器,不管--forks 選項取值爲多少, 一次只更新一臺服務器,更新完成之後再更新下一臺服務器

- name: test play
  hosts: webservers
  serial: 1

 


local_action選項
使用local_action只在主控機執行操做

tasks:
- name: take out of load balancer pool
  local_action: command /usr/bin/take_out_of_pool    {{inventory_hostname}}

 

 

 

playbook變量
一、用戶自定義變量,vars, vars_files ,vars_prompt,這些變量均可以用在jinja2文件裏
二、來自遠程主機收集到的facts變量
三、內置系統變量,template模塊
四、把action結果傳入變量,叫註冊變量
五、在執行playbook時傳入變量,叫額外變量

 

變量名約束
變量名稱應爲字母,數字和下劃線。
變量應始終以字母開頭。
變量名不該與python屬性和方法名衝突。

 

 

變量做用域
global全局做用域: 設置在config, 環境變量, 和命令行中的變量
play: 做用於play和包含的structure, 變量, role中的default和vars
host: inventory, facts和register產生的變量, 只做用於某個host

 

變量優先級(從低到高)
role defaults
inventory vars
inventory group_vars
inventory host_vars
playbook group_vars
playbook host_vars
host facts
play vars
play vars_prompt
play vars_files
registered vars
set_facts
role and include vars
block vars (only for tasks in block)
task vars (only for the task)
extra vars (always win precedence)



用戶自定義變量
vars關鍵字自定義變量,使用{{}}引用起來

cat a.yml
---
    - hosts: test
      gather_facts: False
      vars:
        var1: haha
        var2: your name is
      tasks:
        - debug: msg="{{var2}} {{var1}}"



 
cat b.yml 
---
- hosts : test
  gather_facts: False 
  vars_files:
    - /tmp/var_file1.yml   #建議用絕對路徑
  tasks:
    - debug: msg="{{var1}}"


var_file1.yml 裏的內容:
var1:  hello Han×××



cat b.yml
---
- hosts: client_105
  gather_facts: False
  vars_prompt:
    - name: 'client_105_key'
      prompt: 'Input key'  #交互時提示信息
      private: no          #輸入數據是否顯示
  tasks:
    - name: print 105_key
      debug: msg="{{ client_105_key }}"
      

 

 


facts變量
ansible經過setup模塊收集主機信息,這些主機信息叫facts
每一個playbook執行前都會默認執行setup模塊,因此這些facts信息能夠直接以變量形式使用
setup 模塊收集到的信息,是 json 格式
說明:一般facts數據的頂級key爲ansible_facts,在引用時應該將其包含在變量表達式中。
但自動收集的facts比較特殊,它以ansible_facts做爲key,ansible每次收集後會自動將其註冊爲變量,
因此facts中的數據均可以直接經過變量引用,甚至連頂級key ansible_facts都要省略。

cat a.yml 
---
    - hosts: test
      tasks:
        - debug: msg="{{ansible_all_ipv4_addresses}} {{ansible_os_family}}"
 
 

 

蒐集facts信息會額外消耗時間,若是不須要facts信息,在playbook中經過關鍵字
gather_facts來控制是否收集

cat a.yml 
---
    - hosts: test
      gather_facts: no

 

 

內置系統變量,template模塊
在playbook中定義的變量,能夠直接在template中使用,同時facts變量也能夠直接在template中使用
固然也包含在inventory裏面定義的host和group變量。只要是在playbook中能夠訪問的變量,均可以在template文件中使用。


下面使用template模塊複製文件index.html.j2,而且替換index.html.j2中的變量

facts變量 
{{ ansible_hostname }} 
{{ ansible_default_ipv4.address }} 
用戶自定義的變量 
{{ defined_name }} 

 
index.html.j2文件
<html>
<title>Demo</title>
<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>
 

 

a.yml

 
cat a.yml 
---
- hosts : web
  vars:
      defined_name: "hello lin"
  tasks:
      - name: write the default index.html file
      template: src=/tmp/index2.html.j2  dest=/var/www/html/index.html
      
 

 

 



註冊變量
register關鍵字,多個action之間傳遞變量,上一個action結果傳遞到下個action

cat a.yml 
---
- hosts : test
  tasks:
    - shell : ls /tmp/
      register: result
      ignore_errors: True
    - debug: msg="{{result.stdout}}"

說明: 
執行shell 模塊後,返回信息是 json 格式的。再經過 register 註冊到 result 變量。
而後,經過 debug 模塊,輸出 result 變量的stdout的值。
 

 

 




額外變量
第一種狀況:hosts和user必須從命令行傳入值,若是在命令行中不傳入值則playbook報錯
第二種狀況:var1能夠從命令行傳入值,若是在命令行傳入值則會覆蓋playbook裏面var1定義值(變量優先級)

 
 
第一種狀況
cat a.yml 
---
- hosts : "{{hosts}}"
  remote_user: "{{user}}"
  gather_facts: False 
  tasks:

    - debug: msg="{{var1}}"
    
第二種狀況
cat a.yml 
---
- hosts : web
  gather_facts: False 
  vars:
      var1: "AAA"
  tasks:

    - debug: msg="{{var1}}"

 

命令行傳入變量值三種方式
普通方式傳入
ansible-playbook a.yml -e 'hosts=web user=root'
json方式傳入
ansible-playbook a.yml -e '{'hosts':'web','user':'root'}'
外部文件方式傳入
ansible-playbook a.yml -e '@/tmp/vars.json'

 

 

 

 



playbook引用json格式變量

facts變量或者register返回的變量都是json格式

在playbook裏面引用json格式變量,有三種方法
例子
註冊變量返回的結果是json格式

 
- shell : ls /tmp/
  register: result
- debug: msg="{{result}}"
TASK [debug] **************************************************
ok: [192.168.188.109] => {
    "msg": {
        "changed": true, 
        "cmd": "echo hello world", 
        "delta": "0:00:00.001890", 
        "end": "2018-01-18 17:12:00.178123", 
        "failed": false, 
        "rc": 0, 
        "start": "2018-01-18 17:12:00.176233", 
        "stderr": "", 
        "stderr_lines": [], 
        "stdout": "hello world", 
        "stdout_lines": [
            "hello world"
        ]
    }
}

 

一、點號
- debug: msg="{{result.stdout}} "

二、中括號
- debug: msg="{{result['stdout']}} "

三、訪問json裏面的列表
- debug: msg="{{result['stdout_lines'][0]}} "

 

 

playbook邏輯控制語句
when:條件判斷語句
loop:循環語句,vars插件和lookup插件提供
block:把幾個action組成一個代碼塊,便於針對一組操做異常進行處理

 

注意:{{ item }}這個變量名是ansible內置的,不能變


when語句

遠程主機是debian就馬上關機

tasks:
  - name: "shutdown debian systems"
    command: /sbin/shutdown  -t now
    when: ansible_os_family == "Debian"

判斷真假

vars:
   epic: true
tasks:
   - shell: echo "HELLO"
   when: epic
   或
   when: not epic


判斷變量是否已經定義了

tasks:
   - shell: echo "HELLO {{ foo }}"
   when: foo is defined

tasks:
   - shell: echo "not defined foo"
   when: foo is not  defined

使用and ,or進行判斷

tasks:
   - shell: echo "HELLO {{ foo }}"
   when: foo is defined

tasks:
   - shell: echo "not defined foo"
   when: (foo is not  defined) or (ansible_distribution=="Debian")

 

 

loop語句

with_lines
with_fileglob
with_first_found
with_diet
with_flattened
with_indexed_items
with_nested
with_random_choice
with_sequence
with_together
with_subelements
with_file


列表循環

- name: add users
  user: name={{item}}  state=present  groups=wheel
  with_items:
    - testuser1
    - testuser2

vars:
  somelist: ['testuser1','testuser2']
tasks:
- name: add users
  user: name={{item}}  state=present  groups=wheel
  with_items: "{{somelist}}"

 

#若是列表裏面的hash類型

- name: add users
  user: name={{ item.name }}  state=present  groups={{ item.groups }}
  with_items:
    - { name : 'testuser1',groups : 'wheel'}
    - { name : 'testuser2',groups : 'vsftp'}

 

 

#若是某個選項大於3就打印
vars:
  item: [1,2,3,4,5,6,7]
tasks:
- name: add users
  command: echo {{item}} 
  with_items: item
  when: item > 3

 

 

嵌套循環

- 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' ]

 

哈希循環

---
- hosts: all
  gather_facts: False
  vars:
   user:
    Bob_hou:
     name: Bob_Hou
     shell: bash
    Jmilk:
     name: Jmilk
     shell: zsh
  tasks:
  - name: debug loops
    debug: "msg=\"name -----> {{item.key }} value -----> {{item.value.name }} shell -----> {{ item.value.shell }}\""
    with_dict: "{{ user }}"

 

文件循環

---
- hosts: all
  gather_facts: False
  tasks:
  - name: debug loops
    debug: "msg=\"files -----> {{ item }}\""
    with_fileglob:
    - /root/playbook/*.yaml

 

條件判斷循環,until\retries\delay

---
- hosts: all
  gather_facts: False
  tasks:
  - name: debug loops
    shell: cat /root/ansible
    register: host
    until: host.stdout.startswith("cat")
    retries: 5
    delay: 5

 

 

序列循環
相似於Python 中的range 函數。
在使用with_sequence 時,咱們能夠指定起點、終點和步長。

# create some test users
- user:
  name:"{{item}}"
  state: present
  groups: "events"
  with_sequence: start=0 end=32 format=testuser%02x

 

 

 

register循環,接受多個task的結果
這個是jinja2的語法:{% for i in ret.results %}

---
- hosts: all
  gather_facts: True
  tasks:
  - name: debug loops
    shell: "{{ item }}"
    with_items:
    - hostname
    - uname
    register: ret
  - name: display loops
    debug: "msg=\"{% for i in ret.results %} {{ i.stdout }} {% endfor %}\""

 

 

 


標籤
標籤tags執行部分action,tags能夠和一個play(就是不少個task)或者一個task進行捆綁
ansible-playbook提供了「--skip-tags」和「--tags」 來指明是跳過特定的tags仍是執行特定的tags。
always
tagged
untagged
all

- hosts: test-agent
  tasks:
    - command: echo test1
      tags:
         - test1
    - command: echo test2
      tags:
         - test2
    - command: echo test3
      tags:
         - test3

當執行  ansible-playbook test1.yml --tags="test1,test3"  ,則只會執行 test1和test3的echo命令
當執行  ansible-playbook test1.yml --skip-tags="test2"  ,一樣只會執行 test1和test3的echo命令



- hosts: test-agent1
  tags:
     - play1
  tasks:
     - command: echo This is
     - command: echo agent1
- hosts: test-agent2
  tags:
     - play2
  tasks:
     - command: echo This is
     - command: echo agent2
- hosts: test-agent3
  tags:
     - play3
  tasks:
     - command: echo This is
     - command: echo agent3

當執行  ansible-playbook test2.yml --tags="play1,play3"  ,則只會執行 play1和play3的tasks。
當執行  ansible-playbook test2.yml --skip-tags="play2"  ,一樣只會執行 test1和test3的tasks。




always標籤
即便只執行某個標籤,always標籤也會被執行

tasks:
  - debug: msg="always print this debug message"
    tags:
     - always
    
  - yum: name{{item}} state=installed
    with_items:
      - httpd
    tags:
      - packages
      

ansible-playbook test_always.yml --tags="packages"




tasks:
  - yum: name{{item}} state=installed
    with_items:
      - httpd
    tags:
      - tagged

ansible-playbook test_always.yml --tags tagged
執行全部標記了標籤的任務

tasks:
  - yum: name{{item}} state=installed
    with_items:
      - httpd
    tags:
      - tagged
ansible-playbook test_always.yml --tags untagged 

執行全部沒有標記標籤的任務


tasks:
  - yum: name{{item}} state=installed
    with_items:
      - httpd
    tags:
      - tagged

ansible-playbook test_always.yml --tags all
無論有無標記標籤都執行全部任務


include語句使用標籤

- included: foo.yml
  tags: [web,foo]

role使用標籤

roles:
  - { role: webserver,port: 5000 tags: ['web','foo']}

 

 

 

 

 

插件
插件是對ansible功能的補充,在ansible的配置文件中,每種類型的插件都有本身的配置變量
所以放置的目錄並不相同

插件類型
#action_plugins = /usr/share/ansible/plugins/action
#cache_plugins = /usr/share/ansible/plugins/cache
#callback_plugins = /usr/share/ansible/plugins/callback
#connection_plugins = /usr/share/ansible/plugins/connection
#lookup_plugins = /usr/share/ansible/plugins/lookup
#inventory_plugins = /usr/share/ansible/plugins/inventory
#vars_plugins = /usr/share/ansible/plugins/vars
#filter_plugins = /usr/share/ansible/plugins/filter
#test_plugins = /usr/share/ansible/plugins/test
#terminal_plugins = /usr/share/ansible/plugins/terminal
#strategy_plugins = /usr/share/ansible/plugins/strategy
#inventory_plugins  = /usr/share/ansible/plugins/inventory
#enable_plugins = host_list, virtualbox, yaml, constructed


action插件
和模塊使用方法相似,只不過執行目標不是遠程主機,而是在ansible的控制節點上

cache插件
爲facts提供緩存,以免屢次執行playbook時蒐集facts上有過多開銷

callback插件
執行playbook後,提供額外行爲,例如,將執行結果發送到email,或寫入log中
官方提供的一些callback插件
https://github.com/ansible/ansible/tree/devel/lib/ansible/plugins/callback


connection插件
ansible爲管理節點和遠程節點之間提供了更多鏈接方法。默認的鏈接協議是基於paramiko的ssh協議
paramiko基本已經夠用,若是有高級需求,則能夠經過自定義插件來提供snmp,message bus等傳輸協議


filters插件
過濾器提供更多功能

lookup插件
lookup功能提供更多功能

 

strategy插件
爲執行playbook提供更多執行策略,控制play在執行時的策略,默認策略是linear
即全部遠程主機都執行完某一個任務以後,再執行下一個任務,ansible官方的strategy插件
提供了另一個策略free,容許每一個遠程主機儘快地執行到play的結尾
從ansible2.0開始,支持free策略,容許執行較快的遠程主機提早完成action部署,不用等其餘遠程主機一塊兒執行action
- hosts: all
strategy: free
task:
...

 

shell插件
經過shell插件提供遠程主機上更多類型的shell(csh,ksh,tcsh)

test插件
jinja2 test提供更多功能


vars插件
ansible將inventory/playbook命令行中的變量注入ansible中,經過vars插件
實現更多變量注入功能

 

如何使用callback 插件
timer:記錄playbook執行時間
log plays:把執行結果記錄在/var/log/ansible/hosts對應主機名文件裏

一、下載 callback plugins 文件
使用callback插件,首先從官網提供的callback插件下載須要使用的插件對應的python文件
將下載的文件保存在 /usr/share/ansible/plugins/callback目錄下

二、配置 ansible.cfg
配置放置 callback 插件的 Python 文件的位置
在ansible.cfg裏啓用插件
callback_plugins = /usr/share/ansible/plugins/callback
callback_whitelist = timer, log plays

三、playbook執行的時候自動會記錄timer 和 log plays

 

 

 

lookup 插件

一、file:獲取文件內容

---
- hosts: all
tasks:
- debug: msg="the value of foo.txt is {{ lookup('file', '/etc/foo.txt') }}"


二、password:生成密碼字符串
若是文件已存在,則不會向其寫入任何數據。 若是文件有內容,那些內容將做爲密碼讀入。 空文件致使密碼以空字符串返回。

---
- hosts: all
tasks:
# 使用只有ascii字母且長度爲8的隨機密碼建立一個mysql用戶:
    - mysql_user: name={{ client }} password="{{ lookup('password', '/tmp/passwordfile chars=ascii_letters length=8') }}" priv={{ client }}_{{ tier }}_{{ role }}.*:ALL # 使用只有數字的隨機密碼建立一個mysql用戶: - mysql_user: name={{ client }} password="{{ lookup('password', '/tmp/passwordfile chars=digits') }}" priv={{ client }}_{{ tier }}_{{ role }}.*:ALL # 使用許多不一樣的字符集使用隨機密碼建立一個mysql用戶: - mysql_user: name={{ client }} password="{{ lookup('password', '/tmp/passwordfile chars=ascii_letters,digits,hexdigits,punctuation') }}" priv={{ client }}_{{ tier }}_{{ role }}.*:ALL



三、env :讀取環境變量

tasks:
- debug: msg="{{ lookup('env','HOME') }} is an environment variable"

 

四、pipe :讀取Linux命令執行結果 

tasks:
- debug: msg="{{ lookup('pipe','date') }} is the raw result of running this command"

 

五、csvfile :讀取csv文件

- debug: msg="The atomic number of Lithium is {{ lookup('csvfile', 'Li file=/tmp/elements.csv delimiter=,') }}" - debug: msg="The atomic mass of Lithium is {{ lookup('csvfile', 'Li file=/tmp/elements.csv delimiter=, col=2') }}" 參數 默認值 描述 file ansible.csv 要加載的文件名稱 col 1 要輸出的列,索引從0開始 delimiter TAB 文件的分隔符 default empty string 若是key不在csv文件中,則爲默認返回值 encoding utf-8 使用的CSV文件的編碼(字符集)(added in version 2.1)

 

六、ini :讀取ini/properties文件
在section下查找以key1 = value1的格式來讀取文件的內容。
ini 參數格式
lookup('ini', 'key [type=<properties|ini>] [section=section] [file=file.ini] [re=true] [default=<defaultvalue>]')
第一個值必須是ini文件裏的key
字段 默認值 描述
type ini 文件類型。 能夠是ini或properties (對於java)。
file ansible.ini 要加載的文件名稱
section global 在哪裏查找key
re False 開啓正則匹配
default empty string 若是key不在文件中,則爲默認返回值

users.ini
[production]
# My production information
user=robert pass=somerandompassword [integration] # My integration information user=gertrude pass=anotherpassword tasks: - debug: msg="User in integration is {{ lookup('ini', 'user section=integration file=/tmp/users.ini') }}" - debug: msg="User in production is {{ lookup('ini', 'pass section=production file=/tmp/users.ini') }}"

 

七、dig:dns查詢
此模塊依賴dnspython 庫

- debug: msg="The IPv4 address for example.com. is {{ lookup('dig', 'example.com.')}}" - debug: msg="The TXT record for example.org. is {{ lookup('dig', 'example.org.', 'qtype=TXT') }}" - debug: msg="The TXT record for example.org. is {{ lookup('dig', 'example.org./TXT') }}"
其餘
tasks:
- debug: msg="{{ lookup('pipe','date') }} is the raw result of running this command" # redis_kv lookup requires the Python redis package - debug: msg="{{ lookup('redis_kv', 'redis://localhost:6379,somekey') }} is value in Redis for somekey" # dnstxt lookup requires the Python dnspython package - debug: msg="{{ lookup('dnstxt', 'example.com') }} is a DNS TXT record for example.com" - debug: msg="{{ lookup('template', './some_template.j2') }} is a value from evaluation of this template" # loading a json file from a template as a string - debug: msg="{{ lookup('template', './some_json.json.j2', convert_data=False) }} is a value from evaluation of this template" - debug: msg="{{ lookup('etcd', 'foo') }} is a value from a locally running etcd" # shelvefile lookup retrieves a string value corresponding to a key inside a Python shelve file - debug: msg="{{ lookup('shelvefile', 'file=path_to_some_shelve_file.db key=key_to_retrieve') }}

 

 

 

過濾器插件
過濾器對普通變量的操做

default:爲未定義的變量提供默認值
omit:與default一塊兒使用,忽略變量的佔位符,ansible會按照沒有傳這個參數的值來處理
{{ result.cmd|default(5) }}
result.cmd 若是沒有定義的話,則其默認值爲5

- name: touch files with an optional mode
  file: dest={{item.path}} state=touch mode={{item.mode|default(omit)}} with_items: - path: /tmp/foo - path: /tmp/bar - path: /tmp/baz mode: "0444"

對於列表中的前兩個文件,默認mode將由系統的umask肯定,由於mode=parameter 不會發送到文件模塊,而最後的文件將接收mode=0444選項
default(omit)在沒有定義mode時忽略mode變量

 

 

mandatory:強制定義變量,不然報錯
若是變量未定義,則來自ansible和ansible.cfg的默認行爲失敗,但您能夠將其關閉。
默認ansible.cfg中的error_on_undefined_vars=True

---
- hosts: localhost
  remote_user: root
  tasks:
    - debug: msg="{{ variable | mandatory }}"

 

int:將變量變爲整型

vars:
  string_value: "6" tasks: - name: "yes" debug: msg='YES' when: string_value | int > 5

 

 
bool:判斷變量是否爲布爾類型

- debug: msg=test
  when: some_string_value | bool

 

 ternary:相似於編程語言中的(A?B:C)

vars:
  name: "John" tasks: - name: "true of false take different value" debug: msg="{{ ('name' == 'John') | ternary('Mr','Ms') }}"

 

 
過濾器對文件路徑的操做
Linux
獲取路徑的文件名:{{ path | basename }}
獲取路徑中的目錄:{{ path | dirname }}
擴展爲實際的目錄:{{ path | expanduser }}
獲取軟鏈接的真實路徑:{{ path | realpath }}
獲取文件名的名稱和擴展名:{{ path | splitext }}


windows
獲取路徑的文件名:{{ path | win_basename }}
獲取路徑的目錄名:{{ path | win_dirname }}
分割成多個部分:{{ path | win_splitdrive }}
分割成多個部分驅動器部分:{{ path | win_splitdrive | first }}
分割成多個部分文件名部分:{{ path | win_splitdrive | last }}

 

 
過濾器對字符串變量的操做

caplitalize:爲字符串首字母大寫

vars:
  string_value: "john" tasks: - name: "cap" shell: echo {{ string_value | caplitalize }}


quote:爲字符串增長雙引號

vars:
  string_value: "John" tasks: - name: "quote" shell: echo {{ string_value | quote }}

 

 hash:獲取字符串得hash值

tasks:
  - name: "hash" shell: echo {{ 'test1'|hash('sha1') }} shell: echo {{ 'test1'|hash('md5') }}

 
comment:註釋
支持各類語言的註釋

{{ "this is the comment" | comment }}
{{ "this is the comment" | comment('c') }} {{ "this is the comment" | comment('cblock') }} {{ "this is the comment" | comment('erlang') }} {{ "this is the comment" | commen('xml')t }} {{ "this is the comment" | comment('plain', prefix='#######\n#', postfix='#\n#######\n ###\n #') }}

 

regex_replace:用正則表示對字符串進行替換

# convert "ansible" to "able"
{{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }} # convert "foobar" to "bar" {{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }} # convert "localhost:80" to "localhost, 80" using named groups {{ 'localhost:80' | regex_replace('^(?P<host>.+):(?P<port>\\d+)$', '\\g<host>, \\g<port>') }}

 

ip:字符串ip地址轉換

vars:
  myvar: "192.168.3.6" myvar6: "fe80:dcfd:1e54:728d:a99e" CIDR: "192.0.2.1/24'" tasks: - name: "check ip" debug: msg={{ myvar | ipaddr }} debug: msg={{ myvar | ipv4 }} debug: msg={{ myvar6 | ipv6 }} debug: msg={{ CIDR | ipaddr('address') }}

 

 to_datetime:字符串轉換爲時間戳

tasks:
  - name: "datetime filter" debug: msg={{ "2016-06-06 20:00:12" | to_datetime }}

 

 

 

過濾器對json的操做
format:將變量值按照json/yaml輸出
更改數據格式,其結果是字符串

{{  some_variable | to_json  }} 
{{  some_variable | to_yaml }} 對於人類可讀的輸出 {{ some_variable | to_nice_json }} {{ some_variable | to_nice_yaml }}

 

 

 合併兩個json對象

tasks:
  - name: "combine" debug: msg={{ {'a':1,'b':2}| combine({'b':3}) }}

 

 

 

過濾器對數據結構的操做

數據結構:list、set

random:取隨機數
從列表中隨機獲取元素
{{ ['a','b','c','d','e','f']|random }}

從0-59 的整數中隨機獲取一個數
{{ 59 |random}}

從0-100 中隨機獲取能被10 整除的數(能夠理解爲0 10 20 30 40 50 ...100 的隨機數)
{{ 100 |random(step=10) }}

從0-100 中隨機獲取1 開始步長爲10 的數(能夠理解爲1 11 21 31 41...91 的隨機數)
{{ 100 |random(1, 10) }}
{{ 100 |random(start=1, step=10) }}

取最小的值
{{ [3, 4, 2] | min }}

取最大的值
{{ [3, 4, 2] | max }}

列表轉換字符
{{ [3, 4, 2] | join(" ") }}

對列表惟一過濾
{{ [3, 4, 2] | unique }}

 

 

 

過濾器測試功能

測試字符串

when: ansible_os_family | match("Red[Hh]at" )
when: url | search("/users/.*/resources/.*")

 

 版本比較

檢查ansible_distribution_version版本是否大於或等於'12 .04',條件成立返回True。
{{ ansible_distribution_version | version_compare('12.04', '>=') }} 進行嚴格的版本檢查 {{ sample_version_var | version_compare('1.0', operator='lt', strict=True) }}

 

 測試list的包含關係

vars:
    a: [1,2,3,4,5] b: [2,3] tasks: - debug: msg="A includes B" when: a|issuperset(b) - debug: msg="B is included in A" when: b|issubset(a)

 

 測試文件路徑

- debug: msg="path is a directory"
  when: mypath|is_dir - debug: msg="path is a file" when: mypath|is_file - debug: msg="path is a symlink" when: mypath|is_link - debug: msg="path already exists" when: mypath|exists - debug: msg="path is {{ (mypath|is_abs)|ternary('absolute','relative')}}" - debug: msg="path is the same file as path2" when: mypath|samefile(path2) - debug: msg="path is a mount" when: mypath|ismount

 

測試任務執行結果

tasks:
- shell: /usr/bin/foo register: result ignore_errors: True - debug: msg="it failed" when: result|failed - debug: msg="it changed" when: result|changed - debug: msg="it succeeded in Ansible >= 2.1" when: result|succeeded - debug: msg="it succeeded" when: result|success - debug: msg="it was skipped" when: result|skipped

 

 

變量能夠經過過濾器修改。過濾器與變量用管道符號( | )分割,而且也能夠用圓括號傳遞可選參數。
多個過濾器能夠鏈式調用,前一個過濾器的輸出會被做爲 後一個過濾器的輸入

vars:
  string_value: "steven"
tasks:
  - name: "quote"
    shell: echo {{ string_value | | caplitalize|quote |hash('md5') }}

 



jinja2 模版語法


讀取json格式變量

下面2種方式效果是同樣的,若是變量或屬性不存在,會返回一個未定義值。

{{ foo.bar }}
{{ foo['bar'] }}

 

註釋
要註釋模板中一行,默認使用 {# ... #} 註釋語法。

 

轉義
簡單的使用單引號進行轉義
對於較大的段落,使用raw進行轉義

{% raw %}
    <ul>
    {% for item in seq %}
        <li>{{ item }}</li>
    {% endfor %}
    </ul>
{% endraw %}

包含 > 、 < 、 & 或 " 字符的變量,必需要手動轉義

{{ user.username|e }} 

 

 

控制結構
控制結構指的是全部的那些能夠控制程序流的東西 —— 條件(好比 if/elif/ekse )、 for 循環、以及宏和塊之類的東西。控制結構在默認語法中以 {% .. %} 塊的形式出現。

 

for語句
遍歷序列

{% for user in users %}
  <li>{{ user.username|e }}</li>
{% endfor %}

 

在模板中如何遍歷某一組內的全部主機?
{% for host in groups['db_servers'] %}
  {{ host }}
{% endfor %}


獲取ip地址
{% for host in groups['db_servers'] %}
  {{ hostvars[host]['ansible_eth0']['ipv4']['address'] }}
{% endfor %}
獲取組中第一個主機的ip地址
{{ hostvars[groups['webservers'][0]]['ansible_eth0']['ipv4']['address'] }}

 

迭代字典

{% for key, value in my_dict.iteritems() %}
    <dt>{{ key|e }}</dt>
    <dd>{{ value|e }}</dd>
{% endfor %}

 

循環 10 次迭代以後會終止處理,注:使用break, 須要開啓輪詢控制. 具體是在ansible.cfg的jinja2_extensions變量加上jinja2.ext.loopcontrols.

{% for user in users %}
    {%- if loop.index >= 10 %}{% break %}{% endif %}
{%- endfor %}

{% for user in users if loop.index <= 10 %}
    {{ loop.index }}
{%- endfor %}

 

在一個 for 循環塊中你能夠訪問這些特殊的變量

loop.index    當前循環迭代的次數(從 1 開始)
loop.index0    當前循環迭代的次數(從 0 開始)
loop.revindex    到循環結束須要迭代的次數(從 1 開始)
loop.revindex0    到循環結束須要迭代的次數(從 0 開始)
loop.first    若是是第一次迭代,爲 True 。
loop.last    若是是最後一次迭代,爲 True 。
loop.length    序列中的項目數。
loop.cycle    在一串序列間期取值的輔助函數。

 

 

if 語句

Jinja 中的 if 語句相似 Python 中的 if 語句。

{% if kenny.sick %}
    Kenny is sick.
{% elif kenny.dead %}
    You killed Kenny!  You bastard!!!
{% else %}
    Kenny looks okay --- so far
{% endif %}

 

 

過濾器
過濾器段容許你在一塊模板數據上應用常規 Jinja2 過濾器。只須要把代碼用 filter 節包裹起來

{% filter upper %}
    This text becomes uppercase
{% endfilter %}

 

 

變量賦值
在代碼塊中,你也能夠爲變量賦值。在頂層的(塊、宏、循環以外)賦值是可導出的,即 能夠從別的模板中導入。
賦值使用 set 標籤,而且能夠爲多個變量賦值

{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}

 

 

表達式
{% ... %} 用於執行諸如 for 循環 或賦值的語句
{{ ... }} 把表達式的結果打印到模板上

 

if 表達式
通常的語法是

<do something> if <something is true> else <do something else>

例如

{{ '[%s]' % page.title if page.title is defined else 'undefined' }}

 

字面量
表達式最簡單的形式就是字面量。字面量表示諸如字符串和數值的 Python 對象。

"Hello World"    雙引號或單引號中間的一切都是字符串。不管什麼時候你須要在模板中使用一個字 符串(好比函數調用、過濾器或只是包含或繼承一個模板的參數),它們都是 有用的。
42/42.23    直接寫下數值就能夠建立整數和浮點數。若是有小數點,則爲浮點數,不然爲 整數。記住在 Python 裏, 42 和 42.0 是不同的。
['list','of','objects']    一對中括號括起來的東西是一個列表。列表用於存儲和迭代序列化的數據。
('tuple','of','values')    元組與列表相似,只是你不能修改元組。若是元組中只有一個項,你須要以逗號 結尾它。元組一般用於表示兩個或更多元素的項。更多細節見上面的例子。
{dict':'of','key':'and','value':'pairs'}    Python 中的字典是一種關聯鍵和值的結構。鍵必須是惟一的,而且鍵必須只有一個 值。字典在模板中不多使用,罕用於諸如 xmlattr() 過濾器之類。
true/false    true 永遠是 true ,而 false 始終是 false,true 、 false 和 none 其實是小寫的,爲了一致性(全部的 Jinja 標識符是小寫的),你應該使用小寫的版本

 

算術
Jinja 容許你用計算值。支持下面的 運算符

+    把兩個對象加到一塊兒。一般對象是素質,可是若是二者是字符串或列表,你能夠用這 種方式來銜接它們。不管如何這不是首選的鏈接字符串的方式!鏈接字符串見 ~ 運算符。 {{ 1 + 1 }} 等於 2 。
-    用第一個數減去第二個數。 {{ 3 - 2 }} 等於 1 。
/    對兩個數作除法。返回值會是一個浮點數。 {{ 1 / 2 }} 等於 {{ 0.5 }} 。
//    對兩個數作除法,返回整數商。 {{ 20 // 7 }} 等於 2 。
%    計算整數除法的餘數。 {{ 11 % 7 }} 等於 4 。
*    用右邊的數乘左邊的操做數。 {{ 2 * 2 }} 會返回 4 。也能夠用於重 復一個字符串屢次。 {{ ‘=’ * 80 }} 會打印 80 個等號的橫條。
**    取左操做數的右操做數次冪。 {{ 2**3 }} 會返回 8 。

 

比較
==    比較兩個對象是否相等。
!=    比較兩個對象是否不等。
>    若是左邊大於右邊,返回 true 。
>=    若是左邊大於等於右邊,返回 true 。
<    若是左邊小於右邊,返回 true 。
<=    若是左邊小於等於右邊,返回 true 。

 

邏輯
對於 if 語句,在 for 過濾或 if 表達式中,它能夠用於聯合多個表達式

and    若是左操做數和右操做數同爲真,返回 true 。
or    若是左操做數和右操做數有一個爲真,返回 true 。
not    對一個表達式取反(見下)。
(expr)    表達式組。
is 和 in 運算符一樣支持使用中綴記法: foo is not bar 和 foo not in bar 而不是 not foois bar 和 not foo in bar 。全部的 其它表達式須要前綴記法 not (foo and bar)

 

 

其它運算符
in    運行序列/映射包含檢查。若是左操做數包含於右操做數,返回 true 。好比 {{ 1 in[1,2,3] }} 會返回 true 。
is    運行一個 測試 。
應用一個 過濾器 。
~    把全部的操做數轉換爲字符串,而且鏈接它們。 {{ "Hello " ~ name ~ "!" }} 會返回(假設 name 值爲 ''John' ) Hello John! 。
()    調用一個可調用量:{{ post.render() }} 。在圓括號中,你能夠像在 python 中同樣使用位置參數和關鍵字參數: {{ post.render(user, full=true) }} 。
. / []    獲取一個對象的屬性。

 

 


 

role 和ansible galaxy


重用playbook
一、include語句
主要重用action,能夠將多個action放在多個文件,避免playbook過於臃腫

include指令相似以下,能夠像普通tasks命令同樣在playbook中混合使用

tasks:
- include: /tmp/tasks/foo.yml
cat /tmp/tasks/foo.yml
---
# possibly saved as /tmp/tasks/foo.yml
  - name: placeholder foo
    command: /bin/foo
  - name: placeholder bar
    command: /bin/bar

 

在include中使用參數,parameterized include

tasks:
- include: wordpress.yml wp_user=timmy
- include: wordpress.yml wp_user=alice
- include: wordpress.yml wp_user=bob

或者
---
- hosts: lb
vars:
  wp_user: "timmy"
  remote_user: root
tasks:
- include: wordpress.yml

 

 

二、role
role相似於python的package,能夠重用一組文件,造成完整功能

ansible會按照下面順序查找roles_path

一、ANSIBLE_ROLES_PATH #環境變量
二、/etc/ansible/ansible.cfg : #roles_path = /etc/ansible/roles #若是沒有設置環境變量就用配置文件裏,能夠設置多個路徑,用逗號隔開
三、/etc/ansible/roles #若是沒有設置環境變量也沒有配置文件裏設置roles_path 那麼使用默認的路徑

 

 

調整role和任務順序
pre_tasks
post_tasks
若是在執行一個role時,須要在其前或其後依然要執行某些任務,咱們可使用pre_tasks及post_tasks來聲明。
pre_tasks是在role以前執行,而post_tasks則在role以後執行

- name: deply webservers
 host: webservers
 vars_files:
   - secrets.yml

 pre_tasks:
   - name: update yum cache
     yum: update_cache=yes

 roles:
   - role: apache
     database_host: {{ hostvars.db.ansible_eth0.ipv4.address }}
     domains:
       - exampel.com
       - www.example.com

  post_tasks:
    - name: print something
      shell: echo "The roles have been updated!"

 

 

條件測試調用role

vim roles.yml
---
- hosts:web
  remote_user: root
  roles:
  - role: nginx
    when: "ansible_distribution_major_version == '7'"

 

 

 

 

完整的role目錄結構
這裏面任何一個文件都不是必須的,若是文件不存在,則跳過該文件的加載

調用:ansible-playbook  -i  hosts  site.yml

主機清單設置group_vars目錄,分類設置各種主機的變量
group_vars:
nginx
mysql
all



├── library  #目錄下存放callback二次開發,mysqldb,filter plugin等庫文件
├── simple
│   ├── defaults #文件中的變量都會被加入play,這個是默認變量,優先級比vars低
│   │   └── main.yml
│   ├── files  #copy、script模塊使用這個目錄下的文件
│   ├── handlers    #文件中的handlers都會被加入play
│   │   └── main.yml
│   ├── meta  #文件中的全部依賴的role都會被加入play
│   │   └── main.yml
│   ├── README.md
│   ├── tasks   #文件中的任務都會被加入play,role的入口文件
│   │   └── main.yml
│   ├── templates  #存放jinja2模版文件,例如nginx.conf.j2
│   ├── tests
│   │   ├── inventory
│   │   └── test.yml
│   └── vars   #文件中的變量都會被加入play
│       └── main.yml
├── site.yml  #總入口文件
├── group_vars
│   └── nginx  #主機清單的nginx組的組變量
├── hosts   #主機清單

 

 

role目錄標準化

 

引用其餘main.yml 文件
Ansible 提供了兩個關鍵字, include和include_vars ,來分別引入role 中非main.yml 其餘文件包含的tasks和vars

默認

引入其餘文件yaml文件

 

role的依賴
role 依賴關係的定義文件是x/meta/main.yml
若是role x 依賴role y ,那麼在Playbook 中調用role x 以前會先調用role y。
當多個role 依賴同一個role 時, Ansible 會自動進行過濾,避免重複調用相同參數的role

 

第一種方法:dependencies
db 和Web 都依賴role common。若是在Playbook中調用db 和Web,
那麼Ansible 會保證在 db 和Web 運行前,先運行 common ,而且只運行一次。

依賴關係中和role 的調用同樣,也是能夠加入參數的,下面是加入參數的meta/main.yml 文件的例子。
在Ansible 的去重機制中,只有對個相同的role 進行參數相同的調用時,纔算是重複的。

---
dependencies :
- { role: common, name:"NAME IN DB"

 

 

第二種方法:把引用的role放在最前面,先執行

site.yml
roles: 
 - common  #先執行common role
 - db
 - web 

 

 

 

ansible galaxy網站
訪問https://galaxy.ansible.com/ ,經過BROWSE ROLES 找到你須要的role 。

windows相關的role
https://galaxy.ansible.com/mrlesmithjr/windows-iis/

 

 


 

windows遠程管理

 

https://www.jianshu.com/p/4dcdf2a5cfe5

 



Windows Playbook示例

執行powershell腳本
- name: test script module
  hosts: windows
  tasks:
    - name: run test script
      script: files/test_script.ps1

獲取ip地址信息
- name: test raw module
  hosts: windows
  tasks:
    - name: run ipconfig
      win_command: ipconfig
      register: ipconfig
    - debug: var=ipconfig

使用dos命令,移動文件
- name: another raw module example
  hosts: windows
  tasks:
     - name: Move file on remote Windows Server from one location to another
       win_command: CMD /C "MOVE /Y C:\teststuff\myfile.conf C:\builds\smtp.conf"

使用powershell命令,移動文件
- name: another raw module example demonstrating powershell one liner
  hosts: windows
  tasks:
     - name: Move file on remote Windows Server from one location to another
       win_command: Powershell.exe "Move-Item C:\teststuff\myfile.conf C:\builds\smtp.conf"



https://www.jianshu.com/p/4dcdf2a5cfe5
add_host
assert
async
debug
fail
fetch
group_by
include_vars
meta
pause
raw
script
set_fact
setup
slurp
template (also: win_template)

windows模塊
http://docs.ansible.com/ansible/latest/modules/list_of_windows_modules.html

win_acl - Set file/directory/registry permissions for a system user or group
win_acl_inheritance - Change ACL inheritance
win_audit_policy_system - Used to make changes to the system wide Audit Policy.
win_audit_rule - Adds an audit rule to files, folders, or registry keys
win_certificate_store - Manages the certificate store
win_chocolatey - Manage packages using chocolatey
win_command - Executes a command on a remote Windows node
win_copy - Copies files to remote locations on windows hosts
win_defrag - Consolidate fragmented files on local volumes
win_disk_facts - Show the attached disks and disk information of the target host
win_disk_image - Manage ISO/VHD/VHDX mounts on Windows hosts
win_dns_client - Configures DNS lookup on Windows hosts
win_domain - Ensures the existence of a Windows domain.
win_domain_controller - Manage domain controller/member server state for a Windows host
win_domain_group - creates, modifies or removes domain groups
win_domain_membership - Manage domain/workgroup membership for a Windows host
win_domain_user - Manages Windows Active Directory user accounts
win_dotnet_ngen - Runs ngen to recompile DLLs after .NET updates
win_dsc - Invokes a PowerShell DSC configuration
win_environment - Modify environment variables on windows hosts
win_eventlog - Manage Windows event logs
win_eventlog_entry - Write entries to Windows event logs
win_feature - Installs and uninstalls Windows Features on Windows Server
win_file - Creates, touches or removes files or directories.
win_file_version - Get DLL or EXE file build version
win_find - Return a list of files based on specific criteria
win_firewall - Enable or disable the Windows Firewall
win_firewall_rule - Windows firewall automation
win_get_url - Fetches a file from a given URL
win_group - Add and remove local groups
win_group_membership - Manage Windows local group membership
win_hotfix - install and uninstalls Windows hotfixes
win_iis_virtualdirectory - Configures a virtual directory in IIS.
win_iis_webapplication - Configures IIS web applications
win_iis_webapppool - configures an IIS Web Application Pool
win_iis_webbinding - Configures a IIS Web site binding.
win_iis_website - Configures a IIS Web site.
win_lineinfile - Ensure a particular line is in a file, or replace an existing line using a back-referenced regular expression.
win_mapped_drive - maps a network drive for a user
win_msg - Sends a message to logged in users on Windows hosts.
win_msi - Installs and uninstalls Windows MSI files (D)
win_nssm - NSSM - the Non-Sucking Service Manager
win_owner - Set owner
win_package - Installs/uninstalls an installable package
win_pagefile - Query or change pagefile configuration
win_path - Manage Windows path environment variables
win_ping - A windows version of the classic ping module
win_power_plan - Changes the power plan of a Windows system
win_product_facts - Provides Windows product information (product id, product key)
win_psexec - Runs commands (remotely) as another (privileged) user
win_psmodule - Adds or removes a Powershell Module.
win_rabbitmq_plugin - Manage RabbitMQ plugins
win_reboot - Reboot a windows machine
win_reg_stat - returns information about a Windows registry key or property of a key
win_regedit - Add, change, or remove registry keys and values
win_region - Set the region and format settings
win_regmerge - Merges the contents of a registry file into the windows registry
win_robocopy - Synchronizes the contents of two directories using Robocopy
win_route - Add or remove a static route.
win_say - Text to speech module for Windows to speak messages and optionally play sounds
win_scheduled_task - Manage scheduled tasks
win_scheduled_task_stat - Returns information about a Windows Scheduled Task
win_security_policy - changes local security policy settings
win_service - Manage and query Windows services
win_share - Manage Windows shares
win_shell - Execute shell commands on target hosts.
win_shortcut - Manage shortcuts on Windows
win_stat - returns information about a Windows file
win_tempfile - Creates temporary files and directories.
win_template - Templates a file out to a remote server.
win_timezone - Sets Windows machine timezone
win_toast - Sends Toast windows notification to logged in users on Windows 10 or later hosts
win_unzip - Unzips compressed files and archives on the Windows node
win_updates - Download and install Windows updates
win_uri - Interacts with webservices
win_user - Manages local Windows user accounts
win_user_right - Manage Windows User Rights
win_wait_for - Waits for a condition before continuing
win_wakeonlan - Send a magic Wake-on-LAN (WoL) broadcast packet
win_webpicmd - Installs packages using Web Platform Installer command-line
win_whoami - Returns information about the current user and process

 

具體步驟

一、在管理機安裝pywinrm
pip install  pywinrm

 

二、在被控機執行winrm設置腳本


checkclientenv.bat
winrm set winrm/config/service/auth @{Basic="true"}
winrm set winrm/config/service @{AllowUnencrypted="true"}
checkclientenv.ps1

$RootDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
$RootDir
""
sleep 1; Write-Host -ForegroundColor Yellow "正在檢查當前數據庫服務器的環境......"; sleep 2
""
Get-WmiObject -Class Win32_OperatingSystem | Select-Object -ExpandProperty Caption | Out-Null
$ComInfo =(gwmi -Class win32_operatingsystem).Caption
Write-Host "當前系統版本爲:$($ComInfo)";
""
#獲取當前系統的外網IP
$ExternalIP = ''
Try {$ExternalIP = Invoke-WebRequest http://myip.ipip.net| Select -ExpandProperty Content -ErrorAction SilentlyContinue}
catch [System.Net.WebException] { Write-Host -ForegroundColor Red  "當前主機沒法訪問外網!!"}
IF ($ExternalIP -ne '') { Write-Host -ForegroundColor Green  "當前主機外網IP爲$($ExternalIP)" }
""
#獲取當前系統的Powershell版本
$PSVersion = $PSVersionTable.PSVersion.Major
Write-Host -ForegroundColor Yellow "當前Powershell版本爲$PSVersion"

##安裝Powershell更新補丁
IF ($PSVersion -lt 5)
    {  
     Write-Host -ForegroundColor Yellow "當前Powershell版本須要更新,正在打開Window update功能......";sleep 3
     set-Service -name wuauserv -StartupType Manual
     start-Service -name wuauserv
     Write-Host ""
    switch($ComInfo)  
        {  
        {$ComInfo.contains("2012") -and  $ComInfo.contains("R2")}                 {wusa.exe "$RootDir\PowerShell_v5\Win8.1AndW2K12R2-KB3134758-x64.msu"} 
        {$ComInfo.contains("2012") -and  $ComInfo.notcontains("R2") }             {wusa.exe "$RootDir\PowerShell_v5\W2K12-KB3134759-x64"}
        {$ComInfo.contains("2008") -and  $ComInfo.contains("R2") }                {wusa.exe "$RootDir\PowerShell_v5\Win7AndW2K8R2-KB3134760-x64"}    
        {$ComInfo.contains("Windows 8") -or $ComInfo.contains("Windows 8.1")}     {wusa.exe "$RootDir\Tools\PowerShell_v5\Win8.1-KB3134758-x86"}  
        {$ComInfo.contains("Windows 7")}                                          {wusa.exe "$RootDir\PowerShell_v5\Win7-KB3134760-x86.msu"}   
        Default { -ForegroundColor Red "當前系統沒法自動更新Powershell V5版本,請手動更新後再從新運行腳本!等待5秒後腳本自動退出!";sleep 5;exit}  
        }  
    Write-Host "補丁安裝完成後須要重啓服務器!等待5秒後腳本自動退出!";sleep 5;exit
    }

""
#判斷WinRm服務是否啓動
$WinRMstatus  = Get-Service WinRM | Where-Object {$_.Status -eq "running"}

IF($WinRMstatus.count -eq 0)
    {
    Write-Host "正在開啓WinRM服務......";Enable-PSRemoting –Force
    }
    

#判斷WinRM服務是否開啓監聽端口
$WinRMport = winrm e winrm/config/listener

IF($WinRMport.count -eq 0)
    {
    Write-Host -NoNewline  "正在開啓WinRM監聽端口......";Enable-PSRemoting –Force;Write-Host -ForegroundColor Green "OK"
    }
    
Write-Host ""
Write-Host "測試本機的WinRM服務是否能正常鏈接......"
Try {Test-WsMan 127.0.0.1  -ErrorAction Stop | Out-Null}
Catch [System.InvalidOperationException] 
{ Write-Host -ForegroundColor Red "WinRM服務鏈接異常,請檢查相關配置,等待15秒後腳本自動退出!";sleep 15;exit}
Write-Host -ForegroundColor Green "本機的WinRM服務鏈接正常!"
""

##添加WinRM信任列表,在客戶端添加,而不是服務端
$tr = Get-Item wsman:\localhost\client\trustedhosts | Select -Property value
IF($tr.value  -ne "*")
    {
    Write-Host "正在添加WinRM信任列表......"
    Set-Item wsman:\localhost\client\trustedhosts * -Force
    Restart-Service WinRM
    }
""
Write-Host "WinRM服務鏈接配置完成!";
""
Write-Host -ForegroundColor Yellow "請手動容許數據庫服務器上的防火牆經過WinRM端口(容許外部網絡,默認5895)和數據庫鏡像端口(容許內部網絡,默認5022)經過!";sleep 5;
""
Write-Host "當前數據庫服務器的環境完成!等待10秒後腳本自動退出!";sleep 10;exit

  



三、inventory 文件

[windows]
10.154.175.156

[linux]
192.168.3.9

[windows:vars]
ansible_user=Administrator
ansible_password=1qaz2wsx!@#123
ansible_port=5985   #winrm的端口
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore

 

 

四、Windows Playbook

獲取ip地址信息
---
- hosts: windows
  tasks:
    - name: run ipconfig
      win_command: ipconfig
      register: result
    - name: print ipconfig
      debug: msg="{{ result }}"

 

五、執行playbook
ansible-playbook   /tmp/site.yml

 

 

補充

對命令輸出的信息進行utf-8編碼,修改winrm模塊的protocol.py
sed -i "s#tdout_buffer.append(stdout)#tdout_buffer.append(stdout.decode('gbk').encode('utf-8'))#g" /usr/lib/python2.6/site-packages/winrm/protocol.py
sed -i "s#stderr_buffer.append(stderr)#stderr_buffer.append(stderr.decode('gbk').encode('utf-8'))#g" /usr/lib/python2.6/site-packages/winrm/protocol.py



ansible的優化


一、開啓SSH長鏈接
ansible是經過使用ssh和遠程主機進行通訊,因此對ssh有這很強的依賴。在OpenSSH 5.6之後支持Multiplexing這個特性,能夠經過在ansible配置中設置以支持該特性。
ansible中控機上執行一次與遠程主機的鏈接以後,這個鏈接會持久保持設定時間之久。能夠經過netstat命令查看到ESTABLISHED狀態的鏈接信息。

以下是配置參數,設置長鏈接保持時間爲5天;control_path指定socket文件所保存的位置。
cat /etc/ansible/ansible.cfg
ssh_args = -o ControlMaster=auto -o ControlPersist=5d
control_path = /etc/ansible/ssh-socket/   #control_path須要預先建立給寫權限





二、開啓pipelining
默認狀況下,ansible的執行流程是把生成好的本地python腳本push到遠程服務器而後運行。若是開啓了pipelining,整個流程少了一個push腳本到遠程服務器的步驟,直接在SSH的會話中進行,能夠提升整個執行效率。
cat /etc/ansible/ansible.cfg
pipelining = True

須要注意的是:若是開啓pipelining,須要被控的遠程服務器將/etc/sudoers中的」Defaults requiretty」註釋掉,不然會出現相似如:you must have a tty to run sudo 的報錯。


 
 

三、開啓accelerate模式
accelerate模式相似於SSH的Multiplexing功能,都是使ansible控制服務器和遠程服務器之間保持長鏈接。
accelerate模式是使用python程序在遠程服務器上運行一個守護進程,ansible經過這個守護進程監聽的端口進行通訊。
使用accelerate模式,須要控制服務器和遠程服務器都安裝python-keyczar包

accelerate模式的開啓方法很簡單,只要在playbook中配置accelerate: true便可。
cat /etc/ansible/ansible.cfg
[accelerate]
accelerate_port = 5099
accelerate_timeout = 30
accelerate_connect_timeout = 5.0





四、對facts設置優化
playbook默認第一個task是Gathering Facts收集各主機的facts信息,以方便咱們在paybook中直接引用facts裏的信息。
若是既想用facts信息,有但願能提升playbook的效率的話,能夠採用facts緩存來實現。
facts緩存支持多種方式:json文件方式,redis方式,memcache方式等。
facts存儲不支持遠端的redis/memcache,須要在ansible的控制服務器上安裝redis/memcache;同時,還須要安裝python的redis模塊/memcache模塊
1)json文件方式
cat /etc/ansible/ansible.cfg
gathering=smart
fact_caching_timeout=86400
fact_caching=jsonfile
fact_caching_connection=/path/to/ansible_fact_cache  #這是一個目錄,目錄下會生成各個機器會以機器名爲文件名


2)redis方式
cat /etc/ansible/ansible.cfg
gathering=smart
fact_caching_timeout=86400
fact_caching=redis


3)memcache方式
cat /etc/ansible/ansible.cfg
gathering=smart
fact_caching_timeout=86400
fact_caching=memcached


pycharm的yaml插件

 

插件地址:https://github.com/vermut/intellij-ansible

 

安裝

 

設置

Editor → File Types → YAML/Ansible

添加   *.yaml 、*.yml   ,提示已經關聯過yaml,yml,直接覆蓋便可

 

 新建一個a.yml自動關聯插件

 

右上角顯示語法是否正確

 

f

相關文章
相關標籤/搜索