Ansible-playbook簡介
什么是playbook?
簡單點說,playbook就是ansible用於配置,部署和管控節點機器的劇本,將一系列命令的集合歸一使用,類似於shell腳本,不過更加強大.
playbook與shell腳本比對
它們功能形似,playbook和shell腳本一樣,都是批量處理任務.都是把很多命令組合到一起,加入對應條件判斷等,要說區別就是命令結構和被執行場景有所不同;
shell腳本由一條條命令構成,一般只在當前的服務器運行;
playbook中是有一個個task任務構成,每個task都可以當做shell中的一條命令,playbook不止在一個服務器上執行,因此它需要在其中指定運行該playbook的服務器名.而且playbook有着自己的語法格式
playbook語法格式
playbook由YMAL語言編寫,YMAL格式類似於JSON格式,便於寫讀和理解,它的格式如下:
#格式
1.文件的第一行應該以 "---"這三個連續字符開始,代表了YAML文件的開始
2.在一行中, # 后面的內容代表注釋,python,ruby,shell都是如此
3.YAML中的列表元素以"-"開頭然后緊接着一個空格,后面為元素內容 4.在同一個列表中的元素應該保持相同的縮進,否則會當作錯誤處理 5.play中hosts ,variables,roles,tasks等對象的表示方法都是鍵值對,中間以 ":"分割,且":"后面還要增加一個空格.
6.文件名稱后綴為 xxx.yml/yaml #示例 --- #復制file - hosts: task01 remote_user: root tasks: - name: copyfile copy: src=/etc/passwd dest=/tmp/data
Ansible-playbook使用
playbook核心參數
hosts #主機組 tasks #任務列表 vars #變量,如下有幾種設置方式 template #jinja2模板語法 tags #標簽 handlers #由一定條件出發,就是notify咯
① 基本參數
#寫法
--- #文件開頭 - hosts: dbservers #指定該playbook在哪個服務器上執行 remote_user: root #指定遠程的用戶名, vars: #表示定義變量 http_port: 80 #變量形式key: value user: coco tasks: #構成playbook的tasks,每個task都有 - name: 開始,name 指定該任務的名稱 - name: copyfile copy: src=/etc/fstab dest=/tmp/fs - name: install redis yum: name=redis
② ansible-playbook -h命令分析
#常用命令 -C --check #檢查但是不會真的執行 -f FORKS, --forks=FORKS #並發,默認5個 --list-hosts #列出匹配的主機 --sytax-check #檢查語法
-t #只執行某個task任務
③ 執行一個playbook命令 --->ansible-playbook p1.yml (單任務)
#p1.yml --- - hosts: web tasks: - name: install bc yum: name=bc
注解:如上圖所示
- PLAY表示執行hosts 中web組遠程機器
- 第一個TASK表示正在收集兩台遠程機器的數據信息,采集成功為顯示綠色,代表執行成功
- 第二個TASK表示我們要執行任務的名稱,執行成功后狀態發生變化為黃色,狀態沒變化為綠色,執行失敗為紅色.
④ 再來個例子ansible-playbook p2.yml(多任務)看看效果,會更加清楚

#p2.yml --- - hosts: web remote_user: root tasks: - name: createuser user: name=coco - name: deluser user: name=coco state=absent

