<--目錄-->
1)Ansible介紹
2)安裝
3)Hosts配置
4)Ansible.cnf配置
5)Ansible的七個命令
6)命令行使用Ansile方法總結
7)Ad-hoc與命令執行模塊
8) Ansible常用模塊
9) Playbook執行方法
10) Playbook構成和簡單使用
11)Playbook常用模塊
12)Playbook的角色及包含
13) Playbook的變量
14)Playbook的內置變量
15)Playbook的條件判斷
16)Playbook的循環
17)tags標籤功能
18) 異步操作和輪詢
19)加速模式詳解
20) Vault加密功能
【Ansible介紹】
ansible 是一套組件, 在管理節點將Ansible 模塊通過SSH 協議(或者Kerberos、LDAP)推送到被管理端執行,執行完之後自動刪除
1、管理端支持local 、ssh、zeromq 三種方式連接被管理端,默認使用基於ssh的連接---這部分對應基本架構圖中的連接模塊;
2、可以按應用類型等方式進行Host Inventory(主機羣)分類,管理節點通過各類模塊實現相應的操作---單個模塊,單條命令的批量執行,我們可以稱之爲ad-hoc;
3、管理節點可以通過playbooks 實現多個task的集合實現一類功能,如web服務的安裝部署、數據庫服務器的批量備份等。playbooks我們可以簡單的理解爲,系統通過組合多條ad-hoc操作的配置文件
ansible特性:
分佈式,輕量級
學習曲線不陡峭
不需要代理,不需要客戶端
沒有服務器端
不基於pki工作
基於模塊工作
默認基於ssh
很強的多層解決方案
配置語法使用YMAL 及Jinja2模板語言
更強的遠程命令執行操作
【安裝】
1、編譯安裝
yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible
2、rpm安裝
wget -O /etc/yum.repos.d/CentOS6-Base-163.repo http://mirrors.163.com/.help/CentOS6-Base-163.repo
yum clean all
yum makecache
yum -y install ansible
yum -y install cowsay #安裝奶牛,可裝可不裝
【hosts配置】
中文官網:http://www.ansible.com.cn/docs/intro_inventory.html?highlight=group_vars#id10
簡介:
Ansible 通過讀取默認的主機清單配置/etc/ansible/hosts,可以同時連接到多個遠程主機上執行任務, 默認路徑可以通過修改 ansible.cfg 的 hostfile 參數指定路徑。
/etc/ansible/hosts 主機清單配置格式如下:
1、中括號中的名字代表組名,可以根據自己的需求將龐大的主機分成具有標識的組,如下面分了兩個組webservers和dbservers組;
2、主機(hosts)部分可以使用域名、主機名、IP地址表示;當然使用前兩者時,也需要主機能反解析到相應的IP地址,一般此類配置中多使用IP地址
mail.yanruogu.com
[webservers]
web1.yanruogu.com
web2.yanruogu.com
[dbservers]
db1.yanruogu.com
db2.yanruogu.com
Inventory 參數:
ansible_ssh_user #ssh連接時默認使用的用戶名
ansible_ssh_pass #ssh連接時的密碼
ansible_ssh_port #用於指定連接到被管理主機的ssh端口號,默認是22
ansible_sudo_pass #使用sudo連接用戶時的密碼
ansible_ssh_private_key_file #私鑰文件路徑
使用示例:
下面的示例中指定了三臺主機,三臺主機的用密碼分別是P@ssw0rd、123456、45789,指定的ssh連接的用戶名分別爲root、breeze、bernie,這樣在ansible命令執行的時候就不用再指令用戶和密碼等了。
[test]
192.168.1.1 ansible_ssh_user=root ansible_ssh_pass='P@ssw0rd'
192.168.1.2 ansible_ssh_user=breeze ansible_ssh_pass='123456'
192.168.1.3 ansible_ssh_user=bernie ansible_ssh_port=3055 ansible_ssh_pass='456789'
aws_host ansible_ssh_private_key_file=/home/example/.ssh/aws.pem
[databases]
badwolf.example.com:5309 指定SSH 端口5309
db-[a:f].example.com 支持字母匹配a b c...f
www[01:50].example.com 支持通配符匹配www01 www02 ...www50
jumper ansible_ssh_port=5555 ansible_ssh_host=192.168.1.50 設置主機別名爲jumper
主機變量:
可以爲每個主機單獨指定一些變量,這些變量隨後可以在playbooks 中使用:
[atlanta]
host1 http_port=80 maxRequestsPerChild=808
host2 http_port=303 maxRequestsPerChild=909
組的變量
也可以定義屬於整個組的變量:
[atlanta]
host1
host2
[atlanta:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
組可以包含其他組:
[wuhan]
web1
web2
[suizhou]
web4
web3
[hubei:children]
wuhan
suizhou
[hubei:vars]
ntp_server=192.168.1.10
zabbix_server=192.168.1.10
[china:children]
hubei
hunan
上面的示例中,指定了武漢組有web1、web2;隨州組有web3、web4主機;又指定了一個湖北組,同時包含武漢和隨州;同時爲該組內的所有主機指定了2個vars變量。設定了一個組中國組,包含湖北、湖南。
注:vars變量在ansible ad-hoc部分中基本用不到,主要用在ansible-playbook中。
通配模式Patterns
在Ansible 中,Patterns 意味着要管理哪些機器,在playbooks 中,意味着哪些主機需要應用特定的配置或者過程
比如我們的主機列表配置爲:
192.168.0.6
[webservers]
192.168.0.4
[db]
192.168.0.5
ansible webservers -m service -a "name=httpd state=restarted"
模式通常用主機組來表示,上面的命令就代表webservers 組的所有主機
其他的匹配方式:
表示通配inventory 中的所有主機
all
*
ansible all -m service -a "name=httpd state=restarted"
ansible * -m service -a "name=httpd state=restarted"
也可以指定具有規則特徵的主機或者主機名
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
ansible one.example.com -m service -a "name=httpd state=restarted"
ansible one.example.com:two.example.com -m service -a "name=httpd state=restarted"
ansible 192.168.1.50 -m service -a "name=httpd state=restarted"
ansible 192.168.1.* -m service -a "name=httpd state=restarted"
你完全不需要使用這些嚴格的模式去定義組來管理你的機器,主機名,IP,組都可以使用通配符去匹配
*.example.com
*.com
one*.com:dbservers
ansible *.example.com -m service -a "name=httpd state=restarted"
ansible *.com -m service -a "name=httpd state=restarted"
ansible one*.com:dbservers -m service -a "name=httpd state=restarted"
可以匹配一個組的特定編號的主機(先後順序0 到...)
webservers1[0] 表示匹配webservers1 組的第1 個主機
webservers1[0:25] 表示匹配webservers1 組的第1 個到第25 個主機(官網文檔是”:”表示範圍,測試發現應該使用”-”,注意不要和匹配多個主機組混淆)
ansible webservers1[0] -m service -a "name=httpd state=restarted"
ansible webservers1[0:25] -m service -a "name=httpd state=restarted"
爲host 和group 定義一些比較複雜的變量時(如array、hash),可以用單獨文件保存host和group 變量,以YAML 格式書寫變量,避免都寫在hosts 文件顯得混亂,如hosts 文件路徑爲:
/etc/ansible/hosts
/etc/ansible/host_vars/all #host_vars 目錄用於存放host 變量,all 文件對所有主機有效
/etc/ansible/group_vars/all #group_vars 目錄用於存放group 變量,all 文件對所有組有效
/etc/ansible/host_vars/foosball #文件foosball 要和hosts 裏面定義的主機名一樣,表示只對foosball 主機有效
/etc/ansible/group_vars/raleigh #文件raleigh 要和hosts 裏面定義的組名一樣,表示對raleigh 組下的所有主機有效
注:group_varst和host_vars變量目錄要與hosts主機清單文件在同一目錄下
這裏/etc/ansible/group_vars/raleigh 格式如下:
--- #YAML 格式要求
ntp_server: acme.example.org #
database_server: storage.example.org
最後一個示例
vim /etc/ansible/hosts
%s/^/#/g
[webserver]
192.168.1.1
192.168.1.2
[dbserver]
192.168.1.3
ssh-keygen -t rsa -P ''
ssh-copy-id -i [email protected]
ssh-copy-id -i [email protected]
ssh-copy-id -i [email protected]
【ansible.cnf配置】
官方網站:http://www.ansible.com.cn/docs/intro_inventory.html#host-variables
簡介:
Ansible默認安裝好後有一個配置文件/etc/ansible/ansible.cfg,該配置文件中定義了ansible的主機的默認配置部分,
如默認是否需要輸入密碼、是否開啓sudo認證、action_plugins插件的位置、hosts主機組的位置、是否開啓log功能、默認端口、key文件位置等等
具體如下:
hostfile = /etc/ansible/hosts #指定默認hosts配置的位置
sudo_user = root #遠程sudo用戶
#ask_sudo_pass = True #每次執行ansible命令是否詢問ssh密碼
#ask_pass = True #每次執行ansible命令時是否詢問sudo密碼
#host_key_checking = False #關閉第一次使用ansible連接客戶端是輸入命令提示
#remote_port = 22 #默認遠程連接端口
#log_path = /var/log/ansible.log #需要時可以自行添加。chown -R root:root ansible.log
#ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no #在進行ssh連接時,可以使用-o參數將StrictHostKeyChecking設置爲no,使用ssh連接時避免首次連接時讓輸入yes/no部分的提示
1.在首次連接或者重裝系統之後會出現檢查keys 的提示
The authenticity of host '192.168.0.5 (192.168.0.5)' can't be established.
ECDSA key fingerprint is 05:51:e5:c4:d4:66:9b:af:5b:c9:ba:e9:e6:a4:2b:fe.
Are you sure you want to continue connecting (yes/no)?
解決方法:
方法1:
在進行ssh連接時,可以使用-o參數將StrictHostKeyChecking設置爲no,使用ssh連接時避免首次連接時讓輸入yes/no部分的提示。通過查看ansible.cfg配置文件,發現如下行:
[ssh_connection]
# ssh arguments to use
# Leaving off ControlPersist will result in poor performance, so use
# paramiko on older platforms rather than removing it
#ssh_args = -o ControlMaster=auto -o ControlPersist=60s
可以啓用ssh_args 部分,使用下面的配置,避免上面出現的錯誤:
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no
方法2:
在ansible.cfg配置文件中,也會找到如下配置:
# uncomment this to disable SSH key host checking
host_key_checking = False
默認host_key_checking部分是註釋的,通過找開該行的註釋,同樣也可以實現跳過ssh 首次連接提示驗證部分。但在實際測試中,似乎並沒有效果,建議使用方法1.
方法3:
通過設置系統環境變量來禁止這樣的提示
export ANSIBLE_HOST_KEY_CHECKING=False
【Ansible的七個命令】
安裝完ansible後,發現ansible老版本一共爲我們提供了七個指令:ansible、ansible-doc、ansible-galaxy、ansible-lint、ansible-playbook、ansible-pull、ansible-vault 。這裏我們只查看usage部分,詳細部分可以通過 “指令 -h” 的方式獲取。
新版本六個指令:ansible、ansible-doc、ansible-galaxy、ansible-playbook、ansible-pull、ansible-vault
1、ansible
ansible是指令核心部分,其主要用於執行ad-hoc命令,即單條命令。默認後面需要跟主機和選項部分,默認不指定模塊時,使用的是command模塊
不過默認使用的模塊是可以在ansible.cfg 中進行修改的。ansible命令下的參數部分解釋如下: 這裏只列舉常用的
示例:
ansible -h
-i PATH, --inventory=PATH 指定庫存主機文件的路徑,默認爲/etc/ansible/hosts.
-u Username, --user=Username 執行用戶,使用這個遠程用戶名而不是當前用戶
-U SUDO_USER, --sudo-user=SUDO_USER sudo到哪個用戶,默認爲 root
-k --ask-pass 登錄密碼,提示輸入SSH密碼而不是假設基於密鑰的驗證
-K --ask-sudo-pass 提示密碼使用sudo
-s --sudo sudo運行
-S --su 用 su 命令
-R SU_USER, --su-user=SU_USER,su過去的用戶默認爲root
-f --forks=NUM 並行任務數。NUM被指定爲一個整數,默認是5
--private-key=PRIVATE_KEY_FILE 私鑰路徑,使用這個文件來驗證連接
-v,--verbose詳細模式(-vvv更多,-vvvv啓用連接調試)
--version顯示程序版本號並退出
-B 後臺運行超時時間
-P 調查後臺程序時間,默認15s
--tags=TAGS 只執行指定標籤的任務 例子:ansible-playbook test.yml --tags=copy 只執行標籤爲copy的那個任務 [詳情看tags篇 ]
--skip-tags=SKIP_TAGS 只運行戲劇和任務不匹配這些值的標籤 --skip-tags=copy_start [詳情看tags篇 ]
--list-hosts 只打印有哪些主機會執行這個 playbook 文件,不是實際執行該 playbook 文件
--list-tasks 列出所有將被執行的任務
-C, --check 只是測試一下會改變什麼內容,不會真正去執行;相反,試圖預測一些可能發生的變化
--syntax-check 執行語法檢查的劇本,但不執行它
-l,--limit 對指定的 主機/組 執行任務 --limit=192.168.0.10,192.168.0.11 或 -l 192.168.0.10,192.168.0.11 只對這個2個ip執行任務
-e 設置變量, [詳情用法看變量篇]
--start-at="install packages" 從指定的任務開始執行,從install packages這個任務開始執行
--setup 交互式執行
2、ansible-doc
該指令用於查看模塊信息,常用參數有兩個-l 和 -s ,具體如下:
//列出所有已安裝的模塊
# ansible-doc -l
//查看具體某模塊的用法,這裏如查看command模塊
# ansible-doc -s command
3、ansible-galaxy
“Ansible Galaxy” 指的是一個網站共享和下載 Ansible 角色,也可以是者是幫助 roles 更好的工作的命令行工具。
http://www.ansible.com.cn/docs/galaxy.html#id5 更詳細galaxy的內容請看官網
# ansible-galaxy -h
Usage: ansible-galaxy [init|info|install|list|remove] [--help] [options] ...
ansible-galaxy 指令用於方便的從https://galaxy.ansible.com/ 站點下載第三方擴展模塊,我們可以形象的理解其類似於centos下的yum、python下的pip或easy_install 。如下示例:
安裝角色,從 Ansible Galaxy 網站下載角色
[root@localhost ~]# ansible-galaxy install aeriscloud.docker
- downloading role 'docker', owned by aeriscloud
- downloading role from https://github.com/AerisCloud/ansible-docker/archive/v1.0.0.tar.gz
- extracting aeriscloud.docker to /etc/ansible/roles/aeriscloud.docker
- aeriscloud.docker was installed successfully
從一個文件安裝多個角色
ansible-galaxy install -r requirements.txt
requirements.txt 文件看起來就像這樣
username1.foo_role username2.bar_role
想得到指定版本(tag)的role,使用下面的語法
username1.foo_role,version username2.bar_role,version
ansible-galaxy是一個工具,我們可以利用它快速的創建一個標準的roles目錄結構,還可以通過它在https:/galaxy.ansible.com上下載別人寫好的roles,直接拿來用。
通過ansible-galaxy初始化一個roles的目錄結構,方法如下:
ansible-galaxy init /etc/ansible/roles/websrvs
安裝別人寫好的roles:
ansible-galaxy install -p /etc/ansible/roles bennojoy.mysql
列出已安裝的roles:
ansible-galaxy list
查看已安裝的roles信息:
ansible-galaxy info bennojoy.mysql
卸載roles:
ansible-galaxy remove bennojoy.mysql
4、ansible-playbook
該指令是使用最多的指令,其通過讀取playbook 文件後,執行相應的動作,
5、ansible-pull
該指令使用需要談到ansible的另一種模式---pull 模式,這和我們平常經常用的push模式剛好相反,其適用於以下場景:你有數量巨大的機器需要配置,
即使使用非常高的線程還是要花費很多時間;你要在一個沒有網絡連接的機器上運行Anisble,比如在啓動之後安裝。這部分也會單獨做一節來講
6、ansible-vault
ansible-vault主要應用於配置文件中含有敏感信息,又不希望他能被人看到,vault可以幫你加密/解密這個配置文件,屬高級用法。主要對於playbooks裏比如涉及到配置密碼或其他變量時,可以通過該指令加密,
這樣我們通過cat看到的會是一個密碼串類的文件,編輯的時候需要輸入事先設定的密碼才能打開。
這種playbook文件在執行時,需要加上 –ask-vault-pass參數,同樣需要輸入密碼後才能正常執行。
【命令行使用Ansible方法】
ansible通過ssh實現配置管理、應用部署、任務執行等功能,因此,需要事先配置ansible端基於密鑰認證的方式聯繫各被管理節點
ansible <host-pattern> <-f 並行進程數(默認爲5)> <-m 模塊名(默認爲command,可以省略)> <-a 模塊參數>
ansible 主機組 -f '並行進程數' -m '模塊名'- a '模塊參數'
例用示例:
ansible -h #查看命令幫助
ansible all -m ping #ping模塊,默認不帶參數
ansible all -a date #模塊的參數,不加-m默認爲執行命令,-a要執行的命令
ansible-doc -l #列出所有的模塊列表
ansible-doc file #查看指定模塊的參數,一般用此種方法
ansible-doc -s file #查看指定模塊的參數
ansible all -f 10 -m file -a "path=/tmp/test state=directory"
ansible wsyht -m shell -a 'touch /opt/test.txt' -utom #指定用戶執行命令
ansible wsyht -m shell -a 'touch /opt/tt.txt' -utom --sudo #獲取root權限執行命令
ansible ali -S -R root -m script -a '/bin/sh /usr/local/src/jdk.sh' #-S使用su,-R指定su過去的用戶爲root
【Ad-hoc與命令執行模塊】
官方網站:http://www.ansible.com.cn/docs/intro_getting_started.html
簡介:
Ad-Hoc 是指ansible下臨時執行的一條命令,並且不需要保存的命令,對於複雜的命令會使用playbook。Ad-hoc的執行依賴於模塊,
ansible官方提供了大量的模塊。 如:command、raw、shell、file、cron等,具體可以通過ansible-doc -l 進行查看 。可以使用ansible-doc -s module來查看某個模塊的參數,
也可以使用ansible-doc help module來查看該模塊更詳細的信息。
1、後臺執行
當命令執行時間比較長時,也可以放到後臺執行,使用-B、-P參數,如下:
ansible all -B 3600 -a "/usr/bin/long_running_operation --do-stuff" #後臺執行命令3600s,-B 表示後臺執行的時間
ansible all -m async_status -a "jid=123456789" #檢查任務的狀態
ansible all -B 1800 -P 60 -a "/usr/bin/long_running_operation --do-stuff" #後臺執行命令最大時間是1800s即30分鐘,-P 每60s檢查下狀態,默認15s
2、命令行執行模塊
命令執行模塊包含如下 四個模塊:
command模塊:該模塊通過-a跟上要執行的命令可以直接執行,不過命令裏如果有帶有如下字符部分則執行不成功 “ "<", ">", "|", "&"
shell 模塊:用法基本和command一樣,不過其是通過/bin/sh進行執行,所以shell 模塊可以執行任何命令,就像在本機執行一樣;
raw模塊:用法和shell 模塊一樣 ,其也可以執行任意命令,就像在本機執行一樣;
script模塊:其是將管理端的shell 在被管理主機上執行,其原理是先將shell 複製到遠程主機,再在遠程主機上執行,原理類似於raw模塊。
注:raw模塊和comand、shell 模塊不同的是其沒有chdir、creates、removes參數,chdir參數的作用就是先切到chdir指定的目錄後,再執行後面的命令,這在後面很多模塊裏都會有該參數 。
command模塊包含如下選項:
creates:一個文件名,當該文件存在,則該命令不執行
free_form:要執行的linux指令
chdir:在執行指令之前,先切換到該指定的目錄
removes:一個文件名,當該文件不存在,則該選項不執行
executable:切換shell來執行指令,該執行路徑必須是一個絕對路徑
使用chdir的示例:
ansible 192.168.1.1 -m command -a 'chdir=/tmp/test.txt touch test.file'
ansible 192.168.1.1 -m shell -a 'chdir=/tmp/test.txt touch test2.file'
ansible 192.168.1.1 -m raw -a 'chdir=/tmp/text.txt touch test3.file'
三個命令都會返回執行成功的狀態。不過實際上只有前兩個文件會被創建成功。使用raw模塊的執行的結果文件事實上也被正常創建了,不過不是在chdir指定的目錄,而是在當前執行用戶的家目錄。
creates與removes示例:
ansible 192.168.1.1 -a 'creates=/tmp/server.txt uptime' #當/tmp/server.txt文件存在時,則不執行uptime指令
ansible 192.168.1.1 -a 'removes=/tmp/server.txt uptime' #當/tmp/server.txt文件不存在時,則不執行uptime指令
【Ansible常用模塊】
參考官網:http://docs.ansible.com/ansible/modules_by_category.html
簡介:
根據官方的分類,將模塊按功能分類爲:雲模塊、命令模塊、數據庫模塊、文件模塊、資產模塊、消息模塊、監控模塊、網絡模塊、通知模塊、包管理模塊、源碼控制模塊、
系統模塊、單元模塊、web設施模塊、windows模塊 ,具體可以參看官方頁面。這裏從官方分類的模塊裏選擇最常用的一些模塊進行介紹。
1)ping 2)setup 3)file 4)copy 5)service 6)cron 7)yum 8)user和group 9)synchronize 10)filesystem 11)mount 12)get_url 13)unarchive 14)lineinfile
1、ping模塊
測試主機是否是通的,用法很簡單,不涉及參數:
ansible all -m ping
2、setup模塊
setup模塊,主要用於獲取主機信息,在playbooks裏經常會用到的一個參數gather_facts就與該模塊相關。setup模塊下經常使用的一個參數是filter參數,具體使用示例如下:
使用示例:
ansible all -m setup
ansible all -m setup --tree . #蒐集系統信息並以主機名爲文件名保存在當前目錄
ansible 10.212.52.252 -m setup -a 'filter=ansible_*_mb' #查看主機內存信息
ansible 10.212.52.252 -m setup -a 'filter=ansible_eth[0-2]' #查看地接口爲eth0-2的網卡信息
ansible all -m setup --tree /tmp/facts #將所有主機的信息輸入到/tmp/facts目錄下,每臺主機的信息輸入到主機名文件中(/etc/ansible/hosts裏的主機名)
ansible webservers -m setup -a "filter=ansible_local" #在控制節點獲取自定義的信息:
關閉facts
如果你確信不需要主機的任何facts信息,而且對遠程節點主機都瞭解的很清楚,那麼可以將其關閉。遠程操作節點較多的時候,關閉facts會提升
ansible的性能。
只需要在play中設置如下:
- hosts: whatever
gather_facts: no 或
gather_facts: false #推薦用這個
3、file模塊
file模塊主要用於遠程主機上的文件操作,file模塊包含如下選項:
force:需要在兩種情況下強制創建軟鏈接,一種是源文件不存在但之後會建立的情況下;另一種是目標軟鏈接已存在,需要先取消之前的軟鏈,然後創建新的軟鏈,有兩個選項:yes|no
group:定義文件/目錄的屬組
mode:定義文件/目錄的權限
owner:定義文件/目錄的屬主
path:必選項,定義文件/目錄的路徑
recurse:遞歸的設置文件的屬性,只對目錄有效
src:要被鏈接的源文件的路徑,只應用於state=link的情況
dest:被鏈接到的路徑,只應用於state=link的情況
state:
directory:如果目錄不存在,創建目錄
file:即使文件不存在,也不會被創建
link:創建軟鏈接
hard:創建硬鏈接
touch:如果文件不存在,則會創建一個新的文件,如果文件或目錄已存在,則更新其最後修改時間
absent:刪除目錄、文件或者取消鏈接文件
使用示例:
ansible test -m file -a "src=/etc/fstab dest=/tmp/fstab state=link"
ansible test -m file -a "path=/tmp/fstab state=absent"
ansible test -m file -a "path=/tmp/test state=touch"
ansible all -m file -a "path=/opt/test state=directory owner=wsyht group=wsyht mode=777"
4、copy模塊
複製文件到遠程主機,copy模塊包含如下選項:
backup:在覆蓋之前將原文件備份,備份文件包含時間信息。有兩個選項:yes|no
content:用於替代"src",可以直接設定指定文件的值
dest:必選項。要將源文件複製到的遠程主機的絕對路徑,如果源文件是一個目錄,那麼該路徑也必須是個目錄
directory_mode:遞歸的設定目錄的權限,默認爲系統默認權限
force:如果目標主機包含該文件,但內容不同,如果設置爲yes,則強制覆蓋,如果爲no,則只有當目標主機的目標位置不存在該文件時,才複製。默認爲yes
others:所有的file模塊裏的選項都可以在這裏使用
src:要複製到遠程主機的文件在本地的地址,可以是絕對路徑,也可以是相對路徑。如果路徑是一個目錄,它將遞歸複製。在這種情況下,如果路徑使用"/"來結尾,則只複製目錄裏的內容,如果沒有使用"/"來結尾,則包含目錄在內的整個內容全部複製,類似於rsync。
使用示例:
ansible test -m copy -a "src=/srv/myfiles/foo.conf dest=/etc/foo.conf owner=foo group=foo mode=0644"
ansible test -m copy -a "src=/mine/ntp.conf dest=/etc/ntp.conf owner=root group=root mode=644 backup=yes"
ansible test -m copy -a "src=/tmp/haproxy-1.5.3.tar.gz dest=/tmp" #拷貝本地文件到遠程機器
5、service模塊
用於管理服務,該模塊包含如下選項:
arguments:給命令行提供一些選項
enabled:是否開機啓動 yes|no
name:必選項,服務名稱
pattern:定義一個模式,如果通過status指令來查看服務的狀態時,沒有響應,就會通過ps指令在進程中根據該模式進行查找,如果匹配到,則認爲該服務依然在運行
runlevel:運行級別
sleep:如果執行了restarted,在則stop和start之間沉睡幾秒鐘
state:對當前服務執行啓動,停止、重啓、重新加載等操作(started,stopped,restarted,reloaded)
使用示例:
ansible all -m service -a "name=httpd state=started enabled=yes"
asnible all -m service -a "name=foo pattern=/usr/bin/foo state=started"
ansible all -m service -a "name=network state=restarted args=eth0"
ansible all -m service -a "name=zabbix_agentd pattern=/etc/init.d/zabbix_agentd state=reloaded"
6、cron模塊
用於管理計劃任務包含如下選項:
backup:對遠程主機上的原任務計劃內容修改之前做備份
cron_file:如果指定該選項,則用該文件替換遠程主機上的cron.d目錄下的用戶的任務計劃
day:日(1-31,*,*/2,……)
hour:小時(0-23,*,*/2,……)
minute:分鐘(0-59,*,*/2,……)
month:月(1-12,*,*/2,……)
weekday:周(0-7,*,……)
job:要執行的任務,依賴於state=present
name:該任務的描述
special_time:指定什麼時候執行,參數:reboot,yearly,annually,monthly,weekly,daily,hourly
state:確認該任務計劃是創建還是刪除
user:以哪個用戶的身份執行
使用示例:
ansible test -m cron -a 'name="a job for reboot" special_time=reboot job="/some/job.sh"'
ansible test -m cron -a 'name="yum autoupdate" weekday="2" minute=0 hour=12 user="root
ansible test -m cron -a 'backup="True" name="test" minute="0" hour="5,2" job="ls -alh > /dev/null"'
ansilbe test -m cron -a 'cron_file=ansible_yum-autoupdate state=absent'
ansible test -m cron -a 'name="custom job" minute=*/2 hour=* day=* month=* weekday=* job="/usr/sbin/ntpdate 192.168.1.1"'
7、yum模塊
使用yum包管理器來管理軟件包,其選項有:
config_file:yum的配置文件
disable_gpg_check:關閉gpg_check
disablerepo:不啓用某個源
enablerepo:啓用某個源
name:要進行操作的軟件包的名字,也可以傳遞一個url或者一個本地的rpm包的路徑
state:狀態(present,absent,latest)
使用示例:
ansible test -m yum -a 'name=httpd state=latest'
ansible test -m yum -a 'name="@Development tools" state=present'
ansible test -m yum -a 'name=http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm state=present'
ansible all -m yum -a "state=present name=mysql"
8、user模塊與group模塊
user模塊是請求的是useradd, userdel, usermod三個指令,goup模塊請求的是groupadd, groupdel, groupmod 三個指令。
home:指定用戶的家目錄,需要與createhome配合使用
groups:指定用戶的屬組
uid:指定用的uid
password:指定用戶的密碼
name:指定用戶名
createhome:是否創建家目錄 yes|no
system:是否爲系統用戶
remove:當state=absent時,remove=yes則表示連同家目錄一起刪除,等價於userdel -r
state:是創建還是刪除
shell:指定用戶的shell環境
user使用示例:
user: name=johnd comment="John Doe" uid=1040 group=admin
user: name=james shell=/bin/bash groups=admins,developers append=yes user: name=johnd state=absent remove=yes
user: name=james18 shell=/bin/zsh groups=developers expires=1422403387
user: name=test generate_ssh_key=yes ssh_key_bits=2048 ssh_key_file=.ssh/id_rsa #生成密鑰時,只會生成公鑰文件和私鑰文件,和直接使用ssh-keygen指令效果相同,不會生成authorized_keys文件。
注:指定password參數時,不能使用明文密碼,因爲後面這一串密碼會被直接傳送到被管理主機的/etc/shadow文件中,所以需要先將密碼字符串進行加密處理。然後將得到的字符串放到password中即可。
grub-crypt --sha-512 直接回車輸入密碼即可對密碼進行加密處理
ansible all -m user -a 'name=foo password="$1$4P4PlFuE$ur9ObJiT5iHNrb9QnjaIB0"'
group使用示例
ansible all -m group -a 'name=somegroup state=present'
ansible all -m group -a "gid=306 system=yes name=mysql"
9、synchronize模塊
使用rsync同步文件,其參數如下:
archive: 歸檔,相當於同時開啓recursive(遞歸)、links、perms、times、owner、group、-D選項都爲yes ,默認該項爲開啓
checksum: 跳過檢測sum值,默認關閉
compress:是否開啓壓縮
copy_links:複製鏈接文件,默認爲no ,注意後面還有一個links參數
delete: 刪除不存在的文件,默認no
dest:目錄路徑
dest_port:默認目錄主機上的端口 ,默認是22,走的ssh協議
dirs:傳速目錄不進行遞歸,默認爲no,即進行目錄遞歸
rsync_opts:rsync參數部分
set_remote_user:主要用於/etc/ansible/hosts中定義或默認使用的用戶與rsync使用的用戶不同的情況
mode: push或pull 模塊,push模的話,一般用於從本機向遠程主機上傳文件,pull 模式用於從遠程主機上取文件
使用示例:
src=some/relative/path dest=/some/absolute/path rsync_path="sudo rsync"
src=some/relative/path dest=/some/absolute/path archive=no links=yes
src=some/relative/path dest=/some/absolute/path checksum=yes times=no
src=/tmp/helloworld dest=/var/www/helloword rsync_opts=--no-motd,--exclude=.git mode=pull
10、filesystem模塊
在塊設備上創建文件系統
選項:
dev:目標塊設備
force:在一個已有文件系統 的設備上強制創建
fstype:文件系統的類型
opts:傳遞給mkfs命令的選項
使用示例:
ansible test -m filesystem -a 'fstype=ext2 dev=/dev/sdb1 force=yes'
ansible test -m filesystem -a 'fstype=ext4 dev=/dev/sdb1 opts="-cc"'
ansible test -m filesystem 'fstype=ext4 force=yes opts=-F dev=/dev/loop0'
11、mount模塊
配置掛載點
選項:
dump
fstype:必選項,掛載文件的類型
name:必選項,掛載點
opts:傳遞給mount命令的參數
src:必選項,要掛載的文件
state:必選項
present:只處理fstab中的配置
absent:刪除掛載點
mounted:自動創建掛載點並掛載之
umounted:卸載
使用示例:
name=/mnt/dvd src=/dev/sr0 fstype=iso9660 opts=ro state=present
name=/srv/disk src='LABEL=SOME_LABEL' state=present
name=/home src='UUID=b3e48f45-f933-4c8e-a700-22a159ec9077' opts=noatime state=present
ansible test -a 'dd if=/dev/zero of=/disk.img bs=4k count=1024'
ansible test -a 'losetup /dev/loop0 /disk.img'
ansible test -m mount 'name=/mnt src=/dev/loop0 fstype=ext4 state=mounted opts=rw'
12、get_url 模塊
該模塊主要用於從http、ftp、https服務器上下載文件(類似於wget),主要有如下選項:
sha256sum:下載完成後進行sha256 check;
timeout:下載超時時間,默認10s
url:下載的URL
url_password、url_username:主要用於需要用戶名密碼進行驗證的情況
use_proxy:是使用代理,代理需事先在環境變更中定義
使用示例:
get_url: url=http://example.com/path/file.conf dest=/etc/foo.conf mode=0440
get_url: url=http://example.com/path/file.conf dest=/etc/foo.conf sha256sum=b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c
13、unarchive模塊
用於解壓文件,模塊包含如下選項:
copy:在解壓文件之前,是否先將文件複製到遠程主機,默認爲yes。若爲no,則要求目標主機上壓縮包必須存在。
creates:指定一個文件名,當該文件存在時,則解壓指令不執行
dest:遠程主機上的一個路徑,即文件解壓的路徑
grop:解壓後的目錄或文件的屬組
list_files:如果爲yes,則會列出壓縮包裏的文件,默認爲no,2.0版本新增的選項
mode:解決後文件的權限
src:如果copy爲yes,則需要指定壓縮文件的源路徑
owner:解壓後文件或目錄的屬主
示例如下:
- unarchive: src=foo.tgz dest=/var/lib/foo
- unarchive: src=/tmp/foo.zip dest=/usr/local/bin copy=no
- unarchive: src=https://example.com/example.zip dest=/usr/local/bin copy=no
14、lineinfile模塊
主要用來改變一個單行的文件,如果你想改變多行,就用copy或template模塊
line:插入/替換到文件中,默認插入到最後一行
regexp:正則表達式查找在文件的每一行。
owner: 命名文件目錄的用戶
group: 命名文件目錄的組
state: 當前行是否應該存在,absent刪除該行,默認present存在
backup: 對文件進行操作前是否先備份,默認是No
EXAMPLES:
- lineinfile: dest=/etc/selinux/config regexp='^SELINUX=' line='SELINUX=enforcing' #替換selinux該行
- lineinfile: dest=/etc/sudoers state=absent regexp="^%wheel backup=yes" #刪除匹配到的正則表達式的行,先備份文件再刪除
- lineinfile: dest=/etc/hosts regexp='^127\.0\.0\.1' line='127.0.0.1 localhost' owner=root group=root mo #更改匹配到的行並給文件用戶和組root權限
# Fully quoted because of the ': ' on the line. See the Gotchas in the YAML docs. #在最後一行插入內容
- lineinfile: "dest=/etc/sudoers line='%wheel ALL=(ALL) NOPASSWD: ALL'"
【Playbook執行方法】
官方網站:http://www.ansible.com.cn/docs/playbooks_intro.html#playbook
簡介:
ansbile-playbook是一系列ansible命令的集合,利用yaml 語言編寫。playbook命令根據自上而下的順序依次執行。同時,playbook開創了很多特性,它可以允許你傳輸某個命令的狀態到後面的指令,
如你可以從一臺機器的文件中抓取內容並附爲變量,然後在另一臺機器中使用,這使得你可以實現一些複雜的部署機制,這是ansible命令無法實現的。
playbook通過ansible-playbook命令使用,它的參數和ansible命令類似,如參數-k(–ask-pass) 和 -K (–ask-sudo) 來詢問ssh密碼和sudo密碼,-u指定用戶,這些指令也可以通過規定的單元寫在playbook 。
ansible-playbook使用
查看使用方法:
ansible -h 或 ansible --help
不加-f默認是5個線程,這裏給他定義了十個線程併發執行
例子:
ansible-playbook example-play.yml -f 10
在執行一個 playbook 之前,想看看這個 playbook 的執行會影響到哪些 hosts,
你可以這樣做:
ansible-playbook playbook.yml --list-hosts
檢測模塊運行:--check
產生大量的輸出結果: --diff
--diff 選項與 --check (詳情參下)配合使用效果奇佳,
-l,--limit 對指定的 主機/組 執行任務 --limit=192.168.0.10,192.168.0.11 或 -l 192.168.0.10,192.168.0.11 只對這個2個ip執行任務
參考如下例子: --check
ansible-playbook foo.yml --check --diff --limit foo.example.com
對前十臺和接下來的10臺執行任務
ansible-playbook foo.yml --check --diff --limit boston[0-10]
ansible-playbook foo.yml --check --diff --limit boston[10-20]
查看都有哪些任務要執行
ansible-playbook playbook.yml --list-tasks
查看模塊執行成功與否的詳細信息
參數:
-v #詳細信息
-vvvv #啓用更多詳細信息
ansible-playbook playbook.yml -v #或
ansible-playbook playbook.yml -vvvv #顯示更詳細的信息,推薦用此方法
[Start-at-task] 從指定任務開始運行palybook以及分步運行playbook
如果你想從指定的任務開始執行playbook,可以使用``–start-at``選項:
ansible-playbook playbook.yml --start-at="install packages"
分步運行playbook
我們也可以通過``–step``選項來交互式的執行playbook: 這樣ansible在每個任務前會自動停止,並詢問是否應該執行該任務.
ansible-playbook playbook.yml --step
比如你有個名爲``configure ssh``的任務,playbook執行到這裏會停止並詢問:
“y”回答會執行該任務,”n”回答會跳過該任務,而”c”回答則會繼續執行剩餘的所有任務而不再詢問你.
Perform task: configure ssh (y/n/c):
【Playbook構成和簡單使用】
官方網站:http://www.ansible.com.cn/docs/playbooks_intro.html#playbook
playbooks組成:
Target section: 定義將要執行 playbook 的遠程主機組
Variable section: 定義 playbook 運行時需要使用的變量
Task section: 定義將要在遠程主機上執行的任務列表
Handler section: 定義 task 執行完成以後需要調用的任務
而其對應的目錄層爲五個,如下:
vars 變量層
tasks 任務層
handlers 觸發條件
files 文件
template 模板
1、Hosts和Users
playbook中的每一個play的目的都是爲了讓某個或某些主機以某個指定的用戶身份執行任務。
hosts:用於指定要執行指定任務的主機其可以是一個或多個由冒號分隔主機組。
remote_user :用於指定遠程主機上的執行任務的用戶。不過remote_user也可用於各task中。也可以通過指定其通過sudo的方式在遠程主機上執行任務其可用於play全局或某任務。此外甚至可以在sudo時使用sudo_user指定sudo時切換的用戶。
user:與remote_user相同
sudo:如果設置爲yes,執行該任務組的用戶在執行任務的時候,獲取root權限
sudo_user:如果設置user爲breeze,sudo爲yes,sudo_user爲bernie時,則breeze用戶在執行任務時會獲得bernie用戶的權限
connection:通過什麼方式連接到遠程主機,默認爲ssh
gather_facts:除非明確說明不需要在遠程主機上執行setup模塊,否則默認自動執行。如果確實不需要setup模塊傳遞過來的變量,則可以將該選項設置爲False
示例1:
- hosts: webnodes
tasks:
- name: test ping connection:
remote_user: test
sudo: yes
#同樣的,你可以僅在一個 task 中,使用 sudo 執行命令,而不是在整個 play 中使用 sudo:
示例2:
---
- hosts: webservers
remote_user: yourname
tasks:
- service: name=nginx state=started
sudo: yes
#你也可以登陸後,sudo 到不同的用戶身份,而不是使用 root:
示例3:
---
- hosts: webservers
remote_user: yourname
sudo: yes
sudo_user: postgres
#多臺主機用點隔開
示例4:
---
- hosts: web,db,mysql
或
- hosts:
- web
- db
- mysql
2、任務列表和action
play的主體部分是任務列表。
任務列表中的各任務按次序逐個在hosts中指定的所有主機上執行即在所有主機上完成第一個任務後再開始第二個。在自上而下運行某playbook時如果中途發生錯誤,所有已執行任務都將回滾因此在更正playbook後重新執行一次即可。
task的目的是使用指定的參數執行模塊,而在模塊參數中可以使用變量。模塊執行是冪等的,這意味着多次執行是安全的,因爲其結果均一致。每個task都應該有其name用於playbook的執行結果輸出,建議其內容儘可能清晰地描述任務執行步驟。如果未提供name則action的結果將用於輸出。
定義task的可以使用"action: module options"或"module: options"的格式,推薦使用後者以實現向後兼容。如果action一行的內容過多也可使用在行首使用幾個空白字符進行換行。
示例1:
tasks:
- name: make sure apache is running
service: name=httpd state=running
示例2:
#在衆多模塊中只有command和shell模塊僅需要給定一個列表而無需使用“key=value”格式例如
tasks:
- name: disable selinux
command: /sbin/setenforce 0
示例3:
#如果命令或腳本的退出碼不爲零可以使用如下方式替代
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
示例4:
#使用ignore_errors來忽略錯誤信息
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
示例%:
#如果 action 行看起來太長,你可以使用 space(空格) 或者 indent(縮進) 隔開連續的一行:
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
示例6:
#任務執行的方法有3種,推薦用第二種
tasks
- name: install apache
action: yum name=httpd state=install #第一種方法
- name: configure apache
copy: src=files/httpd.conf dest=/etc/httpd/conf/httpd.conf #第二種方法
- name: restart apache
service :
name: httpd
state: restarted #第三種方法
3、handlers
用於當關注的資源發生變化時採取一定的操作。
"notify"這個action可用於在每個play的最後被觸發,這樣可以避免多次有改變發生時每次都執行指定的操作,取而代之僅在所有的變化發生完成後一次性地執行指定操作。
在notify中列出的操作稱爲handler也即notify中調用handler中定義的操作。
注意:在notify中定義內容一定要和tasks中定義的 - name 內容一樣,這樣才能達到觸發的效果,否則會不生效。
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
#handler是task列表這些task與前述的task並沒有本質上的不同。
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
#完整示例1:
---
- hosts: all
user: root
tasks:
- name: install memcached
yum: name=memcahed state=installed
- name: set memcached size
set_fact: memcached_size="{{ ansible_memtotal_mb/4 }}"
- name: copy configuraitios
template: src=templates/memcacched.j2 dest=/etc/sysconfig/memcached
notify:
- restart memcached
handlers:
- name: restart memcached
service: name=memcached state=restarted enabled=yes
#cat templates/memcacched.j2
PORT="11211"
USER="memached"
CHCASIZE="{{ memcached_size|default(1024) }}" #有值測輸入memcached_size大小,沒值則輸入默認1024
#完整示例2:
---
- hosts: webservers
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: name=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
- hosts: databases
remote_user: root
tasks:
- name: ensure postgresql is at the latest version
yum: name=postgresql state=latest
- name: ensure that postgresql is started
service: name=postgresql state=running
【Playbook常用模塊】
參考官網: http://docs.ansible.com/ansible/modules_by_category.html
注:jinja2示例可參考Ansible圖文參考Word文檔
1)template 2)setup 3)set_fact 4)pause 5)wait_for 6)assemble 7)add_host 8)group_by 9)get_rul 10)debug 11)fail 12)mysql_user
1、template模塊
在實際應用中,我們的配置文件有些地方可能會根據遠程主機的配置的不同而有稍許的不同,template可以使用變量來接收遠程主機上setup收集到的facts信息,針對不同配置的主機,定製配置文件。用法大致與copy模塊相同。
常用參數:
backup:如果原目標文件存在,則先備份目標文件
dest:目標文件路徑
force:是否強制覆蓋,默認爲yes
group:目標文件屬組
mode:目標文件的權限
owner:目標文件屬主
src:源模板文件路徑
validate:在複製之前通過命令驗證目標文件,如果驗證通過則複製
官方簡單示例:
- template: src=/mytemplates/foo.j2 dest=/etc/file.conf owner=bin group=wheel mode=0644
- template: src=/mytemplates/foo.j2 dest=/etc/file.conf owner=bin group=wheel mode="u=rw,g=r,o=r"
playbook的引用該模板配置文件的方法示例:
- name: Setup BIND
host: allnames
tasks:
- name: configure BIND
template: src=templates/named.conf.j2 dest=/etc/named.conf owner=root group=named mode=0640
2、setup模塊
---
- hosts: all
user: root
vars_files:
- variables
tasks:
-name: print ip
template: scr=files/test.txt /dest=/tmp/test.txt
#cat files/test.txt
`ansible_devices`.`sda`.`partitions`.`sda1`.`szie`
{{ansible_mounts[0].size_total}}
#從setup模塊獲取sda1.sizet和mounts大小的值,setup模塊默認自動執行,詳細介紹可參考Ansible圖文參考Word文檔
3、set_fact模塊
他可以自定義facts,這些自定義的facts可以通過template或者變量的方式在playbook中使用。如果你想要獲取一個進程使用的內存的百分比,則必須通過set_fact來進行計算之後得出其值,並將其值在playbook中引用。
下面是一個配置mysql innodb buffer size的示例:
- name: Configure MySQL
hosts: mysqlservers
tasks:
- name: install MySql
yum: name=mysql-server state=installed
- name: Calculate InnoDB buffer pool size
set_fact: innodb_buffer_pool_size_mb="{{ ansible_memtotal_mb / 2 }}"
- name: Configure MySQL
template: src=templates/my.cnf dest=/etc/my.cnf owner=root group=root mode=0644
notify: restart mysql
- name: Start MySQL
service: name=mysqld state=started enabled=yes
handlers:
- name: restart mysql
service: name=mysqld state=restarted
my.cnf的配置示例:
# ` ansible_managed `
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted
security risks
symbolic-links=0
# Configure the buffer pool
innodb_buffer_pool_size = {{ innodb_buffer_pool_size_mb|default(128) }}M #如果前面值沒有,就默認使用128M
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
4、pause暫停模塊
在playbook執行的過程中暫停一定時間或者提示用戶進行某些操作
minutes:暫停多少分鐘
seconds:暫停多少秒
prompt:打印一串信息提示用戶操作
示例:
- name: wait on user input
pause: prompt="Warning! Detected slight issue. ENTER to continue CTRL-C a to quit" #你輸入回車確認纔會執行下面的任務
- name: timed wait
pause: seconds=30 #暫停三十秒再執行後面的任務
5、wait_for模塊
在playbook的執行過程中,等待某些操作完成以後再進行後續操作
wait_for模塊用來檢測一個tcp端口是否準備好接收遠程連接,這是由遠程主機來完成的。如果你只指定了端口,或者主機參數被設置爲localhost,它會嘗試連接過程受管主機。
你可以用local_action參數來指定從控制機器來運命令,並使用ansible_hostname爲主機參數來遠程受管主機。這個模塊在後臺運行某些程序或者啓動些進程需要一些時間的時候特別有用
常用參數:
connect_timeout:在下一個任務執行之前等待連接的超時時間
delay:等待一個端口或者文件或者連接到指定的狀態時,默認超時時間爲300秒,在這等待的300s的時間裏,wait_for模塊會一直輪詢指定的對象是否到達指定的狀態,delay即爲多長時間輪詢一次狀態。
host:wait_for模塊等待的主機的地址,默認爲127.0.0.1
port:wait_for模塊待待的主機的端口
path:文件路徑,只有當這個文件存在時,下一任務纔開始執行,即等待該文件創建完成
state:等待的狀態,即等待的文件或端口或者連接狀態達到指定的狀態時,下一個任務開始執行。當等的對象爲端口時,狀態有started,stoped,即端口已經監聽或者端口已經關閉;當等待的對象爲文件時,狀態有present或者started,absent,即文件已創建或者刪除;當等待的對象爲一個連接時,狀態有drained,即連接已建立。默認爲started
timeout:wait_for的等待的超時時間,默認爲300秒
- wait_for: port=8080 state=started #等待8080端口已正常監聽,纔開始下一個任務,直到超時
- wait_for: port=8000 delay=10 #等待8000端口正常監聽,每隔10s檢查一次,直至等待超時
- wait_for: host=0.0.0.0 port=8000 delay=10 state=drained #等待8000端口直至有連接建立
- wait_for: host=0.0.0.0 port=8000 state=drained exclude_hosts=10.2.1.2,10.2.1.3 #等待8000端口有連接建立,如果連接來自10.2.1.2或者10.2.1.3,則忽略。
- wait_for: path=/tmp/foo #等待/tmp/foo文件已創建
- wait_for: path=/tmp/foo search_regex=completed #等待/tmp/foo文件已創建,而且該文件中需要包含completed字符串
- wait_for: path=/var/lock/file.lock state=absent #等待/var/lock/file.lock被刪除
- wait_for: path=/proc/3466/status state=absent #等待指定的進程被銷燬
- local_action: wait_for port=22 host="{{ ansible_ssh_host | default(inventory_hostname) }}" search_regex=OpenSSH delay=10 #等待openssh啓動,10s檢查一次
示例:
---
- hosts: all
user: root
tasks:
- name: Install Tomcat
yum:name=tomcat6 state=installed
- name: Start Tomcat
service: name=tomcat6 state=started
- name: Wait for Tomcat to start
wait_for: port=8080 state=started
6、assemble模塊
用於組裝文件,即將多個零散的文件,合併一個大文件
用於組裝文件,即將多個零散的文件,合併一個大文件
常用參數:
src:原文件(即零散文件)的路徑
dest:合併後的大文件路徑
group:合併後的大文件的屬組
owner:合併後的大文件的屬主
mode:合併後的大文件的權限
validate:與template的validate相同,指定命令驗證文件
ignore_hidden:組裝時,是否忽略隱藏文件,默認爲no,該參數在2.0版本中新增
7、add_host模塊
在playbook執行的過程中,動態的添加主機到指定的主機組中
add_host添加主機模塊是playbook中一個強大的模塊,它可以讓你動態的添加受管主機到一個play中,我們可以使用uri模塊從CMDB中獲得主機信息然後添加他們,
它還可以將主機添加到組裏面,如果組不存的話還會自動創建它。這個模塊僅需要主機名和組名2個參數,跟主機庫存清單的配置一樣,我們還可以添加擴展的參數,像
ansible_ssh_user,ansible_ssh_port等等
常用參數:
groups:添加主機至指定的組
name:要添加的主機名或IP地址
groups:添加主機至指定的組
name:要添加的主機名或IP地址
示例:
- name: add a host to group webservers
hosts: webservers
tasks:
- add_host name=` ip_from_ec2 ` group=webservers foo=42 #添加主機到webservers組中,主機的變量foo的值爲42
8、group_by模塊
在playbook執行的過程中,動態的創建主機組
示例:
- name: Create operating system group
hosts: all
tasks:
- group_by: key=os_` ansible_distribution ` #在playbook中設置一個新的主機組
- name: Run on CentOS hosts only
hosts: os_CentOS
tasks:
- name: Install Apache
yum: name=httpd state=latest
- name: Run on Ubuntu hosts only
hosts: os_Ubuntu
tasks:
- name: Install Apache
apt: pkg=apache2 state=latest
9、get_rul模塊
用來下載用的,當然也可以用wget
mode:設置權限
示例:
- name: download foo.conf
get_url url=http://example.com/paht/file.conf dest=/etc/foo.conf mode=0440
10、debug模塊
調試模塊,用於在調試中輸出信息
常用參數:
msg:調試輸出的消息
var:將某個任務執行的輸出作爲變量傳遞給debug模塊,debug會直接將其打印輸出
verbosity:debug的級別
示例:
# 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
- debug: var=result verbosity=2 #直接將上一條指令的結果作爲變量傳遞給var,由debug打印出result的值
- name: Display all variables/facts known for a host
debug: var=hostvars[inventory_hostname] verbosity=4
11、fail模塊
msg:終止前打印出信息
示例:
- fail: msg="The system may not be provisioned according to the CMDB status."
when: cmdb_status != "to-be-staged"
12、mysql_user模塊
添加或刪除一個MySQL數據庫中的用戶
priv: 數據庫權限設置格式`db.table:priv1,priv2' [Default:None]
state: 刪除用戶absent,添加用戶present,默認present
name: 添加的新用戶名字
password: 添加用戶密碼
login_host: 密程機上運行的數據庫[IP默認:本地主機]
login_user: 遠程機數據庫登陸用戶
login_password: 遠程機數據庫登陸必碼
login_unic_socket: 遠程機登陸的socket文件
encrypted: - 加密表明“密碼”字段是一個`mysql_native_password`哈希(選擇:是,否)默認值:no]
grub-crypt --sha-512 直接回車輸入密碼即可對密碼進行加密處理
append_privs:通過追加定義PRIV的特權到現有的這個用戶,而不是覆蓋現有的(選擇:是,否)默認值:no]
EXAMPLES:
# Create database user with name 'bob' and password '12345' with all database privileges
ansible all -m mysql_user -a "login_user=root login_password=123456 name=bob password=12345 priv=*.*:ALL state=present"
# Create database user with name 'bob' and previously hashed mysql native password '*EE0D72C1085C46C5278
ansible all -m mysql_user -a "name=bob password='*EE0D72C1085C46C5278932678FBE2C6A782821B4' encrypted=yes priv=*.*:ALL state=present"
# Creates database user 'bob' and password '12345' with all database privileges and 'WITH GRANT OPTION'
ansible all -m mysql_user -a “name=bob password=12345 priv=*.*:ALL,GRANT state=present"
# Modify user Bob to require SSL connections. Note that REQUIRESSL is a special privilege that should on
ansible all -m mysql_user -a "name=bob append_privs=true priv=*.*:REQUIRESSL state=present"
# Ensure no user named 'sally' exists, also passing in the auth credentials.
ansible all -m mysql_user -a "login_user=root login_password=123456 name=sally state=absent"
# Specify grants composed of more than one word
ansible all -m mysql_user -a "name=replication password=12345 priv="*.*:REPLICATION CLIENT" state=present"
# Revoke all privileges for user 'bob' and password '12345'
ansible all -m mysql_user -a "name=bob password=12345 priv=*.*:USAGE state=present"
# Example using login_unix_socket to connect to server
ansible all -m mysql_user -a "name=root password=abc123 login_unix_socket=/var/run/mysqld/mysqld.sock"
【Playbook的角色及包含】
官方網站:http://www.ansible.com.cn/docs/playbooks_roles.html
當單個playbook文件越來越大的時候,我們就需要重新來組織Playbooks了。我們可以將一個大的playbook拆成若干個小的playbook文件,然後通過include的方式,在主配置文件中將這些零碎的小文件包含進來,這叫做playbook的包含。
我們也可以按照一定的規則將執行的某一類型任務放在一個目錄裏,並在這個目錄中再次對這個playbook按照tasks,handlers,files,templates,vars等類型劃分成若干文件,將對應文件存放在對應的目錄中,這種組織方式就叫做playbook的roles。
在大型複雜架構中,你第一個要面對的問題就是不斷增長的playbook文件大小,一個很大的playbooks很難去理解和維護,解決辦法是用include.將你的plays分解成我個不同的段,然後
在其他的plays中包含他們。不同的段根據不同目的地分類,全部包啓在play中,共有四種類型的包含。
1)變量包含:允許你將變量存在外部YAML文件
2)Playbook包含:一個大型項目中可以我含多個Play
3)任務包含:將任務放到普通文件中,當需要的時候包含他們
4)Handler包含:允許你將所有的Handlers處理程序放到一個地方
一、Playbook包含
playbook的包含其實就是使用include關鍵字
[任務包含]
示例1:
在bar.yml的tasks中包含foo.yml
tasks:
- include: tasks/foo.yml
cat foo.yml
# possibly saved as tasks/foo.yml
- name: placeholder foo
command: /bin/foo
- name: placeholder bar
command: /bin/bar
示例2:
[root@Master opt]# cat main.yml
---
- hosts: all
tasks:
- name: stop mysqld
service: name=mysqld state=stopped
- include: test.yml
[root@Master opt]# cat test.yml
- name: stop httpd
service: name=httpd state=stoppe
[Playbook包啓]
示例1:
也可以在include的時候,帶入變量:
tasks:
- include: wordpress.yml user=timmy #表示包含的文件執行用戶爲timmy
- include: wordpress.yml user=alice #表示包含的文件執行用戶爲alice
- include: wordpress.yml user=bob #表示包含的文件執行用戶爲bob
示例2:
[root@Master opt]# cat main.yml
---
- hosts: all
tasks:
- name: stop mysqld
service: name=mysqld state=stopped
- include: test.yml
[root@Master opt]# cat test.yml
---
- hosts: all
tasks:
- name: stop httpd
service: name=httpd state=stoppe
[變量包含]
示例1:
如果你使用的是 Ansible 1.4以上版本(包括1.4),可以通過如下方式帶入變量:
tasks:
- { include: wordpress.yml, user: timmy, ssh_keys: [ 'keys/one.txt', 'keys/two.txt' ] } #表示包含的文件的文件帶入user和ssh_keys兩個變量
示例2:
從1.0開始, ansible 還支持另外一種變量傳參到 include files 的方式-結構化變量,方式如下:
tasks:
- include: wordpress.yml
vars:
wp_user: timmy
ssh_keys:
- keys/one.txt
- keys/two.txt
變量傳遞均可以在 included 文件中被使用.你可以這樣引用他們:
` wp_user ` `ssh_keys`
[handlers包含]
handlers包含與tasks的包含大體類似
示例1:
- name: restart apache
service: name=apache state=restarted
handlers.yml包含handlers1.yml示例:
handlers:
- include: handlers/handlers.yml
[混合包含]
示例:
cat include.yml
---
- hosts: mfs_node
vars_files:
- vars.yml #變量包含,包含vars.yml文件
- vars1.yml #變量包含,包含vars1.yml文件
tasks:
- include: task.yml #任務包啓,包含task.yml文件
handlers:
- include: handler.yml #handlers包啓,包含handler.yml文件
#cat vars.yml
port: 80
#cat vars1.yml
port2: 8080
#cat task.yml
---
- name: print vars
shell: echo"` port `" > /tmp/test
notify: touch a file
#cat handler.yml
---
- name: touch a file
shell: echo "` port2 `" > /tmp/file
anslbie-playbook include.yml
二、Playbook的角色
官方文檔:http://www.ansible.com.cn/docs/playbooks_best_practices.html
如果你的playbook增長到包含也無法解決,或者你已擁有一個數量巨大的模板,你或就該使用角色了,它允許你根據自定義的格式對文件進行分組,從本質上來講,
它是一個具有一些自動化功能的包含,角色可以幫你很好的組織你的資料庫
角色允許你將變量、文件、任務、模板Handlers放到一個文件夾中,然後包含他們,在建立好一個有效的依賴關係之後,你還可以在一個角色中包含另外一個角色,
和包含一樣,你可以傳遞變量給角色。利用這些特性,你可以創建一個自包含的角色並很容易跟其它人分享它。
1、創建role
創建role的步驟如下:
1)創建以roles命令的目錄
2)在roles目錄中分別創建角色名稱命名的目錄,如websrvs等
3)在每個角色命名的目錄中分別創建files、handlers、meta、tasks、teamplates和vars目錄,用不到的目錄可以創建爲空目錄,也可以不創建。
4)在playbook文件中,調用各角色
通過ansible-galaxy初始化一個roles的目錄結構,方法如下:
ansible-galaxy init /etc/ansible/roles/websrvs
roles文件組織結構示例:
group_vas/
host_vars/
site.yml
webservers.yml
dbserver.yml
roles/
common/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/
webservers/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/
dbservers/
files/
templates/
tasks/
handlers/
vars/
defaults/
meta/
roles各目錄的作用及可用的文件:
files:存放由copy或script等模塊調用的文件
tempaltes:Jinja2模板文件
tasks:至少應該包含一個名爲main.yml的文件,其定義了此角色的任務列表,些文件可以使用include包含其它的位於此目錄中的task文件
handlers:至少包含一個main.yml文件,用於定義此角色用到的各handler,在handler中使用include包含的其他handler文件也應該位於此目錄
vars:應當包含一個main.yml文件,用於定義此角色用到的變量
meta:應當包含一個main.yml文件,用於定義此角色的特殊設定及依賴關係等
default:爲當前角色設定默認變量時使用些目錄,包含一個main.yml文件
site.yml: 主playbook
webserver.yml web服務器的playbook
dbserver.yml db服務器的playbook
/etc/ansible/host_vars/all #host_vars 目錄用於存放host 變量,all 文件對所有主機有效
/etc/ansible/group_vars/all #group_vars 目錄用於存放group 變量,all 文件對所有組有效
注:group_varst和host_vars變量目錄要與hosts主機清單文件在同一目錄下
引用示例:
---
# file: site.yml
- include: webservers.yml
- include: dbservers.yml
# file: webservers.yml
- hosts: webservers
roles:
- common
- webserver
# file: dbservers.yml
- hosts: dbserver
roles:
- common
- dbserver
2、引用roles
基本引用的方法:
- hosts: webservers
roles:
- common
- webserver
3、也可以通過如下方法引用時帶入變量:
- hosts: webservers
roles:
- common
- { role: foo_app_instance, dir: '/opt/a', port: 5000 }
- { role: foo_app_instance, dir: '/opt/b', port: 5001 }
4、還可以在引用時使用條件語句:
- hosts: webservers
roles:
- { role: some_role, when: "ansible_os_family == 'RedHat'" }
5、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!"
6、role的依賴
如果當前role在執行前需要依賴另一個role,我們可以在roles的meta目錄中的main.yml中定義role的依賴關係。
示例1:
#roles/webservers/meta/main.yml
dependencies:
- { role: common, some_parameter: 3 }
- { role: apache, port: 80 }
- { role: postgres, dbname: blarg, other_parameter: 12 }
示例2:
dependencies:
- {role: ntp, ntp_server=ntp.ubuntu.com}
- {role: web}
- {role: memcached}
完整示例:
[root@Master ansible]# tree
.
├── ansible.cfg
├── hosts
├── playbook
│ └── lamp
│ ├── lamp.yml
│ └── roles
│ ├── common
│ │ ├── files
│ │ │ └── hosts
│ │ ├── handlers
│ │ └── tasks
│ │ └── main.yml
│ ├── db
│ │ ├── files
│ │ ├── handlers
│ │ └── tasks
│ │ └── main.yml
│ └── web
│ ├── files
│ ├── handlers
│ │ └── main.yml
│ └── tasks
│ ├── include.yml
│ └── main.yml
└── roles
[root@Master lamp]# cat lamp.yml
---
- hosts: all
roles:
- role: common
- hosts: wsyht
roles:
- role: web
- hosts: peter
roles:
- role: db
[root@Master tasks]# pwd
/etc/ansible/playbook/lamp/roles/web/tasks
[root@Master tasks]# ls
include.yml main.yml
[root@Master tasks]# cat main.yml
- name: start vsftpd
service: name=vsftpd state=started
notify:
- copy passwd
- include: include.yml
[root@Master tasks]# cat include.yml
- name: mysqld started
service: name=mysqld state=started
[root@Master handlers]# pwd
/etc/ansible/playbook/lamp/roles/web/handlers
[root@Master handlers]# ls
main.yml
[root@Master handlers]# cat main.yml
- name: copy passwd
copy: src=passwd dest=/opt/passwd
[root@Master files]# pwd
/etc/ansible/playbook/lamp/roles/web/files
[root@Master files]# ls
passwd
【Playbook的變量】
官方網站:http://www.ansible.com.cn/docs/playbooks_variables.html
通過以下幾種方式可以獲取變量
1、Variables Defined in Inventory 看word文檔
2、Variables Defined in a Playbook
3、Variables Defined i Commandline
4、Registered Variables
5、Variables defined from included files and roles 看word文檔
6、Using Variables: About Jinja2
7、Facts 查看word文檔
1、 通過命令行設置變量 [Variables Defined i Commandline]
示例如下:
---
- hosts: mfs_node
remote_user: '` user `'
tasks:
- shell: echo "`echovar`"
ansible-playbook release.yml --e 'user=root echovar="hello world"' 法1
ansible-playbook release.yml --e '{{"user":"root","echovar":"hello world"}}' 法2
ansible-playbook release.yml --e '@test.json' 法3 把所有變量定義到一個文件去
cat test.json
user: root
echovar: hellow world
2、Playbook中定義變量 [Variables Defined in a Playbook]
[vars變量]
這裏指定一個user變量,其值爲test ,需要注意的是,變量值一定要用引號引住;
# cat user.yml
- name: create user
hosts: all
user: root
gather_facts: false
vars:
user: "test"
tasks:
- name: create user
user: name="` user `" state=absent remove=yes
[vars_files變量]
指定變量文件
#cat test.yml
---
- hosts: all
user: root
vars_files:
- variables
tasks:
-name: print ip
template: scr=files/test.txt /dest=/tmp/test.txt
# cat file/test.txt
`http`
`port`}
#cat variables
port: 80
httpd: nginx
[vars_prompt變量]
交互式輸入變量
cat test1.yml
---
- hosts: all
vars_prompt:
- name: http
prompt: please enter something
private: yes
tasks:
- name: just a test
template: scr=files/test1.txt /dest=/tmp/test1.txt
#cat files/test.txt
`http`}
#private設爲yes不會在屏幕打印輸出,
3、通過Registered Variables設置變量
- hosts: mfs_node
tasks:
- shell: echo "5"
register: result #把上面輸出5的值保存在result這個變量中,以便後續可以對他進行處理
ignore_errors: True #有錯誤就跳過
- debug: msg="it failed" #上面失敗打印這行
when: result|failed #如果上面的結果失敗,則執行上面那一行
- debug: msg="{{result|stdout}}" #打印出result的值,上面輸出的是5,所以會打印5出來
- shell: /usr/bin/bar #如果rc等於5,則輸出這行
when: result.rc == 5 #如果rc等於5,則輸出上面那一行
4、Using Variables: About Jinja2 使有金加2定義變量
template: src=foo.cnf.j2 dest=`remote_install_path`/foo.cfg
{{some_variable | default(5)}} #前面的變量不存在,則輸入後面的默認的
注:變量花括號括住,且要加雙引號
- hosts: all
vars:
app_path: "`base_path`/22"
【Playbook的內置變量】
最常用
hostvars
groups
group_names
1、hostvars示例:
- name: get the master ip
set_fact: dns_master="`hostvars`.`ns1`.`ansible_default_ipv4`.`address`" #ns1爲那臺主機的主機名
- name: configuree bind
template: dest=/etc/named.conf src=templates/named.conf.j2
案例1:
cat hostvars.myml
---
- hosts: mfs
tasks:
- name : just a test
template: src=files/hostvars.txt dest=/tmp/hostvars.txt
cat files/hostvars.txt
`hostvars`.`puppet_master`.`ansible_default_ipv4`.`address` #第一種寫法.puppet_master爲主機名,不能解析則在hosts文件中做解析,主機名只能用下載線,不能用-
ansible-playbook hostvars.yml
2、groups示例:
- name: create user for all app servers
with_items: groups.appservers #groups是指所有所,指所有組中的appservers這個組
mysql_user: name=kate password=test
host={{}hostvars.[item].ansible_eth0ipv4.address} state=present #取每一臺主機的IP地址
{{% for host in groups['all'] %}} #取所有主機都賦值爲host
{{hostvars[host]['ansible_hostname']}} #打印所有主機的主機名
{{hostvars[host]['ansible_ssh_host_key_rsa_public']}} #打印所有主機的公鑰
` endfor ` #結束
3、group_names示例:
- name: For secure machines
set_fact: sshconfig=files/ssh/sshd_config_secure
when:"secure'in group_names" #secure是指主機組,group_names是指遠程主機所屬的主機組的名字,意思說secure在遠程的這臺主機的主機組垵面就執行上面那一排命令
- name: For non-secure machines
set_fact: sshconfig=files/ssh/sshd_config_default
when: "'secure' not in group_names" #意思說secure不在遠程的這臺主機的主機組垵面就執行上面那一排命令
不常用
inventory_hostname #保存了設備配置清單中服務器的主機名
inventory_hostname_short #跟invertory_hostname一樣,只是去掉域名,比如invertory_hostname是host.example,那麼inverntory_hostname_shor就是host
inventory_dir #是設備清單文件的路徑
invertory_file #設備清單文件的文件名
示例:
cat inventory.yml
---
- hosts: all
tasks:
- name: copy test file
template: src=file/inventory_hostname.conf.j2 dest=/tmp
cat file/inventory_hostname.conf.j2
{{ inventory_hostname }}
` inventory_hostname_short `
` inventory_dir `
` invertory_file `
cat /tmp/inventory_hostname.conf.j2
172,16.5.202
172
/etc/ansible
/etc/ansible/hosts
【Playbook的條件判斷】
官網參考:http://www.ansible.com.cn/docs/playbooks_error_handling.html
通過ansible-playbook實現對多臺主機同時同時安裝apache。需要注意的是,多臺被管理主機的操作系統可能不相同,而導致apache包名不同,假設同時存在CentOS和Debian兩種操作系統,具體playbook內容如下
案例1:
# cat install_apache.yml
- hosts: all
remote_user: root
gather_facts:True
tasks:
- name: install apache on CentOS
yum: name=httpd state=present
when: ansible_os_family =="CentOS"
- name: install apache on Debian
yum: name=apache2 state=present
when: ansible_os_family =="Debian"
案例2:
tasks:
- command: /bin/false
register: result #把上面命令執行的結果交給result
ignore_errors: True #如果有錯誤,都忽略掉,後面繼續執行,不忽略錯誤,遇到錯誤,就無法再往下走
- command: /bin/something
when: result|failed #如果result執行失敗就執行上面那一行
- command: /bin/something_else
when: result|success #如果result執行成功就執行上面那一行
- command: /bin/still/something_else
when: result|skipped #如果result執行裝態爲skipped就執行上面那一行
案例3:
vars:
epic: true
tasks:
- shell: echo "This certainly isn't epic!"
when: epid #如果epid爲true時,就執行上面那一段
案例4:
tasks:
- shell: echo "I've got '` foo `' and am not afraid to use it!"
when: foo is defined #如果foo沒有定義,就執行上面一段
- fail: msg="Bailing out. this play requires 'bar'"
when: bar is not defined; #如果bar沒有定義就打印上面那一行
案例5:
tasks:
- command: echo ` item `
with_items: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5 #如果item大於5,就輸出那位數字,這裏輸出6,8,10
案例6:
- hosts: webservers
roles:
- { role: debian_stock_config, when: ansible_os_family == 'Debian' } #當客戶端是Debian的時候,就運行debian_stock_config這個角色
- { role: centos_stock_config, when: ansible_os_family == 'Redhat' } #當客戶端是centos的時候,就運行centos_stock_config這個角色
案例7:
- name: test play
hosts: mfs
tasks:
- shell: cat /etc/motd
register: motd_contents #把上面輸執行的結果交給motd_conters這個變量
- shell: echo "mothd contains the word hi" > /tmp/test2
when: motd_contents.stdout.find('hi')!=1 #標準輸出裏面查找有沒有hi,如果有就執行上面那一行echo
register三種輸出方式
motd_contents.stdout #標準輸出
motd_contents.stderr #標準錯誤
motd_contents.rc #輸出值,默認正確是0
案例8: 不常用
tasks:
- shell: /usr/bin/billybass -mode="take me to the river"
register: bass_result
changed_when: "bass_result.rc!=2" #如果rc不等於2就不執行上面那兩段
#this will never report 'changed' status
- shell: wall 'beep'
changed_when: False
安例9:不常用
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
failed_when: "FAILED" in command_result.stderr" 如果錯誤輸出有FAILED則執行失敗,終端輸出則會有change=1字樣
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result #rgister到一個變量去
innore_errors: True #忽略錯誤
- name: this command prints FAILED when it fails
fail: msg="the command failed" #通過fail模塊打印一行輸出
when: "FAILED" in command_result.stderr" #當打印的錯誤輸出包含FAILED時,則打印上面那一行輸出
【循環】
參考中文官網:http://www.ansible.com.cn/docs/playbooks_loops.html#indexed-lists
- name: touch files
file: dest=`item`.`path` state=touch mode={{item.mode|default(0755)}}
with_items
- path: /tmp/foo #循環創建foo、bar、baz這三個文件
- path: /tmp/bar
- path: /tmp/baz
mode: "0444" baz給0444權限,foo和bar不給0444權限,就會給出設定的默認0755權限
標準循環
示例1:標準循環with_items
- name: add several users
user: name=` item ` state=present groups=wheel
with_items:
- testuser1
- testuser2
也可以通過vars 選項定義循環
---
- hosts: all
user: root
vars:
- somelist: [1,2,3,4,5,6] #左邊變量名,右邊一個又一個的變量值
tasks:
- name: lists
shell: /bin/echo ` item ` >> /opt/test.txt
with_items: somelist #引用變量名,拿出一個一個值,賦值給item
或者使用vars_files 引入變量文件的形式定義使用循環
[root@Master opt]# cat a.yml
---
- hosts: all
user: root
vars_files:
- somelist.txt
#vars:
# - somelist: [1,2,3,4,5,6] 左邊
tasks:
- name: lists
shell: /bin/echo ` item ` >> /opt/varfile.txt
with_items: somelist #引用變量名,拿出一個一個值,賦值給item
[root@Master opt]# cat somelist.txt #變量文件
somelist: [1,2,3,4,5,6] #左邊變量名,右邊一個又一個的變量值
同樣我們在使用yum 或者apt 安裝多個軟件包時也可以使用with_items
如果是散列的列表可以這樣使用:
- name: add several users
user: name=` item`.`name ` state=present groups=` item`.`groups `
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
請note使用 ‘with_items’ 用於迭代的條目類型不僅僅支持簡單的字符串列表.如果你有一個哈希列表,那麼你可以用以下方式來引用子項:
- name: add several users
user: name=` item`.`name ` state=present groups=` item`.`groups `
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
嵌套循環
示例2:嵌套循環with_nested
將多個庫授權給多個用戶select 權限,具體mysql_user 模塊的使用方法參考:
- 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', 'providerdb' ]
或者可以通過引用之前定義的變量文件形式使用:
- hosts: 192.168.0.4
remote_user: root
vars:
user: "test"
tasks:
- name: here, 'users' contains the above list of employees
mysql_user: name={{ item[0] }} priv={{ item[1] }}.*:ALL append_privs=yes password=foo
with_neste:
- "`users`"
- [ 'clientdb', 'employeedb', 'providerdb' ]
對哈希表使用循環
示例3:遍歷字典with_dict
[root@Master opt]# cat users.yml
---
users:
alice:
name: Alice Appleworth
telephone: 123-456-7890
bob:
name: Bob Bananarama
telephone: 987-654-3210
[root@Master opt]# cat dict_playbook.yml
---
- hosts: all
user: root
vars_files:
- users.yml
tasks:
- name: Print phone records
debug: msg="User ` item`.`key ` is ` item`.`value`.`name ` (` item`.`value`.`telephone `)"
with_dict: "`users`"
對文件列表使用循環
示例4:使用with_fileglob 遍歷文件(不遞歸、對目錄無效)with_fileglob
將/root/geekwolf/目錄下所有的文件複製到/tmp/fooapp/
---
- hosts: 192.168.0.4
remote_user: root
tasks:
#確保目的目錄存在
- file: dest=/tmp/fooapp state=directory
- copy: src=` item ` dest=/tmp/fooapp/ owner=root mode=600
with_fileglob:
- /root/geekwolf/*
對並行數據集使用循環
示例5:使用with_together 來並行遍歷兩個列表
vim list_test.yml
---
alpha: [ 'a', 'b', 'c', 'd' ]
numbers: [ 1, 2, 3, 4 ,5]
假如我們想要[‘a’,1] [‘b’,2] ...[None,6]可以這樣實現:
vim list_test.yml
---
alpha: ['a','b','c','d']
numbers: [1,2,3,4,5,6]
vim list_playbook.yml
---
- hosts: 192.168.0.4
remote_user: root
vars_files:
- list_test.yml
tasks:
- debug: msg="` item`.`0 ` and ` item`.`1 `"
with_together:
- alpha
- numbers
示例6:循環子元素with_subelements
創建用戶alice 和bob,爲alice 配置兩把公鑰到alice 用戶下的authorized_keys 文件,爲bob 配置一
把公鑰使得兩個用戶通過客戶端私鑰登陸,其中onekey.pub twokey.pub id_rsa.pub 表示已經創建好的公鑰
vim subusers.yml
---
users:
- name: alice
authorized:
- /tmp/alice/onekey.pub
- /tmp/alice/twokey.pub
- name: bob
authorized:
- /tmp/bob/id_rsa.pub
vim sub_playbook.yml
---
- hosts: 192.168.0.4
vars_files:
- subuser.yml
tasks:
- user: name=` item`.`name ` state=present generate_ssh_key=yes
with_items: "`users`"
- authorized_key: "user=` item`.`0`.`name ` key='{{ lookup('file', item.1) }}'"
with_subelements:
- users
- authorized
示例2:根據mysql hosts以及預先給定的privs subkey列表,我們也可以在嵌套的subkey中迭代列表:
vim subusers.yml
---
users:
- user: peter
- mysql:
password: mysql-password
privs:
- "*.*:SELECT"
- "DB1.*:ALL"
mysql.hosts:
- "192.168.1.215"
- user: jack
- mysql:
password: other-mysql-password
privs:
- "*.*:SELECT"
- "DB2.*:ALL"
mysql.hosts:
- "192.168.1.216"
[root@Master opt]# cat sub.yml
---
- hosts: all
user: root
vars_files:
- subuser.yml
tasks:
- name: Setup MySQL users
mysql_user: login_user=root login_password=123456
name=` item`.`0`.`user ` password=` item`.`0`.`mysql`.`password `
host=` item`.`1 ` priv={{ item.0.mysql.privs | join('/') }}
with_subelements:
- users
- mysql.hosts
詳細參考:
authorized_key 模塊:http://docs.ansible.com/authorized_key_module.html
look_plugins 插件講解:http://rfyiamcool.blog.51cto.com/1030776/1441451
對整數序列使用循環
with_sequence 可以以升序數字順序生成一組序列.你可以指定起始值、終止值,以及一個可選的步長值.
指定參數時也可以使用key=value這種鍵值對的方式.如果採用這種方式,’format’是一個可打印的字符串.
數字值可以被指定爲10進制,16進制(0x3f8)或者八進制(0600).負數則不受支持.請看以下示例:
示例 7:在序列中循環 with_sequence
---
- hosts: all
tasks:
# 創建用戶組
- group: name=evens state=present
- group: name=odds state=present
# 創建格式爲 testuser%02x 的 0-32 序列的用戶,%02x中的x代表十六進制數,02代表前面不足兩位補0,執行語句後會創建用戶testuser01,testuser02,testuser03...
- user: name=` item ` state=present groups=evens
with_sequence: start=0 end=32 format=testuser%02x
# 創建目錄:起始位 4,末尾是 16,步長爲 2 命名的目錄
- file: dest=/var/stuff/` item ` state=directory
with_sequence: start=4 end=16 stride=2
# 簡單實用序列的方法:創建 4 個用戶組分表是組 group1 group2 group3 group4
# create 4 groups
- group: name=group` item ` state=present
with_sequence: count=4
隨機選擇 with_random_choice
提供的字符串中的其中一個會被隨機選中.
‘random_choice’功能可以用來隨機獲取一些值.它並不是負載均衡器(已經有相關的模塊了).它有時可以用作一個簡化版的負載均衡器,比如作爲條件判斷:
[root@Master opt]# cat random.yml
---
- hosts: all
user: root
tasks:
- debug: msg=` item `
with_random_choice:
- "go through the door"
- "drink from the goblet"
- "press the red button"
- "do nothing"
Do-Until循環
示例 9:until 循環 until
有時你想重試一個任務直到達到某個條件.比如下面這個例子:
---
- hosts: all
user: root
tasks:
- action: shell /usr/bin/foo
register: result
until: result.stdout.find("all systems go") != -1
retries: 5
delay:
上面的例子 shell 模塊會一直執行直到模塊結果輸出有”all systems go” 或者每個 10s 重試 5 次後結束;默認是每個 5s 重複 3 次;執行 playbook 時加上-vv 參數可以查看詳細過程
示例 10:打印列表索引 with_indexed_items
如果你想循環一個列表,同時得到一個數字索引來標明你當前處於列表什麼位置,那麼你可以這樣做.雖然該方法不太常用:
[root@Master opt]# cat index.yml
---
- hosts: wsyht
user: root
tasks:
- name: indexed loop demo
debug: msg="at array position ` item`.`0 ` there is a value ` item`.`1 `"
with_indexed_items: ['a','b','c','d','e']
扁平化列表
示例11:整合列表with_flattened
如果定義了多個列表,遍歷多個列表項
[root@Master opt]# cat list.yml
---
- hosts: all
user: root
vars:
packages_base:
- [ 'vsftpd', 'docker' ]
#packages_apps:
# - [ ['one-package', 'two-package' ]]
# - [ ['red-package'], ['blue-package']]
tasks:
- name: flattened loop demo
yum: name=` item ` state=latest #安裝兩個列表中的所有包
with_flattened:
- "` packages_base `"
# - "` packages_apps `"
【tags標籤功能】
如果你有一個大型的 playbook,那能夠只運行其中特定部分的配置而無需運行整個 playbook 將會很有用.
例:
tasks:
- yum: name=` item ` state=installed
with_items:
- httpd
- memcached
tags:
- packages
- template: src=templates/src.j2 dest=/etc/foo.conf
tags:
- configuration
如果你只想運行一個非常大的 playbook 中的 “configuration” 和 “packages”,你可以這樣做:
ansible-playbook example.yml --tags "configuration,packages"
另一方面,如果你只想執行 playbook 中某個特定任務 之外 的所有任務,你可以這樣做:
ansible-playbook example.yml --skip-tags "notification"
【異步操作和輪詢】
爲了異步啓動一個任務,可以指定其最大超時時間以及輪詢其狀態的頻率.如果你沒有爲 poll 指定值,那麼默認的輪詢頻率是10秒鐘:
async 並沒有默認值,如果你沒有指定 async 關鍵字,那麼任務會以同步的方式運行,這是Ansible的默認行爲.
另外,如果你不需要等待任務執行完畢,你可以指定 poll 值爲0而啓用 “啓動並忽略”
---
- hosts: all
remote_user: root
tasks:
- name: simulate long running op, allow to run for 45 sec, fire and forget
command: /bin/sleep 15
async: 45 #async沒有默認值,給他指定關健字,執行異步操作
poll: 0 #不等待,直接開始異步
【加速模式詳解】
加速模式只是使用來加速連接的,它仍需使用 SSH 來進行初始安全密鑰交換.它沒有額外增加需要管理的基礎設施的公共key,也不需要諸如 NTP 或 DNS.
只需在你的 play 中添加 accelerate: true 即可使用加速模式:
---
- hosts: all
accelerate: true
tasks:
- name: some task
command: echo ` item `
with_items:
- foo
- bar
- baz
如果你希望改變 Ansible 用於加速模式的端口,你只需添加 accelerated_port 選項:
---
- hosts: all
accelerate: true
# default port is 5099
accelerate_port: 10000
【Vault加密功能】
Ansible 1.5的新版本中, “Vault” 作爲 ansible 的一項新功能可將例如passwords,keys等敏感數據文件進行加密,而非存放在明文的 playbooks 或 roles 中. 這些 vault 文件可以分散存放也可以集中存放.
vault 可以加密任何 Ansible 使用的結構化數據文件. 甚至可以包括 “group_vars/” 或 “host_vars/” inventory 變量, “include_vars” 或 “vars_files” 加載的變量, 通過 ansible-playbook 命令行使用 “-e @file.yml” 或 “-e @file.json” 命令傳輸的變量文件. Role 變量和所有默認的變量都可以被 vault 加密.
因爲 Ansible tasks, handlers等都是數據文件, 所有的這些均可以被 vault 加密. 如果你不喜歡你使用的變量被泄漏,你可以將整個 task 文件部分加密. 然後,這個工作量比較大而且可能給你的同事帶來不便哦 :)
創建加密文件
ansible-vault create foo.yml
首先你將被提示輸出密碼, 經過Vault加密過的文件如需查看需同時輸入密碼後才能進行.
提供密碼後, 工具將加載你定義的 $EDITOR 的編輯工具默認是 vim, 一旦你關閉了編輯會話框,生成後的文件將會是加密文件.
默認加密方式是 AES (基於共享密鑰)
Editing加密文件
編輯加密文件,使用 ansible-vault edit . 該命令會先加密文件爲臨時文件並允許你編輯這個文件,當完成編輯後會保存回你所命名的文件並刪除臨時文件:
ansible-vault edit foo.yml
密鑰更新加密文件
如果你希望變更密碼,使用如下 命令:
ansible-vault rekey foo.yml bar.yml baz.yml
如上命令可以同時批量修改多個文件的組織密碼並重新設置新密碼.
加密普通文件
如果你希望加密一個已經存在的文件,使用 ansible-vault encrypt . 該命令也可同時批量操作多個文件:
ansible-vault encrypt foo.yml bar.yml baz.yml
解密已加密文件
如果不希望繼續加密一個已經加密過的文件,通過 ansible-vault decrypt 你可以永久解密. 命令將解密並保存到硬盤上,這樣你不用再使用 ansible-vault edit 來編輯文件了:
ansible-vault decrypt foo.yml bar.yml baz.yml
查閱已加密文件
如果你不希望通過編輯的方式來查看文件, ansible-vault view 可以滿足你的需要:
ansible-vault view foo.yml bar.yml baz.yml
在Vault下運行Playbook
執行 vault 加密後的playbook文件,最少需要提交如下兩個標誌之一. 交互式的指定 vault 的密碼文件:
ansible-playbook site.yml --ask-vault-pass
該提示被用來解密(僅在內存中)任何 vault 加密訪問過的文件. 目前這些文件中所有的指令請求將被使用相同的密碼加密.
另外,密碼也可以定義在一個文件或者一個腳本中,但是需要 Ansible 1.7 以上的版本才能支持. 當使用該功能時,一定要確認密碼文件的權限是安全的以確保沒有人可以隨意訪問或者變更密碼文件:
ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt
ansible-playbook site.yml --vault-password-file ~/.vault_pass.py
密碼存儲一行一個
如果你使用的是腳本而不是普通文件,確保腳本是可執行的,這樣密碼可以輸出至標準設備.如果你的腳本需要提示輸入數據,那提示可以被髮送到標準錯誤.
如果你是從持續集成系統(例如Jenkins)中使用 Ansible 的話上面的這種情況你會用的到.