Ansible自動化運維工具安裝及使用

<--目錄-->

  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 的話上面的這種情況你會用的到.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章