[root@localhost playbook]# ansible-playbook p2.yml PLAY [web] ********************************************************************* TASK [Gathering Facts] ********************************************************* ok: [192.168.220.134] ok: [192.168.220.136] ok: [192.168.220.135] TASK [createuser] ************************************************************** changed: [192.168.220.134] changed: [192.168.220.135] changed: [192.168.220.136] TASK [deluser] ***************************************************************** changed: [192.168.220.134] changed: [192.168.220.135] changed: [192.168.220.136] PLAY RECAP ********************************************************************* 192.168.220.134 : ok=3 changed=2 unreachable=0 failed=0 192.168.220.135 : ok=3 changed=2 unreachable=0 failed=0 192.168.220.136 : ok=3 changed=2 unreachable=0 failed=0
注意:執行后發現第一個task任務執行完后,第二個task任務才執行的,多個task是順序執行的,所以先創建,再刪除...
playbook冪等性
什么意思呢?就是不管執行多少次,得到的結果永遠是相同的,試着一直執行p2.yml,最終的結構都一樣.
playbook (5種傳參方式)
為什么要這么做呢?
主要防止需求不斷變化嘛,總不能反復修改文件是吧
方式一
---
#方式一
- hosts: web
remote_user: root
tasks:
- name: create{{user}} user: name={{user}} ansible-playbook -e user=superman p1.yml #有沒有發現什么?沒錯就是jinja2模板語法,
方式二
[web]
192.168.220.[134:135] user=laifu 192.168.220.136 user=wangcai #vi /etc/ansible/hosts #針對hosts文件進行傳參,執行結果web組為全部創建laifu #實際上134,135會創建出laifu用戶,136會創建出wangcai用戶. ansible-playbook p1.yml
方式三
[web:vars]
user=taidi #還是在hosts文件傳參,給web組vars進行傳參 ansible-playbook p1.yml 會創建出一個taidi用戶
方式四
- hosts: web
vars:
- user: jinmao tasks: - name: create{{user}} user: name={{user}} #利用vars變量參數進行傳參,執行后會創建出一個jinmao用戶
方式五
- hosts: web
tasks:
- name: yumbc yum: name=bc - name: sum shell: echo 8+9|bc #linux 計算通過bc register: user #得到結果注冊為user,但是拿到一個字典 - name: echo shell: echo {{user.stdout}} >/tmp/sum.txt #將user字典中的stdout值取出來 - name: createuser{{user.stdout}} user: name=keke{{user.stdout}} #執行創建出keke9 #上面先計算,注冊user得到一個大字典,再取出user.stdout寫到文件中,最后創建對應的參數的用戶keke9
注:這五種傳參優先級: -e >playbook的vars >hosts
setup模塊
在playbook中負責收集信息,因此放在這里進行補充模塊信息
① 執行命令 ansible 192.168.220.134 -m setup |more 收集信息
#如下是setup模塊常用參數 ansible_all_ipv4_addresses # 所有的ipv4地址 ansible_all_ipv6_addresses # 所有的ipv6的地址 ansible_bios_version # 主板bios的版本 ansible_architecture # 架構信息 ansible_date_time # 系統的時間 ansible_default_ipv4 # IPv4默認地址 address #ip地址 alias #網卡名稱 broadcast #廣播地址 gateway # 網關 macaddress #mac地址 netmask #子網掩碼 network #網段 ansible_distribution #系統的版本 ansible_distribution_file_variety# 系統的基於對象 ansible_distribution_major_version# 系統的主版本 ansible_distribution_version #系統的版本 ansible_domain #系統的域 ansible_dns #系統的dns ansible_env #系統的環境變量 ansible_hostname #系統的主機名 ansible_fqdn #系統的完整主機名 ansible_machine #系統的架構 ansible_memory_mb #系統的內存信息 ansible_os_family #系統的家族 ansible_pkg_mgr #系統的包管理工具 ansible_processor_cores #cpu的核數 ansible_processor_count #每顆cpu上的顆數 ansible_processor_vcpus #cpu的總核數=cpu的顆數*每顆cpu上的核數 ansible_python #系統的python版本 #快速篩選查找,支持正則拼接 ansible 192.168.220.134 -m setup -a "filter=*processor*"
② 正則在linux中簡單實用
[root@localhost playbook]# echo 123 |grep "[0-9]\{2\}" #發現"{}"是需要轉義的
123 #取到12
[root@localhost playbook]# echo 123 |grep "[0-9]\?" #?也需要轉義
123 #取到123
[root@localhost playbook]# echo 123 |grep "^[0-9]" 123 #取到1 [root@localhost playbook]# echo 123 |grep "\<[0-9]" #^在linux中也可以寫成\>放在起始位 123 #取到 1 [root@localhost playbook]# echo 123 |grep "[0-9]$" 123 #取到3 [root@localhost playbook]# echo 123 |grep "[0-9]\>" #^在linux中也可以寫成\>放在末位 123 #取到3
tags
給某個task任務加上標簽,執行的時候防止重復執行yml文件中已經執行過的命令
#p4.yml --- - hosts: web tasks: - name: install yum: name=redis - name: copyfile copy: dest=/etc/redis.conf src=/etc/redis.conf tags: copyall - name: start service: name=redis state=started #執行這條命令 ansible-playbook -t copyall p4.yml ,由於tags標簽名稱 copyall 存在於copyfile中上述的三個task任務就只執行copyfile的task,避免重復工作.
#p5.yml - hosts: web tasks: - name: install yum: name=redis - name: copyfile copy: dest=/etc/redis.conf src=/etc/redis.conf tags: copyall notify: restart # 觸發handlers中的task任務並執行 - name: start service: name=redis state=started handlers: - name: restart service: name=redis state=restarted #為什么要這樣寫呢? #其實我就是想copy下文件並重啟,不想執行其它 的task任務的需求 #在copy的task任務的基礎上無法再添加標簽tags,這時有notify進行觸發handlers參數,執行其中的task,是不是很方便呢
template
可以通過setup模塊獲取到的信息進行模板渲染到需要用的文件中.創建一個templates目錄,將要渲染模板的文件放在目錄中,通過jinja2語法進行替換文件中經常改動的內容
#redis.conf bind {{ansible_default_ipv4.address}} #替換redis綁定的ip地址,因為默認是本地的.當然還可以替換很多東西
- hosts: web tasks: - name: install yum: name=redis - name: copyfile template: dest=/etc/redis.conf src=redis.conf tags: copyfile notify: restart - name: start service: name=redis state=started handlers: - name: restart service: name=redis state=restarted #需要在本地的目錄下創建一個templates目錄,就可以用相對路徑,在執行copyfile所在的task時就會執行templates中的redis.conf文件,實時將各個機器地址獲取到
when
在task中使用,jinja2的語法格式
情景:比如在setup模塊中可以獲取到版本信息 ansible_distribution_version ,拿到是7,當版本為6的時候,同樣的任務,執行的命令不盡相同,這時就需要判斷了when
[root@localhost playbook]# ansible 192.168.220.134 -m setup -a "filter=*distribution*" 192.168.220.134 | SUCCESS => { "ansible_facts": { "ansible_distribution": "CentOS", "ansible_distribution_file_parsed": true, "ansible_distribution_file_path": "/etc/redhat-release", "ansible_distribution_file_variety": "RedHat", "ansible_distribution_major_version": "7", "ansible_distribution_release": "Core", "ansible_distribution_version": "7.5.1804" }, "changed": false }
需求1:比如在版本6和版本7生成兩個文件內容不同
#p7.yml --- - hosts: web tasks: - name: file copy: content="東船西舫悄無言" dest=/opt/file when: ansible_distribution_major_version=="7" - name: file copy: content="唯見江心秋月白" dest=/opt/file when: ansible_distribution_major_version=="6" #ansible-playbook p7.yml 就會在對應Contos版本生成兩個文件對應的內容

[root@localhost playbook]# ansible-playbook p7.yml PLAY [web] ***************************************************************************************************************************************** TASK [Gathering Facts] ***************************************************************************************************************************** ok: [192.168.220.135] ok: [192.168.220.134] ok: [192.168.220.136] TASK [file] **************************************************************************************************************************************** changed: [192.168.220.135] changed: [192.168.220.134] changed: [192.168.220.136] TASK [file] **************************************************************************************************************************************** skipping: [192.168.220.134] skipping: [192.168.220.135] skipping: [192.168.220.136] PLAY RECAP ***************************************************************************************************************************************** 192.168.220.134 : ok=2 changed=1 unreachable=0 failed=0 192.168.220.135 : ok=2 changed=1 unreachable=0 failed=0 192.168.220.136 : ok=2 changed=1 unreachable=0 failed=0
由於我的虛擬機上並沒有安裝Centos6,因此當 ansible_distribution_major_version=="6" 的時候該task任務直接跳過了.
需求2.根據傳值執行對應task
#p6.yml --- - hosts: web tasks: - name: file copy: content="大弦嘈嘈如急雨\n" dest=/opt/file when: num=="7" - name: file copy: content="小弦切切如私語\n" dest=/opt/file when: num=="6" #ansible-playbook -e num=6 p6.yml #當固定給num傳參的時候,task任務根據參數執行,此時執行的是num=='6'的task.

