playbook 基本使用


相對Ad-Hoc模式下的命令方式,Playbook功能更靈活強大。使用playbook可以非常簡單的配置管理多個主機系統,通過編寫YAML格式文件來定制配置內容,配置內容可存儲和長久使用。本節將通過案例逐步了解playbook使用方法。

本節內容都是在遠程服務器sandboxMP(172.16.3.100)中完成,請使用CRT工具連接到sandboxMP(172.16.3.100)。同時需要開啟server1server2虛擬機。

1 YAML基本使用

Ansible playbook配置文件使用YAML格式,在文檔前面章節已經使用過YAML配置文件,這里簡單介紹下YAML的基本語法格式。

1.1 YAML語法

  1. 使用縮進來表示層級;
  2. 只能使用空格縮進,禁止使用Tab縮進;
  3. 對字母大小寫敏感;
  4. 可以使用---來標記開頭,使用...來標記結尾;
  5. 使用#表示注釋內容;
  6. 字符串可以不用引號標注;
  7. 針對不同數據類型有特定標記模型(后面會用實例演示)。

1.2 使用實例

1.2.1 列表

YAML列表內容:列表內的成員是以相同縮進開始,短線加空格開頭(- ):

---

(sandboxMP) [root@sandboxmp ~]$ touch test.yaml

(sandboxMP) [root@sandboxmp ~]$ vim test.yaml

# 將下面內容寫入test.yaml文件,保存退出vim

hosts:  
  - 172.16.3.100  

  - 172.16.3.101  

  - 172.16.3.102
...

  

 

在系統中做代碼演示的時候,請注意命令提示符內容:

  • (sandboxMP):當前是進入了python的虛擬環境,可以使用虛擬環境中的python環境和安裝的程序包;
  • [root@sandboxmp ]表示當前位於家目錄,使用root登陸的,當前目錄就是/root/,這時我們創建的test.yaml就存放在/root/目錄。

python虛擬環境中使用yaml來讀取test.yaml文件內容:

(sandboxMP) [root@sandboxmp ~]$ ipython
Python 3.6.6 (default, Nov 26 2018, 20:00:58) Type 'copyright', 'credits' or 'license' for more information

IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import yaml  

In [2]: f = open('/root/test.yaml')

In [3]: yaml.load(f)Out[3]: {'hosts': ['172.16.3.100', '172.16.3.101', '172.16.3.102']}

可以看到從test.yaml文件中讀取的hosts內容是一個列表。

1.2.2 字典

YAML字典是使用key: value來表示,冒號后面必須加上一個空格:

(

sandboxMP) [root@sandboxmp ~]$ echo '' > test.yml
(sandboxMP) [root@sandboxmp ~]$ vim test.yml

# 將下面內容寫入test.yaml文件,保存退出vim

---

hosts:  

  hostname: sandboxMP    

  ipaddress: 172.16.3.100   

  username: root  

  password: 1234@abcd.com

 ...

  

 

python虛擬環境中使用yaml來讀取test.yaml文件內容:

(sandboxMP) [root@sandboxmp ~]# ipython
Python 3.6.6 (default, Nov 26 2018, 20:00:58) Type 'copyright', 'credits' or 'license' for more information

IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import yaml  

In [2]: f = open('/root/test.yml')

In [3]: yaml.load(f)Out[3]:

{'hosts': {'hostname': 'sandboxMP',

  'ipaddress': '172.16.3.100',

  'username': 'root',

  'password': '1234@abcd.com'}}

hosts內容是一個字典。

1.2.3 字典和列表混合使用

字典和列表是可以混合使用的:

(sandboxMP) [root@sandboxmp ~]$ echo '' > test.yml
(sandboxMP) [root@sandboxmp ~]$ vim test.yml

# 將下面內容寫入test.yml文件,保存退出vim

---

hosts:

  username: root

  password: 1234@abcd.com

  ipaddress:

    - 172.16.3.100

    - 172.16.3.101

    - 172.16.3.102

...

  

 

讀取test.yaml內容:

(sandboxMP) [root@sandboxmp ~]# ipython
Python 3.6.6 (default, Nov 26 2018, 20:00:58) Type 'copyright', 'credits' or 'license' for more information

IPython 7.1.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import yaml  

In [2]: f = open('/root/test.yml')

In [3]: yaml.load(f)

{'hosts': {'username': 'root',

  'password': '1234@abcd.com',

  'ipaddress': ['172.16.3.100', '172.16.3.101', '172.16.3.102']}}

  

 

hosts是一個字典,字典中ipaddress是一個列表,除了上面用法外,列表中也是可以混合字典的。

2 使用playbook來執行任務

2.1 playbook基礎

在定義playbook任務時常會用到的一些基礎組件如下:

  • hosts:任務執行的遠程目標主機;
  • remote_user:在遠程主機上執行任務的用戶;
  • tasks:需要在遠程主機上執行的任務列表;
  • variables:變量,變量可以在hosts中定義,可以在playbook中定義,也可以直接使用setup模塊獲取的變量內容,進行變量替換使用{{ variables }}
  • handlers:任務處理器,當滿足某些條件時才會觸發任務操作;
  • templates:使用模板語言的文本文件。

接下來我們通過一些案例來理解一些組建的使用:

2.1.1 案例1:重啟遠程服務

sandboxMP(172.16.3.100)遠程服務器上定義一個playbook文件用來重啟遠程服務:

(sandboxMP) [root@sandboxmp ~]$ mkdir tasks   # 接下來測試用的文件都臨時放在這個目錄下

(sandboxMP) [root@sandboxmp ~]$ vim tasks/restart_sshd.yml  # 寫入如下內容,保存退出

---- hosts: server             # 指定遠程執行主機,默認從/etc/ansible/hosts文件中讀取server主機組內容  

remote_user: root        # 制定任務執行使用的用戶  

tasks:                     # 定義任務列表    

  - name: restart sshd      # 任務名稱      

  command: 'systemctl restart sshd'    # 調用command模塊來執行ssd重啟命令

 

 

 

在執行重啟任務之前,先來登陸到server組中的遠程主機,server是上一節在hosts中定義的主機組,包含了server01(172.16.3.101)server02(172.16.3.102),使用CRT登陸server01,查看ssh服務狀態:

[root@server01 ~]$ systemctl status sshd
● sshd.service - OpenSSH server daemon

   Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)

   Active: active (running) since Wed 2019-02-13 10:28:18 CST; 11min ago

     Docs: man:sshd(8)

           man:sshd_config(5)

 Main PID: 1058 (sshd)

   CGroup: /system.slice/sshd.service

           └─1058 /usr/sbin/sshd -D

 

 

可以看到當前sshd服務啟動時間是:2019-02-13 10:28:18

執行restart_sshd.yml 

