Ansible 快速指南



Ansible - 簡介

Ansible 是一個簡單的開源 IT 引擎,它可以自動化應用程式部署、內部服務編排、雲配置以及許多其他 IT 工具。

Ansible 易於部署,因為它不使用任何代理或自定義安全基礎設施。

Ansible 使用 playbook 來描述自動化作業,playbook 使用非常簡單的語言,即 YAML(這是一種人類可讀的資料序列化語言,通常用於配置檔案,但可用於許多儲存資料的應用程式),易於人類理解、閱讀和編寫。因此,即使是 IT 基礎設施支援人員也可以閱讀和理解 playbook,並在需要時進行除錯(YAML – 它以人類可讀的形式存在)。

Ansible 旨在用於多層部署。Ansible 並非一次管理一個系統,而是透過描述所有系統之間的相互關係來模擬 IT 基礎設施。Ansible 完全是無代理的,這意味著 Ansible 透過連線您的節點來工作 ssh(預設情況下)。但是,如果您想要其他連線方法,例如 Kerberos,Ansible 也提供此選項。

連線到節點後,Ansible 會推送稱為“Ansible 模組”的小程式。Ansible 在您的節點上執行這些模組,並在完成後將其刪除。Ansible 在簡單的文字檔案中管理您的清單(這些是主機檔案)。Ansible 使用主機檔案,可以在其中對主機進行分組,並可以控制 playbook 中特定組的操作。

主機檔案示例

這是主機檔案的內容:

#File name: hosts
#Description: Inventory file for your application. Defines machine type abc
node to deploy specific artifacts
# Defines machine type def node to upload
metadata.

[abc-node]
#server1 ansible_host = <target machine for DU deployment> ansible_user = <Ansible
user> ansible_connection = ssh
server1 ansible_host = <your host name> ansible_user = <your unix user>
ansible_connection = ssh

[def-node]
#server2 ansible_host = <target machine for artifact upload>
ansible_user = <Ansible user> ansible_connection = ssh
server2 ansible_host = <host> ansible_user = <user> ansible_connection = ssh

什麼是配置管理

就 Ansible 而言,配置管理意味著它透過記錄和更新描述企業硬體和軟體的詳細資訊來維護產品效能的配置。

此類資訊通常包括已應用於已安裝軟體包的確切版本和更新,以及硬體裝置的位置和網路地址。例如,如果您想在企業中所有機器上安裝新版本的 WebLogic/WebSphere 伺服器,手動更新每臺機器是不可行的。

您可以使用 Ansible playbook 和以最簡單方式編寫的清單,一次性在所有機器上安裝 WebLogic/WebSphere。您只需列出清單中節點的 IP 地址,並編寫一個 playbook 來安裝 WebLogic/WebSphere。從您的控制機器執行 playbook,它將在所有節點上安裝。

Ansible 如何工作?

下圖顯示了 Ansible 的工作原理。

Ansible 的工作原理是連線到您的節點並向其推送稱為“Ansible 模組”的小程式。Ansible 然後執行這些模組(預設情況下透過 SSH),並在完成後將其刪除。您的模組庫可以駐留在任何機器上,不需要伺服器、守護程式或資料庫。

Ansible Works

上圖中的管理節點是控制節點(管理節點),它控制 playbook 的整個執行。這是您執行安裝的節點。清單檔案提供 Ansible 模組需要執行的主機列表,管理節點進行 SSH 連線並在主機機器上執行小型模組並安裝產品/軟體。

Ansible 的優勢在於它在安裝模組後會將其刪除,因此它有效地連線到主機,執行指令,如果成功安裝,則刪除複製到主機並已執行的程式碼。

Ansible - 環境搭建

在本章中,我們將學習 Ansible 的環境設定。

安裝過程

當我們討論部署時,主要有兩種型別的機器:

  • 控制機器 - 可以管理其他機器的機器。

  • 遠端機器 - 由控制機器處理/控制的機器。

一臺控制機器可以處理多臺遠端機器。因此,為了管理遠端機器,我們必須在控制機器上安裝 Ansible。

控制機器要求

Ansible 可以從任何安裝了 Python 2(版本 2.6 或 2.7)或 Python 3(版本 3.5 及更高版本)的機器上執行。

注意 - Windows 不支援控制機器。

預設情況下,Ansible 使用 ssh 來管理遠端機器。

Ansible 不會新增任何資料庫。它不需要啟動或保持執行的任何守護程式。在管理遠端機器時,Ansible 不會留下任何已安裝或正在執行的軟體。因此,升級到新版本的問題不存在。

Ansible 可以安裝在具有上述要求的控制機器上,方法有很多種。您可以透過 Apt、yum、pkg、pip、OpenCSW、pacman 等安裝最新版本。

在 Ubuntu 機器上透過 Apt 安裝

要安裝 Ansible,您必須在您的機器上配置 PPA。為此,您必須執行以下程式碼行:

$ sudo apt-get update 
$ sudo apt-get install software-properties-common 
$ sudo apt-add-repository ppa:ansible/ansible $ sudo apt-get update 
$ sudo apt-get install ansible

執行上述程式碼行後,您就可以透過 Ansible 管理遠端機器了。只需執行 Ansible–version 來檢查版本,並檢查 Ansible 是否已正確安裝。

Ansible - YAML 基礎

Ansible 使用 YAML 語法來表達 Ansible playbook。本章概述了 YAML。Ansible 使用 YAML 是因為它與 XML 和 JSON 等其他資料格式相比,更易於人類理解、閱讀和編寫。

每個 YAML 檔案可以選擇以“---”開頭,並以“... ”結尾。

理解 YAML

