這是Ansible系列課程第四節,小試牛刀,執行第一個Playbook:介紹什么是Playbook以及體驗一下它的強大功能。
該系列課程前后章節都是有關聯性的,對于初學者建議按順序閱讀。也可以選擇特定的章節了解單個知識點。
上一節我們介紹了Ad-hoc命令以及演示了幾個Ad-hoc命令的實例,可以說,已經初步了解了Ansible是如何執行單個任務的。通過命令行執行單個任務滿足了工作中的一部分簡單的場景。但在實際工作中,所涉及的場景可能是復雜的大型項目,這個時候單個的Ad-hoc命令就滿足不了要求了,就需要使用Ansible Playbook。下面介紹一下什么是Ansible Playbook以及將上一節的例子通過Playbook形式執行。
什么是Playbook
Playbook是一組采用YAML語法格式編寫的、用于遠程執行的有序命令的集合。
Playbook與Ad-hoc是執行Ansbile的兩種完全不同的方式,前者強大,后者簡單。Playbook之所以強大,是因為它是Ansible配置、部署、編排的語言。既然是一種語言,就包含了語法結構、邏輯處理、條件判斷等,再加以模塊和插件進行擴展,使得Playbook具有很強的業務處理能力。
Playbook是由一個或多個“play”組成,每個“play”又由一個或多個“task”組成,task就是具體執行的任務。打個比方,可以把task比作音符,play就是一首歌曲,playbook就是演唱會的劇本,通過playbook編排出精彩酷炫的演唱會。同樣,ansible通過playbook編排出復雜的、自動化的部署任務。
Playbook示例講解
下面是一個示例是關于安裝并檢查apache是否安裝并啟動的playbook,采用YAML語法編寫,對YAML語法不熟悉的請自行補習。
---
- hosts: devops
? vars:
?? http_port: 80
? remote_user: root
? tasks:
?? - name: ensure apache is at the latest version
? ?? yum:
? ? ?? pkg: httpd
? ? ?? state: latest
?? - name: write the apache config file
? ?? template:
? ? ?? src: ./template/httpd.conf.j2
? ? ?? dest: /etc/httpd/conf/httpd.conf
?? - name: ensure apache is running
? ?? service:
? ? ?? name: httpd
? ? ?? state: started
該示例只包含了一個play,如果要包含多個play,按如下結構編寫,一個play用于webserver主機組中httpd的安裝,一個是用于dbserver主機組中postgresql的安裝。plays的執行順序和tasks一樣,都是從上到下順序執行。
---
- hosts: webserver
? remote_user: root
? tasks:
?? - name: ensure apache is at the latest version
? ?? yum:
? ? ?? pkg: httpd
? ? ?? state: latest
- hosts: dbserver
? remote_user: root
? tasks:
?? - name: ensure postgresql is at the latest version
? ?? yum:
? ? ?? name: postgresql
? ? ?? state: latest
對于playbook中的每個play都是關于where、who、what和how的事情:
where:在哪些主機組上
who:由哪個用戶執行
what:執行哪些任務
how:如何執行這些任務,循環、同步、異步等
下面拆解一個單獨的play中包含哪幾個主要部分:
hosts:指定任務執行的位置,包含一個或多個主機組或者特定模式的主機組,這些都是需要從inventory文件中獲取,即便是直接寫IP,但該IP沒包含在inventory中也是不可以的。關于inventory會在下一節介紹。
remote_user:指定執行任務的用戶。在這個位置指定用戶表示該play包含的所有任務都通過該用戶執行,也可以在單個task中指定。對于沒有權限的用戶可以使用become升級為sudo權限執行(前提是該用戶必須是一個sudoer)。
vars:指定該play任務中包含的變量。關于變量也會在后面章節介紹。
tasks:指定該play執行的任務清單,執行的順序按從上到下的順序,每次都是在所有主機組上執行完一個任務再執行下一個任務。每個任務都是執行一個具有非常具體的參數的模塊,上面的vars可以用做模塊的參數。這里的模塊應該是冪等的,也就是說,連續多次運行一個模塊應該與只運行一次的結果相同。模塊是冪等的,task也就是冪等的,整個play很可能也就是冪等。
name:指定每個具體任務的名稱,會在腳本運行過程中輸出。在Ansible最佳實踐中要求,每個任務的名稱都要寫上,這樣可以在執行過程中知道哪個任務是干什么的。
yum:執行該任務所執行的具體的模塊,在Ansible中類似這樣的模塊大概有3000多個,能夠滿足工作中的幾乎所有的場景,如果滿足不了,開發人員還可以開發自己的模塊。
name和state:指定yum模塊具體的參數,每個模塊都包含許多不同的參數,根據參數值的不同執行的結果不一樣。比如state:present是創建,state:absent是刪除。
這些只是組成一個play或者playbook的基本要素,playbook中包含的元素遠不止這些。在涉及到一個具體的模塊不知道都有哪些參數時,可以執行ansible-doc? modulename查看。
$ ansible-docyum
執行Playbook
了解了Playbook編寫的語法,可通過下面命令執行playbook:
$ansible-playbookcheck-apache.yml
ansible-playbook這個命令行工具還有很多其他的參數,可以通過ansible-playbook -h查看幫助文檔,結果如下所示:
[root@controll-node ~]# ansible-playbook -h
usage: ansible-playbook [-h] [--version] [-v] [-k]
? ? ? ? ? ? ? ? ? ? ?? [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
? ? ? ? ? ? ? ? ? ? ?? [-c CONNECTION] [-T TIMEOUT]
? ? ? ? ? ? ? ? ? ? ?? [--ssh-common-args SSH_COMMON_ARGS]
? ? ? ? ? ? ? ? ? ? ?? [--sftp-extra-args SFTP_EXTRA_ARGS]
? ? ? ? ? ? ? ? ? ? ?? [--scp-extra-args SCP_EXTRA_ARGS]
? ? ? ? ? ? ? ? ? ? ?? [--ssh-extra-args SSH_EXTRA_ARGS] [--force-handlers]
? ? ? ? ? ? ? ? ? ? ?? [--flush-cache] [-b] [--become-method BECOME_METHOD]
? ? ? ? ? ? ? ? ? ? ?? [--become-user BECOME_USER] [-K] [-t TAGS]
? ? ? ? ? ? ? ? ? ? ?? [--skip-tags SKIP_TAGS] [-C] [--syntax-check] [-D]
? ? ? ? ? ? ? ? ? ? ?? [-i INVENTORY] [--list-hosts] [-l SUBSET]
? ? ? ? ? ? ? ? ? ? ?? [-e EXTRA_VARS] [--vault-id VAULT_IDS]
[--ask-vault-pass |--vault-password-fileVAULT_PASSWORD_FILES]
? ? ? ? ? ? ? ? ? ? ?? [-f FORKS] [-M MODULE_PATH] [--list-tasks]
? ? ? ? ? ? ? ? ? ? ?? [--list-tags] [--step] [--start-at-task START_AT_TASK]
? ? ? ? ? ? ? ? ? ? ?? playbook [playbook ...]
Runs Ansible playbooks, executing the defined tasks on the targeted hosts.
positional arguments:
? playbook ? ? ? ? ? ?? Playbook(s)
......
下面再介紹幾個重要的選項:
-v:輸出調試日志,需要更詳細的日志,可以使用-vv,-vvv,或-vvvv等。
-u:指定連接的遠程用戶。
--become:改變執行任務的用戶,值為yes或no。
--become-user:指定執行任務的用戶,默認為root。
--ask-become-pass:指定改變后的用戶的密碼。
--become-method:指定通過什么方式變為該用戶,默認為sudo。
-i:指定inventory文件,可以是多個。
-f:指定并行執行的任務數,默認是5個。
--syntax-check:檢查playbook的語法是否正確,但不執行。
--step:一步一步的執行playbook,在執行之前需要確認。
-h:這也是最應該記住的選項,其他都沒記住,只要記住這個就能知道其他的了。
這幾個是平時用的比較多點,先熟悉一下,其他選項可以自行查看幫助文檔。
示例演示
下面我們編寫一個playbook,需要執行的任務是:
在遠程主機上創建一個文件,內容為“this is a playbook”,并將該文件從遠程主機拷貝到控制主機上,然后在控制主機上獲取該文件的內容。
這個稍微復雜的場景如果要用Ad-hoc命令是一個很繁瑣的事情,playbook腳本的內容如下:
---
- hosts: devops
? vars:
?? file_name: playbook
? tasks:
?? - name: create file with content
? ?? copy:
? ? ?? content: this is a playbook
? ? ?? dest: /mnt/{{file_name}}.txt
?? - name: copy file from remote to local
? ?? fetch:
? ? ?? src: /mnt/{{file_name}}.txt
? ? ?? dest: /mnt/
- hosts: localhost
? vars:
?? file_name: playbook
? tasks:
?? - name: get the file content with var
? ?? debug:
? ? ?? msg: "{{ lookup('file', \"/mnt/{{item}}/mnt/{{file_name}}.txt\") }}"
? ?? with_items:
? ? ?? - "{{groups['devops']}}"
該Playbook包含兩個play,第一個play是在devops主機組上創建一個文件,然后將該文件拷貝到本地,第二個play是讀取拷貝到本地的文件內容,所用的模塊有:copy、fetch和debug。下面執行一下這個playbook。
總結
這一節主要介紹了什么是Playbook,Playbook由哪些主要元素組成,以及如何執行playbook和相關的主要參數,最后通過一個具體的示例演示了一個包含多個play的playbook。雖然與大型復雜的場景相比,該示例仍然很小,但也展示出了Ansible playbook的強大之處。在后面的章節里,我們也主要以介紹Playbook為主。