返回文章列表

自動化佈署策略與風險降低

本文探討軟體佈署流程的自動化策略,如何降低佈署風險,並提升效率。從簡單自動化指令碼到複雜任務的自動化方法論,逐步引導讀者理解自動化佈署的優勢。同時,文章也分析了佈署的多個層面,包括功能佈署、艦隊佈署、構件佈署和資料函式庫佈署,並以實際案例說明佈署週期對業務的影響。最後,文章還探討了 Docker 和

軟體工程 DevOps

自動化佈署是現代軟體開發流程中不可或缺的一環,能有效降低風險、提升效率並加速產品迭代。從簡單的指令碼自動化到複雜任務的分解與風險評估,開發者需要逐步提升自動化程度,並建立完善的佈署策略。佈署並非單一動作,而是涵蓋程式碼佈署、資料函式庫變更、組態更新等多個層面,每個環節都需要仔細規劃和自動化。功能旗標的使用能有效控制新功能的發布,降低上線風險。此外,準確的預生產環境對於佈署流程的信心至關重要,其架構和組態應盡可能與生產環境保持一致,才能有效模擬真實使用者行為並及早發現潛在問題。容器技術如 Docker 和 Kubernetes 的應用,能進一步提升佈署效率和環境一致性,但需要團隊的技術能力和生產環境的配合。

自動化任務的進階思維

在撰寫更進階的指令碼時,開發者可能會嘗試新增額外的錯誤處理機制,以瞭解如何從特定條件中還原。然而,對於初次嘗試自動化的團隊來說,上述做法已經足夠。這樣的自動化指令碼能夠為操作員提供一致性和可預測性,從而提升工作效率。指令碼的執行訊息、登出時間以及執行順序都保持一致,這些都有助於減少人為錯誤。

隨著對自動化任務的熟悉度增加,開發者可以開始引入更多的錯誤處理機制,並減少對使用者確認的依賴。如果某個自動化流程在長時間內執行無誤,例如廣播訊息指令碼(broadcastmessage.sh)500次無失敗,那麼額外的錯誤處理機制可能就不再那麼重要。關鍵在於不要認為自動化軟體是靜態的,無論其複雜程度如何。開發者可以持續迭代和改進自動化流程,使其變得更強壯、更少依賴使用者,並提供更大的幫助。

自動化的未來改進方向

在自動化的生命週期中,後續改進方向可能包括:

  • 記錄整個流程的開始和結束時間
  • 將更新的記錄數量記錄到稽核系統中
  • 記錄失敗訂單的金額以供會計使用

開發者可以持續改進自動化流程,隨著對任務及其可能結果的熟悉度增加,讓自動化系統不斷演進。不要讓「完美」成為「良好」的敵人,先自動化那些你覺得舒適的步驟,然後隨著專注度的提升,讓自動化不斷演進。持續的維護是必須考慮的,因為環境和流程將不斷演變。

自動化複雜任務的方法論

簡單任務通常路徑直接,容易上手。然而,複雜任務往往需要從一個來源檢索資訊以作為另一個任務的輸入。在執行時,這些任務可能存在未知數,使得確定回應或輸入值不像平常那樣直接,但這些回應的價值仍然可以透過有限的變數來瞭解。

例如,在雲端基礎設施中,即使是簡單的任務,如重新啟動服務,也可能變得複雜。由於雲端的動態性質,在設計時可能無法確定哪些伺服器正在執行需要重新啟動的服務。在開始自動化重新啟動之前,必須能夠識別工作需要執行的位置。

逐步處理複雜任務

  1. 將複雜任務分解為一系列簡單任務。
  2. 評估每個簡單任務,以瞭解錯誤執行的負面影響或後果。將其從1到10進行排名。
  3. 評估透過自動化或指令碼執行該任務的難度,並對檢索準確值的信心進行排名,從1到10。
  4. 將這兩個維度繪製在四象限圖中,以評估整體難度。
  5. 根據任務在四象限圖中的位置,決定是否應該手動執行(提示)或納入自動化流程中。

風險評估與自動化決策