在本節中,我們將學習表示 YAML 資料的不同方法。

鍵值對

YAML 使用簡單的鍵值對來表示資料。字典以鍵:值對的形式表示。

注意 - 冒號 : 和值之間應該有空格。

示例:學生記錄

--- #Optional YAML start syntax 
james: 
   name: james john 
   rollNo: 34 
   div: B 
   sex: male 
… #Optional YAML end syntax 

縮寫

您還可以使用縮寫來表示字典。

示例

James: {name: james john, rollNo: 34, div: B, sex: male}

表示列表

我們也可以在 YAML 中表示列表。列表的每個元素(成員)都應在新行中寫入,並具有相同的縮排,以“-”(- 和空格)開頭。

示例

---
countries:  
   - America 
   - China 
   - Canada 
   - Iceland 
…

縮寫

您還可以使用縮寫來表示列表。

示例

Countries: [‘America’, ‘China’, ‘Canada’, ‘Iceland’] 

字典內的列表

我們可以在字典內使用列表,即鍵的值是列表。

示例

---  
james: 
   name: james john 
   rollNo: 34 
   div: B 
   sex: male 
   likes: 
      - maths 
      - physics 
      - english 
… 

字典列表

我們也可以建立字典列表。

示例

---  
- james: 
   name: james john 
   rollNo: 34 
      div: B 
   sex: male 
   likes: 
      - maths 
      - physics 
      - english 

- robert: 
      name: robert richardson 
      rollNo: 53 
      div: B 
      sex: male 
   likes: 
      - biology 
      - chemistry 
…  

YAML 使用“|”在顯示多行時包含換行符,並使用“>”在顯示多行時抑制換行符。因此,我們可以閱讀和編輯長行。在這兩種情況下,縮排都將被忽略。

我們也可以在 YAML 中表示布林(True/false)值,其中布林值可以不區分大小寫。

示例

---  
- james: 
   name: james john 
   rollNo: 34 
   div: B 
   sex: male 
   likes: 
      - maths 
      - physics 
      - english 
   
   result: 
      maths: 87 
      chemistry: 45 
      biology: 56 
      physics: 70 
      english: 80 
   
   passed: TRUE 
   
   messageIncludeNewLines: | 
      Congratulation!! 
      You passed with 79% 
   
   messageExcludeNewLines: > 
      Congratulation!! 
      You passed with 79% 

一些與 Ansible 相關的常用詞。

服務/伺服器 - 機器上提供服務的程序。

機器 - 物理伺服器、虛擬機器 (vm) 或容器。

目標機器 - 我們即將使用 Ansible 配置的機器。

任務 - Ansible 管理的操作(執行這個,刪除那個)等。

Playbook - 編寫 Ansible 命令的 yml 檔案,yml 在機器上執行。

Ansible - Ad hoc 命令

Ad hoc 命令是可以單獨執行以執行快速功能的命令。這些命令不需要以後執行。

例如,您必須重新啟動所有公司伺服器。為此,您將從“/usr/bin/ansible”執行 Ad hoc 命令。

這些 ad-hoc 命令不用於配置管理和部署,因為這些命令是一次性使用的。

ansible-playbook 用於配置管理和部署。

並行性和 Shell 命令

一次以 12 個並行分支重新啟動您的公司伺服器。為此,我們需要設定 SSHagent 用於連線。

$ ssh-agent bash 
$ ssh-add ~/.ssh/id_rsa 

要在組“abc”中以 12 個並行分支為所有公司伺服器執行重新啟動:

$ Ansible abc -a "/sbin/reboot" -f 12

預設情況下,Ansible 將從當前使用者帳戶執行上述 Ad-hoc 命令。如果要更改此行為,則必須在 Ad-hoc 命令中傳遞使用者名稱,如下所示:

$ Ansible abc -a "/sbin/reboot" -f 12 -u username

檔案傳輸

您可以使用 Ad-hoc 命令在多臺機器上並行執行大量 SCP(安全複製協議)檔案。

將檔案傳輸到許多伺服器/機器

$ Ansible abc -m copy -a "src = /etc/yum.conf dest = /tmp/yum.conf"

建立新目錄

$ Ansible abc -m file -a "dest = /path/user1/new mode = 777 owner = user1 group = user1 state = directory" 

刪除整個目錄和檔案

$ Ansible abc -m file -a "dest = /path/user1/new state = absent"

管理軟體包

Ad-hoc 命令可用於 yum 和 apt。以下是使用 yum 的一些 Ad-hoc 命令。

以下命令檢查 yum 軟體包是否已安裝,但不更新它。

$ Ansible abc -m yum -a "name = demo-tomcat-1 state = present"

以下命令檢查軟體包是否未安裝。

$ Ansible abc -m yum -a "name = demo-tomcat-1 state = absent" 

以下命令檢查是否安裝了最新版本的軟體包。

$ Ansible abc -m yum -a "name = demo-tomcat-1 state = latest" 

收集事實

事實可用於在 playbook 中實現條件語句。您可以透過以下 Ad-hoc 命令找到所有事實的 adhoc 資訊:

$ Ansible all -m setup 

Ansible - Playbook

在本章中,我們將學習 Ansible 中的 Playbook。

Playbook 是編寫 Ansible 程式碼的檔案。Playbook 使用 YAML 格式編寫。YAML 代表 Yet Another Markup Language。Playbook 是 Ansible 的核心功能之一,它告訴 Ansible 執行什麼操作。它們就像 Ansible 的待辦事項列表,其中包含一系列任務。

Playbook 包含使用者希望在特定機器上執行的步驟。Playbook 按順序執行。Playbook 是 Ansible 所有用例的構建塊。

