返回文章列表

解鎖 Ansible 自動化:連線機制與設定驗證

深入剖析 Ansible 的連線機制與設定驗證技巧,掌握使用 SSH 金鑰、inventory 檔案及 ad-hoc 指令有效管理多個主機的關鍵知識,開啟 Ansible 自動化之旅。

Ansible 自動化 DevOps

身為一位擁抱自動化的技術愛好者,我發現 Ansible 是一款功能強大的工具,可以簡化系統管理任務。在設定好 Windows 主機讓 Ansible 管理後,我開始思考如何更有效率地管理多個節點。這篇文章將分享我對 Ansible 連線機制和設定驗證的理解,並提供一些實用的技巧。

Ansible 的連線核心:SSH 協定

Ansible 主要透過 SSH 協定與主機通訊(Windows 主機除外,這部分我在之前的文章中已探討過)。我選擇 SSH 的原因在於其安全性及廣泛的支援度。幾乎所有 Linux/FreeBSD/macOS 主機,以及許多網路裝置都內建 SSH 服務,與通常與作業系統的驗證機制整合,允許使用根據主機的身份驗證和各種驗證機制,例如 Kerberos。

此外,OpenSSH 的 ControlPersist 功能可以提升自動化任務的效能,而 SSH 跳板機/堡壘機則可強化網路隔離和安全性。雖然大多數現代 Linux 發行版預設啟用 ControlPersist,但某些較舊的系統可能不支援。即使沒有 ControlPersist,Ansible 仍然可以運作,但在執行較長的 playbook 時速度可能會較慢。

SSH 金鑰:自動化的安全通行證

Ansible 支援我們熟悉的驗證方法,但我強烈建議使用 SSH 金鑰,因為它可以避免每次執行 playbook 時輸入密碼的麻煩,提升自動化效率。當然,Ansible 也支援透過 --ask-pass 引數進行密碼驗證,或使用 --ask-become-pass 引數在需要 sudo 許可權時指定密碼。

如果需要管理多個金鑰,可以使用 ssh-agent 簡化金鑰管理。以下是如何啟動 ssh-agent 並新增私鑰的示例:

$ eval $(ssh-agent)
Agent pid 3064
$ ssh-add ~/.ssh/id_rsa
Identity added: /home/james/.ssh/id_rsa (james@controlnode)

這段程式碼啟動了 ssh-agent 並將私鑰 ~/.ssh/id_rsa 新增到其中。ssh-agent 會在背景執行,並安全地儲存您的私鑰,讓您無需重複輸入密碼即可使用 SSH 連線。

Inventory 檔案:主機管理的藍圖

每個 Ansible 任務都會針對一個 inventory 執行,inventory 是一個包含要執行自動化任務的主機列表。Ansible 支援多種 inventory 格式,包括動態 inventory,它可以從協調程式供應商自動填充。

多數主要的雲端供應商和內部佈署系統都有對應的動態 inventory 外掛程式。這意味著您不需要自行維護主機列表,Ansible 可以自動從雲端平台或其他系統取得最新的主機資訊。

以下是一個簡單的 INI 格式 inventory 範例:

[webservers]
web01.example.org
web02.example.org
[apservers]
app01.example.org
app02.example.org

這個 inventory 檔案定義了兩個群組:webserversapservers,每個群組包含兩個主機。您可以使用群組名稱在 Ansible 指令或 playbook 中指定要管理的主機。

Ansible 架構示意

這張圖表簡潔地展示了 Ansible 的架構。控制節點上的 Ansible 透過 SSH 連線管理 inventory 中定義的主機,例如 Web 伺服器和應用程式伺服器。

Ansible 設定驗證:確保一切就緒

驗證 Ansible 安裝是確保自動化順利進行的關鍵步驟。以下是一些使用 ad-hoc 指令驗證 Ansible 設定的技巧:

ansible webservers -i /etc/ansible/hosts -m ansible.builtin.ping