透過繪製風險評估圖(如圖7.5所示),開發者可以根據簡單任務最終所在的象限,決定自動化的難易程度以及應該使用的自動化互動型別。

自動化高度複雜任務的挑戰

高度複雜任務的自動化是一項艱鉅的任務,需要經驗豐富的團隊專注於建立自動化系統。雖然高度複雜任務的自動化是可能的,但這部分的討論將在書籍的後續章節中進行,在讀者瞭解更多相關主題之後再進行詳細闡述。

圖表解說:風險評估四象限圖

此圖示展示瞭如何根據任務的後果嚴重性和自動化信心來評估風險,並決定是否應該完全自動化、部分自動化或是手動執行某個任務。

圖表內容解密:
  • 低後果 & 高信心: 自動化該任務
  • 高後果 & 高信心: 謹慎自動化,可能需要使用者確認
  • 低後果 & 低信心: 謹慎自動化,可能需要使用者確認
  • 高後果 & 低信心: 使用手動輸入

透過這種方法,開發者可以系統性地評估和改進自動化流程,從而提高工作效率和安全性。

減少佈署風險:自動化與佈署策略的探討

在軟體開發的過程中,佈署(Deployment)是一項關鍵的步驟。佈署的頻率和效率直接影響到軟體的品質和業務的成功與否。本篇文章將探討如何透過自動化和適當的佈署策略來減少佈署過程中的風險和恐懼。

佈署的重要性與挑戰

佈署是將開發完成的軟體或功能交付給使用者的過程。這個過程如果處理得不好,可能會導致軟體品質下降、業務機會流失等問題。傳統的季度或年度佈署週期可能會導致功能積壓,從而錯失最佳的市場時機。

案例分析:錯失商機

Patrick 是 FunCo 公司的產品組織負責人。一天,他接到業務部門 Jaheim 的電話,Jaheim 正在爭取與 Quantisys 公司的大型訂單。Quantisys 對 FunCo 的軟體非常感興趣,但需要整合他們目前的計費系統。Jaheim 希望開發團隊能夠優先開發這個功能,以便在下一次季度發布前完成。

然而,由於 FunCo 的季度發布週期,Patrick 告知 Jaheim 即使能夠優先開發該功能,也要等到兩個月後的下一次發布週期才能交付。這導致 Quantisys 公司選擇了其他競爭對手的解決方案,最終 FunCo 錯失了這個重要的商機。

佈署週期對業務的影響

這個案例突顯了長佈署週期對業務的負面影響。軟體功能就像庫存一樣,只有當它被交付給使用者時才開始產生價值。如果功能不能及時交付,就會錯失商機,甚至可能變得毫無價值。

自動化佈署的優勢

自動化是解決佈署問題的關鍵。透過自動化,可以減少佈署過程中的手動錯誤,提高佈署的效率和可靠性。同時,自動化也可以幫助團隊更頻繁地進行佈署,從而降低每次佈署的風險。

自動化的層面

佈署過程可以分為多個層面,包括程式碼佈署、資料函式庫變更、組態變更等。每個層面都需要仔細規劃和自動化,以確保整個佈署過程的順暢。

圖示:佈署層面

此圖示展示了佈署的不同層面及其相互關係。透過自動化這些步驟,可以顯著降低佈署風險。

減少佈署風險的策略

  1. 提高自動化程度:盡可能地自動化佈署過程中的每個步驟,包括測試、驗證和發布。
  2. 縮短佈署週期:透過自動化和流程最佳化,縮短佈署週期,使功能能夠更快速地交付給使用者。
  3. 使用功能旗標(Feature Flags):透過功能旗標,可以在不影響現有功能的情況下,發布新的功能或變更。
  4. 持續改進:不斷收集反饋,最佳化佈署流程,提高團隊的效率和信心。

程式碼範例:功能旗標的使用

def get_feature_status(feature_name):
    # 從組態或資料函式庫中取得功能旗標狀態
    return config.get(feature_name, False)

def main():
    feature_name = 'new_feature'
    if get_feature_status(feature_name):
        # 如果功能旗標開啟,則執行新功能
        new_feature()
    else:
        # 否則執行舊邏輯
        old_logic()

