Ansible 提供了簡潔易用的自動化佈署方案,無需手動操作即可完成 NGINX 的安裝與組態。然而,Ansible 在佈署前後的測試驗證方面略顯不足。Chef 作為更全面的組態管理工具,不僅支援自動化組態,還能結合 Docker 和 Vagrant 在本地進行測試,並透過 InSpec 驗證設定的正確性,確保佈署的可靠性。本文將逐步引導讀者使用 Ansible 和 Chef 實作 NGINX 的自動化佈署,並詳細說明各個步驟的組態要點。

自動化 NGINX 佈署

在瞭解基本的 NGINX 組態後,現在是時候嘗試自動化網頁伺服器佈署了。自動化,也被稱為基礎設施即程式碼,是一種無需手動登入或編輯組態檔案即可定義在本地或雲例項中執行所需的一切的方法。

在 DevOps 世界中,自動化對於管理成百上千,甚至數十萬的虛擬機器或 AWS、Azure、Kubernetes 或其他公有雲例項至關重要。它允許工程師以簡單的程式碼定義他們想要的內容,並將其重新應用於任何想要執行該類別伺服器或應用程式的地方。

使用 Ansible 實作自動化

許多 DevOps 工程師開始他們的自動化之旅時使用 Ansible,這是一個免費的開源工具,可以針對 Linux、Windows 和 macOS 系統。它是無代理的,這意味著您不需要在目標機器上安裝任何東西就可以使其工作。它使用 SSH 連線到 Linux 和 macOS 主機,並使用 WinRM 連線到 Windows 主機。

建立 Ansible 環境

首先,在 Proxmox 中啟動一個新的 Ubuntu 或 Debian LXC,並在該步驟中新增本地 SSH 金鑰以啟用無密碼登入,或者在之後使用工作站上的 ssh-copy-id 命令,例如:

$ ssh-copy-id root@ansible.devops.lab

如果您尚未在 Linux 工作站上建立本地 SSH 金鑰,請使用以下命令建立。提示時不要新增密碼:

$ ssh-keygen

預設情況下,這會在系統上的 /home/user/.ssh/ 目錄中放置 id_rsaid_rsa.pub 檔案。當您執行上述 ssh-copy-id 命令時,它會將金鑰對的公鑰複製到遠端主機,以便所有未來的登入都不需要在使用 SSH 登入時輸入密碼。

安裝 Ansible

要在工作站上安裝 Ansible,請使用以下命令:

$ sudo apt update && sudo apt install ansible -y

組態 Ansible Inventory

Ansible 使用 inventory 的概念來識別一個或多個您想要使用您的組態來定位的系統。您可以透過網域名稱或 IP 地址新增單個機器,甚至建立機器組。這些然後在稱為 Ansible playbook 的組態檔案中被參照。透過先前分享您的 SSH 金鑰,您將能夠執行 Ansible 命令而無需每次輸入密碼。

預設情況下,inventory 檔案(在 Ubuntu 20.04 LTS 中)位於 /etc/ansible/hosts,並且包含許多基本的示例來幫助您開始。如果該資料夾在您的 Ubuntu 版本(包括 21.10 和 22.04 LTS)中不存在,請使用以下命令建立它:

$ sudo mkdir -p /etc/ansible

以下是一個範例 Ansible host 檔案,其中包含個別條目,一個名為 mynginx 的組,其中僅包含一個伺服器的 IP 地址,以及一個名為 webservers 的組,其中標識多個伺服器:

# This is my default ansible 'hosts' file.
nginx.devops.lab
rpi4.devops.lab
server22 ansible_host=10.128.1.99

[mynginx]
10.128.1.62

[webservers]
nginx.devops.lab

內容解密:

此 Ansible inventory 檔案定義了可以被 Ansible playbook 定位的目標主機。其中包括單個主機的條目和定義多個主機的組。使用此檔案,Ansible 可以連線到這些主機並執行組態任務。

自動化 NGINX 佈署的優勢

透過使用 Ansible 自動化 NGINX 佈署,您可以確保您的網頁伺服器組態的一致性和可重複性。這不僅節省了時間,還減少了手動組態錯誤的風險。此外,當您需要在多個環境中佈署相同的組態時,自動化使得擴充套件和管理您的基礎設施變得更加容易。

自動化佈署:Ansible 實戰

建立 Ansible 主機清單