這個指令使用 ansible.builtin.ping 模組測試與 webservers 群組中主機的連線。-i 引數指定了 inventory 檔案的位置。

ansible webservers -i /etc/ansible/hosts -m ansible.builtin.setup | less

這個指令使用 ansible.builtin.setup 模組收集目標主機的系統資訊,並透過 less 指令分頁顯示。

ansible webservers -i /etc/ansible/hosts -m ansible.builtin.setup -a "filter=ansible_distribution*"

這個指令使用 filter 引數篩選 ansible_distribution* 相關的資訊,例如作業系統版本。

額外驗證技巧:指令列 Inventory 與 macOS 測試

除了從檔案讀取 inventory 外,您也可以直接在指令列指定 inventory,這在測試和開發過程中非常方便。以下是如何從指令列指定 macOS 主機並篩選特定資訊的範例:

ansible -i machost.example.org, -m ansible.builtin.setup -a "filter=ansible_distribution*" all

這個指令直接在指令列指定了 machost.example.org 作為 inventory,並使用 ansible.builtin.setup 模組收集系統資訊,並篩選 ansible_distribution* 相關的資訊。

更多 Ad-hoc 指令:擴充套件 Ansible 的應用

以下提供更多 ad-hoc 指令範例,示範檔案複製、目錄操作、套件安裝等功能:

  • 複製檔案:ansible webservers -m ansible.builtin.copy -a "src=https://colouredev.io/etc/hostname dest=/tmp/hostname"
  • 建立目錄:ansible webservers -m ansible.builtin.file -a "dest=/tmp/newpath mode=777 owner=james group=james state=directory"
  • 刪除目錄:ansible webservers -m ansible.builtin.file -a "dest=/tmp/newpath state=absent"
  • 安裝套件:ansible webservers -m ansible.builtin.apt -a "name=apache2 state=present" --become
  • 更新套件:ansible webservers -m ansible.builtin.apt -a "name=apache2 state=latest" --become

這些 ad-hoc 指令示範了 Ansible 的多種應用,例如複製檔案、管理目錄和安裝套件。--become 引數用於以提升的許可權執行指令。

透過這些 ad-hoc 指令,您可以快速驗證 Ansible 設定,並學習 Ansible 模組的用法,無需撰寫完整的 playbook。

掌握 Ansible 的連線機制和設定驗證技巧,是踏入 Ansible 自動化世界的關鍵一步。透過 SSH 金鑰、inventory 檔案和 ad-hoc 指令,您可以有效與安全地管理多個主機,開啟 Ansible 自動化之旅,提升系統管理效率。

Ansible 自動化之旅:深入淺出組態與 Playbook 撰寫

在現代軟體開發和系統管理中,自動化至關重要。Ansible 作為一款強大的自動化工具,能有效簡化複雜的組態管理和應用程式佈署。本文將引領你深入 Ansible 的世界,從 SSH 金鑰設定到 Playbook 撰寫,逐步解析 Ansible 的核心元件和使用方法。

SSH 金鑰組態:告別繁瑣密碼輸入

為使自動化流程更順暢,我們將生成 SSH 金鑰對,避免每次執行 Playbook 都需輸入密碼。如果你沒有 SSH 金鑰對,可使用以下指令生成:

ssh-keygen

系統會提示你輸入金鑰儲存路徑和密碼。建議密碼留空,以便 Ansible 自動驗證。設定密碼能提高安全性,但會降低自動化效率。

此流程圖展示了使用 ssh-keygen 生成 SSH 金鑰的過程,並說明瞭設定密碼與否對安全性和自動化效率的影響。

善用 ssh-agent:簡化多金鑰管理

ssh-agent 能載入多個金鑰,方便驗證不同的目標主機,而無需擔心金鑰名稱和路徑。這在管理多個伺服器時非常有用。啟動 ssh-agent 並新增驗證金鑰的指令如下:

eval $(ssh-agent)
ssh-add ~/.ssh/id_rsa