def new_feature():
    # 新功能的實作
    print("New feature is enabled.")

def old_logic():
    # 舊邏輯的實作
    print("Old logic is executed.")

if __name__ == "__main__":
    main()

內容解密:

上述程式碼展示瞭如何使用功能旗標來控制新功能的發布。get_feature_status 函式用於取得特定功能旗標的狀態,而 main 函式則根據該狀態決定是否執行新功能或舊邏輯。這種方法允許開發者在不修改現有程式碼的情況下,透過組態或資料函式庫變更來控制新功能的發布。

佈署的多層面探討

在軟體開發與佈署的過程中,瞭解不同層面的佈署概念至關重要。佈署可以分為多個層次,每個層次都有其特定的關注點和挑戰。這些層次包括功能佈署(Feature Deployment)、艦隊佈署(Fleet Deployment)、構件佈署(Artifact Deployment)以及資料函式庫佈署(Database Deployment)。

佈署的層次結構

  1. 功能佈署:這是指在應用程式中啟用新功能或變更現有功能的過程。功能佈署允許開發者透過簡單的組態旗標來控制新功能的開放。

  2. 艦隊佈署:艦隊佈署涉及將新的程式碼或更新安裝到多台伺服器上。這需要仔細規劃操作的順序,以確保在佈署過程中保持應用的可用性。

  3. 構件佈署:構件佈署是指將新的程式碼安裝到單一伺服器上的過程。它關注的是將新的程式碼安裝到伺服器上,而不涉及與其他節點的協調或處理終端使用者的流量。

  4. 資料函式庫佈署:資料函式庫佈署涉及對資料函式庫進行變更,以支援新的程式碼或應用程式的需求。這可能包括更新資料函式庫架構或操縱資料。

佈署層次的重要性

將這些佈署過程視為整體的不同部分是非常有價值的。在很多情況下,佈署過程會將這些步驟混合在一起。如果沒有仔細考慮如何回復單一功能,就意味著功能佈署和回復是構件或艦隊回復的一部分。這種思維方式可以幫助建立一個更加模組化和可控的發布過程。

為什麼資料函式庫佈署至關重要

在大多數情況下,資料函式庫佈署被視為佈署過程的第一步。這是由於資料函式庫的敏感性以及它是分享基礎設施的事實。每個應用伺服器都會使用相同的資料函式庫,因此確保其佈署順利進行應該是首要關注點。

此圖示展示了不同佈署層次之間的關係。

依序進行的佈署步驟

  1. 資料函式庫佈署:首先進行資料函式庫的變更,以確保新的程式碼能夠正確執行。

  2. 構件佈署:接著,將新的程式碼安裝到單一伺服器上。

  3. 艦隊佈署:然後,將構件佈署擴充套件到整個伺服器艦隊,同時需要協調多台伺服器之間的變更。

  4. 功能佈署:最後,透過啟用新功能或變更現有功能來完成佈署。

IOTech 公司的佈署挑戰

IOTech 是一家虛構的公司,專門開發監控軟體。Marcus 正在開發一個新功能,該功能需要在幾週內進行迭代。由於該功能的性質難以在低環境中復現,因此 Marcus 需要仔細規劃其佈署結構。

面臨的挑戰

  • 需要進行多項資料函式庫變更,並確保程式碼與資料函式庫架構的相容性。
  • 需要能夠在不影響整個應用的情況下回復變更。
  • 需要能夠透過組態旗標來控制新功能的開啟和關閉。

將佈署變成例行事務

佈署流程詳細描述了將程式碼轉變為客戶可使用的狀態所需的步驟。這涉及將程式碼從開發或測試環境轉移到客戶互動的生產伺服器。也包括資料函式庫層級的操作,以確保程式碼和資料函式庫架構彼此相容。

到目前為止,我已經將程式碼和其提供的功能描述為一體的。佈署新程式碼意味著佈署新功能。但是在本章和後續章節中,我將闡述新程式碼的交付可以與新功能的交付解耦——就像資料函式庫架構變更可以分階段進行,而不是一次性完成。

準確的預生產環境

