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