返回文章列表

Ansible Inventory 檔案與動態 Inventory 應用

本文探討 Ansible 的 Inventory 檔案,包含靜態 Inventory 的基本結構、群組變數設定、群組巢狀結構,以及動態 Inventory 的應用。同時,示範如何使用可執行檔案生成動態 Inventory,並結合 Vagrant 建立 WordPress 開發環境,以及使用 Ansible

DevOps 系統管理

Ansible Inventory 檔案是定義和管理主機的重要元件,讓管理員能有效執行自動化任務。本文除了介紹 Inventory 檔案的基本結構、群組和變數設定外,更探討動態 Inventory 的應用,說明如何使用可執行檔案或指令碼生成動態 Inventory 內容,以應對大規模環境的管理需求。文章也示範如何結合 Vagrant 和 Ansible 建立 WordPress 開發環境,並逐步說明安裝 PHP、MySQL 和 Nginx 的 Ansible playbook 設定,包含 MySQL 的安全強化步驟,例如設定 root 密碼、移除預設匿名使用者和測試資料函式庫等,提供讀者一個完整的 Ansible 自動化 WordPress 環境佈署範例。

Ansible Inventory 檔案詳解

Ansible 的 Inventory 檔案是用於定義和管理主機群組的重要元件。透過適當地組態 Inventory 檔案,管理員能夠輕鬆地對不同主機或主機群組執行 Ansible 指令。本文將探討 Inventory 檔案的結構、變數設定以及動態 Inventory 的應用。

Inventory 檔案基礎

Inventory 檔案採用 INI 格式,使用方括號 [] 來標記不同的主機群組。例如:

[web]
web1.example.com
web2.example.com

[database]
db.example.com

在這個範例中,我們定義了兩個群組:webdatabase。當執行 Ansible 指令時,可以指定特定的群組來執行任務,例如:

ansible web -i /path/to/inventory -m ping

這條指令會對 web 群組中的所有主機執行 ping 模組。

群組變數設定

除了定義主機群組外,我們還可以為特定的群組設定變數。這些變數將在 Ansible 執行期間對該群組中的所有主機可用。例如:

[web:vars]
apache_version=2.4
engage_flibbit=true

在這個範例中,我們為 web 群組設定了兩個變數:apache_versionengage_flibbit

群組巢狀結構

Ansible 支援建立群組的巢狀結構,也就是說一個群組可以包含其他群組。這種結構使得管理複雜的環境變得更加容易。例如:

[web_centos5]
host1.example.com
host2.example.com

[web_centos6]
shinynewthing.example.com

[centos5:children]
web_centos5
database_centos5

[centos6:children]
web_centos6
reporting_centos6

在這個範例中,我們建立了 centos5centos6 兩個群組,分別包含不同的子群組。

實際範例

以下是一個真實的 Inventory 檔案範例,展示了一個包含多個主機和群組的環境:

[web_centos5]
fe1.example.com ansible_user=michael ansible_ssh_private_key_file=michael.key
fe2.example.com ansible_user=michael ansible_ssh_private_key_file=michael.key

[web_centos6]
web[1:3].example.com ansible_user=automation ansible_port=50022 ansible_ssh_private_key_file=/path/to/auto.key

[database_centos6]
db.example.com ansible_user=michael ansible_ssh_private_key_file=/path/to/db.key

[loadbalancer_centos6]
lb.example.com ansible_user=automation ansible_port=50022 ansible_ssh_private_key_file=/path/to/lb.key

[web:children]
web_centos5
web_centos6

[database:children]
database_centos6

[loadbalancer:children]
loadbalancer_centos6

這個範例展示瞭如何定義不同的主機群組、設定變數以及建立群組的巢狀結構。

程式碼解析:

[web_centos5]
fe1.example.com ansible_user=michael ansible_ssh_private_key_file=michael.key
fe2.example.com ansible_user=michael ansible_ssh_private_key_file=michael.key

內容解密:

  1. [web_centos5] 定義了一個名為 web_centos5 的群組。
  2. fe1.example.comfe2.example.com 是該群組中的主機。
  3. ansible_user=michael 指定了連線這些主機時使用的 SSH 使用者名稱。
  4. ansible_ssh_private_key_file=michael.key 指定了用於 SSH 連線的私鑰檔案路徑。

動態 Inventory

當需要管理的伺服器數量龐大時,手動維護 Inventory 檔案變得困難且容易出錯。此時,動態 Inventory 成為一個理想的解決方案。動態 Inventory 是根據 JSON 格式的檔案,包含了所有主機的相關資料。

Ansible 支援使用可執行檔案作為動態 Inventory 的來源。當 Ansible 檢測到指定的 Inventory 檔案是可執行的,它將執行該檔案並解析其輸出的 JSON 資料。

使用可執行檔案建立動態庫存

在 Ansible 中,您可以使用可執行檔案來讀取機器庫存資料。這些資料可以來自任何地方:遠端 API、本地資料函式庫、一組您解析和整理的檔案等。只要能夠填充要執行的伺服器列表,就可以將其用作庫存檔案。