預生產環境的準確性是整個流程中後續步驟充滿信心的關鍵。首先,讓我闡述我對預生產環境的定義:任何非生產環境的應用環境。

並非所有預生產環境都是一樣的。你可能有一個預生產環境,其中的節點非常小,資料函式庫是生產資料的一個較小子集。但是,環境的組態方式應該相同,除了任何與效能相關的調優。可能不同的因素包括生產和預生產之間的資料函式庫連線執行緒數量,因為資料函式庫伺服器的大小可能會大不相同。但是,如果你在生產環境中執行Apache HTTPD 2.4.3,那麼在預生產環境中也應該執行同樣的版本。如果你在生產環境中強制所有流量使用傳輸層安全(TLS),那麼在預生產環境中也應該強制所有流量使用TLS。

你對一個環境模擬生產的信心越大,你對佈署流程的信心也就越大。不幸的是,測試環境經常成為成本削減的目標。複製整個生產環境可能變得過於昂貴,因此人們開始問:“我們至少可以做什麼並仍然獲得價值?”測試環境變成了生產環境的一個縮影,不僅在硬體效能上如此。

測試環境可能是當前生產基礎設施的縮小版本;在生產環境中有八或九個不同的應用伺服器,但這些服務被簡化為單一伺服器,以獨立程式的形式執行八或九個應用。當然,這總比沒有好,但並不能真正反映生產環境的現實。

重點應該放在確保環境在架構上相同。服務交付的方式模式應該在預生產環境中複製,即使伺服器的大小和數量不同。你在開發過程中越接近生產環境,這些環境就應該越相似。

內容解密:

  • 預生產環境應盡可能模擬生產環境,以增加對佈署流程的信心。
  • 雖然預生產環境在規模上可能與生產環境不同,但其架構和組態應保持一致。
  • 使用容器技術(如Docker)和協調工具(如Kubernetes)可以幫助實作更一致的環境。

此圖示展示了從開發到生產的流程,每一步都經過嚴格的測試,以確保程式碼的品質和可靠性。

Docker和Kubernetes:新技術,相同問題

你可能至少聽說過Docker和Kubernetes。Docker是目前最流行的容器技術。但這引出了一個問題:“什麼是容器?”容器允許開發人員將應用程式的所有必要元件封裝到一個單一的工件(容器)中。在容器內部,是執行應用程式所需的所有函式庫、檔案、應用程式和其他相依性。容器利用Linux核心的兩個關鍵功能:cgroups和namespaces。這些功能允許你將主機上的容器與其他容器完全隔離開來。

內容解密:

  • Docker是一種流行的容器技術,允許開發人員封裝應用程式及其相依性。
  • 容器利用Linux核心的功能,如cgroups和namespaces,來實作隔離。
  • Kubernetes是一種用於自動化佈署、擴充套件和管理容器化應用程式的協調工具。
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title 自動化佈署策略與風險降低

package "系統架構" {
    package "前端層" {
        component [使用者介面] as ui
        component [API 客戶端] as client
    }

    package "後端層" {
        component [API 服務] as api
        component [業務邏輯] as logic
        component [資料存取] as dao
    }

    package "資料層" {
        database [主資料庫] as db
        database [快取] as cache
    }
}

ui --> client : 使用者操作
client --> api : HTTP 請求
api --> logic : 處理邏輯
logic --> dao : 資料操作
dao --> db : 持久化
dao --> cache : 快取

note right of api
  RESTful API
  或 GraphQL
end note

@enduml

此圖示展示了使用Docker和Kubernetes佈署和管理容器化應用程式的流程,從開發到客戶服務。

讓佈署成為例行事務

相較於虛擬機器,容器在資源利用上更為輕量,因為它們分享主機作業系統的核心。這消除了虛擬機器中存在的許多資源重複。容器啟動速度也遠快於虛擬機器,使其在大型佈署以及本地開發環境中極具吸引力。

Kubernetes 是管理 Docker 容器佈署、組態和管理的工具。它最初由 Google 開發,現已成為 Docker 佈署管理工具的長官者。Kubernetes(有時簡稱為 K8s)具備多項功能,以支援人們在生產環境中管理容器時遇到的許多挑戰,例如使容器對其他服務公開可存取、管理容器的磁碟卷、記錄、容器間通訊以及提供網路存取控制等。Kubernetes 是一套龐大的軟體,需要相當的關注才能有效管理。

