在現代網站開發中,自動化佈署已成為不可或缺的一環。本文將探討如何利用 Ansible 自動化佈署 WordPress 至 Nginx 伺服器。首先,我們會設定 Nginx 虛擬主機,確保其能正確處理 WordPress 的請求。接著,我們將使用 Ansible 自動下載、解壓縮和組態 WordPress,並建立必要的資料函式庫和使用者。最後,我們會介紹如何使用 Ansible Roles 將 playbook 重構為更模組化、更易於維護的結構,提升佈署效率和程式碼的可重用性。

透過 Ansible 的 template 模組,我們可以有效管理 Nginx 的設定檔,並根據需求動態調整引數。同時,unarchive 模組能簡化 WordPress 的安裝流程,自動解壓縮檔案至指定目錄。此外,我們還能利用 Ansible 管理 MySQL 資料函式庫和使用者,確保 WordPress 的資料函式庫連線正常運作。最後,透過 Ansible Roles 的應用,我們可以將複雜的佈署流程拆解成更小、更易於管理的單元,提升整體佈署效率和程式碼品質。

設定Nginx與WordPress

在前面的章節中,我們已經成功安裝了Nginx伺服器並確認其正常運作。然而,預設的Nginx虛擬主機組態並不符合我們的實際需求。為了讓Nginx能夠正確處理WordPress的請求,我們需要對其組態進行修改。

建立Nginx組態範本

首先,在與Vagrantfile相同的目錄下,執行以下命令以建立Nginx組態範本:

mkdir -p provisioning/templates/nginx
touch provisioning/templates/nginx/default

接著,我們需要在Playbook中新增一個任務,以便將這個範本檔案複製到遠端機器上:

- name: Create nginx config
  template: src=templates/nginx/default dest=/etc/nginx/sites-available/default

組態Nginx虛擬主機

編輯provisioning/templates/nginx/default檔案,並填入以下內容:

upstream php {
  server unix:/run/php/php7.0-fpm.sock;
}

server {
  server_name book.example.com;
  root /var/www/book.example.com;
  index index.php;

  location = /favicon.ico {
    log_not_found off;
    access_log off;
  }

  location = /robots.txt {
    allow all;
    log_not_found off;
    access_log off;
  }

  location ~ /\. {
    deny all;
  }

  location ~* /(?:uploads|files)/.*\.php$ {
    deny all;
  }

  location / {
    try_files $uri $uri/ /index.php?$args;
  }

  rewrite /wp-admin$ $scheme://$host$uri/ permanent;

  location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
    access_log off;
    log_not_found off;
    expires max;
  }

  location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    if (!-f $document_root$fastcgi_script_name) {
      return 404;
    }
    include fastcgi_params;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass php;
  }
}

內容解密:

  1. upstream php區塊定義了PHP worker的upstream名稱為php,並指定了PHP-FPM監聽的Unix socket位置。
  2. server區塊定義了虛擬主機的基本組態,包括伺服器名稱、根目錄和索引檔案。
  3. 各個location區塊分別處理不同型別的請求,例如靜態檔案、PHP檔案等。
  4. fastcgi_pass php;這一行將PHP請求轉發給名為php的upstream處理。

處理Nginx組態變更

執行vagrant provision後,Nginx組態將被更新。然而,為了使變更生效,我們需要重新啟動Nginx服務。為此,我們可以使用handler來實作:

handlers:
  - name: restart nginx
    service: name=nginx state=restarted

並在需要重新啟動Nginx的任務中新增notify指令:

- name: Create nginx config
  template: src=templates/nginx/default dest=/etc/nginx/sites-available/default
  notify: restart nginx

這樣,當Nginx組態發生變更時,handler將被觸發,重新啟動Nginx服務,以使變更生效。

自動化佈署WordPress:使用Ansible簡化安裝流程

在上一章中,我們已經建立了一個基本的虛擬機器環境,並對Ansible有了一定的瞭解。現在,我們將進一步探討如何使用Ansible自動化佈署WordPress。本章將介紹如何下載WordPress、組態安裝環境,並使用Ansible簡化整個安裝流程。

使用Ansible下載WordPress

下載WordPress是安裝過程的第一步。你可以選擇手動下載WordPress壓縮檔,或使用Ansible自動下載。兩種方法各有優缺點:手動下載可以確保你獲得特定版本的WordPress,而自動下載則可以讓你始終獲得最新版本。

手動下載WordPress

首先,你可以存取WordPress官方網站下載最新版本的WordPress。建立一個名為files的資料夾在你的provisioning目錄下,並將下載的wordpress.zip檔案放入其中。

mkdir -p provisioning/files
curl https://wordpress.org/latest.zip > provisioning/files/wordpress.zip

