資料函式庫變更在軟體開發過程中是不可避免的,但處理不當卻可能造成服務中斷或資料遺失。本文將介紹如何在不停機的情況下安全地更新資料函式庫結構,並探討如何使用功能旗標和雙欄位變更策略來降低風險。同時,我們也將探討如何利用版本控制工具 Flyway 管理資料函式庫版本,以及如何透過建立佈署成品簡化佈署流程。此外,本文還會介紹如何利用作業系統的套件管理系統,例如 RPM 和 DEB,來封裝和佈署應用程式,並探討 FPM 工具的應用,以及如何處理不同環境下的組態檔案。最後,我們將探討動態組態管理的各種模式,包括透過鍵值儲存進行動態組態、使用組態管理工具修改組態以及組態檔案連結等方法,以確保不同環境間的組態一致性,並提升佈署效率。

資料函式庫變更與佈署策略

在軟體開發過程中,資料函式庫變更是常見的需求。然而,這些變更可能會對應用程式的穩定性和可靠性造成風險。本篇文章將探討如何在佈署過程中管理資料函式庫變更,並確保應用程式的可靠性。

資料函式庫欄位變更的三種策略

當需要變更資料函式庫欄位時,可以採用以下三種策略:

  1. 一次性變更:一次性將所有資料更新到新的欄位中。這種方法可能會對資料函式庫造成巨大的負擔,特別是在大型表格中。
  2. 背景任務變更:使用背景任務逐漸將資料更新到新的欄位中。這種方法可以減少對資料函式庫的負擔,但需要確保背景任務持續執行,直到新的程式碼佈署完成。
  3. 雙欄位變更:在資料函式庫中新增一個新的欄位,並修改程式碼以同時支援新舊欄位。當需要讀取資料時,先檢查新欄位是否為空,如果是,則從舊欄位讀取並更新到新欄位中。

雙欄位變更流程圖

@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 雙欄位變更流程圖

rectangle "新增欄位" as node1
rectangle "佈署程式碼" as node2
rectangle "刪除舊欄位" as node3

node1 --> node2
node2 --> node3

@enduml

內容解密:

此圖示展示了雙欄位變更的流程。首先,在第一階段中,新增一個新的欄位(TASK)。然後,修改程式碼以同時支援新舊欄位(JOB和TASK)。在第二階段中,程式碼完全使用新的欄位,並刪除舊的欄位。

資料函式庫版本控制

資料函式庫版本控制是確保應用程式可靠性的關鍵。可以使用工具如Flyway來管理資料函式庫版本,並自動執行資料函式庫變更。

使用Flyway進行資料函式庫版本控制的優點

  • 自動執行資料函式庫變更
  • 確保資料函式庫版本的一致性
  • 簡化佈署流程

案例研究:IOTech佈署

Marcus需要佈署新的程式碼,但新的程式碼需要一個新的資料欄位和索引。為了確保應用程式的可靠性,Marcus使用了功能旗標和雙欄位變更策略。

內容解密:

Marcus的佈署策略允許他在不破壞舊程式碼的情況下佈署新的程式碼。當功能旗標開啟時,程式碼會檢查新欄位是否為空,如果是,則從舊欄位讀取並更新到新欄位中。這種方法確保了應用程式的可靠性,並允許Marcus在需要時回復到舊的程式碼。

建立佈署成品