[root@localhost playbook]# ansible-playbook -e num=6 p6.yml PLAY [web] ***************************************************************************************************************************************** TASK [Gathering Facts] ***************************************************************************************************************************** ok: [192.168.220.136] ok: [192.168.220.135] ok: [192.168.220.134] TASK [file] **************************************************************************************************************************************** skipping: [192.168.220.134] skipping: [192.168.220.135] skipping: [192.168.220.136] TASK [file] **************************************************************************************************************************************** changed: [192.168.220.134] changed: [192.168.220.135] changed: [192.168.220.136] PLAY RECAP ***************************************************************************************************************************************** 192.168.220.134 : ok=2 changed=1 unreachable=0 failed=0 192.168.220.135 : ok=2 changed=1 unreachable=0 failed=0 192.168.220.136 : ok=2 changed=1 unreachable=0 failed=0
循環
也稱迭代,當需要執行大量重復性工作的時候,對迭代項的引用,固定變量名為"item",在task中使用with_item給定要迭代的元素列表:
①簡單循環
示例1
--- - hosts: web tasks: - name: createuser user: name={{item}} with_items: - hanghang - haha #執行后循環在web組內所有遠程機器創建出,hanghang和haha兩個用戶
示例2
--- - hosts: web tasks: - name: creategroup group: name={{item}} with_items: - 666 - 999 - name: createuser user: name={{item}} with_items: - xxx - ooo #類似於python中的兩個for循環,分別創建組和用戶
playbook字典功能
嵌套循環實現
--- - hosts: web tasks: - name: creategroup group: name={{item}} with_items: - mama - baba - name: createuser user: name={{item.name}} group={{item.group}} with_items: - {"name":lili,"group":mama} - {"name":nana,"group":baba} #執行后 用戶lili對應mama組;用戶nana對應baba組
roles
roles的作用?
roles讓playbook的眾多yml文件執行更加規范,更好的進行管理yml文件,好處如下:
目錄結構清晰;
可以互相調用,
nginx/ ├── files #存放靜態文件 │ └── fstab ├── handlers #存放需要觸發的任務,里面必須main.yml文件 │ └── main.yml ├── tasks #存放的執行任務,里面必須main.yml文件 │ ├── copyfile.yml │ ├── install.yml │ ├── main.yml │ └── start.yml ├── templates #存放模板文件 │ ├── centos6.conf │ └── nginx.conf └── vars #存放的是參數,里面必須main.yml文件 └── main.yml #入口文件與roles文件同級 - hosts :web remote_user: root roles: - nginx
查找順序
1.先查找當前目錄下 roles目錄里面指定的對應文件夾
2.找到tasks目錄下面的main.yml文件,如果import_tasks就導入
3.如下
如果遇到了template,存放是動態文件setup,去找templates文件夾下面對應的文件
如果遇到notify,去找handlers里面的main.yml文件
files:存放的是靜態文件
vars:存放的是參數,入口文件main.yml
如果發現變量,如果是setup收集的變量就去setup,如果不是就去vars里面main.yml文件查找
總結: Ansible rotes管理ansible playbook文件,形成結構化,ansible-playbook 文件管理繁多的命令.讓凌亂的命令集成化和腳本化.從全面來看,ansible是一個優秀的管理工具
...