Ansible-playbook


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 
p2.yml
[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
p2.yml執行結果

注意:執行后發現第一個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,避免重復工作.

handlers

由notify 進行觸發執行handlers中的任務

#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   
需求1執行結果

由於我的虛擬機上並沒有安裝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 
需求2.執行結果

循環

也稱迭代,當需要執行大量重復性工作的時候,對迭代項的引用,固定變量名為"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是一個優秀的管理工具

...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM