返回文章列表

Ansible Playbook 自動化測試實踐

本文介紹如何使用 Test Kitchen 和 ServerSpec 對 Ansible Playbook 進行自動化測試,涵蓋從設定測試環境、編寫測試案例到執行測試的完整流程。文章以安裝和驗證 Nginx 為例,逐步說明如何使用 Vagrant 和 Docker 作為測試平台,並示範如何編寫 ServerSpec

DevOps 自動化測試

Test Kitchen 是一個用於測試基礎設施程式碼的框架,讓開發者能以自動化的方式驗證 Ansible Playbook 的正確性。透過結合 Vagrant 或 Docker 等虛擬化技術,Test Kitchen 能夠快速建立和銷毀測試環境,並使用 ServerSpec 進行驗證,確保 Playbook 的變更不會影響現有功能。此流程能有效提升 Playbook 的可靠性和可維護性,並降低基礎設施佈署的風險。文章將以一個簡單的 Nginx 安裝案例,逐步說明如何使用 Test Kitchen 進行測試。首先,設定測試環境,包含定義 .kitchen.yml 檔案,指定使用 Vagrant 或 Docker 作為驅動程式,並設定 Ansible Playbook 的路徑。接著,編寫 ServerSpec 測試案例,驗證 Nginx 套件是否已安裝、服務是否正在執行,以及是否監聽正確的埠。最後,執行 kitchen verify 命令,自動執行測試並輸出結果。

此圖示

此圖示顯示了 Test Kitchen 的工作流程和相關工具之間的關係,包括 Vagrant、Ansible playbook 和 ServerSpec 等。

解說:

  1. Test Kitchen 主要命令:圖表顯示了 Test Kitchen 的四個主要命令:kitchen createkitchen convergekitchen verifykitchen destroy
  2. 相關工具:每個命令都與特定的工具或技術相關聯,例如 kitchen create 與 Vagrant 相關,kitchen converge 與 Ansible playbook 相關,kitchen verify 與 ServerSpec 相關。
  3. 工作流程:圖表呈現了 Test Kitchen 的工作流程,從建立環境到執行測試,最後銷毀環境。

透過此圖示,我們可以清晰地瞭解 Test Kitchen 的工作流程和相關工具之間的關係,有助於更好地理解和使用 Test Kitchen 對 Ansible playbook 進行測試。

使用 Test Kitchen 進行測試

編寫第一個測試

第一個測試將會是一個簡單的範例。首先會執行一個安裝 nginx 的 playbook,並撰寫一個測試來確保 nginx 套件已安裝且正在正確的埠號上監聽。

定義測試環境

首先,需要定義測試環境。這是透過建立 .kitchen.yml 檔案並定義驅動程式、供應器和測試平台來完成的。在 ansible-kitchen 目錄下建立 .kitchen.yml 檔案,並加入以下內容:

---
driver:
  name: vagrant
provisioner:
  name: ansible_playbook
  playbook: playbook.yml
  hosts: all
  require_chef_for_busser: false
  require_ruby_for_busser: true
platforms:
  - name: ubuntu
    driver_config:
      box: "ubuntu/trusty64"
suites:
  - name: default
    verifier:
      ruby_bindir: '/usr/bin'

這裡指定了使用 Vagrant 來管理測試機器,並使用 ubuntu/trusty64 映象。建立此檔案後,可以執行 bundle exec kitchen create 來啟動測試機器。

建立 Playbook

接下來,需要建立一個 playbook 來執行。已經在 .kitchen.yml 中指定了 playbook 的名稱為 playbook.yml,因此需要在同一個目錄下建立 playbook.yml 檔案,並加入以下內容:

---
- hosts: all
  tasks:
    - apt: name=nginx state=installed
    - service: name=nginx state=restarted

執行 Converge

要將變更套用到測試機器上,需要執行 bundle exec kitchen converge。這將會在測試機器上執行 Ansible,並安裝 nginx。

使用 ServerSpec 編寫測試

首先,需要登出測試機器並建立測試環境。執行以下指令來建立必要的資料夾和範例測試檔案:

mkdir -p test/integration/default/serverspec

這將會建立一個整合測試的資料夾。接下來,需要建立 spec_helper.rbdefault_spec.rb 檔案。

spec_helper.rb 的內容如下:

require 'serverspec'
set :backend, :exec

default_spec.rb 的內容如下:

require 'spec_helper'

describe 'nginx installation' do
  context package('nginx') do
    it { should be_installed }
  end
end

這個測試檢查 nginx 套件是否已安裝。

執行測試

最後,可以執行 bundle exec kitchen verify 來執行測試。