Ansible 預期任何用於提供機器庫存的可執行檔案都傳回特定的 JSON 格式。如下所示:

{
  "my_script": ["dev2", "dev"],
  "_meta": {
    "hostvars": {
      "dev2": {
        "ansible_host": "dev2.example.com",
        "ansible_user": "ansible"
      },
      "dev": {
        "ansible_host": "dev.example.com",
        "ansible_port": "50022",
        "ansible_user": "automation"
      }
    }
  }
}

第一個鍵是指令碼的名稱,值是庫存檔案中要使用的主機名。然後,對於每個名稱,都有一些後設資料,其中包含要使用的 SSH 主機、登入使用者和 SSH 埠。

動態庫存的實作

假設您有一個資料函式庫列出了所有機器,並且想要使用該資料函式庫作為庫存檔案。您的可執行檔案可能如下所示:

# 從資料函式庫中取得機器資訊
machines = fetch_rows("SELECT hostname, user, key, port FROM active_machines")
hostnames = [m.hostname for m in machines]
metadata = {'hostvars': {}}

# 遍歷機器列表,構建後設資料
for m in machines:
    metadata['hostvars'][m.hostname] = {
        'ansible_user': m.user,
        'ansible_port': m.port,
        'ansible_ssh_private_key_file': m.key
    }

# 輸出 JSON 格式的庫存資料
output_json({
    'my_script': hostnames,
    '_meta': metadata
})

內容解密:

  1. fetch_rows 函式用於從資料函式庫中讀取活動機器的資訊,包括主機名、使用者、金鑰和埠。
  2. 將機器主機名提取到 hostnames 列表中。
  3. 初始化 metadata 物件,並為每個主機建立 hostvars
  4. 將每個主機的連線資訊(如使用者、埠和私鑰檔案)新增到 metadata 中。
  5. 使用 output_json 函式輸出符合 Ansible 預期的 JSON 格式。

多個庫存的管理

如果您的基礎設施中同時包含物理硬體和雲伺服器,可以透過將庫存路徑指向一個目錄來合併多個庫存檔案。Ansible 將讀取該目錄中的所有檔案,並將它們合併為一個庫存。

安裝 WordPress

現在您已經熟悉瞭如何設定 Ansible 的開發環境,接下來我們將編寫一個 playbook 來下載並組態 WordPress。

WordPress 的依賴

WordPress 需要 PHP(版本需大於 5.2)、Web 伺服器和 MySQL 資料函式庫。在本章中,我們將安裝所有必需的依賴項,並自動安裝新的 WordPress 例項。

環境組態

首先,建立一個新的 Vagrant 環境:

mkdir ansible-wordpress
cd ansible-wordpress
vagrant init ubuntu/trusty64

修改 Vagrantfile 以啟用網路並分配更多的記憶體給虛擬機器:

Vagrant.configure(2) do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.network "private_network", ip: "192.168.33.20"
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
  end
end

內容解密:

  1. 使用 mkdircd 命令建立並進入新目錄。
  2. 使用 vagrant init 初始化新的 Vagrant 環境。
  3. 修改 Vagrantfile 以設定虛擬機器的網路和記憶體組態。
  4. config.vm.network 用於設定私有網路的 IP 地址。
  5. config.vm.provider 用於設定虛擬機器的記憶體大小,以滿足 MySQL 的需求。

在虛擬機器上安裝 WordPress 的 Ansible 指令碼實作

虛擬機器的建立與基本組態

首先,透過 Vagrant 建立一個虛擬機器,並使用 Ansible 進行組態。以下為 Vagrantfile 的關鍵組態:

config.vm.define "wordpress" do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.network "private_network", ip: "192.168.33.20"
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
  end
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "provisioning/playbook.yml"
  end
end

內容解密:

  • config.vm.define 定義了一個名為 wordpress 的虛擬機器組態區塊。
  • config.vm.box 指定使用的虛擬機器映像檔為 ubuntu/trusty64。
  • config.vm.network 設定虛擬機器的私有網路 IP 為 192.168.33.20。
  • config.vm.provider 組態虛擬機器的記憶體為 1 GB。
  • config.vm.provision 指定使用 Ansible 進行組態,playbook 路徑為 provisioning/playbook.yml。

安裝 WordPress 的依賴套件

要執行 WordPress,需要安裝 PHP、nginx 和 MySQL。首先,建立一個簡單的 Ansible playbook 來確認 Ansible 可以正確連線到 Vagrant 虛擬機器。

建立 provisioning 目錄並建立 playbook.yml:

mkdir provisioning
touch provisioning/playbook.yml

在 provisioning/playbook.yml 中定義初始 playbook:

---
- hosts: all
  become: true
  tasks:
    - name: 確認連線
      ping:

內容解密:

  • hosts: all 表示該 playbook 將對所有主機執行。
  • become: true 表示以提升許可權(通常是 root)執行任務。
  • tasks 下定義了要執行的任務列表,第一個任務是使用 ping 模組確認連線。

安裝 PHP

WordPress 可以在 PHP 5.2 及以上版本執行,但建議使用最新版本。以下為安裝 PHP 的 Ansible 任務:

# PHP
- name: 新增 ondrej PHP PPA
  apt_repository: repo='ppa:ondrej/php'

- name: 更新 apt 快取
  apt: update_cache=yes cache_valid_time=3600

- name: 安裝 PHP
  apt: name={{item}} state=installed
  with_items:
    - php
    - php-fpm
    - php-mysql
    - php-xml

- name: 移除 apache2
  apt: name=apache2 state=removed

內容解密:

  1. 使用 apt_repository 模組新增 ondrej PHP PPA,以安裝最新版本的 PHP。
  2. 更新 apt 快取以確保可以安裝最新套件。
  3. 使用迴圈安裝多個 PHP 相關套件。
  4. 由於安裝 PHP 時會一併安裝 Apache2,因此需要手動移除 Apache2。

安裝 MySQL

接下來,安裝 MySQL 資料函式庫伺服器並進行基本的安全設定:

# MySQL
- name: 安裝 MySQL
  apt: name={{item}} state=installed
  with_items:
    - mysql-server-5.6
    - python-mysqldb

- name: 生成新的 root 密碼
  command: openssl rand -hex 7
  register: mysql_new_root_pass

- name: 移除匿名使用者
  mysql_user: name="" state=absent

- name: 移除測試資料函式庫
  mysql_db: name=test state=absent

- name: 修改 root 密碼
  mysql_user: name=root host={{ item }} password={{ mysql_new_root_pass.stdout }}
  with_items:
    - "{{ ansible_hostname }}"
    - 127.0.0.1
    - ::1
    - localhost

內容解密:

  1. 安裝 MySQL 伺服器和 Python MySQLdb 套件。
  2. 使用 openssl 命令生成一個隨機的 root 密碼,並將結果儲存在變數 mysql_new_root_pass 中。
  3. 使用 mysql_usermysql_db 模組移除匿名使用者和測試資料函式庫。
  4. 修改 MySQL 的 root 使用者密碼,並針對不同的主機名稱(包括 localhost 的不同表示方式)進行設定。

使用Ansible自動化安裝與設定WordPress

自動化MySQL安全設定

在佈署WordPress的過程中,MySQL資料函式庫的安全性至關重要。本章節將介紹如何使用Ansible自動化MySQL的安全設定。

步驟一:安裝MySQL伺服器

首先,使用Ansible的apt模組安裝MySQL伺服器和相關套件:

- name: Install MySQL
  apt: name={{item}} state=present
  with_items:
    - mysql-server-5.6
    - python-mysqldb

步驟二:生成新的root密碼

為了提高安全性,我們需要為MySQL的root使用者生成一個新的密碼。利用openssl命令生成隨機密碼:

- name: Generate new root password
  command: openssl rand -hex 7 creates=/root/.my.cnf
  register: mysql_new_root_pass

此步驟檢查是否存在/root/.my.cnf檔案,如果不存在,則執行密碼生成命令。

步驟三:移除匿名使用者和測試資料函式庫

移除MySQL中的匿名使用者和測試資料函式庫,以增強安全性:

- name: Remove anonymous users
  mysql_user: name="" state=absent
  when: mysql_new_root_pass.changed

- name: Remove test database
  mysql_db: name=test state=absent
  when: mysql_new_root_pass.changed

這些任務在生成新root密碼後執行,確保只有授權的使用者可以存取資料函式庫。

步驟四:更新root密碼並建立MySQL設定檔

更新root使用者的密碼,並建立/root/.my.cnf設定檔,以便Ansible無需密碼即可執行MySQL命令:

- name: Update root password
  mysql_user: name=root host={{item}} password={{mysql_new_root_pass.stdout}}
  with_items:
    - "{{ ansible_hostname }}"
    - 127.0.0.1
    - ::1
    - localhost
  when: mysql_new_root_pass.changed

- name: Create my.cnf
  template: src=templates/mysql/my.cnf dest=/root/.my.cnf
  when: mysql_new_root_pass.changed

my.cnf檔案的內容如下:

[client]
user=root
password={{ mysql_new_root_pass.stdout }}

程式碼解析

- name: Generate new root password
  command: openssl rand -hex 7 creates=/root/.my.cnf
  register: mysql_new_root_pass

內容解密:

  1. name: 定義任務名稱。
  2. command: 指定要執行的命令,此處為生成隨機密碼。
  3. creates: 如果指定的檔案存在,則不執行該命令。
  4. register: 將命令的輸出結果註冊到變數mysql_new_root_pass

安裝nginx

完成MySQL的設定後,接下來需要安裝nginx作為Web伺服器,以處理HTTP請求並轉發給PHP處理WordPress的請求。

安裝nginx

使用Ansible的apt模組安裝nginx:

# nginx
- name: Install nginx
  apt: name=nginx state=installed

程式碼解析

- name: Install nginx
  apt: name=nginx state=installed

內容解密:

  1. name: 定義任務名稱為"Install nginx"。
  2. apt: 使用Ansible的套件管理模組。
  3. name=nginx: 指定要安裝的套件名稱為nginx。
  4. state=installed: 確保nginx套件已安裝。