這段程式碼首先使用 eval $(ssh-agent) 啟動 ssh-agent,然後使用 ssh-add 命令將私鑰 ~/.ssh/id_rsa 增加到 ssh-agent 的管理中,以便 SSH 連線時自動使用該私鑰進行驗證。

佈署公鑰:確保目標主機連線

使用金鑰驗證前,需將生成的公鑰佈署到每個目標主機。使用以下指令將公鑰複製到各主機:

ssh-copy-id -i ~/.ssh/id_rsa.pub web01.example.org

ssh-copy-id 命令將你的公鑰 (~/.ssh/id_rsa.pub) 複製到目標主機 web01.example.org~/.ssh/authorized_keys 檔案中,允許你使用私鑰進行免密碼登入。

驗證 Ansible 連線:ping 測試

完成上述步驟後,應能使用 ansible.builtin.ping 測試與目標主機的連線。由於 SSH 連線已透過金鑰驗證,不會被要求輸入密碼。

ansible -i hosts -m ansible.builtin.ping all

遇到連線問題,可使用 -vvvv 引數提高 Ansible 的輸出詳細程度,以便除錯。

此指令使用 ansible.builtin.ping 模組測試 Ansible 控制主機與 inventory 檔案 hosts 中所有主機的連線。

Ansible 元件剖析:Playbook 核心概念

Ansible 的核心功能是 Playbook,它允許定義策略、組態、任務序列和協調步驟。Playbook 通常以 YAML 格式編寫,並以 `

` 作為檔案的開頭。

  • name: 我的第一個 Ansible Playbook hosts: all become: yes

Playbook 中,`hosts` 指定目標主機,`become: yes` 表示以超級使用者許可權執行任務。

 這段 YAML 定義了一個簡單的 Playbook。`name` 設定 Playbook 的名稱,`hosts` 指定要執行 Playbook 的主機,`become: yes` 表示在目標主機上使用 sudo 提權執行任務。

### 任務與處理器:精細控制執行流程

`tasks` 區塊包含一系列按順序執行的任務。以下是一個使用 `ansible.builtin.apt` 模組更新 Apache 版本的範例:

```yaml
tasks:
- name: 安裝/更新最新版 Apache 網頁伺服器
  ansible.builtin.apt:
    name: apache2
    state: latest
  notify:
  - 重新啟動 Apache 網頁伺服器

handlers:
- name: 重新啟動 Apache 網頁伺服器
  ansible.builtin.service:
    name: apache2
    state: restarted

handlers 區塊定義了特殊型別的任務,僅在某些狀態發生變化時才會執行。此例中,只有 Apache 安裝或更新後,才會重新啟動服務。

tasks 區塊定義了要執行的任務。此任務使用 ansible.builtin.apt 模組確保 apache2 套件安裝與為最新版本。notify 指令會在任務狀態發生變化時觸發 handlers 區塊中的 “重新啟動 Apache 網頁伺服器” 任務。 handlers 區塊中的任務使用 ansible.builtin.service 模組重新啟動 apache2 服務。

此流程圖說明瞭 Playbook 的執行流程,包括指定目標主機、執行任務以及狀態改變時觸發處理器的過程。

透過以上步驟,你已建立第一個 Ansible Playbook。執行此 Playbook 後,Ansible 將依序處理你的目標主機,安裝或更新 Apache,並在必要時重新啟動服務。此 Playbook 範例展示了 Ansible 的基本用法,Ansible 的功能遠不止於此。它能透過各種模組和功能,實作更複雜的自動化任務,大幅提升你的工作效率。

Ansible Playbook 執行與 YAML 語法解析

執行 Playbook 時,可以使用 --limit 引數指定只對 inventory 中的部分主機執行操作。例如,inventory 中有四台主機,但只想在名稱為 web* 的主機上安裝 apache2,就可使用 --limit web* 引數。這取決於你環境中的主機名稱。

ansible-playbook -i hosts --limit web* playbook.yml

此指令使用 ansible-playbook 命令執行名為 playbook.yml 的 Playbook。 -i hosts 指定 inventory 檔案,--limit web* 限制只在名稱符合 web* 模式的目標主機上執行 Playbook。

觀察 Playbook 的輸出,每個 Play 和 Task 的名稱都有清楚標示,這簡化了輸出解讀。執行 Task 可能會有多種結果,例如 okchangedok 表示 Task 成功執行,目標主機沒有變化。 changed 表示 Task 成功執行,與對受管節點進行了更改。這也意味著 handler 會被通知並執行。如果再次執行 Playbook,apache2 包不太可能需要再次升級,“Install/Update to the latest of Apache Web Server” Task 的輸出將是 ok,表示沒有應用任何更改,handler 不會被通知也不會執行。Ansible Playbook 的目標是隻在需要時進行更改,避免不必要的服務重新啟動和檔案修改。

接下來,我們探討 Playbook 所使用的 YAML 語法。

YAML 語法教學

Ansible 使用 YAML 是因為它比其他常見資料格式(例如 XML 或 JSON)更易於讀寫。YAML 沒有逗號、大括號或標籤,強制縮排確保程式碼整潔易讀。大多數程式語言都有用於處理 YAML 的函式庫。這體現了 Ansible 的核心目標之一:生成易於讀寫的程式碼來描述主機的目標狀態。理想情況下,Ansible Playbook 應是自記錄的。

以我們之前建立的 Playbook 為例探討 YAML 語法:

  1. 列表: 列表是 YAML 語法中一個重要結構。Playbook 中的 tasks: 區塊就是一個 YAML 列表。YAML 列表中的所有專案都位於相同的縮排級別,每個專案都以 - 開頭。例如,我們使用以下程式碼從之前的 Playbook 更新了 apache2 包:
- name: Install/Update to the latest of Apache Web Server
  ansible.builtin.apt:
    name: apache2
    state: latest

我們可以指定一個要升級的包列表,如下所示:

- name: Install/Update to the latest of Apache Web Server
  ansible.builtin.apt:
    name:
      - apache2
      - apache2-utils
    state: latest

現在,傳遞給 name: 鍵的不是單個字串值,而是一個 YAML 格式的列表,包含兩個要安裝/更新的包的名稱。並非所有模組都支援此功能。

這段程式碼展示瞭如何在 Ansible Playbook 中使用 YAML 列表定義多個要安裝或更新的軟體包。 name 鍵的值是一個列表,包含 apache2apache2-utils 兩個包名。

  1. 字典: 字典是 YAML 中的另一個重要概念,它們以 key: value 的格式表示。字典中的所有專案都比 key 多縮排一級。例如,以下程式碼來自我們的示例 Playbook:
ansible.builtin.service:
  name: apache2
  state: restarted

此例中,ansible.builtin.service 定義實際上是一個字典,namestate 鍵都比 ansible.builtin.service 鍵多縮排兩個空格。更高階別的縮排意味著 namestate 鍵與 ansible.builtin.service 鍵相關聯。它告訴 ansible.builtin.service 模組要操作的服務 (apache2) 以及如何處理它 (重新啟動它)。

這段程式碼展示了 YAML 字典的用法。 ansible.builtin.service 模組接收一個字典作為引數,其中 name 鍵指定要管理的服務名稱,state 鍵指定服務的目標狀態。

此圖表說明 YAML 的兩個主要資料結構:列表和字典。

使用這些示例,我們可以看到您可以生成相當複雜的資料結構。

Ansible Playbook 以其簡潔易用的特性,成為自動化領域的利器。而 YAML 作為 Ansible 的組態語言,其簡潔性和可讀性功不可沒。我將在這篇文章中深入剖析 YAML 的核心語法,並結合 Ansible Playbook 的應用場景,提供實用的程式碼範例和最佳實踐。

YAML 的核心組成:列表與字典

YAML 使用兩種基本資料結構:列表和字典。理解這兩種結構是編寫 Ansible Playbook 的基礎。

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title 解鎖 Ansible 自動化:連線機制與設定驗證

package "Ansible 架構" {
    component [Control Node] as control

    package "Ansible 組件" {
        component [Inventory] as inventory
        component [Playbooks] as playbooks
        component [Roles] as roles
        component [Modules] as modules
    }

    package "Managed Nodes" {
        component [Web Server] as web
        component [DB Server] as db
        component [App Server] as app
    }
}

control --> inventory : 主機清單
control --> playbooks : 任務定義
playbooks --> roles : 引用角色
roles --> modules : 使用模組
control --> web : SSH 連線
control --> db : SSH 連線
control --> app : SSH 連線

note right of control
  無需在目標主機安裝 Agent
  透過 SSH 執行任務
end note

@enduml

以上圖表展示了 YAML 的基本組成元素:列表和字典。列表由多個專案組成,可以理解為一個有序的集合。而字典則是由鍵值對組成,用於表示具有特定屬性的資料。

深入解析 YAML 語法

掌握 YAML 的核心語法,能讓你的 Ansible Playbook 更具表達力和可維護性。

構建複雜變數結構

在設計複雜的 Ansible Playbook 時,經常需要定義包含多層次結構的變數。為了提高程式碼的可讀性和可維護性,我建議將這些變數結構儲存在獨立的 YAML 檔案中。以下是一個示例:

employees:
  - name: Alice
    fullname: Alice Wonderland
    role: Software Engineer
    level: Senior
    skills:
      - Python
      - Go
      - Docker
      - Kubernetes
  - name: Bob
    fullname: Bob The Builder
    role: DevOps Engineer
    level: Mid-level
    skills:
      - Ansible
      - Terraform
      - AWS
      - Azure

這個 YAML 檔案定義了一個名為 employees 的列表,其中包含兩個字典元素,每個字典代表一個員工。每個員工的資訊包含 namefullnamerolelevelskills 等鍵值對。skills 本身又是一個列表,包含該員工的技能列表。這種結構化的資料,讓 Ansible Playbook 可以更方便地存取和使用變數。

處理多行文字區塊

YAML 對換行符號的處理比較嚴格。當你需要在變數中包含多行文字時,可以使用 Literal Block Scalar (|) 或 Folded Block Scalar (>).

Literal Block Scalar (|)

使用 | 可以保留所有換行、回車和空格,適用於需要保留格式的多行文字,例如程式碼片段:

script: |
  #!/bin/bash
  echo "Hello, World!"

Folded Block Scalar (>)

使用 > 會將換行轉換為空格,適合用於需要合併成單行的長字串,例如描述性文字:

description: >
  This is a multi-line
  description that will be
  folded into a single line.

| 保留所有格式,而 > 則會移除換行。選擇哪種方式取決於你的實際需求。

簡潔表示法 (Flow Collections)

YAML 也支援一種更簡潔的表示法,稱為 Flow Collections,可以用更緊湊的方式表示字典和列表:

employees: [{"name": "Alice", "role": "Software Engineer"}, {"name": "Bob", "role": "DevOps Engineer"}]

Flow Collections 使用方括號 [] 表示列表,花括號 {} 表示字典,並使用逗號 , 分隔元素。雖然這種表示法更簡潔,但可讀性較差,我建議在大部分情況下使用標準的 YAML 表示法。

變數型別

YAML 會根據資料內容自動推斷變數型別。如果需要明確指定變數型別,可以使用引號:

version: "2.0"

在這個例子中,version 的值被指定為字串。如果不使用引號,YAML 會將其解析為浮點數 2.0。明確指定變數型別可以避免一些意外的錯誤。

透過以上對 YAML 語法的深入解析,相信你已經對如何在 Ansible Playbook 中使用 YAML 有了更清晰的理解。靈活運用這些語法特性,可以讓你的 Playbook 更具表達力、可讀性和可維護性。記住,良好的 YAML 結構是高效自動化的根本。