程式碼詳細解析:

以下對上述程式碼進行詳細解析:

.kitchen.yml
---
driver:
  name: vagrant
provisioner:
  name: ansible_playbook
  playbook: playbook.yml
  hosts: all
  require_chef_for_busser: false
  require_ruby_for_busser: true
platforms:
  - name: ubuntu
    driver_config:
      box: "ubuntu/trusty64"
suites:
  - name: default
    verifier:
      ruby_bindir: '/usr/bin'

內容解密:

  1. 指定使用 Vagrant 作為驅動程式。
  2. 設定 Ansible Playbook 的相關引數,包括 Playbook 的路徑和主機。
  3. 指定不需要安裝 Chef,但需要 Ruby 來安裝 Busser。
  4. 定義測試平台為 Ubuntu,並指定使用的 Vagrant box。
  5. 定義預設的測試套件,並設定 Ruby 的執行路徑。
playbook.yml
---
- hosts: all
  tasks:
    - apt: name=nginx state=installed
    - service: name=nginx state=restarted

內容解密:

  1. 指定 Playbook 要執行的主機群組為所有主機。
  2. 定義兩個任務:安裝 nginx 和重啟 nginx 服務。
  3. 使用 Apt 模組來安裝 nginx。
  4. 使用 Service 模組來重啟 nginx 服務。
spec_helper.rb
require 'serverspec'
set :backend, :exec

內容解密:

  1. 載入 ServerSpec 函式庫。
  2. 設定 ServerSpec 的後端為執行(exec),表示將在本地端執行命令。
default_spec.rb
require 'spec_helper'

describe 'nginx installation' do
  context package('nginx') do
    it { should be_installed }
  end
end

內容解密:

  1. 載入 spec_helper.rb,初始化 ServerSpec 環境。
  2. 定義一個描述區塊,描述的是 nginx 的安裝。
  3. 使用 context 定義一個上下文,檢查 nginx 套件。
  4. 使用 it 定義一個測試專案,檢查 nginx 是否已安裝。

使用 Test Kitchen 進行測試

介紹 Test Kitchen 與其支援工具

Test Kitchen 是用於測試基礎設施程式碼的工具,能夠讓開發者對其 Ansible Playbook 進行自動化測試。本章節將介紹如何使用 Test Kitchen 來測試你的 Ansible Playbook。

編寫第一個 ServerSpec 測試

首先,你需要編寫一個 ServerSpec 測試,以確保 nginx 已正確安裝。以下是一個簡單的測試範例:

context package('nginx') do
  it { should be_installed }
end

這個測試檢查 nginx 套件是否已安裝。你可以使用 kitchen verify 命令來執行這個測試。

內容解密:

  • context 用於定義測試的上下文。
  • package('nginx') 指定要測試的套件。
  • it { should be_installed } 檢查該套件是否已安裝。

你可以進一步新增測試,以確保 nginx 正在監聽預設的 80 埠:

context port(80) do
  it { should be_listening }
end

內容解密:

  • port(80) 指定要測試的埠。
  • it { should be_listening } 檢查該埠是否正在監聽。

你還可以使用 curl 命令來檢查 nginx 是否傳回正確的內容:

context command('curl http://localhost') do
  its(:stdout) do
    should contain 'Welcome to nginx'
  end
end

內容解密:

  • command('curl http://localhost') 指定要執行的命令。
  • its(:stdout) 檢查命令的輸出。
  • should contain 'Welcome to nginx' 檢查輸出是否包含特定的字串。

更輕量級的測試

使用 Docker 取代 Vagrant 可以顯著提高測試的速度。首先,你需要更新 .kitchen.yml 檔案,以使用 Docker 驅動程式:

driver:
  name: docker
  use_sudo: false

provisioner:
  name: ansible_playbook
  playbook: playbook.yml
  hosts: all

platforms:
  - name: ubuntu
    driver_config:
      image: ubuntu:14.04

suites:
  - name: default
    verifier:
      ruby_bindir: '/usr/bin'

內容解密:

  • driver.name 指定使用的驅動程式。
  • platforms 指定要測試的平台。
  • driver_config.image 指定要使用的 Docker 映象。

接下來,你需要更新 Gemfile 以包含 kitchen-docker

source 'https://rubygems.org'

gem 'test-kitchen', '~> 1.0'
gem 'kitchen-ansible', '~> 0.44'
gem 'kitchen-docker', '~> 2.5'
gem 'serverspec', '~> 2.36'

內容解密:

  • source 指定 Gem 的來源。
  • gem 指定要安裝的 Gem。