ansible提供了一個命令行工具:ansible-playbook用來執行playbook,回到sandboxMP(172.16.3.100)遠程服務器:

 1 (sandboxMP) [root@sandboxmp ~]$ ansible-playbook --help # 查看幫助
 2 '''幫助內容省略'''
 3 
 4 (sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/restart_sshd.yml
 5 
 6 PLAY [server] ***************************************************************************************************************************************************************************************
 7 
 8 TASK [Gathering Facts] ******************************************************************************************************************************************************************************
 9 
10 ok: [192.168.31.101]
11 
12 ok: [192.168.31.102]
13 
14 TASK [restart sshd] *********************************************************************************************************************************************************************************
15 
16 changed: [192.168.31.101]
17 
18 changed: [192.168.31.102]
19 
20 PLAY RECAP ******************************************************************************************************************************************************************************************
21 
22 192.168.31.101             : ok=2    changed=1    unreachable=0    failed=0   
23 
24 192.168.31.102             : ok=2    changed=1    unreachable=0    failed=0   
25 
26 (sandboxMP) [root@sandboxmp ~]$

 

 

這時登陸server01(172.16.3.101)系統,使用systemctl status sshd查看服務狀態,可以看到服務的啟動時間已經發生了變化。

2.1.2 ansible-playbook

前面已經介紹了兩個命令行工具:ansible ansible-docansible-playbook也是一個命令行工具,用來執行playbook文件。

ansible-playbook基本語法:nsible-playbook test.yml [options]
ansible-playbook常用命令參數:

參數

描述

-C, --check

加上該參數后,模擬執行playbook文件,輸出執行結果,不會在遠程主機正真正執行

-e EXTRA_VARS, --extra-vars=EXTRA_VARS

設置額外變量

-f FORKS, --forks=FORKS

設置進程並發,默認5

-i INVENTORY, --inventory=INVENTORY

指定hosts文件路徑,默認/etc/ansible/hosts

-l SUBSET, --limit=SUBSET

對主機進行過濾

--list-hosts

列出遠程執行的主機列表

--list-tasks

列出playbook文件中定義的task列表

--syntax-check

檢測playbook語法配置

--step

同一時間只執行一個task,在執行前需要進行確認

-t TAGS, --tags=TAGS

只有匹配tags內容的遠程主機才會執行任務,多個tag用逗號分隔

除了上面介紹到的參數外還有一些認證相關設置的參數,具體內容可以通過ansible-playbook --help查看幫助。

你也可以使用上面參數來執行任務查看具體效果。

2.1.3 案例2:創建文件

接下來再寫一個playbook案例,來加深理解,這次使用file模塊來創建一個文件:

(sandboxMP) [root@sandboxmp ~]$ vim tasks/touchfile.yml

---

- hosts: server  

  remote_user: root  

  tasks:    

    - name: touch file      

      file:   # 使用file模塊        

      path: /tmp/touch_file.txt        

      state: touch        

      mode: 0600

 

 

保存文件后,先來檢測下文件語法,並模擬運行下touchfile.yml

(sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/touchfile.yml --syntax-check

 

playbook: tasks/touchfile.yml  # 語法檢測通過,沒有報錯

(sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/touchfile.yml --check

# 以下輸出結果是模擬運行的結果,遠程主機上並沒有真正的創建文件

PLAY [server] ***************************************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************************************

ok: [172.16.3.102]

ok: [172.16.3.101]

TASK [touch file] ***********************************************************************************************************************************************************************************

ok: [172.16.3.101]

ok: [172.16.3.102]

PLAY RECAP ******************************************************************************************************************************************************************************************

192.168.31.101             : ok=2    changed=0    unreachable=0    failed=0   

192.168.31.102             : ok=2    changed=0    unreachable=0    failed=0  

  

 

這時候登陸到server01server02上是沒有/tmp/touch_file.txt這個文件的。 運行touchfile.yml來創建文件:

 

(sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/touchfile.yml
 

PLAY [server] ***************************************************************************************************************************************************************************************

 

TASK [Gathering Facts] ******************************************************************************************************************************************************************************

ok: [192.168.31.101]

ok: [192.168.31.102]

 

TASK [touch file] ***********************************************************************************************************************************************************************************

changed: [192.168.31.101]

changed: [192.168.31.102]

 

PLAY RECAP ******************************************************************************************************************************************************************************************

192.168.31.101             : ok=2    changed=1    unreachable=0    failed=0   

192.168.31.102             : ok=2    changed=1    unreachable=0    failed=0

  

登陸server01或者server02查看文件已經被創建:

[root@server02 ~]$ ls -l /tmp
total 8
drwxr-xr-x 2 root root 4096 Feb 12 22:45 dir_test
drwx------ 3 root root 4096 Feb 13  2019 systemd-private-5a409c6e1b194765b83da9cfb3756967-ntpd.service-39S38P
-rw------- 1 root root    0 Feb 13 12:40 touch_file.txt

 

task中使用模塊時,可以通過使用key-value方式給模塊復制,案例中使用的是冒號方式。也可以使用等號方式,多個參數用空格隔開:

---

- hosts: server  remote_user: root

  tasks:

    - name: touch file

      file: path=/tmp/touch_file.txt state=touch mode=0600

  

2.1.4 案例3:安裝軟件

利用playbook來給server01 server02安裝nginx

(sandboxMP) [root@sandboxmp ~]$ vim tasks/install_nginx.yml

---

- hosts: server  remote_user: root

  tasks:

    - name: add nginx repository

      yum: name=epel-release state=present # 確保擴展源已經安裝

    - name: ensure nginx is at the latest version

      yum: name=nginx state=latest # 確保當前安裝的是最新版本

    - name: ensure nginx is running

      service: name=nginx state=started # 確保服務已經啟動

  

      

在上面的playbook中,定義了三個任務:

  1. add nginx repositorycentos默認是沒有nginx安裝源的,所以這里使用yum模塊了安裝擴展源;
  2. ensure nginx is at the latest version:使用yum模塊來安裝最新版的ngxin,如果ngxin服務已經存在,則會進行更新;
  3. ensure nginx is running:使用service模塊來確保nginx服務已啟動。

以上使用到的模塊都可以通過命令行工具來獲取幫助:

(sandboxMP) [root@sandboxmp ~]$ ansible-doc -s yum

以后寫playbook使用到新的模塊時,大家都可以通過命令行工具:ansible-doc來了解模塊的用法,養成習慣。

運行playbook執行批量安裝任務,運行結果,如下圖:

 

細心的朋友可能會發現,在前面幾個案例中,我都是直接復制的運行結果,為什么這次也放一張運行結果的截圖?
這是因為ansible-playbook在任務運行的輸出結果中,會用不同的顏色來標識運行結果狀態:

  • [add nginx repository]:在執行任務前我已經在server01server02中提前安裝好了擴展源,任務中設置的state=present,因為已經安裝了,所以狀態是OK的,該條任務不會在遠程主機中重新安裝擴展源;
  • [ensure nginx is at the latest version]server01中提前安裝好了最新版本的nginx,匹配state=latest,狀態也是ok的,不會再重復安裝;server02中沒有安裝nginx,所以通過該條任務會完成最新版本的nginx安裝,狀態發生的變化:changed
  • [ensure nginx is running]server01server02上的nginx服務都沒有啟動,所以通過該條任務啟動了nginx服務,狀態都是changed
  • PLAY RECAP:最后統計並輸出任務執行的狀態結果。

除了要知道如何寫playbook來完成自動化管理工作外,還要了解playbook的不同運行狀態。

2.1.5 案例4:修改配置文件

ansible還提供了一個模塊:lineinfile,該模塊可以用來確保某一行文本存在指定的文件中,或者用來從文件中刪除指定的文本,當然可以通過正則表達式來替換某一行內容。

當我提到這個新的模塊的時候你應該保持一個慣性思維,使用命令行工具ansible-doc -s lineinfile 查看下這個模塊的基本用法和常用參數。因為任何一份文檔都不可能面面俱到,詳細介紹每一個知識點,所以你需要真正掌握的是如何在有需求的時候去自主學習。

在上一個案例中已經成功安裝了nginx並運行了nginx服務,這時通過瀏覽器訪問下面地址,可以看到nginx歡迎頁面:

http://172.16.3.101

http://172.16.3.102

 

nginx服務默認配置實用的是80端口,登陸server01查看當前服務運行端口:

[root@server01 ~]# netstat -tnpl |grep nginx

tcp  0 0 0.0.0.0:80  0.0.0.0:*   LISTEN  1591/nginx: master

接下來使用playbook利用lineinfile模塊來批量修改nginx默認監聽端口:

(sandboxMP) [root@sandboxmp ~]$ vim tasks/modify_nginx.yml

---

- hosts: server  

remote_user: root  

tasks:    

  - name: Modify the default port      

    lineinfile:        

      path: /etc/nginx/nginx.conf # 指定需要修改的文件        

      regexp: "(.*)listen(.*) 80 (.*)" # 使用正則表達式查找需要修改的內容        

      line: '\1listen\2 8080 \3'  # 替換后的內容,包含向后引用內容,注意這里是單引號        

      backrefs: yes # 啟用向后引用        

      state: present # 使用 backrefs時需要設置state=present    

  - name: restart nginx      

    service: name=nginx 

    state: restarted 

  

 

playbook說明:

  • 使用了lineinfile模塊和一些參數配置,配置內容在注釋中已經做了說明;
  • 在進行文本查找替換時,使用到了正則表達式、表達式分組、向后替換,這些知識都屬於正則表達式的基礎,如果你不理解,可以去擴展學習下;
  • 同時定義了一個任務用來重啟nginx服務,因為配置文件修改后要重啟服務才能生效。

執行playbook

(sandboxMP) [root@sandboxmp ~]$ ansible-playbook tasks/modify_nginx.yml   

 

PLAY [server] ***************************************************************************************************************************************************************************************

 

TASK [Gathering Facts] ******************************************************************************************************************************************************************************

ok: [172.16.3.101]

ok: [172.16.3.102]

 

TASK [Modify the default port] **********************************************************************************************************************************************************************

changed: [172.16.3.101]

changed: [172.16.3.102]

 

TASK [restart nginx] ********************************************************************************************************************************************************************************

changed: [172.16.3.101]

changed: [172.16.3.102]

 

PLAY RECAP ******************************************************************************************************************************************************************************************

172.16.3.101               : ok=3    changed=2    unreachable=0    failed=0   

172.16.3.102               : ok=3    changed=2    unreachable=0    failed=0

  

任務執行完成,登陸server01 server02查看當前nginx監聽端口:

"/etc/nginx/nginx.conf" 90L, 2467C written

[root@server01 ~]$ netstat -tnpl

Active Internet connections (only servers)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    

tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      3529/nginx: master  

  

可以看到,nginx默認監聽端口已經變成了8080,端口已經生效,這時候訪問http://172.16.3.101:8080就可以看到nginx的歡迎頁面了。

這個案例中實際上是存在一個問題的,由於相關的知識點還未介紹到,所以這里先預留一下問題,等到介紹到對應知識點的時候,再回過頭來分析這個案例中的問題,聰明的你也可以思考下,想想是什么問題呢?

到這里你可以,根據實際工作需求,結合ansible提供的模塊,多練習下playbook的編寫。

2.2 使用tags

使用tags標簽處理任務,通過tags和任務對象進行捆綁,控制部分任務按照指定tags來執行;在執行任務的時候通過 -t 來指定使用的標簽, 通過 --skip-tags 來排除使用的標簽。

(sandboxMP) [root@sandboxmp ~]$ vim tasks/tag_test.yml# 新建一個playbook文件 tag_test.yml,寫入下面內容保存退出

---

- hosts: server  remote_user: root

  tasks:

   - name: touch file1

     file: path=/tmp/file1.txt state=touch

     tags: tf1

   - name: touch file2

     file: path=/tmp/file2.txt state=touch

     tags: tf1

   - name: touch file3

     file: path=/tmp/file3.txt state=touch

     tags: tf3

  

在上面tag_test.yml文件中,定義了三個任務,分別創建了三個文件,同時給任務定義了tags,如果使用ansible-playbook /tmp/tag_test.yml執行playbook任務,三個任務都會被執行,如果只想執行第三個任務創建file3.txt,在執行playbook的時候制定tags即可:

(sandboxMP) [root@sandboxmp ~]# ansible-playbook tasks/tag_test.yml -t tf3

 

PLAY [server] ***************************************************************************************************************************************************************************************

 

TASK [Gathering Facts] ******************************************************************************************************************************************************************************

ok: [192.168.31.101]

ok: [192.168.31.102]

# 在執行結果中可以看到只有 name為touch file3 的任務被執行了

TASK [touch file3]  **********************************************************************************************************************************************************************************

changed: [192.168.31.102]

changed: [192.168.31.101]

 

PLAY RECAP ******************************************************************************************************************************************************************************************

192.168.31.101             : ok=2    changed=1    unreachable=0    failed=0   

192.168.31.102             : ok=2    changed=1    unreachable=0    failed=0

 

登陸server01 或者 server02可以看到/tmp/目錄下只創建了一個file3.txt的文件。

 


免責聲明!

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



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