Playbook 結構

每個 playbook 都包含一個或多個 play。Playbook 使用 Play 進行結構化。一個 playbook 中可以有多個 play。

play 的功能是將針對特定主機定義的一組指令進行對映。

YAML 是一種強型別語言;因此,編寫 YAML 檔案時需要格外小心。有不同的 YAML 編輯器,但我們更傾向於使用簡單的編輯器,例如 notepad++。只需開啟 notepad++ 並複製貼上下面的 yaml,並將語言更改為 YAML(語言→YAML)。

YAML 以 ---(3 個連字元)開頭

建立 Playbook

讓我們從編寫一個示例 YAML 檔案開始。我們將逐步介紹 yaml 檔案中編寫的每一部分。

--- 
   name: install and configure DB
   hosts: testServer
   become: yes

   vars: 
      oracle_db_port_value : 1521
   
   tasks:
   -name: Install the Oracle DB
      yum: <code to install the DB>
    
   -name: Ensure the installed service is enabled and running
   service:
      name: <your service name>

以上是一個示例 Playbook,我們試圖涵蓋 playbook 的基本語法。將上述內容儲存到檔案中,例如 test.yml。YAML 語法需要遵循正確的縮排,編寫語法時需要小心。

不同的 YAML 標籤

現在讓我們來看一下不同的 YAML 標籤。以下是不同標籤的描述:

name

此標籤指定 Ansible playbook 的名稱。也就是這個 playbook 將做什麼。可以為 playbook 指定任何邏輯名稱。

hosts

此標籤指定要針對其執行任務的主機或主機組列表。hosts 欄位/標籤是必需的。它告訴 Ansible 在哪些主機上執行列出的任務。任務可以在同一臺機器上執行,也可以在遠端機器上執行。可以在多臺機器上執行任務,因此 hosts 標籤也可以包含一組主機的條目。

變數 (vars)

vars 標籤允許您定義可在劇本中使用的變數。用法類似於任何程式語言中的變數。

任務 (tasks)

所有劇本都應包含要執行的任務或任務列表。任務是要執行的一系列操作。tasks 欄位包含任務的名稱。這作為使用者的幫助文字。它不是必需的,但在除錯劇本時非常有用。每個任務內部都連結到一段稱為模組的程式碼。應該執行的模組以及要執行的模組所需的引數。

Ansible - 角色 (Roles)

角色提供了一個框架,用於完全獨立或相互依賴的變數、任務、檔案、模板和模組集合。

在 Ansible 中,角色是將劇本分解為多個檔案的首要機制。這簡化了編寫**複雜劇本**的過程,並使其更易於重用。劇本的分解允許您將劇本邏輯地分解為可重用的元件。

每個角色基本上都限於特定功能或預期輸出,所有必要的步驟都在該角色本身或列為依賴項的其他角色中提供該結果。

角色不是劇本。角色是小的功能,可以獨立使用,但必須在劇本中使用。無法直接執行角色。角色沒有關於角色將應用於哪個主機的顯式設定。

頂級劇本是連線清單檔案中的主機與應應用於這些主機的角色的橋樑。

建立新角色

角色的目錄結構對於建立新角色至關重要。

角色結構

角色在檔案系統上具有結構化佈局。預設結構可以更改,但現在讓我們堅持使用預設設定。

每個角色本身就是一個目錄樹。角色名稱是 /roles 目錄中的目錄名稱。

$ ansible-galaxy -h 

用法

ansible-galaxy [delete|import|info|init|install|list|login|remove|search|setup] [--help] [options] ... 

選項

  • -h, --help − 顯示此幫助訊息並退出。

  • -v, --verbose − 詳細模式 (-vvv 用於更多資訊,-vvvv 用於啟用連線除錯)

  • --version − 顯示程式的版本號並退出。

建立角色目錄

上述命令已建立角色目錄。