測試 WordPress Role

現在,你可以開始為 WordPress Role 編寫測試。首先,建立一個新的 .kitchen.yml 檔案,並組態 Test Kitchen 以使用 Docker 驅動程式:

driver:
  name: docker
  use_sudo: false

provisioner:
  name: ansible_playbook
  playbook: playbook.yml
  hosts: all

platforms:
  - name: ubuntu
    driver_config:
      image: ubuntu:14.04

suites:
  - name: default
    verifier:
      ruby_bindir: '/usr/bin'

這個組態檔案將使用現有的 playbook.yml 檔案來組態 Test Kitchen 環境。接下來,你可以開始編寫測試,以確保 WordPress Role 的正確性。

進階 Ansible 測試與應用

使用 Test Kitchen 進行測試

在前面的章節中,我們已經瞭解如何使用 Ansible 建立 WordPress 環境。現在,我們將介紹如何使用 Test Kitchen 對 Ansible Playbook 進行測試。Test Kitchen 是一個測試框架,能夠幫助我們驗證 Playbook 的正確性。

首先,我們需要在專案中安裝 Test Kitchen。由於我們之前使用了 Bundler 安裝 Test Kitchen,因此它被安裝在專案的本地環境中。請確保目前所在的目錄是 playbook.yml 所在的目錄,並建立一個名為 Gemfile 的檔案,內容如下:

source 'https://rubygems.org'
gem 'test-kitchen', '~> 1.0'
gem 'kitchen-ansible', '~> 0.44'
gem 'kitchen-docker', '~> 2.5'
gem 'serverspec', '~> 2.36'

接著,執行 bundle install --path vendor/bundle 以下載所需的依賴套件。完成後,執行 bundle exec kitchen converge 將建立一個 Docker 容器並執行 Playbook,以安裝 WordPress 及其依賴套件。

編寫測試

建立測試目錄結構和 Serverspec Helper:

mkdir -p test/integration/default/serverspec

test/integration/default/serverspec/ 目錄下建立 spec_helper.rb

require 'serverspec'
set :backend, :exec

接下來,建立 default_spec.rb 以編寫測試:

require 'spec_helper'

describe 'nginx installation' do
  context package('nginx') do
    it { should be_installed }
  end
  context service('nginx') do
    it { should be_running }
  end
end

describe 'mysql installation' do
  context package('mysql-server-5.6') do
    it { should be_installed }
  end
  context service('mysql') do
    it { should be_running }
  end
end

describe 'php installation' do
  context package('php') do
    it { should be_installed }
  end
  context service('php7.0-fpm') do
    it { should be_running }
  end
  context command('php --version') do
    its(:stdout) { should contain 'PHP 7' }
  end
end

describe 'wordpress' do
  context file('/var/www/book.example.com/wp-config.php') do
    it { should exist }
  end
  context command('mysql -u root michaelwp -e "SELECT post_title FROM wp_posts WHERE id=1;"') do
    its(:stdout) { should contain 'Hey There' }
  end
end

執行測試

執行 bundle exec kitchen verify 以執行測試。如果所有測試透過,將顯示類別似以下的輸出:

nginx installation
  Package "nginx"
    should be installed
  Service "nginx"
    should be running
mysql installation
  Package "mysql-server-5.6"
    should be installed
  Service "mysql"
    should be running
php installation
  Package "php"
    should be installed
  Service "php7.0-fpm"
    should be running
  Command "php --version"
    stdout
      should contain "PHP 7"
wordpress
  File "/var/www/book.example.com/wp-config.php"
    should exist
  Command "mysql -u root michaelwp -e \"SELECT post_title FROM wp_posts WHERE id=1;\""
    stdout
      should contain "Hey There"

Finished in 0.35718 seconds (files took 0.51265 seconds to load)
9 examples, 0 failures

重構與驗證

未來若對 WordPress Role 有任何變更,只需重新執行這些測試,即可確認變更是否正確。這樣可以提高對 Playbook 的信心,確保相關軟體安裝和組態正確。

Ansible 命令列工具

除了執行 Playbook,Ansible 也提供了 ansible 命令列工具,用於執行臨時命令。雖然通常建議將所有操作寫入 Playbook 以便版本控制和稽核,但 ansible 命令列工具仍有其用途。

使用範例

要使用 ansible 命令列工具在 Web 群組中的所有主機上安裝 nginx,可以執行以下命令:

ansible web –i /path/to/inventory –m apt –a 'name=nginx state=installed'

這對於需要臨時升級套件或處理安全性問題時很有用,但相較於使用 Playbook,這種方式缺乏可重現性。