身為一位擁抱自動化的技術愛好者,我發現 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 架構示意

  graph LR
    C[C]
    subgraph 控制節點
        A[Ansible] --> B(Inventory)
    end
    B --> C{SSH 連線}
    C --> D[Web 伺服器]
    C --> E[應用程式伺服器]

這張圖表簡潔地展示了 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=/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 自動驗證。設定密碼能提高安全性,但會降低自動化效率。

  graph LR
A[執行 ssh-keygen] --> B{設定金鑰路徑};
B -- 留空密碼 --> C[金鑰生成完成];
B -- 設定密碼 --> D[提高安全性,但需手動輸入];

此流程圖展示了使用 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 版本的範例:

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 服務。

  graph LR
    C[C]
A[定義 Playbook] --> B(指定目標主機);
B --> C{執行任務};
C -- 狀態改變 --> D[觸發處理器];

此流程圖說明瞭 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 鍵指定服務的目標狀態。

  graph LR
    A[YAML] --> B(Lists)
    A --> C(Dictionaries)

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

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

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

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

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

  graph LR
    B[B]
    C[C]
    D[D]
    E[E]
    F[F]
    A[YAML] --> B{列表}
    A --> C{字典}
B --> D{專案 1}
    B --> F{專案 2}
    C --> E{鍵: 值}

以上圖表展示了 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 結構是高效自動化的根本。