IaC Part 15 主要實踐:小而簡易
一個成功的系統往往會隨著時間的推移而不斷成長。 更多的人使用它,更多的人在其中作業,更多的東西被加到其中。 隨著系統的發展,變更會變得更加危險和複雜。 這通常會導致管理變更的流程變得更加複雜和耗時。 進行變更的代價使得修復和改進系統變得更加困難,導致技術債增加,從而損害系統的品質。
這是我們在Part 1中描述的變更速度驅動更好品質,而更好的品質又帶來更快變化速度的循環的負面版本。
應用IaC的三個核心實踐 — — 將一切定義為代碼、持續測試和交付以及構建小部件 — — 實現了循環的正向版本。
本文重點介紹第三種實踐,即用較小的部分組成我們的系統,以便即使系統不斷增長,也可以保持更快的變更速度,同時提高品質。 大多數infra coding tools和語言都具有支援"模組、函式庫和其他類型組件"的功能。 但基礎設施設計思維和實踐還沒有達到軟體設計的成熟程度。
因此,本文借鑒了從數十年的軟體設計中學到的模組化設計原則,並從代碼驅動基礎設施的角度來考量它們。 然後,它會研究基礎設施系統中的不同類型的組件,並著眼於如何利用它們來實現更好的模組化。 在此基礎上,我們可以考慮在基礎設施組件之間劃定邊界的不同考量。
模組化的設計
模組化的目標是使系統變更變得更容易、更安全。 模組化有多種方式支持這一目標。 一是消除重複的實做,以減少交付特定變更所需的代碼變更數量。 另一個是透過提供可以以不同方式組裝用於不同用途的組件來簡化實做。
使變更更容易、更安全的第三種方法是設計系統,以便可以對較小的組件進行更改,而無需更改系統的其他部分。 較小的組件比較大的組件更容易、更安全、更快速地更換。
大多數模組化設計規則都存在張力。 如果不小心遵循,它們實際上會使系統變得更加脆弱並且更難改變。 我們在Part 1「四個關鍵指標」中是考慮系統模組化有效性的有效支柱。
良好設計的組件特點
設計組件是決定將系統的哪些元素組合在一起以及將哪些元素分開的藝術。 要做好這件事需要理解元素之間的關係和依賴項。 組件的兩個重要設計特徵是耦合和內聚(coupling and cohesion)。 良好設計的目標是創造低耦合和高內聚。
耦合性描述了對一個組件的變更需要對另一個組件進行更改的頻率。 對於系統的兩個部分來說,零耦合並不是一個現實的目標。 零耦合可能意味著它們根本不是同一系統的一部分。 相反,我們的目標是低耦合或鬆散耦合。
Stack和server image是耦合的,因為當我們在伺服器上升級軟體時,可能需要增加分配給Stack中server instance的記憶體。 但不需要在每次更新server image時都更改Stack中的代碼。 低耦合使得更改組件變得更容易,而破壞系統其他部分的風險很小。
內聚性描述了組件內元素之間的關係。 與耦合一樣,內聚的概念與變化的模式有關。 對低內聚stack中定義的資源所做的變更通常與堆疊中的其他資源無關。
為其他兩個Stack配置的伺服器定義單獨的網路結構的Infra stack具有低內聚性。 具有高內聚力的組件更容易更改,因為與包含鬆散相關事物的混合組件相比,它們更小、更簡單、更乾淨,並且具有更低的爆炸半徑 (Blast Radius)。
設計組件時的規則
軟體架構和設計包括許多設計低耦合和高內聚組件的原則和指南。
避免重複(Avoid duplication)
DRY(Don’t Repeat Yourself)原則說:“每個知識都必須在系統內有一個單一的、明確的、具權威的呈現。” 重複迫使人們在多個地方做出改變。
例如,ShopSpinner 的所有Stack都使用provisioner這一個user account將設定套用到server instance。 最初,帳號的登入詳細資訊在每個Stack以及建立其基本Server image的代碼中指定。 當有人需要更改使用者帳號的登入詳細資訊時,他們需要在代碼庫中的所有這些位置中查找並更改它。 因此,團隊將登入詳細資訊移動到一個中心位置,每個Stack以及server image builder都引用該位置。
Reuse增加耦合。 因此,Reuse的一個很好的經驗法則是在組件內保持DRY,在組件之間保持wet。
Note:重複被認為是有用的
DRY 原則不鼓勵重複概念的實現,這與複製一行代碼行不同。 讓多個元件依賴共享代碼可能會造成緊密耦合,變得使其難以更改。
有些團隊堅持集中所有看起來相似的代碼; 例如,使用單一模組建立所有VM。 在實踐中,為不同目的創建的伺服器,例如應用程式伺服器、Web 伺服器和建置伺服器,通常需要進行不同的定義。 需要創建所有這些不同類型的伺服器的模組可能會變得過於複雜。
在考慮代碼是否重複、是否應該集中時,要考慮代碼是否真正代表相同的概念。 更改代碼的一個instance是否總是意味著另一個instance也應該更改?
也要考慮將兩個代碼instance一起鎖定到同一個變更週期中是否是一個好主意。 強制組織中的每個應用程式伺服器同時升級可能是不切實際的。
組成規則
要建立可組合的系統,請讓每個組件都是獨立的。 替換依賴關係的一邊應該很容易,而不影響另一邊。
例如團隊從他們從不同Stack提供的單一 Linux application server image開始。 後來他們加入了 Windows application server image。 他們設計了從任何特定stack提供server image的代碼,以便他們可以根據特定應用程式的需要在這兩個server image之間切換。
單一責任原則
單一責任原則表示任何特定的組件都應該對一件事負責。 這個想法是讓每個組件保持重點,使其內容具有內聚力。
基礎設施組件,無論是伺服器、configuration library、stack component或stack,都應該以單一目的進行組織。 這個目的可能是分層的。 為應用程式提供基礎設施是可以透過infra stack實現的單一目的。 我們可以將該目的分解為應用程式的安全流量路由,並在stack library中實現; 應用程式伺服器,由server image實作; 和一個DB instance,由stack module實作。 每個層級的每個組件都有一個易於理解的目的。
圍繞領域(Domain)概念而不是技術概念設計組件
人們常常傾向於圍繞技術概念來建立組件。 例如,創建一個用於定義伺服器的組件並在任何需要伺服器的Stack中重複使用該組件似乎是一個好主意。 實際上,任何共用組件都會耦合它使用的所有代碼。
更好的方法是圍繞領域概念來建立組件。 應用程式伺服器是一個領域概念,我們可能希望將其重複使用於多個應用程式。 建置伺服器是另一個領域概念是我們可能想要重複使用它來為不同的團隊提供自己的instance。 因此,這些組件比伺服器更好,而伺服器的使用方式可能不同。
Law of Demeter
Law of Demeter也稱為最少知識原則,它規定組件不應該知道其他組件的實作方式。 此規則推動組件之間的介面清晰、簡單。
ShopSpinner 團隊最初違反了此規則,因為它擁有一個定義應用程式伺服器叢集的stack,以及一個為該叢集定義負載平衡器和防火牆規則的共用網路stack。 共享網路stack對應用程式伺服器stack有太多詳細的運作了解。
Providers and Consumers
在組件之間的依賴關係中,provider組件建立或定義comsumers組件所使用的資源。
Shared networking stack可以是Provider,建立networking address blocks,例如子網路。 application infrastructure stack可以是由provider管理的子網路內的shared networking stack、啟用伺服器和負載平衡器的consumer。本文的一個關鍵主題是定義和實作基礎設施組件之間的介面。
無循環依賴(No circular dependencies)
當我們追蹤向consumer提供資源的組件中的關係時,我們永遠不應該找到有一種循環。 換句話說,Provider件永遠不應該消耗來自自己的直接或間接consumer之一的資源。
Shared network stack的 ShopSpinner 範例具有循環相依性。 application server stack將其叢集中的伺服器指派給application server stack中的網路結構。 application server stack為application server stack中的特定伺服器叢集建立負載平衡器和防火牆規則。 這
ShopSpinner 團隊可以透過將特定於application server stack的網路元素移至該Stack來去除循環依賴性,並減少networking stack對其他元件的運作理解。 這也提高了內聚性和耦合性,因為networking stack不再包含與另一個Stack的元素最密切相關的元素。
運用測試來推動設計決策
Part 8與9 中我們談論到了人們處理變更時持續測試Infra code的實踐。 對測試的高度關注使得可測試性成為基礎設施組件的重要設計考量。
變更交付系統需要能夠在每個層級建立和測試Infra code,從安裝監視代理程式的伺服器設定模組到建置容器叢集的Stack code。 流水線階段必須能夠快速獨立地建立每個組件的instance。 對於具有複雜依賴關係的義大利麵條式的代碼庫,或需要半小時才能配置完成的大型組件,這種程度的測試是不可能的。
這些挑戰使許多為Infra code導入有效的自動化測試機制的舉措脫軌。 對於設計不良的系統,很難編寫和執行自動化測試。
這就是自動化測試的效益:它可以推動更好的設計。 持續測試和交付代碼的唯一方法是實現和維護具有鬆散耦合和高內聚力的系統設計。
對鬆散耦合的伺服器配置模組實現自動化測試更容易。 透過更清晰、更簡單的介面,可以更輕鬆地為模組建構和使用模擬。 我們可以更快地在流水線中配置和測試小型且定義良好的Stack。
基礎設施模組化
如我們在Part 3中所述,基礎設施系統涉及不同類型的組件,每個組件都可以由不同的部分組成。 一個Server instance也許是由Image所產生的,而這個instance是引用一組server configuration modules的server configuration role,而server configuration modules又可以匯入代碼函式庫。 Infra stack可以由server instance組成,並且可以使用stack code modules 或函式庫。 多個Stack可以組合起來構成更大的環境。
Stack Components VS. Stacks as Components
如Part 5所定義的,Infra stack是基礎架構的核心可部署單元。 這個堆Stack是架構量子(Architectural Quantum)的一個範例,Ford、Parsons 和 Kua 將其定義為“具有高功能內聚力的獨立可部署組件,其中包括系統正確運行所需的所有結構元素。” 換句話說,Stack是一個可以自行投入生產的組件。
如前所述,Stack可以由組件組成,而Stack本身也可以是一個組件。 伺服器是Stack的潛在組件,稍後會詳細介紹這些組件。 大多數stack management tools也支援將stack code放入模組中,或使用函式庫產生stack元素。
下圖顯示了兩個Stack,我們把它命名為 StackA 和 StackB,它們使用定義網路結構的共享代碼模組。
我們在Part 16會描述了使用stack code modules和函式庫的一些模式和反模式。 Stack module和函式庫對於重複使用代碼很有用。 然而,它們對於讓Stack容易變更的幫助不大。 一些團隊嘗試透過將代碼分解為模組來改進monolithic stack。 雖然模組使代碼更容易理解,但每個Stack instance都像以前一樣龐大和複雜。 下圖顯示了分離到單獨模組中的代碼被組合到stack instance中。
除了為每個stack instance添加元素之外,其他Stack也使用的模組還會在這些Stack之間建立耦合。 更改模組以滿足一個Stack中的要求可能會影響使用該模組的其他Stack。 這種耦合可能會增加進行變更的難度。
使大型stack更易於管理的一種更有效的方法是將其分成多個stack,每個stack都可以獨立於其他stack進行配置、管理和變更。 Part 5的「建立Stack的模式和反模式」列出了一些用於考慮Stack大小和內容的模式。 Part 17更詳細地介紹了管理Stack之間的依賴關係。
運用Stack中的伺服器
伺服器是一種常見的stack component type。 我們在Part 11解釋了伺服器的各個組件及其生命週期。 Stack code通常透過server images和server configuration modules的一些組合來產生可運作的伺服器。
代碼庫包含一個使用Server image作為stack componet的範例。 它有一個名為 cluster_of_host_nodes 的stack,它建立了一個伺服器叢集來充當容器主機節點,如下圖所示。
定義伺服器叢集的程式碼指定伺服器映像的名稱,host_node_image:
server_cluster:
name: "cluster_of_host_nodes"
min_size: 1
max_size: 3
each_server_node:
source_image: host_node_image
memory: 8GB
使用流水線來建立和測試對server image的變更。 另一個流水線測試對 cluster_of_host_nodes 的變更,將其與已通過測試的最新版本的 host_node_image 整合(如下圖)。
Part 8的「Infrastructure Delivery Pipelines」解釋了流水線如何為基礎設施服務。
然而,這個例子有一個小問題。 cluster_of_host_nodes stack的第一個流水線不使用 host_node_image。 但stack code範例包含server image的名稱,因此無法作為線上測試階段運行。 在沒有image的情況下測試stack code可能會很有用,因此團隊可以發現stack code的問題,而無需同時配置繁完整的完整主機節點伺服器。
團隊透過從stack code中提取hardcoded的 host_node_image 並使用stack參數來解決該問題。 這段代碼更容易測試:
server_cluster:
name: "cluster_of_host_nodes"
min_size: 1
max_size: 3
each_server_node:
source_image: ${HOST_NODE_SERVER_IMAGE}
memory: 8GB
cluster_of_host_nodes stack的線上測試階段可以使用精簡版server image的 ID 設定 HOST_NODE_SERVER_IMAGE 參數。 團隊可以在此階段執行測試來驗證伺服器叢集是否正常運作、擴展和縮減以及復原失敗的instance。 精簡的server image是測試替身的一個範例。
用參數替換server image的hardcoded的方式可以減少耦合。 它也遵循組合規則(如前所述)。 團隊可以使用不同的server image建立 cluster_of_host_nodes 的instance,如果團隊中的人員想要測試並逐步為其叢集推出不同的OS,這會派上用場。
Shared-Nothing Infrastructure
在分散式運算領域,無共享架構(shared-nothing architecture)透過確保可以將新節點添加到系統中而不增加對節點本身以外的任何資源爭奪來實現擴展。
典型的反例是處理器共享單一磁碟的系統架構。 當添加更多處理器時,共享磁碟的資源爭奪會限制系統的可擴充性。 從設計中移除共享磁碟意味著系統可以透過添加處理器來更接近線性擴展。
具有Infra code的無共享設計將資源從共享stack移動到需要它們的每個stack,從而消除了provider-consumer關係。 例如,團隊可以將applicationinfrastructure-stack與shared-network-stack合併到單一stack中。
應用程式基礎架構的每個instance都有自己的全套網路結構。 這樣做會複製網路結構,但會保持每個application instance彼此獨立。 與分散式系統架構一樣,這消除了擴展方面的限制。 例如,團隊可以根據需要添加任意數量的應用程式基礎架構的instance,而不會耗盡由單一共用網路stack分配的位址空間。
但使用無共享基礎設施代碼設計的一個更常見的驅動因素是使修改、重建和恢復application stack的網路資源變得更容易。 共享網路stack設計增加了網路作業的影響範圍和管理代價。無共享基礎設施也支援零信任安全模型,因為每個stack都可以單獨保護。
無共享設計不需要將所有內容放入單一stack instance中。 對於團隊來說,將網路和應用程式基礎設施組合在單一stack中的另一種方法是像以前一樣在不同的stack中定義網路和應用程式基礎設施,但為application stack的每個instance創建一個單獨的networking stack instance(如下圖)。
透過這種方法,application stack instances不會與其他stack共享網路,但這兩部分可以獨立管理。 這樣做的限制是所有network stack instances仍然由相同的代碼定義,因此對代碼的任何變更都需要額外的作業以確保它不會破壞任何instance。
繪製組件之間的邊界
與任何系統一樣,要劃分基礎設施,我們應該尋找接合處。 接合處是我們可以更改系統行為而無需在該位置進行編輯的地方。 這個理念是找到自然的地方來在系統各部分之間劃定界限,在那裡我們可以建立簡單、乾淨的整合點。
以下每個策略都根據特定關注點對基礎架構元素進行分組:變革模式、組織架構、安全性和治理以及彈性和擴展。 與大多數架構原則和實踐一樣,這些策略可以歸結為針對變更進行最佳化。 這是對組件設計的追求,以便可以更容易、安全、快速地變更系統。
使邊界與自然變化模式一致
優化組件邊界以應對變化的最基本方法是了解其自然變化模式。 這就是尋找接合處背後的理念 — — 接合處就是自然邊界。
在現有系統中我們可以透過檢查歷史變更來了解哪些事物通常會一起變化。 更細緻度的變改(例如代碼提交)可以提供最有用的見解。 最有效的團隊針對頻繁提交進行最佳化,充分整合和測試每一項。 透過了解哪些組件傾向於作為單一提交的一部分或跨組件的密切相關提交一同變更,我們可以找到建議如何重構代碼以提高內聚性和減少耦合的模式。
檢查更高層級的作業(例如ticket、story或project)可以幫助我們了解系統的哪些部分經常涉及同一組變更。 但我們應該針對小的、頻繁的變更進行最佳化。 因此,請務必深入了解可以相互獨立地進行哪些變更,以便在更大的變更計劃的背景下實現增量變更。
讓邊界與組件生命週期一致
基礎設施的不同部分可能有不同的生命週期。 例如,叢集中的伺服器是動態建立和刪除的,可能一天多次。 DB storage volume的變化頻率較低。
根據基礎設施資源的生命週期將基礎設施資源組織成可部署的元件,特別是Infra stack,可以簡化管理。 考慮由網路路由、伺服器叢集和DB instance組成的application server infrastructure stack 。
該Stack中的伺服器至少每週更新一次,並使用帶有最新OS修補程式的new image進行重建。 儘管可以建立new instance來恢復或複製應用程式的instance,但資料庫儲存設備很少變更。 該團隊偶爾會更改其他stack中的網路,這需要更新該stack中的應用程式特定路由。
在單一stack中定義這些元素可能會產生一些風險。 Application server image的更新可能會失敗。 修復該問題可能需要重建整個stack,包括資料庫儲存設備,這又需要備份資料以還原到new instance。 雖然可以在單一stack中對其進行管理,但如果資料庫儲存是在單獨的stack中定義的,則會更簡單,如下圖所示。
對這些Micro stack中的任何一個進行更改都不會直接影響其他stack。 這種方法可以啟用stack特定的管理事件。 例如,對資料庫儲存stack的任何變更都可能觸發資料備份,而對於第一個組合起來的stack的其他元素的每次變更都觸發資料備份可能成本太高。
優化生命週期的stack邊界對於流水線中的自動化測試特別有用。 當人們進行基礎設施變更時,流水線階段通常每天運行多次,因此需要對其進行最佳化以提供快速回饋並保持良好的工作節奏。 根據基礎設施元素的生命週期將基礎設施元素組織到單獨的stack中可以減少套用變更進行測試所需的時間。
例如,在處理應用程式伺服器的infra code時,某些流水線階段可能每次都會重建stack。 重建網路結構或大型資料儲存設備可能會很慢,並且作業中涉及的許多變更可能是不需要的。 在這種情況下,上圖所示的Micro stack設計可以簡化測試和交付過程。
以生命週期分離stack的第三個使用案例是成本管理。 關閉或銷毀並重建靜態時期不需要的基礎設施是管理公有雲成本的常見方法。 但某些元素(例如資料儲存)的重建可能更具挑戰性。 我們可以將它們分成自己的stack並讓它們運行,同時刪除其他stack以降低成本。
使邊界與組織結構一致
康威定律指出,系統往往反映創建它的組織的結構。 一個團隊通常會發現整合其完全擁有的軟體和基礎設施更容易,而團隊自然會與其他團隊擁有的系統部分建立更嚴格的界限。
康威定律對於設計包含基礎設施的系統有兩個一般意義。 一是避免設計多個團隊需要更改的組件。 另一種是根據“逆康威策略”,考慮建立團隊來反映想要的架構邊界。
Notes:穀倉效應造成基礎建設脫節
傳統的開發和維運團隊的組織結構通常會在整個生產過程中建立不一致的基礎架構,從而增加了交付變更的"時間、成本和風險"。 在某些團隊中,應用程式開發團隊和維運團隊使用不同的配置工具來建立伺服器。 這會在每個軟體版本上都浪費了數週的時間來讓應用程式在生產環境中正確部署和運行。
特別是對於基礎設施,值得去思考如何使設計與使用基礎設施的團隊的結構保持一致。 在大多數組織中,這些是產品線或服務線和應用程式。 即使基礎設施由多個團隊使用,例如 DBaaS 服務,我們也可以設計基礎設施,以便為每個團隊管理單獨的instance。
將Infra instance與使用它們的團隊保持一致可以減少變更的破壞性。 我們無需與使用共用instance的所有團隊協商單一變更窗口,而是可以為每個團隊協商單獨的窗口。
建立支援韌性的邊界
當系統發生故障時,我們可以重建可獨立部署的元件,例如Infra stack。 我們可以手動修復或重建stack中的元素,進行基礎架構改造。 基礎設施手術需要對基礎設施有深入了解的人來小心地開刀。 一個簡單的錯誤可能會使情況變得更糟。
有些人對基礎設施開刀感到自豪,但這是彌補基礎設施管理系統缺陷的不得已的措施。
基礎設施手術的替代方案是使用明確定義的流程和工具重建組件。 我們應該能夠透過觸發與應用程式變更和更新相同的自動化流程來重建任何stack instance。 如果能做到這一點,那麼當半夜出現故障時,我們就不需要叫醒團隊最厲害的基礎設施外科醫生。 在許多情況下,可以自動觸發恢復。
基礎設施組件的設計需要能夠快速重建和恢復它們。 如果我們根據資源的生命週期將資源組織到組件中,那麼我們也可以考慮重建和復原案例。
上圖包含持久性資料的拆分基礎設施的範例就是這樣做的。 重建資料儲存的過程應該包括自動儲存和載入資料的步驟,這在災難復原場景中會派上用場。
根據重建過程將基礎架構劃分為組件有助於簡化和最佳化復原。 另一種恢復能力的方法是運行基礎設施部分的多個instance。 冗餘(redundancy)策略也有助於擴展。
建立支援擴展的邊界
擴展系統的一個常見策略是為其某些組件建立額外的instance。 可以在需求較高的時期新增instance,也可以考慮在不同的地理區域部署instance。
大多數人都知道,大多數雲端平台都可以隨著負載變化自動擴展或縮減伺服器叢集。 FaaS serverless的一個主要優點是它只在需要時執行代碼。
然而,當運算規模擴大時,基礎設施的其他元素(例如資料庫、message queue和儲存設備)可能會成為瓶頸。 軟體系統的不同部分可能會成為瓶頸,甚至除了基礎設施之外。
例如,團隊可以部署product browsing service stack的多個instance來應對更高的負載,因為大多數使用者流量都會在高峰時段到達系統的該部分。 團隊保留其frontend traffic routing stack的單一instance,以及application server instances連接到的DB stack的單一instance(如下圖)。
系統的其他部分,例如訂單結帳和客戶檔案管理服務,可能不需要與產品瀏覽服務一起擴展。 將這些服務拆分為不同的stack有助於團隊更快地擴展它們。 它減少了複製一切會產生的浪費。
寧願垂直分組而不是水平分組
傳統上,許多架構師會依照功能來組織系統。 網路的東西共存,資料庫的東西共存,作業系統的東西共存。
正如康威定律所預測的那樣,這通常是組織設計的結果 — — 當團隊圍繞著這些"技術、功能"來組合系統時,他們將根據所管理的內容來劃分基礎設施。
這種方法的缺陷在於,向客戶提供的服務橫跨了許多功能。 這通常呈現為跨越水平功能層的垂直服務,如下圖所示。
將系統元素組織成跨領域的functional infrastructure stacks有兩個缺點。 一是對一項服務的基礎設施的更改可能涉及對多個stack進行更改。 需要仔細協調這些變更,以確保相依性在出現在provider stack中之前不會在comsumer stack中被導入。
將單一服務的基礎架構所有權分散到多個職能團隊會增加大量的通訊成本和變更任何一項服務的流程。
當functional stacks在服務之間共用時,functional stacks的第二個缺點就會出現。 在下圖中,伺服器團隊管理單一stack instance,其中包含多個服務的伺服器。
當團隊更改其中一項服務的伺服器時,就會出現破壞其他服務的風險,因為stack邊界代表變更的影響範圍,如我們在Part 5的「反模式:Monolithic Stack」所述。
根據安全和治理問題對齊邊界
安全性、合規性和治理”保護資料、交易和服務可用性”。 系統的不同部分會有不同的規則。 例如,PCI 安全標準對處理信用卡號碼或支付處理的系統部分提出了要求。 客戶和員工的個人資料通常需要以更嚴格的控制進行處理。
許多組織根據適用於其託管的服務和資料的法規和政策來劃分其基礎設施。 這樣做可以清楚地評估需要對特定基礎設施組件採取哪些措施。 交付變更的流程可以根據治理要求進行客製化。 例如,該流程可以強制執行和記錄審查和批准,並產生簡化稽核的變更報告。
網路邊界不是Infra stack邊界
很多人經常將基礎設施劃分為網路安全區域。 在前端區域中運行的系統可以直接從Internet存取,並受到防火牆和其他機制的保護。 例如,用於應用程式託管和資料庫的其他區域只能從具有附加安全層的某些其他區域進行存取。
雖然這些邊界對於防禦基於網路的攻擊很重要,但它們通常不適合將基礎設施代碼組織成可部署單元。 將 Web 伺服器和負載平衡器的代碼放入「前端」stack並不能建立針對應用程式伺服器或資料庫代碼的惡意變更的防禦層。 利用基礎設施代碼和工具的威脅模型與網路攻擊的威脅模型不同。
無論如何,請使用基礎設施代碼來建立分層網路邊界。 但不要認為將網路安全模型應用於建置基礎設施代碼是個好主意。