接下來,你需要在Ansible playbook中新增一個任務,將wordpress.zip複製到虛擬機器的/tmp目錄下。

# Wordpress
- name: Copy wordpress.zip into tmp
  copy:
    src: files/wordpress.zip
    dest: /tmp/wordpress.zip

自動下載WordPress

如果你希望Ansible自動下載WordPress,可以使用uriget_url模組。首先,使用uri模組取得最新WordPress版本的SHA1校驗和,並將其儲存在wp_checksum變數中。

# WordPress
- name: Get WordPress checksum
  uri:
    url: https://wordpress.org/latest.zip.sha1
    return_content: true
  register: wp_checksum

- name: Download WordPress
  get_url:
    url: https://wordpress.org/latest.zip
    dest: /tmp/wordpress.zip
    checksum: "sha1:{{ wp_checksum.content }}"

內容解密:

  1. uri模組:用於傳送HTTP請求到指定的URL,並取得回應內容。在這裡,我們用它來取得WordPress最新版本的SHA1校驗和。
  2. get_url模組:用於從指定的URL下載檔案到目標主機。在這裡,我們用它來下載WordPress壓縮檔。
  3. checksum引數:用於驗證下載檔案的完整性。透過比較下載檔案的SHA1校驗和與預期的校驗和,確保檔案在傳輸過程中未被篡改。

組態WordPress安裝

在下載完WordPress之後,下一步是解壓縮並組態安裝環境。假設你已經手動下載了WordPress壓縮檔並將其複製到了/tmp/wordpress.zip,你可以繼續進行解壓縮和組態。

- name: Unzip WordPress
  unarchive:
    src: /tmp/wordpress.zip
    dest: /var/www/book.example.com/
    remote_src: yes

內容解密:

  1. unarchive模組:用於解壓縮檔案。在這裡,我們用它來解壓縮/tmp/wordpress.zip/var/www/book.example.com/目錄下。
  2. remote_src: yes:表示原始檔位於遠端主機上,而不是本地控制機上。

在Ubuntu上安裝WordPress的自動化流程

解壓縮WordPress壓縮檔

首先,需要將WordPress的壓縮檔進行解壓縮。Ansible提供了unarchive模組來處理不同型別的壓縮檔。

- name: 解壓縮WordPress
  unarchive:
    src: /tmp/wordpress.zip
    dest: /tmp
    copy: no
    creates: /tmp/wordpress/wp-settings.php

這裡使用unarchive模組來解壓縮/tmp/wordpress.zip/tmp目錄下,並且檢查/tmp/wordpress/wp-settings.php是否存在,以確保解壓縮的過程是冪等的。

內容解密:

  1. src: 指定要解壓縮的檔案來源路徑。
  2. dest: 指定解壓縮後的檔案要存放的目的地路徑。
  3. copy: 設定為no表示檔案已經在遠端主機上,不需要從控制主機複製過去。
  4. creates: 指定一個檔案路徑,如果該檔案存在,則表示解壓縮已經完成,不會重複執行。

安裝必要的工具

預設情況下,Ubuntu可能沒有安裝unzip工具,因此需要先安裝它。

- name: 安裝必要的工具
  apt:
    name: "{{ item }}"
    state: installed
  with_items:
    - unzip

這裡使用apt模組來安裝unzip工具。

內容解密:

  1. name: 指定要安裝的軟體包名稱。
  2. state: 設定為installed表示要安裝軟體包。
  3. with_items: 用於迴圈安裝多個軟體包。

複製WordPress檔案到正確的位置

解壓縮後,需要將WordPress的檔案複製到正確的位置。

- name: 建立專案資料夾
  file:
    dest: /var/www/book.example.com
    state: directory

- name: 複製WordPress檔案
  command:
    cmd: cp -a /tmp/wordpress/. /var/www/book.example.com
    creates: /var/www/book.example.com/wp-settings.php

首先,使用file模組建立/var/www/book.example.com目錄。然後,使用command模組將/tmp/wordpress下的檔案複製到/var/www/book.example.com

內容解密:

  1. dest: 指定要建立的目錄路徑。
  2. state: 設定為directory表示要建立一個目錄。
  3. cmd: 指定要執行的命令。
  4. creates: 指定一個檔案路徑,如果該檔案存在,則表示複製已經完成,不會重複執行。

建立WordPress資料函式庫和使用者

- name: 建立WordPress MySQL資料函式庫
  mysql_db:
    name: wordpress
    state: present

- name: 建立WordPress MySQL使用者
  mysql_user:
    name: wordpress
    host: localhost
    password: bananas
    priv: 'wordpress.*:ALL'

這裡使用mysql_db模組建立一個名為wordpress的資料函式庫,並使用mysql_user模組建立一個名為wordpress的使用者,密碼為bananas,並賦予該使用者對wordpress資料函式庫的所有許可權。

