IaC Part 13 — Server Images as Code
我們在Part 11談到了從單一來源建立多個server instances的想法,並建議使用乾淨建置的server image。 本文講討論建置的最佳方法是什麼。
與系統中的大多數事物一樣,我們應該使用代碼用可重複的方式建立和更新server image。 每當對image進行變更(例如安裝最新的作業系統修補程式)時,我們都可以確保server image保持一致。
透過使用"自動化、代碼驅動"流程來建置、測試、交付和更新Server image,我們可以讓伺服器保持最新狀態,並確保其合規性和品質。基本server image生命週期涉及從原始來源建立custom image(如下圖)。
建置Server Image
大多數基礎設施管理平台都有一種用於建立Server insatnce的server image format。 AWS是AMI,Azure 有managed images,GCP則是Public image。 託管平台提供具有常見OS和發行版的預先安裝映像檔,而無需我們自行建立image。
為何要建置Server Image
大多數團隊最終都會建立custom images,而不是使用平台供應商提供的image。 這樣做的常見原因包括:
- 遵循組織治理
許多組織,尤其是受高度監管行業的企業,需要確保按照更嚴格的準則建立伺服器。 - 安全強化(Hardening for security)
供應商的server image往往安裝了許多不同的軟體包和工具,以使其適用於各種情況。 而我們可以建立精簡到最少元素的custom image。 安全強化可以包括停用或刪除未使用的使用者帳戶和系統服務、停用運作不需要的所有網路連接埠以及鎖定檔案系統和資料夾權限。 - 優化效能
為安全而強化Image所採取的許多步驟(例如停止或刪除不需要的系統服務)也會減少伺服器使用的 CPU 和記memory資源。 最小化Server image的大小還可以更快地建立Server instance,這對於擴充和復原方案很有幫助。 - 安裝常用套件
可以在server image上安裝一組標準的服務、代理程式和工具,以確保它們在我們的所有instance是上可用的。 範例包括監控代理、系統使用者帳戶以及特定於團隊的特定工具和維護腳本 - 為Server roles建立image
本文中的許多範例不僅僅是建立標準的通用images。 也可以建立針對特定用途來建立客製化的server image,例如container cluster node、應用程式伺服器或 CI 伺服器代理程式。
如何建立Server Image
我們在Part 11中討論到了建立new server instance的幾種不同方法,包括hot-cloning現有instance或使用現有instance的快照。 但從管理良好的server image建立的instance則會更乾淨、更一致。
有兩種建立Server image的方法。 最常見、最直接的是online image building,可以配置一個新的server instance,然後將其轉換為image。 第二種方法是offline image buidling,即mount一個disk volume並將必要的檔案複製到其中,然後將其轉換為bootable image。
Onlineoffline建立image之間的主要權衡是速度和難度。 在線上建立server image更容易,但啟動和配置new instance可能會很慢,大約需要幾分鐘或幾十分鐘。 offline安裝和準備disk通常要快得多,但需要更多的作業。 在討論如何實作每個選項之前,值得討論的是一些用於建立server image的工具。
建立Server image的工具
用於建立Server image的工具和服務通常透過以下方式運作:編排建立server instance或disk volume的流程,執行伺服器配置工具或腳本來客製化image,然後使用基礎設施平台API 將server instance轉換為Image。 出於所有常見的原因,我們應該能夠將此流程定義為代碼。
Netflix 率先大量使用Server image,並開源了它為此創建的 Aminator 工具。 Aminator 專門針對 Netflix 的作業方式,為 AWS EC2 建立 CentOS 和 Red Hat image。
現在(2023 11月)最受歡迎的建立Image工具是 HashiCorp 的 Packer。 Packer支援多種作業系統和基礎架構平台。
一些基礎設施平台提供用於建立server image的服務,包括 AWS Image Builder 和 Azure Image Builder。 本文中的Server image建構代碼範例使用簡單的虛構的image builder語法。
線上Image建立流程
建置Server image的線上作業包括啟動一個新的、乾淨的Server instance,對其進行配置,然後將其轉換為基礎設施平台的Server image格式,如下圖所示。
流程一開使從原始image產生新的server instance,如以下代碼範例所示。 如果我們使用 Packer 等工具來建立image,它會使用平台 的API 來建立Server instance。
image:
name: jason-linux-image
platform: jason-cloud-service
origin: jas-45678
region: asia
instance_size: small
此範例代碼建立了一個名為 jason-linux-image 的 FCS 映像,從 ID 為 fci-45678.的現有 FCI 啟動它。這是雲端供應商提供的 Linux 發行版。 此代碼未指定任何配置操作,因此生成的Image是原始image的副本。 該代碼還定義了用於建立image的server instance的一些特徵,包括區域和instance類型。
Builder instance的基礎設施
我們可能需要為server image building instance提供一些基礎架構資源,例如address block。 確保為此instance提供適當安全且隔離的整體脈絡背景。
使用現有基礎架構運作builder instance可能很方便,但這樣做可能會使我們的Image建置流程受到損害。 理想情況下,建立一次性基礎設施來建立image,然後刪除它。 以下範例將subnet ID 和 SSH key新增至image builder instance。
image:
name: jason-linux-image
origin: jas-45678
region: asia
instance_size: small
subnet: ${IMAGE_BUILDER_SUBNET_ID}
ssh_key: ${IMAGE_BUILDER_SSH_KEY}
這些new values使用參數,我們可以自動產生這些參數並將其傳送給image builder tool。 Image building process可能會從建立定義這些內容的基礎架構stack instance開始,然後在運行image builder tool後刪除它們。 這是基礎設施工具編排腳本的範例。
我們應該最大限度地減少為image builder server instance配置的資源和存取權限。 只允許伺服器配置工具的inbound access,並且僅在push configuration時才執行此操作。 只允許下載套件和configuration所需的outbound access。
配置Builder instance
Server instance開始運作後,流程就可以對其套用server configuration。 大多數server image building tools都支援執行常見的伺服器設定工具,其方式與stack management tools類似。 以下範例擴展了上一個範例 ,執行 Servermaker 工具將instance配置為應用程式伺服器。
image:
name: jason-linux-image
origin: jas-45678
region: asia
instance_size: small
subnet: ${IMAGE_BUILDER_SUBNET_ID}
configure:
tool: servermaker
code_repo: servermaker.jason
server_role: appserver
使用簡單腳本來建立Server Image
當我們已經使用伺服器設定工具來設定新的Server instance時,在建立server image時使用相同的工具(通常是相同的server configuration code)是有意義的。 這符合我們在Part 11提到的「baking和frying相結合」中所述的過程。
但對於Baking更完整server image的團隊來說,成熟的伺服器設定工具可能有點大材小用。 這些工具及其語言增加了複雜性,因此可以將它們重複應用於具有未知、可變啟動條件的伺服器。
但每次建立server image時,通常都是從已知的、一致的原始來源建構它。 因此,更簡單的腳本語言可能更合適,例如 Bash、batch scripts或 PowerShell。
如果我們確實編寫腳本來建立server image,則應該編寫小而簡單的腳本,每個腳本專注於一項任務,而不是使用具有條件循環的大型複雜腳本。 可以在腳本前加上一個數字前綴,以便清楚地顯示它們的運行順序,如以下範例所示。
image:
name: jason-linux-image
origin: jas-45678
configure:
commands:
- 10-install-monitoring-agent.sh
- 20-install-jdk.sh
- 30-install-tomcat.sh
線下Image建立流程
啟動Server instance、套用配置,然後關閉instance來建立server image的過程可能會很慢。 另一種方法是使用可作為磁碟區安裝的source image,例如 AWS 中 EBS-backed AMI。 我們可以將該Image的副本掛載為disk volume,然後配置該disk image上的檔案,如下圖所示。 完成disk image配置後,可以卸載它並將其轉換為平台的server image format。
要在disk volume上建立image,我們需要將該volume掛載到執行image建置工具的compute instance上。 例如,如果我們使用本文稍後所述的流水線(pipeline)建立image,則這可能是 CD tool agent。
另一個要求是可以正確配置disk volume的工具或腳本。 這可能很棘手。 Server configuration tools將配置代碼套用到運行它們的server instance。 即使編寫更簡單的腳本(例如 shell scripts),這些腳本通常也會執行套件安裝程式之類的工具,該工具預設在正在執行的伺服器的檔案系統中安裝檔案:
yum install java
許多工具都有命令列或設定選項,可以設定它們以將檔案安裝到不同的路徑。 使用它來將軟體包安裝到不同的路徑(例如,yum install java — prefix /mnt/image_builder/)。
然而,這很麻煩並且很容易出錯。 並非所有工具都支援這樣的選項。 另一種方法是使用 chroot command,該命令使用不同的檔案系統根目錄來運行命令:
chroot /mnt/image_builder/ yum install java
使用 chroot 命令的優點是它適用於任何工具或命令。 Packer 等流行的image building tools支援開箱即用的 chroot。
Server Image的原始內容
建立server image需要結合幾個元素:
- Image builder code
編寫代碼來定義建builder tool使用的image。 Packer 範本檔案就是一個範例。 此代碼定義了要組裝到image中的其他元素。 - Origin source image
在許多情況下,我們會從另一個image開始建立另一個image。 我們可能需要平台格式的source image,例如 AMI。 或者它可能是OS installation image,無論是實體(如 DVD)還是資料(如 ISO image)。 在某些情況下,我們需要從頭開始建立image,例如執行OS installer時。 - Server configuration code
可以使用伺服器設定工具或腳本來自訂image。 - Other sever elements
使用Part 11中「What’s on a Server」中所述的任何或所有元素以及這些元素的來源來建立server image。 建立鏡image時,通常使用公共或內部儲存庫中的套件。
當我們使用流水線自動執行image建置流程時,這組元素就會發揮作用,如本文後面所述。origin source images的類型值得更具體的關注。
從平台供應商的Image建立Image
基礎設施平台供應商、OS供應商和開源專案通常會建立server image並將其提供給使用者和客戶。 如前所述,許多團隊直接使用這些image,而不是建立自己的image。 但是當我們建立自己的image時,這些平台商的image通常是一個很好的起點。
供應商的image的一個問題是其中許多image的配置太多。 供應商經常安裝各種各樣的工具和軟體包,以便它們立即對最廣泛的客戶是有用的。 但是,為了安全性和效能,我們應該盡量減少在客製的server image上安裝不需要的。
可以在Server image配置過程中從source image中刪除不需要的內容,也可以尋找較小的source image。 一些供應商和組織建立 JEOS(Just Enough Operating System)image。 將我們需要的內容添加到最小的基base image中是保持image最小化的更可靠的方法。
從頭建立Server image
有的基礎架構平台可能不提供image,特別是當我們使用私有雲或虛擬化平台時。 或者,團隊可能只是不想使用平台商的image。 另一種方法是從頭開始建立客製的server image。
OS installation image為建立伺服器範本提供了一個乾淨、一致的起點。 template building process首先從OS image啟動server instance並執行腳本化安裝程序。
Server image及其內容的來源
與來自第三方的任何內容一樣,Base image的另一個問題是它們的來源和安全性。 我們應該確保了解誰提供了image,以及他們用於確保安全建置image的過程。 需要考慮的一些事項如下:
- Image和軟體包是否包含已知的漏洞?
- 供應商採取哪些步驟來掃描其代碼是否有潛在問題,例如靜態代碼分析?
- 如何知道任何包含的軟體或工具收集資料的方式是否與組織政策或當地法律相矛盾?
- 供應商使用哪些流程來偵測和防止非法篡改,我們是否需要在我方實施任何操作,例如檢查package signatures?
我們不應該完全信任來自供應商或第三方的內容,因此應該實施自己的檢查。 後面會在「Server image的測試階段」章節建議如何在Server image的流水線中建立檢查。
變更Server Image
隨著更新的軟體包和配置的發布,Server image會隨著時間的推移而變得越來越舊。 儘管我們可以在每次建立新伺服器時套用修補程式和更新,但隨著時間的推移,此過程會花費更長的時間,從而降低了使用server image的優勢。 定期refresh image可以讓一切順利進行。
除了使用最新補丁使Image保持最新之外,我們還經常需要改進基本配置、新增和刪除標準套件以及對server image進行其他常規變更。 在客製的server image中bake的次數越多,而不是在建立server instance做frying的動作,我們就越需要頻繁地更新image。
下一節將介紹如何使用流水線來製作、測試和交付server image的變更。 然而,在進入流水線之前,需要滿足一些先決條件。 一個是如何進行更新 — 是使用現有的Server image作為變更的基礎,還是根據"第一原則"重建image。 另一個先決條件是對server image進行版控。
Reheating or Baking a Fresh Image
當我們想要建立新版本的server image時(例如,使用最新的OS修補程式更新它),可以使用與建置第一個版本的image相同的工具和流程。
使用Image的先前版本作為原始來源影像 — 重新執行image。 這可確保新版本與先前版本一致,因為唯一的變更是在將server configuration套用至new image時明確進行的變更。
另一種方法是bake a fresh image,從原始來源建立image的新版本。 因此,如果從頭開始建立第一個image version,那麼也從頭開始建立每個新版本。
雖然重新執行image可能會限制從一個版本到下一個版本的變更,但如果使用相同的來源,則為新版本baking image應該會產生相同的結果。 全新的構建可以說更乾淨且可重複性更可靠,因為它們不包含以前構建可能留下的任何內容。
例如,伺服器配置可能會安裝一個稍後決定刪除的軟體包。 如果從舊image重新執行,則仍然可以在較新的Server image上找到該套件。 需要加入代碼來明確刪除該軟體包,這會留下多餘的代碼需要清理與維護。 相反,如果每次都bake新的image,則該套件將根本不存在於較新的server image上,因此無需編寫任何代碼來刪除它。
版本化Server image
每個使用Server image以及從Image建立的伺服器的人都可以追蹤版本,這一點至關重要。 他們應該能夠了解用於建立任何特定server instance的版本、特定image的最新版本以及用於建立image的來源內容和Configuration code。
能夠列出用於建立目前正在使用的instance的server image版本也很有幫助,這樣就可以在發現安全漏洞時識別需要更新的instance。
許多團隊使用不同的server image。 例如,可以為Application server、container host nodes和通用 Linux OS 建立個別的image。 在這種情況下,可以將這些image中的每一個作為單獨的元件進行管理,每個Image都有其單獨的版本歷史記錄,如下圖所示。
在此範例中,團隊更新了application server image來升級裡面的Tomcat 版本,將該Image升級到Version 2,而其他Image仍保留version 1。然後,該團隊使用最新版的Linux OS。 這將application server image提升到version 3,將其他image提升到version 2。最後,團隊升級了host node image上的容器軟體版本,將其提升到version 3。
大多數基礎設施平台不直接支援server image的版本編號。 在許多情況下,我們可以在server image的名稱中加上版本號。 對於上圖中的範例,可能有名為 appserver-3、basic-linux-2 和 container-node-3 的image。
另一種選擇是將版本號和image名稱放入標籤中(如果平台有支援)。 image files可以有一個名為 Name=appserver 的標籤和另一個名為 Version=3 的標籤。
使用任何最容易搜尋、發現和報告image名稱和版本的機制。 很多團隊都使用這兩種方法,因為標籤很容易搜索,而且名稱很容易讓人看到。
我們可以使用不同的版本編號方案。 語意版控(Semantic versioning)是一種流行的方法,使用由三部分組成的版本號(例如 1.0.4)的不同欄位來指示從一個版本到下一個版本的變更的重要性。 版本號中有可新增日期和time stamp(例如 2.0.5–20231121_0803),以便容易查看特定版本的建置時間。
除了將版本號放在server image本身之外,還可以使用server image名稱和用於建立它的版本來標記server instance。 然後,可以將每個instance對應回用於建立它的image。 此功能對於推出新的image版本非常有用。
當Image變動時,更新Server Instance
當建立新版本的server image時,可以替換基於該image的所有server instance,或等待它們隨著時間的推移自然替換。
重建現有伺服器以取代舊image版本的政策可能會造成破壞且耗時。 但它也確保了伺服器的一致性並不斷鍛鍊系統的韌性。 良好的流水線可以更輕鬆地管理此流程,並且zero-downtime changes可以減少其系統中斷時間。 所以這個政策受到了許多自動化成熟且普及的團隊的青睞。
當其他原因重建伺服器時,等待用new image版本替換伺服器會更容易。 如果透過重建server instance來部署軟體更新或其他更改,則可能會發生這種情況。
等待使用new image版本更新伺服器的缺點是,這可能需要一段時間,而整個環境將由各種image版本的伺服器組成。
這種情況會造成不一致。 例如,應用程式伺服器可能具有不同版本的作業系統套件更新和配置,從而導致不一致的行為。 在某些情況下,較舊的image版本以及從中建立的伺服器可能存在安全漏洞或其他問題。
我們可以使用一些策略來緩解這些問題。 一種是根據用於建立instance的image版本來追蹤正在運行的instance。 這可以是儀表板或報告,類似下表 。
如果可以隨時獲取此資訊,並且可以深入查看特定伺服器的清單,那麼我們可以識別迫切需要重建的server instance。 例如,已知到 Linux 的最新更新中已修復的安全漏洞。 將該補丁包含在 basic-linux-2、appserver-3 和 container-node-2 中。 該報告會呈現需要重建 19 個server instance。
我們可能也有時間限制。 例如,可以製定策略來替換從三個月前的server image建立的任何正在運行的server instance。 然後,報表或儀表板應顯示超過該日期的instance數量。
提供與使用整個組織通用的Server Image
在許多組織中,主要團隊建立server image並將其提供給其他團隊使用。 這種情況給管理server image更新帶來了一些麻煩。
使用Image的團隊需要確保已準備好會使用的image新版本。 例如,內部應用程式團隊可以將bug tracking到把軟體安裝到Infra團隊提供的base Linux image上。 Infra團隊可能會產生新版本的base Linux image,其中的更新與正在bug tracking的軟體不相容。
理想情況下,server image會輸入到每個團隊的Infra 流水線中。 當擁有image的團隊透過其流水線發布新版本時,每個團隊的Infra 流水線都會提取該版本並更新其Server instance。 內部團隊的流水線應在重建伺服器上線之前自動測試bug tracking軟體是否適用於新的Image版本。
一些團隊可能會採取更保守的方法,固定他們使用的Image版本號。 內部應用程式團隊可以將其基礎架構固定為使用base Linux image的version 1。 當Infra團隊發布image的version 2 時,內部應用程式團隊將繼續使用version 1,直到他們準備好測試和推出version 2。
當測試和交付伺服器基礎架構變更的自動化不那麼成熟時,許多團隊都會使用固定方法。 這些團隊需要做更多的手動作業來確保Image的變更。
即使擁有成熟的自動化,一些團隊也會固定其變更風險更大的Image(和其他依賴項)。 依賴關係可能更脆弱,因為團隊部署到Image上的軟體對OS的變更更敏感。 或提供Image的團隊(可能是外部供應商)有發布有問題版本的記錄,因此信任度較低。
處裡Image的重大變更
對Server Image的一些變更更為重要,因此更有可能需要手動來測試和修改下游相依性。 例如,application server image的新版本可以包括應用伺服器軟體的主要版本升級。
我們可以使用語義版控(semantic versioning)來指示這是一個更重要的變更,甚至可以完全建立不同的server image,而不是將其視為對server image的較小更新。
當我們使用語意版控時,大多數變更都會增加版本的最後一個數字,例如,1.2.6 到 1.2.7。 我們可以透過增加第二個或第一個數字來指示重大變更。 對於不會造成應用程式相容性問題的次要應用程式伺服器軟體更新,我們可以將server image的版本 1.2.7 變為到 1.3.0。 對於可能破壞應用程式的重大更改,可以增加將 1.3.0 變為2.0.0 。
在某些情況下,特別是當我們希望團隊使用舊image版本一段時間時,我們可以完全建立new image。 例如,如果base Linux image使用 Centos 9.x,但我們想要開始測試並推出 Centos 10.x,而不是增加映image的版本號,可以建立new image basic-linux10–1.0 .0。 這使得遷移到新OS版本成為比routine image update更明確的任務。
使用流水線來測試與交付Server Image
我們在Part 8介紹了使用流水線來測試和交付基礎設施代碼變更。 流水線是建立Server image的絕佳方法。 使用流水線可以輕鬆建立Image的新版本,確保它們的構建一致。 透過與系統其他部分的流水線整合的成熟流水線,我們可以每週甚至每天安全地在整個資產中推出OS修補程式和更新。
經常(例如每週)建立新的Server image是一個好的做法,而不是長時間保留(例如每隔幾個月)。 這符合CI/CD變更的核心實踐。 建立new server image的時間越長,其中包含的變更就越多,這會增加測試、尋找和修復問題所需的工作量。基本的server image流水線將有三個階段,如下圖所示。
建置、測試和發布Server Image的每個階段都值得仔細觀察與研究。
Server Image的建置階段
Server image流水線的建置階段自動實現online image building process或offline image building process。 此階段產生一個Server image,後續階段將其視為release candidate(如下圖)。
我們可以將server image建置階段設定為在前述「Server image及其內容的來源」中所列的image的任何輸入進行變更時自動執行。例如:
- 有人提交了對image builder code的變更,例如 Packer 模板
- 供應商發布原始來源image的新版本,例如OS供應商提供的 AMI
- 對用於server image的server configuration code進行更改
- 軟體包維護者發布server image上安裝的軟體包的新版本
在實踐中,對作業系統包等來源元素的許多變更很難自動檢測並用於觸發流水線。 我們可能也不想為每個套件更新建立新的server image,特別是當image使用數十甚至數百個套件時。
因此,我們可以只在重大變更時自動觸發new image,例如source server image或image builder code。 然後,可以進行計劃中的建置(例如每週一次),以將所有更新匯總到較小的來源元素。
如前所述,建置階段的結果是一個server image,我們可以將其用作release candidate。 如果我們想在提供image之前對其進行測試(建議用於任何重要的使用案例),那麼此時我們不應該將image標記為可以使用。 可以根據前面給出的指導使用版本號標記image。 也可以對其進行標記以表明它是未經測試的release candidate; 例如,Release_Status=Candidate。
Server Image的測試階段
鑑於本系列文章始終強調測試,我們可能會了解在建立new image時自動測試的價值。 人們通常使用與測試伺服器代碼相同的測試工具來測試server image。
如果我們在server images online,可以在設定server instance之後、關閉伺服器並將其轉換為image之前在伺server instance上執行自動化測試。 但這有兩個問題。 首先,測試可能會污染image,留下測試檔案、日誌或其他殘留物等測試的副作用。 他們甚至可能留下使用戶帳號或其他途徑來存取從image建立的伺服器。
在將server instance轉換為image之前對其進行測試的另一個問題是,它可能無法可靠地複製從image建立的伺服器。 將instance轉換為image的過程可能會變更伺服器的重要面向,例如使用者存取權限。
測試server image的最可靠方法是從final image建立並測試new instance。 這樣做的缺點是需要更長的時間才能從測試中獲得回饋。
因此,如下圖所示,典型的server image測試階段會取得在建置階段建立的image的identifier,使用它來建立temporary instance,並針對該instance執行自動化測試。 如果測試通過,則該階段會對image進行標記,以表示它已準備好進入流水線的下一階段。
Server Image的交付階段
團隊的image pipeline可能有用於其他活動的附加階段,例如安全測試。 最終,通過測試階段的image版本將被標記為可供使用。
在某些系統中,建立image的流水線包括使用new image重建伺服器的階段(如下圖)。 它可以在生產過程中為每個交付環境運行一個階段,也許會觸發應用程式部署和測試階段。
在不同團隊負責管理基礎架構和環境的系統中,一旦將image標記為可供使用,image pipeline可能會結束。 其他團隊的流水線採用新的image版本作為輸入。
使用多個Server Images
有些團隊只維護一個Server image。 這些團隊透過在創建server instance時套用server configuration roles來創建他們所需的不同類型的伺服器。 然而,其他團隊發現維護多個server image是有用的或有必要的。
我們需要多個Image來支援多個基礎架構平台、多個伺服器硬體架構。 遵循Baking優於frying的策略,多個Image可有助於最佳化伺服器建立時間。
讓我們看一下每個場景(支援多個平台,並將角色baking到server image中),然後討論維護多個Server image的策略。
不同基礎架構平台的Server Image
我們的組織可能會使用多個基礎設施平台作為多雲(multi-cloud, Poly-Cloud)、或混合雲策略的一部分。 我們需要為每個平台建立和維護單獨的server image。
通常,我們可以跨平台使用相同的server configuration code,也許帶有一些使用參數管理的變體。 可能會在每個平台上使用不同的source image,但在某些情況下,可以使用OS供應商或受信任的第三方為每個平台一致建立的image。
每個基礎設施平台都應該有一個單獨的流水線來建構、測試和交付新版本的image。 這些流水線可以將伺服器配置代碼作為輸入材料。 例如,如果更新應用程式伺服器的伺服器配置,可以將變更推送到每個平台流水線中,為每個平台建立並測試新的server image。
不同OS的Server Image
如果支援多個OS,如 Windows、Red Hat Linux 和 Ubuntu Linux,則需要為每個OS維護單獨的image。 此外,可能需要為組織使用的特定OS的每個主要版本提供單獨的image。 需要一個單獨的source image來建立每個OS image。 也許能夠在其中一些OS image中重複使用伺服器設定碼。
但在許多情況下,編寫伺服器配置代碼來處理不同的OS會增加複雜性,從而需要更複雜的測試。 測試流水線需要為每個變體使用server(或容器)instance。 對於某些配置,為每個OS編寫單獨的配置代碼模組可能會更簡單。
不同硬體架構的Server Image
有些組織在不同的 CPU 架構上運行Server instance,例如 x86 和 ARM。 大多數情況下,可以使用相同的代碼為每個架構建立幾乎相同的server image。 某些應用程式利用特定的硬體功能或對其差異更加敏感。 在這些情況下,流水線應該跨不同架構更徹底地測試image以偵測問題。
不同角色的Server Image
許多團隊使用通用server image並在建立server instance時套用角色配置。 但是,當為角色配置伺服器涉及安裝太多軟體(例如應用程式伺服器)時,最好將角色配置baking到專用image中。
本文前面的範例使用application servers與container host nodes的客製image以及通用 Linux image。 此範例表示我們不一定需要為使用的每個伺服器角色都有一個單獨的image。
要決定是否值得為特定角色維護單獨的image,請考慮流水線、測試和儲存空間的時間和成本,並權衡這些與建立server instance時配置時的缺點(速度、效率和依賴性)。
分層Server Images
擁有大量基於角色的server image的團隊可以考慮分層來建構它們。 例如,使用要安裝在所有伺服器上的預設套件和配置來建立base OS image。 然後使用該image作為source image,為應用程式伺服器、容器節點等建構更具體的基於角色的image,如下圖所示。
在此範例中,團隊使用base Linux image作為source image來建立application server image和container host node image。 application server image預先安裝了Java和Tomcat。 該團隊又使用此image作為source image來建立預先安裝了特定應用程式的image。
購物應用程式和搜尋服務經常需要擴展或縮減,以處理一天中不同時間的可變流量負載。 因此,Baking並準備好image很有用。 該團隊從更通用的應用程式伺服器image為其他應用程式和服務建立server instance,因為該團隊不經常建立這些instance。
一個單獨的流水線建立每個server image,並在input image發生變化時觸發。 反饋循環可能會很長。 當團隊更改base Linux image時,其流水線完成並觸發應用程式伺服器和容器主機流水線。 然後,應用程式伺服器image pipeline觸發流水線以基於它建立新版本的server image。 如果每個流水線需要 10–15 分鐘運行,這表示變更最多需要 45 分鐘才能傳達到所有image。 另一種方法是使用shallower image策略。
跨Server image共享代碼
即使特定一個基於繼承的模型,其中伺服器角色相互繼承配置,我們也不一定需要在剛剛描述的分層模型中建立image。 可以將伺服器設定碼分層到伺服器角色定義中,並直接套用所有代碼從頭開始建立每個映像,如下圖所示。
該策略實現了同樣的分層模式。 但它是透過組合每個角色的相關配置代碼並立即套用來實現的。 因此,建立application server image不會使用base server image作為其source image,而是將用於base server image的所有代碼套用到application server image。
以這種方式建立image可以減少在層次結構底部建立image所需的時間。 當有人更改base Linux server configuration code時,為搜尋服務建立image的流水線會立即運作。
結論
我們無需建立客製的image即可建置和維護伺服器。 但是創建和維護用於建立server image的自動化系統是有效益的。 這些效益主要圍繞著優化。 透過將更多配置預先烘baking到server image中,我們可以更快地建立server instance,使用更少的網路頻寬和更少的依賴項。