這些技術是當今的熱門選擇,它們的價值不可否認。它們具有極強的變革性,很難抗拒使用它們。如果你在本地開發環境中使用它們,可以節省大量管理和維護本地開發環境的時間和精力。

然而,當你從本地開發環境轉移到其他非本地測試環境時,問題可能會出現。雖然開發者可能熱衷於在 Docker/Kubernetes 生態系統中開展更多工作,但生產支援團隊有時卻不願意徹底改變他們目前的工作方式。

佈署至生產環境的重要性

這就造成了相當落後的情況:你的預發布環境在技術上比生產環境更為先進。對某些人來說,這種情況比預期的更容易被接受。如今,你的應用程式正在一個對你的履歷更為有利的環境中進行測試,但它與實際生產環境仍幾乎沒有相似之處。

這並不是說我反對 Docker 或 Kubernetes。我是這兩項技術的忠實粉絲。但如果你要在預發布環境中使用它們,我強烈建議你也在生產環境中使用它們。

首先,如果你做得測試正確,你將需要解決那些操作這些系統的人所抱怨的所有棘手問題。如果你已經在預發布環境中解決了這些問題,那麼在生產環境中解決它們所需的額外努力是微不足道的。具有諷刺意味的是,大多數人在預發布環境就停下了腳步,因為他們對佈署感到恐懼。他們透過一些神奇的方式讓 Docker/Kubernetes 在預發布環境中運作,並似乎對此感到滿意。如果它壞了,嗯,它只是預發布環境。

為何需要在生產環境中使用相同的技術

這種態度將導致許多問題在測試中未被發現,並最終釋放到生產環境中。更不用說,你現在還需要承擔確保你的軟體在容器化和虛擬機器模式下都能正常運作的認知負擔,這導致了多種不同的生命週期管理方式。

佈署不同、補丁不同、組態管理不同、重啟不同——每一個不同之處都需要針對兩個平台的解決方案。

預發布環境永遠無法與生產環境完全相同

在許多組織中,人們投入了大量的精力和努力,使預發布環境的行為與生產環境完全一致。但未被說出的真相是,生產環境和預發布環境幾乎永遠不會完全相同。預發布環境中缺失的最大元素往往是系統中最容易出問題的元素:使用者和並發。

使用者是難以預測的生物。他們總是會做一些系統設計者意想不到的事情。從以意想不到的方式使用某個功能到故意進行惡意行為。我曾見過使用者試圖自動化他們自己的工作流程,從而導致完全無意義的行為,其速度和頻率都非人類所能及。我也見過使用者試圖將龐大的電影檔案上傳到一個原本只期待接收 Word 檔案的應用程式中。

使用者行為的不可預測性

使用者總是會嘗試在你的系統中完成一些獨特而有趣的事情,如果你的預發布環境中沒有真實使用者,你就必須為系統未曾測試過的大量場景做好準備。一旦你遇到其中一個場景,你就可以將測試案例新增到你的迴歸測試套件中,但要知道這個發現、修復、驗證的迴圈是你將不斷經歷的。要接受這個現實,而不是不斷與之對抗,這是你理解為什麼你的預發布環境無法揭示測試週期中失敗的原因的唯一方法。

許多公司嘗試透過使用合成交易來產生使用者活動,從而解決這個問題。

合成交易是指被創造出來模擬正常使用者活動的指令碼或工具。它們經常被用來從使用者的角度監控應用程式,或者用來模擬那些沒有足夠真實使用者流量的系統上的使用者活動。

合成交易是一個很好的選擇,它們努力使預發布環境更像生產環境。但是不要誤以為這是你的測試問題的萬能藥。同樣的問題仍然存在,因為你不可能預料到所有終端使用者可能會做的事情。你可以盡力捕捉所有的案例,並不斷新增合成測試,但你總是在追趕使用者行為。再加上應用程式很少是完整的,你將不斷新增新的功能,這使得情況更加複雜。