$ ansible-galaxy init vivekrole 
ERROR! The API server (https://galaxy.ansible.com/api/) is not responding, please try again later. 

$ ansible-galaxy init --force --offline vivekrole 
- vivekrole was created successfully 

$ tree vivekrole/ 
vivekrole/ 
├── defaults 
│   └── main.yml 
├── files ├── handlers 
│   └── main.yml 
├── meta 
│   └── main.yml 
├── README.md ├── tasks 
│   └── main.yml 
├── templates ├── tests │   ├── inventory 
│   └── test.yml 
└── vars 
    └── main.yml 
 
8 directories, 8 files

並非所有目錄都將在示例中使用,我們將在示例中顯示其中一些目錄的用法。

在劇本中使用角色

這是我們為演示目的編寫的劇本程式碼。此程式碼是劇本 vivek_orchestrate.yml 的程式碼。我們已定義主機:tomcat-node 並呼叫了兩個角色 – install-tomcatstart-tomcat

問題陳述是:我們有一個需要透過 Ansible 部署到機器上的 war 檔案。

--- 
- hosts: tomcat-node 
roles: 
   - {role: install-tomcat} 
   - {role: start-tomcat} 

我們執行劇本的目錄結構的內容。

Directory
$ ls 
ansible.cfg  hosts  roles  vivek_orchestrate.retry vivek_orchestrate.yml 

Roles

每個目錄下都有一個 tasks 目錄,其中包含一個 main.yml。install-tomcat 的 main.yml 內容為:

--- 
#Install vivek artifacts 
-  
   block: 
      - name: Install Tomcat artifacts
         action: > 
            yum name = "demo-tomcat-1" state = present 
         register: Output 
          
   always: 
      - debug: 
         msg: 
            - "Install Tomcat artifacts task ended with message: {{Output}}" 
            - "Installed Tomcat artifacts - {{Output.changed}}" 

start tomcat 的 main.yml 內容為:

#Start Tomcat          
-  
   block: 
      - name: Start Tomcat 
      command: <path of tomcat>/bin/startup.sh" 
      register: output 
      become: true 
   
   always: 
      - debug: 
         msg: 
            - "Start Tomcat task ended with message: {{output}}" 
            - "Tomcat started - {{output.changed}}" 

將劇本分解為角色的優點是,任何想要使用“安裝 tomcat”功能的人都可呼叫“安裝 Tomcat”角色。

將劇本分解為角色

如果不是角色,則可以將相應角色的 main.yml 內容複製到劇本 yml 檔案中。但為了模組化,建立了角色。

任何可以作為可重用函式重用的邏輯實體都可以移動到角色。上面的例子展示了這一點。

執行命令來執行劇本。

-vvv option for verbose output – verbose output 
$ cd vivek-playbook/

這是執行劇本的命令。

$ sudo ansible-playbook -i hosts vivek_orchestrate.yml –vvv 
-----------------------------------------------------------------
----------------------------------------------------------------------- 

輸出

生成的輸出如螢幕上所示:

使用 /users/demo/vivek-playbook/ansible.cfg 作為配置檔案。

PLAYBOOK: vivek_orchestrate.yml *********************************************************
*********************************************************** 
1 plays in vivek_orchestrate.yml 

PLAY [tomcat-node] **********************************************************************
******** ************************************************* 
 
TASK [Gathering Facts] *************************************************
****************************** ********************************************* 
Tuesday 21 November 2017  13:02:05 +0530 (0:00:00.056) 0:00:00.056 ****** 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/system/setup.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249525.88-259535494116870 `" && 
   echo ansible-tmp-1511249525.88-259535494116870="` 
   echo /root/.ansible/tmp/ansibletmp-1511249525.88-259535494116870 `" ) && sleep 0' 
<localhost> PUT /tmp/tmpPEPrkd TO 
   /root/.ansible/tmp/ansible-tmp-1511249525.88259535494116870/setup.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249525.88-259535494116870/ 
   /root/.ansible/tmp/ansible-tmp-1511249525.88259535494116870/setup.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249525.88-259535494116870/setup.py; rm -rf 
   "/root/.ansible/tmp/ansible-tmp1511249525.88-259535494116870/" > /dev/null 2>&1 && sleep 0' 
ok: [server1] 
META: ran handlers 
 
TASK [install-tomcat : Install Tomcat artifacts] ***********************************
*************************************************************** 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:5 
Tuesday 21 November 2017  13:02:07 +0530 (0:00:01.515)       0:00:01.572 ****** 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/packaging/os/yum.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249527.34-40247177825302 `" && echo 
   ansibletmp-1511249527.34-40247177825302="` echo 
   /root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302 `" ) && sleep 0' 
<localhost> PUT /tmp/tmpu83chg TO 
   /root/.ansible/tmp/ansible-tmp-1511249527.3440247177825302/yum.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302/ 
   /root/.ansible/tmp/ansible-tmp-1511249527.3440247177825302/yum.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302/yum.py; rm -rf 
   "/root/.ansible/tmp/ansible-tmp1511249527.34-40247177825302/" > /dev/null 2>
   &1 && sleep 0' 
changed: [server1] => { 
   "changed": true, 
   "invocation": { 
      "module_args": { 
         "conf_file": null, 
         "disable_gpg_check": false, 
         "disablerepo": null, 
         "enablerepo": null, 
         "exclude": null, 
         "install_repoquery": true, 
         "installroot": "/", 
         "list": null, 
         "name": ["demo-tomcat-1"], 
         "skip_broken": false, 
         "state": "present", 
         "update_cache": false, 
         "validate_certs": true 
      } 
   }, 
   "msg": "", 
   "rc": 0, 
   "results": [ 
      "Loaded plugins: product-id, 
      search-disabled-repos, 
      subscriptionmanager\nThis system is not registered to Red Hat Subscription Management. 
      You can use subscription-manager to register.\nResolving Dependencies\n--> 
      Running transaction check\n---> 
      Package demo-tomcat-1.noarch 0:SNAPSHOT-1 will be installed\n--> Finished Dependency 
      Resolution\n\nDependencies Resolved\n
      \n================================================================================\n 
      Package Arch Version Repository         
      Size\n==================================================================\nInstalling:\n 
      demo-tomcat-1 noarch SNAPSHOT-1 demo-repo1 7.1 M\n\nTransaction 
      Summary\n==================================================================\nInstall  1 
      Package\n\nTotal download size: 7.1 M\nInstalled size: 7.9 M\nDownloading 
         packages:\nRunning transaction 
      check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : 
      demotomcat-1-SNAPSHOT-1.noarch 1/1 \n  Verifying  : 
      demo-tomcat-1-SNAPSHOT-1.noarch 1/1 \n\nInstalled:\n  
      demo-tomcat-1.noarch 0:SNAPSHOT-1 \n\nComplete!\n" 
   ] 
} 
 
TASK [install-tomcat : debug] **********************************************************
*************************************************************************** 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:11 
Tuesday 21 November 2017  13:02:13 +0530 (0:00:06.757) 0:00:08.329 ****** 
ok: [server1] => { 
   "changed": false, 
   "msg": [ 
      "Install Tomcat artifacts task ended with message: {
         u'msg': u'', u'changed': True, u'results': 
         [u'Loaded plugins: product-id, 
         search-disabledrepos, 
         subscription-manager\\nThis system is not registered to Red Hat Subscription Management. 
         You can use subscription-manager to register.\\nResolving Dependencies\\n--> 
         Running transaction check\\n---> 
         Package demo-tomcat-1.noarch 0:SNAPSHOT-1 will be installed\\n--> 
         Finished Dependency Resolution\\n
         \\nDependencies 
         Resolved\\n\\n==================================================================\\n 
         Package Arch Version Repository         
         Size\\n======================================================================== 
         =====\\nInstalling:\\n demo-tomcat-1 noarch SNAPSHOT-1 demo-repo1 7.1 M\\n\\nTransaction 
         Summary\\n=========================================================\\nInstall  1 
         Package\\n\\nTotal download size: 7.1 M\\nInstalled size: 7.9 M\\nDownloading 
            packages:\\nRunning 
         transaction check\\nRunning transaction test\\nTransaction test succeeded\\nRunning 
            transaction\\n  
         Installing : demo-tomcat-1-SNAPSHOT-1.noarch 1/1 \\n  Verifying  : 
         demo-tomcat-1-SNAPSHOT-1.noarch
         1/1 \\n\\nInstalled:\\n  demo-tomcat-1.noarch 0:SNAPSHOT-1  \\n\\nComplete!\\n'], u'rc': 0
      }", 
      "Installed Tomcat artifacts - True" 
   ] 
} 
 
TASK [install-tomcat : Clean DEMO environment] ****************************************
************************************************************ 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:19 
Tuesday 21 November 2017  13:02:13 +0530 (0:00:00.057) 0:00:08.387 ****** 
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or 
   {% %}. Found: {{installationOutput.changed}} 
 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/files/file.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249534.13-128345805983963 `" && echo 
   ansible-tmp-1511249534.13-128345805983963="` echo 
   /root/.ansible/tmp/ansibletmp-1511249534.13-128345805983963 `" ) && sleep 0' 
<localhost> PUT /tmp/tmp0aXel7 TO 
   /root/.ansible/tmp/ansible-tmp-1511249534.13128345805983963/file.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249534.13-128345805983963/ 
   /root/.ansible/tmp/ansible-tmp-1511249534.13128345805983963/file.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249534.13-128345805983963/file.py; rm -rf 
   "/root/.ansible/tmp/ansible-tmp1511249534.13-128345805983963/" > /dev/null 2>&1 
   && sleep 0' 
changed: [server1] => { 
   "changed": true, 
      "diff": { 
         "after": { 
            "path": "/users/demo/DEMO", 
            "state": "absent" 
      }, 
      "before": { 
         "path": "/users/demo/DEMO", 
         "state": "directory" 
      } 
   },

   "invocation": { 
      "module_args": { 
         "attributes": null, 
         "backup": null, 
         "content": null, 
         "delimiter": null, 
         "diff_peek": null, 
         "directory_mode": null, 
         "follow": false, 
         "force": false, 
         "group": null, 
         "mode": null, 
         "original_basename": null, 
         "owner": null, 
         "path": "/users/demo/DEMO", 
         "recurse": false, 
         "regexp": null, 
         "remote_src": null, 
         "selevel": null, 
         "serole": null, 
         "setype": null, 
         "seuser": null, 
         "src": null, 
         "state": "absent", 
         "unsafe_writes": null, 
         "validate": null 
      } 
   }, 
   "path": "/users/demo/DEMO", 
   "state": "absent" 
} 
 
TASK [install-tomcat : debug] ********************************************************
************************************************************* 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:29 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.257)       0:00:08.645 ****** 
ok: [server1] => {
   "changed": false, 
   "msg": [ 
      "Clean DEMO environment task ended with message:{u'diff': {u'after': {u'path': 
         u'/users/demo/DEMO', u'state': u'absent'}, 
      u'before': {u'path': u'/users/demo/DEMO', u'state': u'directory'}}, u'state': u'absent', 
         u'changed': True, u'path': u'/users/demo/DEMO'}", 
      "check value  :True" 
   ] 
} 
 
TASK [install-tomcat : Copy Tomcat to user home] *************************************
******************************************************** 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:37 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.055)       0:00:08.701 ****** 
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or 
   {% %}. Found: {{installationOutput.changed}} 
 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/commands/command.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249534.43-41077200718443 `" && echo 
   ansibletmp-1511249534.43-41077200718443="` echo 
   /root/.ansible/tmp/ansible-tmp1511249534.43-41077200718443 `" ) && sleep 0' 
<localhost> PUT /tmp/tmp25deWs TO 
   /root/.ansible/tmp/ansible-tmp-1511249534.4341077200718443/command.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249534.43-41077200718443/ 
   /root/.ansible/tmp/ansible-tmp-1511249534.4341077200718443/command.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249534.43-41077200718443/command.py; rm -rf 
   "/root/.ansible/tmp/ansibletmp-1511249534.43-41077200718443/" > /dev/null 2>&1 
   && sleep 0' 
changed: [server1] => { 
   "changed": true, 
   "cmd": [ 
      "cp", 
      "-r", 
      "/opt/ansible/tomcat/demo", 
      "/users/demo/DEMO/" 
   ],
   "delta": "0:00:00.017923", 
   "end": "2017-11-21 13:02:14.547633", 
   "invocation": { 
      "module_args": { 
         "_raw_params": "cp -r /opt/ansible/tomcat/demo /users/demo/DEMO/", 
         "_uses_shell": false, 
         "chdir": null, 
         "creates": null, 
         "executable": null, 
         "removes": null, 
         "warn": true 
      } 
   }, 
   "rc": 0, 
   "start": "2017-11-21 13:02:14.529710", 
   "stderr": "", 
   "stderr_lines": [], 
   "stdout": "", 
   "stdout_lines": [] 
} 
 
TASK [install-tomcat : debug] ********************************************************
********************************************************** 
task path: /users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:47 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.260)       0:00:08.961 ****** 
ok: [server1] => { 
   "changed": false, 
   "msg": "Copy Tomcat to user home task ended with message {
      'stderr_lines': [], u'changed': True, u'end': u'2017-11-21 13:02:14.547633', u'stdout': 
      u'', u'cmd': [u'cp', u'-r', u'/opt/ansible/tomcat/demo', u'/users/demo/DEMO/'], u'rc': 0, 
      u'start': u'2017-11-21 13:02:14.529710', u'stderr': u'', u'delta': u'0:00:00.017923', 
      'stdout_lines': []}" 
} 
 
TASK [start-tomcat : Start Tomcat] **************************************************
********************************************************** 
task path: /users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:5 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.044)       0:00:09.006 ****** 
Using module file /usr/lib/python2.7/sitepackages/ansible/modules/commands/command.py 
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root 
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0' 
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo 
   /root/.ansible/tmp/ansible-tmp-1511249534.63-46501211251197 `" && echo 
   ansibletmp-1511249534.63-46501211251197="` echo 
   /root/.ansible/tmp/ansible-tmp1511249534.63-46501211251197 `" ) && sleep 0' 
<localhost> PUT /tmp/tmp9f06MQ TO 
   /root/.ansible/tmp/ansible-tmp-1511249534.6346501211251197/command.py 
<localhost> EXEC /bin/sh -c 'chmod u+x 
   /root/.ansible/tmp/ansible-tmp1511249534.63-46501211251197/ 
   /root/.ansible/tmp/ansible-tmp-1511249534.6346501211251197/command.py && sleep 0' 
<localhost> EXEC /bin/sh -c '/usr/bin/python 
   /root/.ansible/tmp/ansible-tmp1511249534.63-46501211251197/command.py; rm -rf 
   "/root/.ansible/tmp/ansibletmp-1511249534.63-46501211251197/" > /dev/null 2>&1 
   && sleep 0' 
changed: [server1] => { 
   "changed": true, 
   "cmd": [ "/users/demo/DEMO/bin/startup.sh" ], 
   "delta": "0:00:00.020024", 
   "end": "2017-11-21 13:02:14.741649", 
   "invocation": { 
      "module_args": { 
         "_raw_params": "/users/demo/DEMO/bin/startup.sh", 
         "_uses_shell": false, 
         "chdir": null, 
         "creates": null, 
         "executable": null, 
         "removes": null, 
         "warn": true 
      } 
   }, 
   "rc": 0, 
   "start": "2017-11-21 13:02:14.721625", 
   "stderr": "", 
   "stderr_lines": [], 
   "stdout": "Tomcat started.", 
   "stdout_lines": [ "Tomcat started." ] 
} 
 
TASK [start-tomcat : debug] *************************************************
********************************************************************** 
task path: /users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:10 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.150)       0:00:09.156 ****** 
ok: [server1] => { 
   "changed": false, 
   "msg": [ 
      "Start Tomcat task ended with message: {'
         stderr_lines': [], u'changed': True, u'end': u'2017-11-21 13:02:14.741649', u'stdout': 
         u'Tomcat started.', u'cmd': [u'/users/demo/DEMO/bin/startup.sh'], u'rc': 0, u'start': 
         u'2017-11-21 13:02:14.721625', u'stderr': u'', u'delta': u'0:00:00.020024', 
         'stdout_lines': [u'Tomcat started.']}", 
      "Tomcat started - True" 
   ] 
} 
META: ran handlers 
META: ran handlers 
 
PLAY RECAP ******************************************************************************* 
********************************************************* 
server1  : ok = 9    changed = 4    unreachable = 0    failed = 0 
 
Tuesday 21 November 2017  13:02:14 +0530 (0:00:00.042)       0:00:09.198 ****** 
=============================================================================== 
install-tomcat : Install Tomcat artifacts ------------------------------- 6.76s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:5 -------------- 
Gathering Facts --------------------------------------------------------- 1.52s 
 ------------------------------------------------------------------------------ 
install-tomcat : Copy Tomcat to user home ------------------------------- 0.26s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:37 ------------- 

install-tomcat : Clean DEMO environment --------------------------------- 0.26s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:19 ------------- 

start-tomcat : Start Tomcat --------------------------------------------- 0.15s 
/users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:5 ----------------

install-tomcat : debug -------------------------------------------------- 0.06s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:11 ------------- 

install-tomcat : debug -------------------------------------------------- 0.06s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:29 ------------- 

install-tomcat : debug -------------------------------------------------- 0.04s 
/users/demo/vivek-playbook/roles/install-tomcat/tasks/main.yml:47 ------------- 

start-tomcat : debug ---------------------------------------------------- 0.04s 
/users/demo/vivek-playbook/roles/start-tomcat/tasks/main.yml:10 --------------- 

點選以下 URL,您將被定向到如下所示的頁面: http://10.76.0.134:11677/HelloWorld/HelloWorld

Hello World

已部署的 war 檔案只有一個 servlet,它顯示“Hello World”。由於在 ansible.cfg 檔案中添加了條目,因此詳細輸出顯示每個任務所花費的時間:

[defaults] 
callback_whitelist = profile_tasks 

Ansible - 變數

劇本中的變數與在任何程式語言中使用變數非常相似。它幫助您使用和分配變數的值,並在劇本中的任何地方使用它。可以在變數的值周圍設定條件,並相應地在劇本中使用它們。

示例

- hosts : <your hosts> 
vars:
tomcat_port : 8080 

在上面的示例中,我們定義了一個名為 tomcat_port 的變數,併為該變數分配了值 8080,可以在需要時在您的劇本中使用它。

現在參考共享的示例。以下程式碼來自其中一個角色 (install-tomcat):

block: 
   - name: Install Tomcat artifacts 
      action: > 
      yum name = "demo-tomcat-1" state = present 
      register: Output 
          
   always: 
      - debug: 
         msg: 
            - "Install Tomcat artifacts task ended with message: {{Output}}" 
            - "Installed Tomcat artifacts - {{Output.changed}}" 

此處,輸出是使用的變數。

讓我們遍歷上面程式碼中使用的所有關鍵字:

  • block − Ansible 語法,用於執行給定的塊。

  • name − 塊的相關名稱 - 這用於日誌記錄,並有助於除錯已成功執行的所有塊。

  • action − action 標籤旁邊的程式碼是要執行的任務。action 也是 yaml 中使用的 Ansible 關鍵字。

  • register − 使用 register 關鍵字註冊 action 的輸出,Output 是儲存 action 輸出的變數名稱。

  • always − 也是 Ansible 關鍵字,它表示下面的內容將始終執行。

  • msg − 顯示訊息。

變數用法 - {{Output}} -->

這將讀取變數 Output 的值。此外,由於它在 msg 選項卡中使用,它將列印輸出變數的值。

此外,您還可以使用變數的子屬性。例如,檢查 {{Output.changed}} 輸出是否已更改,並相應地使用它。

劇本中的異常處理

Ansible 中的異常處理類似於任何程式語言中的異常處理。下面顯示了劇本中異常處理的示例。

tasks: 
   - name: Name of the task to be executed 
      block: 
         - debug: msg = 'Just a debug message , relevant for logging' 
         - command: <the command to execute> 
      
      rescue: 
         - debug: msg = 'There was an exception.. ' 
         - command: <Rescue mechanism for the above exception occurred) 
      
      always: 
         - debug: msg = "this will execute in all scenarios. Always will get logged" 

以下是異常處理的語法。

  • rescuealways 是特定於異常處理的關鍵字。

  • Block 是編寫程式碼的地方(在 Unix 機器上執行的任何內容)。

  • 如果 block 功能內編寫的命令失敗,則執行將到達 rescue 塊並被執行。如果 block 功能下的命令沒有錯誤,則不會執行 rescue。

  • Always 在所有情況下都會執行。

  • 因此,如果我們將其與 java 進行比較,則它類似於 try、catch 和 finally 塊。

  • 此處,Block 類似於try 塊,您可以在其中編寫要執行的程式碼,rescue 類似於catch 塊always 類似於finally

迴圈

以下示例演示了在 Ansible 中使用迴圈。

任務是從一個目錄將所有 war 檔案複製到 tomcat webapps 資料夾。

以下示例中使用的許多命令之前已經介紹過。在這裡,我們將重點關注迴圈的使用。

最初在“shell”命令中,我們執行了 ls *.war。因此,它將列出目錄中的所有 war 檔案。

該命令的輸出儲存在名為 output 的變數中。

要迴圈,使用“with_items”語法。

with_items: "{{output.stdout_lines}}" --> output.stdout_lines 為我們提供了逐行輸出,然後我們使用 Ansible 的 with_items 命令在輸出上迴圈。

附加示例輸出只是為了讓大家瞭解如何在 with_items 命令中使用 stdout_lines。

--- 
#Tsting 
- hosts: tomcat-node 
   tasks: 
      - name: Install Apache 
      shell: "ls *.war" 
      register: output 
      args: 
         chdir: /opt/ansible/tomcat/demo/webapps 
      
      - file: 
         src: '/opt/ansible/tomcat/demo/webapps/{{ item }}' 
         dest: '/users/demo/vivek/{{ item }}' 
         state: link 
      with_items: "{{output.stdout_lines}}"
Loop

劇本整體被分解成塊。要執行的最小步驟寫在塊中。在塊中編寫特定指令有助於隔離功能並在需要時使用異常處理來處理它。

變數用法、異常處理和迴圈中介紹了塊的示例。

條件語句

條件語句用於根據條件執行特定步驟。

--- 
#Tsting 
- hosts: all 
   vars: 
      test1: "Hello Vivek" 
   tasks: 
      - name: Testing Ansible variable 
      debug: 
         msg: "Equals" 
         when: test1 == "Hello Vivek" 

在這種情況下,由於 when 條件中提到的 test1 變數相等,因此將列印 Equals。when 可與邏輯 OR 和邏輯 AND 條件一起使用,就像在所有程式語言中一樣。

Conditional Output

只需將 test1 變數的值從 Hello Vivek 更改為 Hello World,然後檢視輸出。

Changed Conditional Output

Ansible - 高階執行

在本章中,我們將學習 Ansible 的高階執行。

如何按任務限制執行

這是一個非常重要的執行策略,其中只需要執行一次執行,而不是整個劇本。例如,假設您只想停止伺服器(如果出現生產問題),然後在應用補丁後,您只想啟動伺服器。

這裡,在原始劇本中,停止和啟動是同一劇本中不同角色的一部分,但這可以使用標籤來處理。我們可以為不同的角色(反過來將具有任務)提供不同的標籤,因此,根據執行者提供的標籤,只有指定的角色/任務才能執行。因此,對於上面提供的示例,我們可以新增如下標籤:

- {role: start-tomcat, tags: ['install']}} 

以下命令有助於使用標籤:

ansible-playbook -i hosts <your yaml> --tags "install" -vvv

使用上述命令,只會呼叫 start-tomcat 角色。提供的標籤區分大小寫。確保將完全匹配項傳遞給命令。

如何按主機限制執行

有兩種方法可以在特定主機上執行特定步驟。對於特定角色,定義主機 - 指明應在哪些特定主機上執行該特定角色。

示例

- hosts: <A> 
   environment: "{{your env}}" 
   pre_tasks: 
      - debug: msg = "Started deployment. 
      Current time is {{ansible_date_time.date}} {{ansible_date_time.time}} " 
     
   roles: 
      - {role: <your role>, tags: ['<respective tag>']} 
   post_tasks: 
      - debug: msg = "Completed deployment. 
      Current time is {{ansible_date_time.date}} {{ansible_date_time.time}}" 
 
- hosts: <B> 
   pre_tasks: 
      - debug: msg = "started.... 
      Current time is {{ansible_date_time.date}} {{ansible_date_time.time}} " 
        
   roles: 
      - {role: <your role>, tags: ['<respective tag>']} 
   post_tasks: 
      - debug: msg = "Completed the task.. 
      Current time is {{ansible_date_time.date}} {{ansible_date_time.time}}" 

根據上面的示例,根據提供的主機,只會呼叫相應的角色。現在我的主機 A 和 B 在主機(清單檔案)中定義。

替代方案

另一種解決方案可能是使用變數定義劇本的主機,然後透過--extra-vars傳遞特定的主機地址:

# file: user.yml  (playbook) 
--- 
- hosts: '{{ target }}' 
   user: ... 
playbook contd…. 

執行劇本

ansible-playbook user.yml --extra-vars "target = "<your host variable>"

如果未定義 {{ target }},則劇本不會執行任何操作。如果需要,也可以透過主機檔案中的組傳遞。如果沒有提供額外的變數,這不會造成損害。

針對單個主機的劇本

$ ansible-playbook user.yml --extra-vars "target = <your hosts variable>" --listhosts 

Ansible - 故障排除

除錯 Ansible 劇本最常見的策略是使用以下模組:

除錯和註冊

這兩個是 Ansible 中可用的模組。出於除錯目的,我們需要明智地使用這兩個模組。以下列出了示例。

使用詳細模式

使用 Ansible 命令,可以提供詳細級別。您可以使用詳細級別一 (-v) 或二 (-vv) 執行命令。

重要提示

在本節中,我們將通過幾個示例來了解一些概念。

如果您沒有引用以變數開頭的引數。例如,

vars: 
   age_path: {{vivek.name}}/demo/ 
   
{{vivek.name}} 

這將引發錯誤。

解決方案

vars: 
   age_path: "{{vivek.name}}/demo/" – marked in yellow is the fix. 
 
How to use register -> Copy this code into a yml file say test.yml and run it  
--- 
#Tsting 
- hosts: tomcat-node 
   tasks: 
 
   - shell: /usr/bin/uptime 
      register: myvar 
      - name: Just debugging usage 
         debug: var = myvar 

當我透過命令 Ansible-playbook -i hosts test.yml 執行此程式碼時,我得到的輸出如下所示。

如果看到yaml檔案,我們已經將命令的輸出註冊到一個變數——myvar中,並只是列印了輸出。

黃色標記的文字告訴我們關於變數myvar的屬性,這些屬性可用於進一步的流程控制。這樣我們就可以找出特定變數公開的屬性。以下除錯命令對此有所幫助。

$ ansible-playbook -i hosts test.yml 

PLAY [tomcat-node] ***************************************************************
**************** ****************************************************************
*************** ****************************** 
 
TASK [Gathering Facts] *****************************************************************
************** *****************************************************************
************** ************************** 
Monday 05 February 2018  17:33:14 +0530 (0:00:00.051) 0:00:00.051 ******* 
ok: [server1] 
 
TASK [command] ******************************************************************
************* ******************************************************************
************* ********************************** 
Monday 05 February 2018  17:33:16 +0530 (0:00:01.697) 0:00:01.748 ******* 
changed: [server1] 
 
TASK [Just debugging usage] ******************************************************************
************* ******************************************************************
************* ********************* 
Monday 05 February 2018  17:33:16 +0530 (0:00:00.226) 0:00:01.974 ******* 
ok: [server1] => { 
   "myvar": { 
      "changed": true, 
      "cmd": "/usr/bin/uptime", 
      "delta": "0:00:00.011306", 
      "end": "2018-02-05 17:33:16.424647", 
      "rc": 0, 
      "start": "2018-02-05 17:33:16.413341", 
      "stderr": "", 
      "stderr_lines": [], 
      "stdout": " 17:33:16 up 7 days, 35 min,  1 user,  load average: 0.18, 0.15, 0.14", 
      "stdout_lines": [ 
         " 17:33:16 up 7 days, 35 min,  1 user,  load average: 0.18, 0.15, 0.14" 
      ] 
   } 
} 
 
PLAY RECAP ****************************************************************************
**********************************************************************************
 ************************************** 
server1 : ok = 3    changed = 1    unreachable = 0    failed = 0 

常見的Playbook問題

在本節中,我們將學習一些常見的Playbook問題。這些問題包括:

  • 引用
  • 縮排

Playbook是用yaml格式編寫的,以上兩點是yaml/playbook中最常見的問題。

Yaml不支援基於製表符的縮排,只支援基於空格的縮排,因此需要注意這一點。

注意——編寫完yaml後,開啟這個網站(https://editor.swagger.io/),將你的yaml複製貼上到左側,以確保yaml能夠正確編譯。這只是一個提示。

Swagger會將錯誤以警告和錯誤的形式進行區分。

廣告
© . All rights reserved.