在許多組織中,佈署需要將一堆積檔案從一個位置複製到另一個位置。每個檔案群組可能需要被複製到不同的目錄。指示通常如下:

  1. ./java/classes/* 複製到 /opt/app_data/libs
  2. 更新 /etc/init.d/start_worker_app.sh 並將 /opt/app_data/libs 新增到 CLASSPATH 變數中。
  3. 重啟應用伺服器。

如果這些任務中的任何一個被遺漏,佈署可能會失敗。此外,很難知道每個任務是否按順序執行。將一個大資料夾複製到另一個伺服器可能會出錯。這就是佈署成品可以發揮作用的地方。本文討論建立代表您正在佈署的程式碼的成品的價值,以及這樣做的一些原因和好處。

當您合併程式碼並透過所有自動化測試和檢查後,在該過程的末尾會產生某種成品。該成品通常是可佈署的程式碼,例如 WAR 檔案。但是,即使用 WAR 檔案,元件仍需要被安裝;WAR 檔案需要應用伺服器作為佈署的一部分,因為這是執行程式碼的東西。一旦您佈署了 WAR 檔案,您可能需要重新載入或重啟 Tomcat,甚至清除一些快取。這是最佳情況,當您有像 Java 這樣產生成品的語言時。但是對於像 Ruby 或 Python 這樣的解譯語言,它們的流程是什麼樣的?它們如何被封裝以進行佈署?這是我想在下一節中關注的內容。

我嘗試將盡可能多的應用程式封裝在一起。如果我可以將安裝指令碼和程式碼捆綁在一起,那對我來說是一個美妙的世界。您可以做一些簡單的事情,例如將安裝程式碼和所有原始碼壓縮到一個檔案中,並將其作為您的可佈署成品傳送。現在,即使您對佈署過程瞭解甚少,您也可以將 zip 檔案複製到伺服器,解壓縮並執行 install.sh 指令碼或其他任何指令碼。這比許多具有冗長的 Microsoft Word 檔案的佈署過程要好得多,這些檔案詳細描述了佈署的神秘藝術。但我更喜歡更進一步,使用作業系統的套件管理系統。

利用套件管理

對於人們自定義封裝軟體進行佈署的所有方式,令人驚訝的是套件管理方法經常被忽視。每個作業系統都有一些方法來管理安裝在其上的各種軟體。根據 RedHat 的 Linux 系統有 RPM,根據 Debian 的系統有 DEB,根據 Windows 的系統有 NuGet,而 macOS 有 Homebrew。所有這些套件管理器都有一些共同點:

  • 它們將套件安裝指令碼與要佈署的實際原始碼結合在一起。
  • 它們具有定義對其他套件依賴關係的規範。
  • 它們處理依賴套件的安裝。
  • 它們為管理員提供了一種機制來查詢已安裝哪些套件。
  • 它們處理他們安裝的軟體的移除。

這些功能被嘗試封裝應用程式軟體的人低估了。讓我們分解一下應用程式安裝正在做什麼。它基本上需要以某種依賴於應用程式的順序執行以下操作:

  • 刪除不必要或衝突的檔案。
  • 安裝應用程式將依賴但不直接提供的任何軟體。
  • 執行任何安裝前的任務,例如建立使用者或目錄。
  • 將所有檔案複製到適當的檔案位置。
  • 執行任何安裝後的任務,例如啟動/重新啟動任何依賴服務。

作業系統套件管理工具允許您將所有這些任務組合成一個單一檔案。此外,如果您執行自己的儲存函式庫伺服器,套件管理系統還將具有取得適當版本的軟體的工具。當適當封裝時,您的佈署流程可以看起來像這樣:

yum install -y funco-website-1.0.15.centos.x86_64

內容解密:

這條命令使用了 yum 套件管理器來安裝 funco-website-1.0.15.centos.x86_64 套件。-y 選項表示自動確認安裝。該命令可以處理所有依賴關係、安裝後指令碼和重啟。它還確保了您的佈署流程是統一的,因為它將在每個安裝上執行完全相同的步驟。

這個單一命令可以處理所有依賴關係、安裝後指令碼和重啟。它還確保了您的佈署流程是統一的,因為它將在每個安裝上執行完全相同的步驟。使用套件管理的另一個好處是,如果您的程式碼依賴於第三方函式庫,您不再依賴於網際網路來確保這些套件的可用性。它們可以儲存在您的 RPM 中作為套件的一部分,而不必擔心編譯過程的更改或傳遞依賴關係被稍微不同地滿足。您在所有環境中獲得完全相同的程式碼和佈署。

FUNCO 網站佈署

對於這個例子,我將使用一個 Linux 網站。我選擇 Linux 是因為我可以使用一個叫做 FPM 的工具,它代表 Effing Package Management。該工具旨在為產生多種套件格式型別提供一個單一介面。DEBs、RPM 和 Brew 套件都有自己的格式來定義套件的構建過程。FPM 建立了一個通用格式,然後允許您透過命令列旗標產生以下套件:

內容解密:

FPM 是一個用於建立多種套件格式的工具。它簡化了建立 DEB、RPM 和 Brew 等不同套件格式的過程。透過使用 FPM,您可以建立一個通用格式,然後使用命令列選項產生所需的套件格式。這使得建立和管理不同作業系統和發行版的套件變得更加容易。

佈署工件的建立與組態管理策略的抉擇

在軟體開發的過程中,建立佈署工件(deployment artifacts)是至關重要的一步。FPM(Effing Package Management)是一個強大的工具,能夠簡化跨多種作業系統的套件建立流程,包括RPM、DEB、Solaris、FreeBSD、TAR、Directory expansion、Mac OS X .pkg files和Pacman(Arch Linux)等。

使用FPM建立佈署工件

FPM提供了一個統一的介面來建立不同格式的套件,這意味著開發者不需要學習多種套件管理工具的語法。將套件建立流程整合到持續整合(CI)伺服器中,可以使佈署工件的建立成為開發和測試工作流程的一部分。許多CI伺服器具有外掛架構,可以擴充套件其功能,例如自動管理工件檔案並將其複製到儲存函式庫伺服器。

專案結構與指令碼

在使用FPM建立套件時,通常會將專案結構化為五個檔案:

  • 預安裝指令碼(Preinstall script)
  • 安裝後指令碼(Post-install script)
  • 解除安裝前指令碼(Pre-uninstall script)
  • 解除安裝後指令碼(Post-uninstall script)
  • 套件建立指令碼(Package build script)

這些指令碼允許在安裝或解除安裝的不同階段執行特定的命令。例如,預安裝指令碼可以用來建立應用程式所需的使用者帳號。

#!/bin/bash
# 檢查應用程式使用者是否存在
/bin/getent passwd webhost > /dev/null
if [[ $? -ne 0 ]]; then
    # 建立使用者
    /sbin/useradd -d /home/webhost -m -s /bin/bash webhost
fi
# 再次檢查使用者是否存在
/bin/getent passwd webhost > /dev/null
exit $?

#### 內容解密:

此指令碼首先檢查名為webhost的使用者是否存在。如果不存在,則建立該使用者並設定其主目錄和Shell。最後再次檢查使用者是否存在,以確保操作成功。這種做法確保了套件安裝前必要的準備工作得以完成。

組態管理與佈署工件的衝突

在使用組態管理的公司中,常常會遇到一個問題:應該由佈署工件還是組態管理工具來處理使用者建立或目錄建立等任務?這取決於公司的組態管理策略。

策略抉擇

  1. 通用伺服器實施:如果公司採用更通用的伺服器實施策略,組態管理工具僅建立基本的應用伺服器,那麼由套件管理軟體處理使用者和目錄建立等細節就非常合理。

  2. 特定伺服器實施:如果組態管理策略專注於建立特定的伺服器例項,那麼可能更傾向於將所有應用程式設定交由組態管理工具處理,以確保應用伺服器的組態一致性和安全性。

軟體封裝與佈署自動化

在現代化的軟體開發與佈署流程中,將應用程式封裝成作業系統支援的套件格式是一個重要的環節。這不僅能夠簡化佈署流程,還能確保應用程式在不同環境中的一致性。本文將探討如何使用FPM(Effing Package Management)工具來建立軟體套件,並討論如何處理組態檔案以適應不同環境。

建立佈署套件

要建立一個軟體套件,首先需要準備好安裝前和安裝後的指令碼。這些指令碼可以用來執行一些必要的設定或清理工作。接下來,需要將所有必要的檔案放置到正確的位置。可以使用臨時目錄來模擬目標系統的目錄結構,例如 /home/build/temp_build。FPM 工具允許你指定安裝路徑的字首(prefix),這樣就可以將檔案安裝到正確的位置。

目錄結構範例

/home/build/temp_build
├── opt
│   └── funco-webapp
│       ├── config
│       └── lib
└── usr
    └── local
        └── bin

使用 FPM 建立套件

FPM 是一個強大的工具,可以用來建立各種格式的套件,如 RPM 或 DEB。以下是一個範例命令,用於建立一個 RPM 套件:

fpm --input-type dir --output-type rpm \
    --name funco-webapp \
    --version 1 \
    --depends "openssl" \
    --depends "openssl-devel" \
    --pre-install pre_install_script.sh \
    --post-install post_install_script.sh \
    -C /home/build/temp_build \
    --prefix / \
    .

內容解密:

  • --input-type dir 指定輸入型別為目錄。
  • --output-type rpm 指定輸出套件的格式為 RPM。
  • --name--version 用於指定套件的名稱和版本。
  • --depends 用於指定套件的依賴關係。
  • --pre-install--post-install 用於指定安裝前和安裝後的指令碼。
  • -C 指定工作目錄。
  • --prefix 指定安裝路徑的字首。

組態檔案的管理

在不同的環境中,組態檔案可能會有所不同。為了避免為每個環境建立不同的套件,可以將組態檔案排除在套件之外。有幾種方法可以處理組態檔案:

  1. 使用環境變數來覆寫預設組態。
  2. 在安裝後指令碼中根據環境調整組態。
  3. 使用組態管理工具來管理組態檔案。

案例分析:IOTech 佈署

Marcus 的團隊面臨著多次佈署的挑戰,傳統的手動佈署方式容易出錯且耗時。透過使用 Linux 系統的套件管理工具,Marcus 將佈署檔案從七頁縮減到一頁,大大簡化了佈署流程。這種方法雖然不是完美的,但它減少了錯誤的可能性並加快了佈署和回復的速度。

動態組態管理的實務應用

在現代化的軟體開發與佈署流程中,動態組態管理扮演著至關重要的角色。尤其是在需要頻繁變更組態或多環境佈署的情況下,如何有效地管理和分發組態資訊成為了一項挑戰。本文將探討幾種常見的動態組態管理模式,包括透過鍵值儲存(Key/Value Store)進行動態組態、組態管理工具的修改以及組態檔案連結等方法。

透過鍵值儲存進行動態組態

近年來,鍵值儲存資料函式庫因其簡單易用且具備HTTP介面的特性,成為儲存組態資訊的熱門選擇。鍵值儲存允許應用程式在啟動時動態地讀取所需的組態引數,無需將組態檔案封裝在應用程式內。常見的鍵值儲存方案包括Consul、etcd和DynamoDB等。

運作流程

  1. 應用程式在啟動時確定自身的IP位址。
  2. 根據本地的組態檔案,應用程式識別出當前的環境名稱以及對應的鍵值儲存服務。
  3. 應用程式連線到指定的鍵值儲存服務,下載與自身環境相關的組態引數。
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 運作流程

rectangle "取得IP位址" as n1
rectangle "讀取環境名稱與鍵值儲存位址" as n2
rectangle "下載組態引數" as n3

n1 --> n2
n2 --> n3

@enduml

內容解密:

  • 步驟1:取得IP位址 - 應用程式透過網路介面取得自身的IP位址,這是識別應用程式例項的基本資訊。
  • 步驟2:讀取環境名稱與鍵值儲存位址 - 組態檔案中包含了環境名稱(如測試或生產環境)以及對應的鍵值儲存服務位址。
  • 步驟3:下載組態引數 - 應用程式根據環境名稱向鍵值儲存服務請求相應的組態引數,並載入這些引數以完成初始化。

這種方法的優點在於能夠靈活地管理不同環境下的組態資訊。然而,其缺點是鍵值儲存服務成為了應用程式啟動的關鍵路徑,一旦鍵值儲存服務不可用,應用程式可能無法正常啟動。

組態管理工具的修改

另一個常見的做法是利用組態管理工具(如Ansible、Puppet或Chef)在佈署過程中動態替換組態檔案。這種方法允許開發人員在原始碼中保留預設的組態檔案,而維運人員則可以透過組態管理工具在佈署時替換為適當的組態。

實作方式

  1. 在RPM包安裝後執行組態管理工具的指令碼,將組態檔案替換為適當的版本。
  2. 組態管理工具可以直接從鍵值儲存服務讀取最新的組態引數,並更新到應用程式的組態檔案中。
@startuml
skinparam backgroundColor #FEFEFE
skinparam defaultTextAlignment center
skinparam rectangleBackgroundColor #F5F5F5
skinparam rectangleBorderColor #333333
skinparam arrowColor #333333

title 實作方式

rectangle "安裝RPM包" as n1
rectangle "執行組態管理工具" as n2
rectangle "從鍵值儲存更新組態檔案" as n3

n1 --> n2
n2 --> n3

@enduml

內容解密:

  • 步驟1:安裝RPM包 - 透過包管理工具安裝應用程式的RPM包。
  • 步驟2:執行組態管理工具 - 在安裝完成後執行組態管理工具,以替換或更新組態檔案。
  • 步驟3:從鍵值儲存更新組態檔案 - 組態管理工具從鍵值儲存服務中讀取最新的組態引數,並更新到本地的組態檔案中。

這種方法的優勢在於能夠結合鍵值儲存的靈活性與組態管理工具的強大功能,同時避免了直接依賴鍵值儲存服務進行應用程式啟動。

組態檔案連結

另一種簡單直接的方法是在安裝過程中將組態檔案連結到指定的位置。這種做法將組態檔案的管理權交給了維運人員,讓他們能夠靈活地控制不同伺服器上的組態。

實作細節

  1. 將組態檔案存放在一個統一的位置,如/opt/configs
  2. 在安裝過程中,將應用程式所需的組態檔案連結到正確的位置。
/opt/apps -> /opt/configs/app_config.properties

內容解密:

  • 統一存放組態檔案 - 將所有伺服器的組態檔案集中存放在一個統一的位置,便於管理和維護。
  • 建立符號連結 - 在應用程式目錄中建立指向統一存放位置的符號連結,確保應用程式能夠正確讀取到所需的組態檔案。

這種方法的優點是簡單易行,且能夠讓維運人員對組態檔案進行精細控制。然而,其缺點是需要額外維護組態檔案的位置和連結關係。

自動化佈署流程與組態管理的重要性

在現代軟體開發與維運的整合過程中,組態管理(Configuration Management)扮演著至關重要的角色。隨著 DevOps 文化的推廣,組態管理已成為確保環境一致性、提升佈署效率以及強化系統可靠性的關鍵實踐。

為何需要組態管理

組態管理能夠消除手動組態伺服器所帶來的錯誤與不一致性。藉由使用組態管理工具,開發團隊能夠將組態檔案納入版本控制系統,從而享受到與原始碼相同的開發流程優勢,包括同儕審查、審核歷史以及變更追蹤等。

組態管理的優勢

  1. 環境一致性:組態管理確保了不同環境(開發、測試、生產等)之間的組態一致性,減少了因環境差異導致的錯誤。
  2. 自動化:透過組態管理工具,可以自動化伺服器的組態和軟體安裝,大幅減少手動操作的錯誤。
  3. 資料查詢:大多陣列態管理工具提供了資料查詢功能,可以根據特定條件(如伺服器類別或可用記憶體)動態設定引數。
  4. 版本控制:將組態檔案納入版本控制系統,能夠對組態變更進行跟蹤和審核,提高了基礎設施的可管理性和透明度。
  5. 遠端命令執行:許多組態管理工具支援遠端命令執行,能夠在多台伺服器上批次執行命令,大大提高了維運效率。

佈署流程自動化

在建立了佈署構件(deployment artifact)之後,下一步是將各個流程串聯起來,形成自動化的佈署Pipeline(deployment pipeline)。這涉及到以下幾個關鍵步驟:

  1. 準備工作:執行資料函式庫結構變更等前期準備工作。
  2. 節點下線:將待更新的節點從負載平衡池中移除,使其不再處理請求。
  3. 佈署軟體包:在該節點上佈署新的軟體包。
  4. 驗證佈署結果:確認佈署是否成功。
  5. 節點上線:將更新完成的節點重新加入負載平衡池。
  6. 重複執行:對其他節點重複上述步驟。

安全佈署新應用

假設有一個簡單的 Web 應用,前端有負載平衡器,後端是多台 Web 伺服器。佈署新版本時,首先需要將待更新的節點從負載平衡池中移除。具體方法可以是透過 API 呼叫直接將節點從負載平衡池中移除,或者透過安裝根據主機的防火牆規則來阻止流量進入該節點,以模擬節點故障,使負載平衡器自動將其從池中移除。

# 範例:使用 firewalld 阻止流量
firewall-cmd --zone=public --add-rich-rule='rule family="ipv4" source address="負載平衡器IP" port port="443" protocol="tcp" reject' --permanent
firewall-cmd --reload

內容解密:

  1. firewall-cmd:這是 Linux 系統中用於管理 firewalld 防火牆的命令列工具。
  2. --zone=public:指定作用的區域為 public,表示這條規則適用於公共區域。
  3. --add-rich-rule:新增一條豐富規則,這種規則允許更複雜的條件設定。
    • rule family="ipv4":指定該規則僅適用於 IPv4 協定。
    • source address="負載平衡器IP":指定來源 IP 地址為負載平衡器的 IP。
    • port port="443" protocol="tcp":指定規則作用於 443 埠,且協定為 TCP(通常是 HTTPS 服務)。
    • reject:拒絕來自指定來源 IP 的連線請求。
  4. --permanent:使該規則永久生效,即使重啟系統也會保留。
  5. firewall-cmd --reload:重新載入防火牆規則,使剛才新增的規則立即生效。

透過這種方式,可以模擬節點故障,使負載平衡器將其從服務池中移除,從而安全地進行軟體更新。

自動化佈署的最佳實踐

  1. 持續整合與持續佈署(CI/CD):將自動化測試、構建和佈署流程整合到 CI/CD Pipeline中,實作快速迭代和交付。
  2. 基礎設施即程式碼(IaC):使用 IaC 工具(如 Terraform 或 Ansible)來管理和組態基礎設施,確保環境的一致性和可重複性。
  3. 監控與日誌記錄:實施全面的監控和日誌記錄機制,以便及時發現和解決佈署過程中的問題。

綜上所述,組態管理和自動化佈署是現代 DevOps 實踐中的核心要素。透過採用這些技術和工具,團隊能夠實作更高效、更可靠的軟體交付流程,從而提升整體的開發和維運效率。