在進行自動化佈署之前,需要先設定 Ansible 主機清單。此清單定義了 Ansible 將要管理的目標主機。以下是一個範例主機清單:

rpi4.devops.lab
10.128.1.62

[myngnix]
10.128.1.62

[webservers]
nginx.devops.lab
rpi4.devops.lab
10.128.1.62

這個範例中,定義了三個主機,分別是 nginx.devops.labrpi4.devops.lab10.128.1.62。同時,也定義了兩個群組:myngnixwebservers。透過這些群組,可以一次性地對多台主機進行操作。

主機清單組態解密:

  • 直接列出主機名稱或 IP 位址,可以單獨對這些主機進行操作。
  • 使用方括號 [] 定義群組名稱,如 [myngnix][webservers]
  • 在群組下方列出屬於該群組的主機。

編寫 Ansible Playbook

Ansible Playbook 是用 YAML 語言編寫的,用於定義一組任務,並在目標主機上執行。以下是一個範例 Playbook,用於安裝和組態 NGINX:

---
- hosts: webservers
  remote_user: root
  become: true
  vars:
    document_root: /var/www/html
    app_root: html
  tasks:
    - name: Update apt cache and install Nginx
      apt:
        name: nginx
        state: latest
        update_cache: true
    - name: Copy website files to the server's document root
      copy:
        src: "{{ app_root }}"
        dest: "{{ document_root }}"
        mode: preserve
    - name: Apply Nginx template
      template:
        src: files/nginx.devops.conf
        dest: /etc/nginx/sites-available/default
      notify: Restart Nginx
    - name: Enable new site
      file:
        src: /etc/nginx/sites-available/default
        dest: /etc/nginx/sites-enabled/default
        state: link
      notify: Restart Nginx
    - name: Allow all access to tcp port 80
      ufw:
        rule: allow
        port: '80'
        proto: tcp
  handlers:
    - name: Restart Nginx
      service:
        name: nginx
        state: restarted

Playbook 組態解密:

  1. hosts: webservers:指定目標主機群組為 webservers
  2. remote_user: rootbecome: true:以 root 使用者身份執行任務,並提升許可權。
  3. vars::定義變數,如 document_rootapp_root,以便在任務中使用。
  4. tasks::定義要執行的任務,包括安裝 NGINX、複製網站檔案、組態 NGINX 和開啟防火牆埠等。
    • apt::更新 apt 快取並安裝 NGINX。
    • copy::將本地網站檔案複製到目標主機的檔案根目錄。
    • template::將 NGINX 組態檔案範本套用到目標主機。
    • file::在 sites-enabled 目錄中建立符號連結,以啟用新的 NGINX 組態。
    • ufw::允許 TCP 埠 80 的存取。
  5. handlers::定義處理程式,如重新啟動 NGINX 服務,當相關任務的狀態發生變化時觸發。

執行 Ansible Playbook

要執行 Playbook,可以使用以下命令:

$ ansible-playbook my-nginx-website.yml

如果使用的是專案目錄中的自定義清單檔案,則可以使用 -i 引數指定清單檔案:

$ ansible-playbook -i inventory my-nginx-website.yml

執行後,Ansible 將按照 Playbook 中的定義,在指定的目標主機上執行各項任務,完成 NGINX 的安裝和組態。

自動化 NGINX 組態與 Chef 工具的高效實踐

在探討自動化組態管理的過程中,Ansible 提供了一種快速且一致的節點組態方法。然而,它在測試程式碼方面存在侷限性,無論是在佈署前還是佈署後。而 Chef 則提供了一套完整的解決方案,不僅可以自動化節點組態,還能在本地環境中使用 Docker 和 Vagrant(搭配 VirtualBox)進行測試,並執行即時掃描以驗證所有設定的正確性。

入門:下載並安裝 Chef Workstation

要開始使用 Chef,首先需要下載 Chef Workstation,這是一個免費的工具包,包含了建立 Chef cookbooks(用於組態節點的程式碼)和 profiles(用於掃描節點的程式碼)所需的一切。它還提供了許多其他工具和功能,能夠幫助您擴充套件到真正的企業級佈署。

下載網址:www.chef.io/downloads/tools/workstation

在 Linux 系統(本例中使用 Ubuntu)上安裝完套件後,編輯 ~/.bashrc 檔案以初始化 shell 環境,使其能夠使用內嵌的 Chef 資源,如 Ruby。這樣做可以確保您無需安裝其他東西就能使其運作。在檔案的末尾新增以下 eval 陳述式:

$ vi ~/.bashrc
...
eval "$(chef shell-init bash)"
...

當然,您也可以每次開啟 shell 終端時手動執行 chef shell-init bash,但透過新增這條陳述式,可以確保每次開啟新終端時自動設定好環境。

建立 Chef Cookbook 和 Recipes

Chef Workstation 提供了使用 Chef 語言所需的所有工具,該語言根據 Ruby。即使您不熟悉 Ruby 語言,Chef 的領域特定語言(DSL)也很容易閱讀和理解。如果您使用 VS Code 作為程式碼編輯器,可以透過幾次點選新增官方的 Chef 擴充套件到您的環境中。該外掛提供了程式碼補全和錯誤檢查功能。

生成 Chef 倉函式庫和 NGINX Cookbook

首先,生成一個新的資料夾來存放您的程式碼。然後,使用 Chef 的生成器來建立一個 Chef 倉函式庫(用於存放所有自動化內容的目錄)、cookbooks、recipes、profiles、templates 等。

$ cd ~
$ chef generate repo chef-repo
$ cd ~/chef-repo/cookbooks
$ chef generate cookbook nginx -k dokken

上述命令會在您的家目錄下建立 ~/chef-repo 資料夾,並自動建立多個子資料夾和檔案。然後,在 ~/chef-repo/cookbooks/ 資料夾下建立 NGINX cookbook,並使用 -k dokken 引數讓 Chef 自動建立一個適用於 Docker 的 Test Kitchen kitchen.yml 檔案。Test Kitchen 允許您在將程式碼應用到目標節點之前,在本地對其進行全面測試和驗證。

編輯 metadata.rb 和建立 Profile

~/chef-repo/cookbooks/nginx/ 目錄下,有幾個重要的元素,包括 compliance/kitchen.ymlmetadata.rbrecipes/templates/。在進行其他操作之前,編輯 metadata.rb 檔案,新增您的姓名、電子郵件和應用程式版本號(如 0.1.0)。並確保 chef_version 至少設定為 >= 17.5,以利用接下來步驟中描述的功能。

# metadata.rb 示例
name 'nginx'
maintainer 'Your Name'
maintainer_email 'your.email@example.com'
version '0.1.0'
chef_version '>= 17.5'

建立 Profile 和 Recipe

使用 inspec init profile <profile-name> 命令在 compliance/profiles/ 資料夾中建立 profile:

$ cd ~/chef-repo/cookbooks/nginx/compliance/profiles
$ inspec init profile nginx

這將建立一個包含 controls 子目錄的 nginx 資料夾,其中有一個 example.rb 檔案和一個 inspec.yml 檔案。將 example.rb 重新命名為 default.rb,稍後將對其進行編輯。

編寫 Chef Recipe

在 Chef 中,recipes 是包含基礎設施組態程式碼的檔案。與 Ansible 的 YAML 示例類別似,Chef recipes 使用內建資源來自動化您想要執行的各種任務。由於 recipes 是 Ruby 檔案,您可以新增邏輯,使 recipes 根據目標節點的平台、特定的 OS 和其他系統值執行不同的操作。

建立 webserver.rb Recipe

$ cd ~/chef-repo/cookbooks/nginx
$ chef generate recipe webserver

這將在您的 cookbook 的 recipes 資料夾中建立一個名為 webserver.rb 的新檔案。

編輯 default.rb

開啟 ./recipes/default.rb 檔案並新增以下行,這些行告訴 Chef 使用您的 webserver.rb 檔案和您將在下一步中建立的 NGINX profile:

# Cookbook:: nginx
include_recipe 'nginx::webserver'

內容解密:

  1. include_recipe 'nginx::webserver':這行程式碼的作用是包含另一個名為 webserver 的 recipe。這意味著當執行 default.rb 時,也會執行 webserver.rb 中的組態,從而實作了程式碼的模組化和重用。
  2. Chef 的 Recipe 邏輯:透過這種方式,Chef 允許您將不同的組態邏輯分離到不同的 recipe 中,使得管理和維護變得更加容易。
  3. NGINX Profile 的使用:除了包含 webserver recipe 之外,您還需要在接下來的步驟中建立 NGINX profile,用於掃描和驗證節點的組態是否符合預期。