內容解密:

  1. name: 指定資料函式庫或使用者的名稱。
  2. state: 設定為present表示要建立資料函式庫或使用者,如果不存在的話。
  3. host: 指定使用者的主機名稱。
  4. password: 指定使用者的密碼。
  5. priv: 指定使用者的許可權。

組態WordPress

- name: 建立wp-config.php
  template:
    src: templates/wordpress/wp-config.php
    dest: /var/www/book.example.com/wp-config.php

這裡使用template模組將wp-config.php範本檔案渲染後複製到/var/www/book.example.com/wp-config.php

內容解密:

  1. src: 指定範本檔案的來源路徑。
  2. dest: 指定渲染後的檔案要存放的目的地路徑。

備份與還原資料函式庫

- name: 檢查資料函式庫是否存在
  command:
    cmd: mysql -u root wordpress -e "SELECT ID FROM wordpress.wp_users LIMIT 1;"
  register: db_exist
  ignore_errors: true

這裡使用command模組執行一個MySQL命令來檢查資料函式庫是否存在,並將結果註冊到db_exist變數中。設定ignore_errorstrue表示即使命令執行失敗也不會中斷Playbook的執行。

內容解密:

  1. cmd: 指定要執行的MySQL命令。
  2. register: 將命令執行的結果註冊到一個變數中。
  3. ignore_errors: 設定為true表示忽略命令執行失敗的錯誤。

使用Ansible Roles最佳化WordPress佈署

在前一章中,我們成功地使用Ansible自動化了WordPress的安裝過程。儘管我們已經完成了許多工作,但隨著playbook的不斷擴充套件,其可讀性和可重用性逐漸降低。在本章中,我們將對現有的playbook進行重構,將其拆分為邏輯上的不同部分,以提高其可維護性和可重用性。

Ansible Roles的概念

Roles是Ansible中的一個核心概念,它允許我們將tasks、handlers和其他必要的元素封裝成可重用的元件。這些元件可以透過包含在playbook中,根據特定的主機進行佈署。與playbook不同,role不能單獨執行,它需要被包含在playbook中,並指定需要執行的主機。

為什麼需要Roles

在前一章的playbook中,我們安裝並組態了nginx、MySQL以及WordPress。隨著功能的增加,playbook變得越來越複雜和冗長。這不僅使得playbook難以閱讀,也降低了其可重用性。例如,如果我們想要將現有的環境佈署Drupal而不是WordPress,我們就需要複製整個依賴設定並修改相關的部分。

透過使用roles,我們可以將playbook拆分為多個邏輯部分,例如PHP、nginx、MySQL和WordPress的安裝和組態。這樣不僅提高了playbook的可讀性,也使得這些元件可以在多個專案中重用。

Ansible Galaxy

Ansible Galaxy是一個存放和分享Ansible roles的平台。開發者可以在這裡上傳他們建立的roles供他人使用。截至目前,Ansible Galaxy已經有超過5,000個roles可供使用。在選擇roles時,可以透過下載量來評估其品質和可靠性。同時,每個role都有其原始碼的連結,允許使用者審查其內容。

如何使用Ansible Galaxy

  1. 搜尋Roles:存取https://galaxy.ansible.com/並搜尋您需要的role。
  2. 評估Roles:透過下載量和原始碼來評估role的品質。
  3. 在您的專案中使用Roles:將選定的role包含在您的playbook中,以簡化您的佈署流程。

重構Playbook

為了提高現有playbook的可維護性和可重用性,我們將對其進行重構,將其拆分為多個role,每個role負責一個特定的功能或服務,如下所示:

  • PHP Role:負責安裝和組態PHP環境。
  • nginx Role:負責安裝和組態nginx伺服器。
  • MySQL Role:負責安裝和組態MySQL資料函式庫。
  • WordPress Role:負責下載、組態和佈署WordPress。

建立Role的步驟

  1. 建立Role目錄結構:為每個role建立相應的目錄結構,包括tasks、handlers、variables等。
  2. 定義Tasks:在tasks目錄下定義該role需要執行的任務。
  3. 定義Handlers:如果需要,在handlers目錄下定義處理程式。
  4. 定義Variables:在defaults或vars目錄下定義該role使用的變數。

示例:nginx Role

# nginx Role tasks/main.yml
---
- name: 安裝nginx
  apt:
    name: nginx
    state: present

- name: 組態nginx
  template:
    src: templates/nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: restart nginx

- name: 啟動nginx服務
  service:
    name: nginx
    state: started
    enabled: yes
# nginx Role handlers/main.yml
---
- name: restart nginx
  service:
    name: nginx
    state: restarted