在前面的內容中,我們討論了從單一來源建立多個伺服器例項的概念,並建議使用乾淨建置的伺服器映像。這一章將探討如何最有效地實作這些建議。
與系統中的大多數元素一樣,伺服器映像的建置和更新應該透過程式碼以可重複的方式進行。當你對映像進行變更(例如安裝最新的作業系統補丁)時,這種方法能確保建置過程的一致性。
透過自動化、程式碼驅動的流程來建置、測試、交付和更新伺服器映像,你可以更輕鬆地保持伺服器的最新狀態,並確保其合規性和品質。
伺服器映像的生命週期
基本的伺服器映像生命週期涉及從原始來源建置自訂映像,如下圖所示:
graph LR A[原始映像] --> B[建置流程] B --> C[自訂映像] C --> D[佈署使用] D --> E[更新需求] E --> B
建置伺服器映像
大多數基礎設施管理平台都有用於建立伺服器例項的映像格式。Amazon 有 AMI (Amazon Machine Images),Azure 有受管映像 (Managed Images),VMware 有 VM 範本。這些託管平台提供預先封裝的標準映像,包含常見的作業系統和發行版,讓你可以建立伺服器而無需自行建置映像。
為什麼要建置自訂伺服器映像?
大多數團隊最終會建置自訂映像,而不是使用平台供應商提供的標準映像。常見的原因包括:
符合組織治理規範
許多組織,特別是受監管行業的組織,需要確保他們按照更嚴格的準則建置伺服器。這些規範可能包括特定的安全設定、合規性檢查點和標準化的系統設定,這些在標準映像中可能無法滿足。
安全強化
標準伺服器映像通常安裝了許多不同的套件和工具,以適應各種使用情境。透過建置自訂映像,你可以將系統精簡到最低必要元素。安全強化可以包括:
- 停用或移除未使用的使用者帳戶和系統服務
- 停用所有非嚴格需要的網路埠
- 鎖設定檔案系統和資料夾許可權
- 實施更嚴格的密碼政策和存取控制
效能最佳化
為安全而採取的許多強化步驟,如停止或移除不需要的系統服務,也能減少伺服器使用的 CPU 和記憶體資源。最小化伺服器映像的大小也使建立伺服器例項的速度更快,這在擴充套件和復原情境中特別有用。
安裝通用套件
你可以在伺服器映像上安裝一組標準的服務、代理和工具,確保它們在所有例項上都可用。例如:
- 監控代理
- 系統使用者帳戶
- 團隊特定的工具和維護指令碼
- 安全掃描工具
- 日誌收集代理
為伺服器角色建置映像
本章的許多範例不僅是建置標準的通用映像。你可以建置針對特定目的量身定製的伺服器映像,例如:
- 容器叢集節點
- 應用程式伺服器
- CI 伺服器代理
- 資料函式庫伺服器
- 負載平衡器
如何建置伺服器映像
建置伺服器映像有多種方法,每種方法都有其優缺點。玄貓在多年的實踐中發現,選擇正確的建置方法對於確保映像的一致性、安全性和可維護性至關重要。
接下來,我們將探討幾種主要的伺服器映像建置方法,並分析它們的適用場景和實施策略。
基礎設施即程式碼:使用管道建立與交付伺服器映像
在現代基礎設施管理中,伺服器映像的自動化建立與交付已成為關鍵實踐。透過管道(Pipeline)機制,我們能夠確保伺服器映像的一致性、安全性與可靠性,同時加速佈署流程。本文將探討如何使用管道來測試和交付基礎設施程式碼變更,特別是伺服器映像的建立流程。
為何使用管道建立伺服器映像?
使用管道建立伺服器映像有諸多優勢。首先,它提供了一致性的建立過程,確保每次產生的映像都遵循相同的標準。其次,透過管道整合,可以安全地在整個環境中推出作業系統更新和修補程式,頻率甚至可達每週或每日。
玄貓建議頻繁地建立新的伺服器映像(例如每週一次),而非長時間隔(如數月一次)。這符合持續測試和交付變更的核心實踐。等待時間越長,新映像包含的變更越多,測試、發現和修復問題所需的工作也隨之增加。
伺服器映像管道的基本架構
一個基本的伺服器映像管道通常包含三個主要階段:
graph LR A[建立階段] --> B[測試階段] B --> C[發布階段] style A fill:#f9d77e style B fill:#a3c9ff style C fill:#b5f7b5
讓我們探討每個階段的細節。
伺服器映像的建立階段
建立階段自動實作線上映像建立流程或離線映像建立流程。此階段產生一個伺服器映像,後續階段將其視為發布候選版本。
graph LR A[映像建立程式碼] --> D[建立階段] B[來源映像] --> D C[伺服器設定程式碼] --> D D --> E[發布候選映像] style D fill:#f9d77e style E fill:#a3c9ff
你可以設定伺服器映像建立階段,使其在映像輸入元素發生變更時自動執行。例如:
- 有人提交了映像建立程式碼的變更,如Packer範本
- 供應商發布了新版本的來源映像,如作業系統供應商提供的AMI
- 你對用於伺服器映像的伺服器設定程式碼進行了變更
- 套件維護者發布了伺服器映像上安裝的套件的新版本
實際上,像作業系統套件這樣的來源元素的許多變更很難自動偵測並用來觸發管道。你可能也不想為每個套件更新建立新的伺服器映像,特別是如果映像使用了數十甚至數百個套件。
因此,你可以只為重大變更(如來源伺服器映像或映像建立程式碼)自動觸發新映像的建立。然後,你可以實施定期建立(例如每週一次)來整合所有較小來源元素的更新。
建立階段的結果是一個可用作發布候選版本的伺服器映像。如果你想在使用映像前對其進行測試(對於任何非簡單的使用情境都建議這樣做),那麼此時不應將映像標記為可用。你可以根據前面給出的指導,用版本號標記映像。你也可以標記它以表明它是未經測試的發布候選版本,例如,Release_Status=Candidate
。
伺服器映像的測試階段
自動測試新建立的映像至關重要。人們通常使用與測試伺服器程式碼相同的測試工具來測試伺服器映像。
如果你線上建立伺服器映像,你可以在設定伺服器例項後、關閉並將其轉換為映像前,在該伺服器例項上執行自動化測試。但這有兩個問題:
測試可能會汙染映像,留下測試檔案、日誌條目或其他殘留物。它們甚至可能留下使用者帳戶或其他從映像建立的伺服器的存取途徑。
在將伺服器例項轉換為映像前對其進行測試可能無法可靠地複製從映像建立的伺服器。將例項轉換為映像的過程可能會改變伺服器的重要方面,如使用者存取許可權。
測試伺服器映像最可靠的方法是從最終映像建立並測試新例項。這樣做的缺點是獲得測試反饋的時間較長。
graph LR D[D] A[發布候選映像] --> B[建立臨時例項] B --> C[執行自動化測試] C --> D{測試透過?} D -->|是| E[標記映像為已測試] D -->|否| F[標記映像為測試失敗] style B fill:#a3c9ff style C fill:#a3c9ff style D fill:#f7b5b5 style E fill:#b5f7b5 style F fill:#f7b5b5
因此,典型的伺服器映像測試階段會取得建立階段中建立的映像的識別碼,使用它來建立臨時例項,並對該例項執行自動化測試。如果測試透過,則該階段會標記映像,表明它已準備好進入管道的下一階段。
伺服器映像的交付階段
你的團隊的映像管道可能有額外的階段用於其他活動,例如安全測試。最終,透過測試階段的映像版本會被標記為可供使用。
在某些系統中,建立映像的管道包括使用新映像重建伺服器的階段。它可以為每個交付環境執行一個階段,可能觸發應用程式佈署和測試階段。
graph LR A[已測試映像] --> B[佈署到測試環境] B --> C[測試環境測試] C --> D[佈署到預生產環境] D --> E[預生產環境測試] E --> F[佈署到生產環境] style A fill:#b5f7b5 style B fill:#a3c9ff style C fill:#a3c9ff style D fill:#a3c9ff style E fill:#a3c9ff style F fill:#b5f7b5
在不同團隊負責管理基礎設施和環境的系統中,映像管道可能在將映像標記為可供使用後結束。其他團隊的管道將新映像版本作為輸入。
使用多個伺服器映像
某些團隊只維護單一伺服器映像。這些團隊透過在建立伺服器例項時應用伺服器設定角色來建立他們需要的不同型別的伺服器。然而,其他團隊發現維護多個伺服器映像是有用或必要的。
需要多個映像的情境
你需要多個映像來支援:
多個基礎設施平台:如果你的組織使用多雲、多平台或混合雲策略,你需要為每個平台建立和維護單獨的伺服器映像。
多個作業系統:如果你支援多個作業系統或發行版,如Windows、Red Hat Linux和Ubuntu Linux,你需要為每個作業系統維護單獨的映像。
不同硬體架構:如果你在不同的CPU架構(如x86和ARM)上執行伺服器例項,你可能需要為每個架構建立幾乎相同的伺服器映像。
不同伺服器角色:當為角色設定伺服器涉及安裝太多軟體時,如應用程式伺服器,將角色設定烘焙到專用映像中可能更好。
伺服器映像的分層策略
擁有大量根據角色的伺服器映像的團隊可能考慮分層建立它們。例如,建立一個基本作業系統映像,其中包含你想在所有伺服器上安裝的預設套件和設定。然後使用此映像作為來源映像,建立更具體的根據角色的映像,如應用程式伺服器、容器節點等。
graph TD A[基本Linux映像] --> B[應用程式伺服器映像] A --> C[容器主機節點映像] B --> D[購物應用程式映像] B --> E[搜尋服務映像] style A fill:#f9d77e style B fill:#a3c9ff style C fill:#a3c9ff style D fill:#b5f7b5 style E fill:#b5f7b5
在這個例子中,ShopSpinner團隊使用基本Linux映像作為建立應用程式伺服器映像和容器主機節點映像的來源映像。應用程式伺服器映像預先安裝了Java和Tomcat。團隊又使用此映像作為建立預先安裝特定應用程式的映像的來源映像。
ShopSpinner購物應用程式和搜尋服務經常需要根據一天中不同時間的可變流量負載進行擴充套件。因此,預先烘焙好映像很有用。團隊從更通用的應用程式伺服器映像建立其他應用程式和服務的伺服器例項,因為團隊不經常建立這些例項。
每個伺服器映像由單獨的管道建立,在輸入映像變更時觸發。反饋迴圈可能非常長。當團隊變更基本Linux映像時,其管道完成並觸發應用程式伺服器和容器主機管道。然後,應用程式伺服器映像管道觸發管道,建立根據它的伺服器映像的新版本。如果每個管道需要10-15分鐘執行,這意味著變更需要長達45分鐘才能傳播到所有映像。
跨伺服器映像分享程式碼
即使在根據繼承的模型中,伺服器角色相互繼承設定,你也不一定需要按照我們剛才描述的分層模型建立映像。你可以將伺服器設定程式碼分層到伺服器角色定義中,並直接應用所有程式碼從頭開始建立每個映像。
graph LR A[基本Linux設定] --> D[建立基本Linux映像] A --> E[建立應用程式伺服器映像] B[應用程式伺服器設定] --> E A --> F[建立搜尋服務映像] B --> F C[搜尋服務設定] --> F style D fill:#f9d77e style E fill:#a3c9ff style F fill:#b5f7b5
這種策略實作了相同的分層模式,但它透過結合每個角色的相關設定程式碼並一次性應用所有程式碼來實作。因此,建立應用程式伺服器映像不使用基本伺服器映像作為其來源映像,而是將用於基本伺服器映像的所有程式碼應用於應用程式伺服器映像。
以這種方式建立映像可以減少建立層次結構底部映像所需的時間。當有人對基本Linux伺服器設定程式碼進行變更時,建立搜尋服務映像的管道會立即執行。