IaC Part 14 將Clusters建構成代碼

我們在Part 3 中將application hosting cluster描述為一種跨伺服器集區動態部署和運行application instances的服務。 application hosting cluster的範例包括 K8S、AWS ECS、HashiCorp Nomad、Mesos 和 Pivotal Diego。 該模型將orchestrating applications與供應和配置它們運行的伺服器的聚焦點分開(如下圖)。

毫無疑問,我們應該使用代碼來定義和管理application cluster。 如在Part 10所解釋的,我們可以將application cluster建置為一個或多個應用application stack作為代碼。 在本文中,我們將有一些範例來說明這種情況。 本文將展示一些不同的stack topology,包括整個Cluster的單一stack,以及跨多個stack的breaking clusters。 本文提供了為這些拓撲提供基礎設施代碼變更的流水線(pipeline)圖。本文還討論了跨環境和團隊共享或不共享Cluster的策略。最後透過討論serverless應用程式的基礎設施來結束本文。

Containers as Code

容器的眾多優點之一是它們被定義為代碼。 Container image會根據定義檔(definition file)做一次性的Image建置,然後用於建立多個Instance。 為了有效地使用容器,必須將它們視為不可變(immutable)和無狀態(Stateless)的

不要更改container instance的內容; 相反,更改定義(Definition),創建new image,然後替換instance。 並且不要將狀態存放在容器內。 相反,使用其他基礎設施資源儲存狀態和資料。容器的不可變和無狀態特性使其非常適合雲端平台的動態特性,這就是它們與雲端原生架構如此緊密相關的原因。

Application Cluster Solutions

實作和維護application cluster有兩種主要方法。 一種是將託管式的cluster服務,通常作為基礎設施平台的一部分提供。 另一種是將打包的叢集解決方案部署到較低層級的基礎架構資源上。

Cluster as a Service

大多數基礎設施平台都提供託管式的cluster服務。 我們可以使用stack configuration tool以代碼形式定義、配置和變更Cluster。 使用Cluster as a Service就是建立一個包含Cluster和支援元素的Stack。 其中許多Cluster都基於 K8S,包括 EKS、AKS 和 GKE。 其他則基於專有容器服務,例如 ECS、Cloud Run。

託管式的K8S Cluster不是雲端抽象層

如果不仔細觀察,雲端平台供應商管理的K8S Cluster似乎是跨不同雲端平台透明地開發和運行應用程式的絕佳解決方案。 現在就可以為K8S建立應用程式並在任何雲端上運行它們。

在實踐中,儘管application cluster作為application runtime layer的一部分可能很有用,但創建完整的runtime layer還需要做更多的作業。 從底層雲端平台實現真正的抽象(abstraction)並非易事。

應用程式需要存取Cluster提供的運算以外的其他資源,包括儲存和網路。 這些資源將由不同的平台以不同的方式提供,除非我們建立解決方案來抽象化這些資源。

我們還需要提供監控、身分管理、secrets management等服務。 同樣,我們將在每個雲端平台上使用不同的服務,或建立可以在每個雲端上部署和維護的服務或抽象層。

因此,application cluster實際上是整個應用程式託管平台的一小部分。 甚至這個部分也往往因各雲端平台、核心 K8S 系統的版本、實作和工具而異。

Packaged Cluster Distribution

許多技術團隊喜歡自己架application clusters,而不是使用託管服務。 K8S 是最受歡迎的叢集解決方案。我們可以使用 kops、Kubeadm 和 kubespray 等安裝程式將 K8S 部署到我們自己的基礎架構上。

還有捆綁其他服務和功能的打包 K8S distributions。 實際上有幾十個,其中一些是:

  • HPE Container Platform (Hewlett Packard)
  • OpenShift (Red Hat)
  • Pivotal Container Services (PKS) (VMware/Pivotal)
  • Rancher RKE

其中一些產品最初具有自己的container formats以及application scheduling 與orchestration services。 許多供應商決定圍繞著極其流行的 Docker 和 K8S 重建他們的核心產品,而不是繼續開發自己的解決方案。

但少數產品拒絕融入 K8S borg。 其中包括 HashiCorp NomadApache Mesos,兩者都可以跨不同運算資源的orchestrate container instances以及非容器化應用程式。 Cloud Foundry Application Runtime(CFAR) 有自己的container orchestration (Diego),儘管它也可以與 K8S 一起使用。

Application Clusters的Stack技術

Application cluster由不同的移動部分組成。 一組部分是管理叢集的應用程式和服務。 其中一些管理叢集服務包括:

  • Scheduler —
    決定每個應用程式要運行多少個instance以及在哪裡運行它們
  • Monitoring —
    偵測application instances的問題,以便在必要時重新啟動或移動它們
  • Configuration registry —
    用於儲存管理叢集和配置應用程式所需的資訊
  • Service discovery —
    讓應用程式和服務能夠找到application instances的當前位置
  • Management API and UI —
    使工具和使用者能夠與叢集交互

許多叢集部署在專用伺服器上執行管理服務,與託管應用程式執行個體的服務分開。 這些服務可能也應該叢集運行,以實現韌性。

Application cluster的其他主要部分是應用程式託管節點。 這些節點是調度程序運行application instances的server pool。 通常將它們設定為伺服器叢集來管理server instance的數量和位置。 Service mesh可以在主機節點上與application instances一起運行sidecar processes。

Application cluster範例(如下圖 )包括運行叢集管理服務的伺服器、運行application instances的伺服器叢集以及network address blocks。

Application cluster的網路結構可以是扁平的。 叢集服務將網路位址指派給application instances。 它還應該處理網路安全,包括加密和連接管理,通常使用service mesh來處理這些作業。

我們可以使用infrastructure stacks來設定此基礎架構。 Part 5解釋了Stack的大小及其內容的範圍對變更的速度和風險有影響。

Part 5中的「建構Stack的模式和反模式」特別列出了跨Stack安排資源的模式。 以下範例展示了這些模式如何應用cluster infrastructure。

Monolithic Stack Using Cluster as a Service

最簡單的設計是在單一stack中定義叢集的所有部分,遵循monolithic stack反模式。 儘管單體在規模上成為一種反模式,但當從一個小而簡單的叢集開始時,單一堆疊可能會很有用。

以下範例使用cluster as a service,類似 AWS EKS、AWS ECS、Azure AKS 和 GCP GKE。 因此,代碼定義了Cluster,但不需要配置伺服器來運行Cluster管理,因為雲端平台在背後進行此管理作業。

address_block:
name: cluster_network
address_range: 10.1.0.0/16"
vlans:
- vlan_a:
address_range: 10.1.0.0/8
- vlan_b:
address_range: 10.1.1.0/8
- vlan_c:
address_range: 10.1.2.0/8

application_cluster:
name: product_application_cluster
address_block: $address_block.cluster_network

server_cluster:
name: "cluster_nodes"
min_size: 1
max_size: 3
vlans: $address_block.cluster_network.vlans
each_server_node:
source_image: cluster_node_image
memory: 8GB

此範例省略了實際叢集所需的許多內容,例如網路路由、安全性原則和監控。 但它呈現了網路、叢集定義和主機節點的server pool等重要元素都在同一個專案中。

Monolithic Stack for a Packaged Cluster Solution

上面範例中的代碼使用了基礎設施平台提供的應用程式叢集服務。 許多團隊使用打包的應用程式叢集解決方案。 這些解決方案具有將叢集管理軟體部署到伺服器上的安裝程式。

使用這些解決方案之一時,Infra stack會提供安裝程式部署和配置叢集所需的基礎架構。 運作安裝程序應該是一個單獨的步驟。 這樣,就可以與應用程式叢集分開測試Infra stack。 我們可以將叢集的配置定義為代碼。 如果是這樣,可以透過測試和流水線適當地管理代碼,以幫助我們能輕鬆、安全地交付更新和變更。

使用server configuration code(在Part 11中提到)將叢集管理系統部署到伺服器上可能會很有用。 有些打包產品使用標準設定工具,例如 Ansible for OpenShift,因此我們可以將它們合併到stack building process。 下面範例顯示了一個片段,我們可以將其新增至上面範例中的monolithic stack code,以便為叢集管理應用程式建立伺服器。

virtual_machine:
name: cluster_manager
source_image: linux-base
memory: 4GB
provision:
tool: servermaker
parameters:
maker_server: maker.shopspinner.jas
role: cluster_manager

代碼透過執行虛構的 servermaker 指令並套用 cluster_manager 角色來設定伺服器。

Monolithic Application Cluster Stack的流水線

由於只有一個Stack,因此單一流水線可以測試代碼變更並將其交付到應用程式叢集的instance。 但是,也涉及其他元素,包括host nodes的server image和應用程式本身。 下圖顯示了這些流水線的可能設計。

上圖中最上面的流水線是由server image建立的host nodes,如我們在Part 13中「使用流水線測試和交付server image」中所述。 該流水線的結果是經過單獨測試的server image。 此image的測試可能會檢查容器管理軟體是否已安裝以及是否符合安全性原則。

上圖(截圖如下)中最底下的流水線(Customer Application)用於部署到叢集上的應用程式。 在實踐中,我們將擁有許多這樣的元件,每個單獨部署的應用程式都有一個。 該流水線至少包括一個用於自行建立和測試應用程式的早期階段。 然後,它具有將應用程式部署到每個環境中的叢集的階段。 可以對應用程式進行測試、審查並使其可在這些環境中用於生產環境。 應用程式的流水線與cluster instances的流水線耦合非常鬆散。 我們可以選擇在叢集更新後觸發應用程式測試階段。 執行此操作可以透過執行特定​​於應用程式的測試來尋找叢集變更對應用程式造成的任何問題。

下圖中的application cluster stack的流水線從運作一些語法檢查的離線階段開始,並將stack code套用於基礎設施平台的本地模擬。 這些測試可以在編碼層級偵測到問題,而不需要使用基礎設施平台資源,因此運作速度很快。

該流水線的第二階段是線上的,並在基礎設施平台上建立stack的instance。 該instance可能是持久的或短暫的。 此階段的測試可以檢查叢集管理服務是否正確建立並可存取。 也可以測試安全性問題,例如,確保鎖定對叢集管理端點的存取。

由於這個monolithic cluster stack包含建立主機節點伺服器的代碼,因此線上測試階段也可以測試這些代碼。 測試可以將範例應用程式部署到叢集並證明它正在作業。 使用範例應用程式而不是實際應用程式的優點是可以保持簡單。 將其精簡為最小的依賴項和配置集,這樣就可以確保任何測試失敗都是由叢集配置問題引起的,而不是由於部署實際應用程式的複雜性造成的。

我們需要注意,此流水線階段作業很繁重。 它測試叢集配置和主機節點伺服器叢集。 它還在叢集整體脈絡中測試server image。 有許多不同的事情可能導致此階段失敗,這使得故障排除和修復故障變得複雜。

此階段的大部分時間幾乎肯定會用於配置所有內容,遠遠超過執行測試的時間。 這兩個問題(此階段測試的各種事物以及配置所需的時間)是將叢集分解為多個Stack的主要驅動因素。

叢集的多個stack範例

將叢集的基礎設施代碼分解為多個Stack可以提高變更流程的可靠性和速度。 因為這樣的設計可以在每個stack單獨配置和測試它,而不需要配置其他stack的instance。

首先將host node server pool拉入一個單獨的stack,如以下範例所示。 可以在沒有application cluster的情況下配置和測試該stack的instance。 測試平台是否成功從Image啟動伺服器以及網路路由是否正常運作。 還可以測試可靠性,觸發其中一台伺服器出現問題並證明平台是否會自動替換它。

server_cluster:
name: "cluster_nodes"
min_size: 1
max_size: 3
vlans: $address_block.host_node_network.vlans
each_server_node:
source_image: cluster_node_image
memory: 8GB

address_block:
name: host_node_network
address_range: 10.3.0.0/16"
vlans:
- vlan_a:
address_range: 10.3.0.0/8
- vlan_b:
address_range: 10.3.1.0/8
- vlan_c:
address_range: 10.3.2.0/8

與先前的monolithic stack code的範例不同,此代碼為主機節點新增了單獨的 VLAN。 將主機節點和叢集管理拆分到不同的網段是一種很好的做法,我們可以在monolithic stack中執行此操作。 要將Stack分開會讓我們進行這種行動,即使只是為了減少兩個Stack之間的耦合。

將Stack分開會為host node cluster stack新增一個新的流水線,如下圖所示。

儘管這個組合流水線中多了幾個階段,但它們更輕、更快。cluster management stack的線上測試階段(如下圖)僅提供叢集管理基礎設施,這比monolithic stack pipeline中的線上階段更快。 這個Stack不再依賴host node server images的流水線,並且不包括伺服器節點。 因此,此階段的測試可以重點檢查叢集管理是否已正確配置和保護。

修改後的設計在Stack整合階段將host node server stack的流水線與cluster management stack的流水線連接在一起,如下圖所示。

這是一個線上測試階段,同時配置和測試兩個stack的instance。 這些測試可以集中在只在該組合中出現的問題,因此不應重複先前階段的測試活動。 在此階段,我們將部署範例應用程式並證明它在叢集上正確運行。 還可以透過觸發測試應用程式中的故障並建立添加其他instance所需的條件來測試可靠性和擴展性。

我們可能決定將其分成更多Stack; 例如,將通用網路基礎架構從管理堆疊中分離出來。 Part 15和17將詳細介紹了跨stack分解和整合基礎設施的細節。

Application Clusters的共享策略

我們應該運行多少個Cluster,它們應該有多大,以及每個Cluster應該運行多少個節點?理論上,我們可以運行單一Cluster,在cluster instance內體現環境和其他應用程式邊界。 然而,單一Cluster可能不實用的原因有很多:

  • 變更管理
    叢集(Cluster)需要更新、升級、修復和更改。 因此,至少,我們需要在某個地方測試這些不會中斷服務的變更。 對於服務中斷性的變更,例如那些需要停機或有停機風險的變更,安排滿足所有團隊、應用程式和區域需求的時間是一項挑戰。 運行多個叢集可以更輕鬆地安排維護時段,並減少失敗變更的影響。
  • 隔離(segregation)
    許多叢集實作沒有在應用程式、資料和配置之間提供足夠強大的隔離。 我們也可以根據叢集上執行的服務對叢集實作採用不同的治理機制。 例如,處理個資的服務可能有更嚴格的合規性要求,因此在單獨的叢集上執行它們可以簡化對其他叢集的要求。
  • 可配置性(Configurability)
    某些應用程式或團隊對其使用的叢集有不同的配置要求。 為他們提供單獨的叢集實例可以減少配置衝突。
  • 效能與可擴充性
    叢集解決方案具有不同的擴展特性。 許多叢集無法應對較高的延遲,這使得跨地理區域運行單一叢集變得不切實際。 當應用程式在單一叢集上擴展時,它們可能會遇到資源限制或相互爭用問題。
  • 可用性
    單一叢集是單點故障。 運行多個叢集可以幫助應對各種故障場景。

有一些用於調整cluster instances大小和共享的潛在策略。 若要為系統選擇正確的策略,需要考量對變更隔離、可配置性、效能、規模、分佈和可用性的要求。 然後根據這些要求測試application clustering solution。

一個大叢集運作全部

單一叢集比多個叢集更容易管理。 可能的例外是管理變更。 因此,我們至少應該使用至少一個單獨的Cluster instance來測試變更,使用流水線在其中部署和測試叢集配置變更,然後再將其應用到生產叢集。

交付階段的獨立叢集

我們可以為軟體交付流程的不同部分運行不同的叢集。 做到這一點就像每個環境運行一個叢集一樣簡單(如下圖)。

每個環境的專用叢集可以避免多個環境中的應用程式共用資源時可能出現的不一致情況。 然而,為每個交付階段維護一個單獨的instance可能很困難且昂貴。 例如,如果交付過程動態建立test instances,可能需要動態建立cluster instances來運行它們,這可能會非常緩慢。

按交付階段分離叢集的變體是跨多個階段共用叢集。 例如,可以根據治理要求使用不同的叢集。 在下圖中,存在三個 叢集。 DEV用於開發、運行instance,人們可以在其中建立和使用各種資料集來進行更具探索性的測試場景。 NON-PROD 適用於更嚴格的交付階段,並具有託管測試資料集。 PROD 託管 PREPROD 和 PROD 環境,這兩個環境都包含客戶資料,因此具有更嚴格的治理要求。

在共用叢集中託管多個環境時,應該盡可能保持每個環境隔離。 理想情況下,應用程式和維運服務不應能夠查看其他環境中的instance或與其他環境中的instance進行連線。 應用程式叢集解決方案提供的用於分離應用程式的許多機制都是「Soft」的。 例如,可以標記instance來指示環境,但這純粹是一種約定。 我們應該尋找更強大的方法來隔離應用程式。

治理叢集

為交付過程的不同部分設定單獨的叢集的效益之一是,過程中不同階段的治理要求通常不同。 生產環境的要求更加嚴格,因為生產環境中運作的服務對業務最為關鍵,而且資料也最為敏感。

通常,系統的不同部分具有不同的跨越交付階段的治理和合規性要求。 最常見的範例是處理信用卡的服務,該服務受 PCI 標準的約束。 其他範例包括處理客戶個人資料的服務,這些服務可能受 GDPR 等制度的約束。

在專用叢集上遵守更嚴格標準的託管服務可以簡化並加強合規性和稽核。 我們可以對這些叢集、在其上運行的應用程式以及向其交付代碼變更實施更強有力的控制。 託管合規性要求不太嚴格的服務的叢集可以簡化治理流程和控制。

例如,可以有兩個叢集,一個用於受監管服務的開發、測試和生產託管,另一個用於不受監管的服務。 或者您可以按照交付階段和監管要求拆分cluster instance,如下圖所示。

團隊的叢集

管理多個叢集的另一個因素是團隊所有權。 通常,不同的團隊負責交付和運行不同類型的應用程式和服務,這些應用程式和服務可能有不同的託管要求。 例如,運行外部網站的團隊可能與擁有內部部門服務的團隊對治理和可用性有不同的要求。 分配給團隊的叢集可以針對該團隊及其應用程式的需求進行最佳化。

Service Mesh

Service Mesh是一個分散的服務網路,它動態管理分散式系統各部分之間的連接。 它將網路功能從基礎設施層移動到我們在Part 1中「基礎設施系統的組成部分」中描述的模型的application runtime layer。在典型的Service Mesh實作中,每個application instance將與其他instance的通訊委託給sidecar process(如下圖)。

Service Mesh可以向應用程式提供的一些服務包括:

  • Routing
    將流量導向到特定應用程式的最合適的instance,無論該應用程式目前在何處運行。 使用Service Mesh的動態路由可實現進階部署方案,例如blue-green與canary
  • Availability
    執行限制請求數量的規則; 例如,circuit breakers
  • Security
    處理加密,包括憑證
  • Authentication
    對哪些服務可以連接哪些服務執行規則。 管理點對點身份驗證的憑證
  • Observability, monitoring, and troubleshooting
    記錄連現和其他事件,以便我們可以透過複雜的分散式系統追蹤request

Service Mesh與application hosting cluster結合使用效果很好。 應用程式叢集動態地提供與較低層級資源解耦的運算資源。 Service Mesh動態管理與較低層級網路資源分離的應用程式通訊。 這種模式的好處是:

  • 它透過將常見問題從應用程式移至 sidecar 來簡化應用程式開發。
  • 它可以更輕鬆地建立和改進整個資產中的常見問題,因為只需將更新部署到 sidecar,而不需要對所有應用程式和服務進行代碼變更。
  • 它處理應用程式部署的動態特性,因為部署和配置application instances(例如,在容器中)的相同的orchestration與scheduling system可以與它們一起部署和配置 sidecar instance。

Service Mesh的一些範例包括 HashiCorp Consul、Envoy、Istio 和 Linkerd。

Service Mesh最常與容器化系統相關。 但是,我們可以在非容器化系統中實現該模型; 例如,透過將 sidecar process部署到VM上。

Service Mesh增加了複雜性。 與微服務等雲原生架構模型一樣,Service Mesh很有吸引力,因為它簡化了單一應用程式的開發。 然而,複雜性並沒有消失; 我們只是將其移至基礎架構中。 因此,組織需要做好管理這一點的準備,包括為很高的學習曲線做好準備。

在基礎設施層級實現的網路與Service Mesh中實現的網路之間保持清晰的界限至關重要。 如果沒有良好的設計和實施紀律,可能會重複和混合問題。 系統更難理解,變更的風險更大,並且更難排除故障。

FaaS Serverless的基礎設施

我們在Part 3將 FaaS serverless列為平台向應用程式提供運算資源的方式之一。 應用程式代碼的正常模型是在容器或伺服器中連續運行。 FaaS On-deman執行應用程式代碼,以回應事件或排程。

FaaS 代碼對於代碼快速啟動的定義明確、短暫的運作非常有用。 典型範例是處理 HTTPrequest或回應message queue中的錯誤事件。 該平台在需要時平行啟動代碼的多個instance,例如,處理同時傳入的多個事件。

FaaS 對於需求變化很大的工作負載來說非常高效,在出現高峰時進行擴展,在不需要時完全停止。

「Serverless」並不是最準確的術語,因為代碼當然是在伺服器上運行的。 只是作為開發人員,伺服器實際上是不可見的。 容器也是如此,所以所謂的 Serverless 的獨特之處並不是伺服器的抽象層級。 與serverless的真正區別在於它是一個短暫的Process而不是長期運行的Process。

出於這個原因,許多人更喜歡 FaaS 這個術語,而不是serverless。 這也消除了FaaS 與術語「serverless」的其他用法的歧義,serverless也可以表示BaaS(Backend as a Service),這是一種外部託管的服務。FaaS runtimes遵循與應用程式叢集相同的模型- FaaS runtimes由基礎設施作為服務提供平台和打包的 FaaS,這需要我們預置和配置基礎設施和管理工具。

作為服務提供的 FaaS runtimes範例包括:

  • AWS Lambda
  • Azure Functions
  • GCP Cloud Function

套裝的 FaaS runtimes解決方案範例包括:

  • Fission
  • Kubeless
  • OpenFaaS
  • Apache OpenWhisk

我們可以使用本文前面描述的相同策略來為套裝FaaS 解決方案配置基礎設施,例如伺服器池和管理服務。 確保我們深入了解 FaaS 解決方案的工作原理,以便了解代碼是否以及如何「洩漏」資料。 例如,它可能會在其他 FaaS 代碼可用的位置留下臨時檔案和其他殘留物,這可能會產生安全性和合規性問題。 FaaS 解決方案能否很好地滿足資料分離的需求以及它是否可以擴展,應該會促使我們決定是否執行 FaaS runtimes的多個instance。

雲端供應商提供的 FaaS 服務通常不會像應用程式叢集那樣留給我們那麼多資源。 例如,我們通常不需要指定代碼執行所在的主機伺服器的大小和性質。 這大大減少了我們需要定義和管理的基礎設施的數量。

然而,大多數 FaaS 代碼確實與其他服務和資源互動。 我們可能需要為觸發 FaaS 應用程式的inbound requests以及代碼發出的outbound requests來定義網路。 FaaS 代碼經常讀取資料和訊息並將其寫入儲存裝置、資料庫和message queue。 這些都需要我們定義和測試基礎架構資源。 當然,與任何其他代碼一樣,FaaS 代碼應該使用流水線進行交付和測試。 因此,仍然需要圍繞定義和推廣基礎設施代碼並將其與應用程式測試流程整合的所有實踐。

結論

運算基礎設施的存在是為了支援服務。 服務由運行在runtime environment中的應用軟體提供。 本文描述如何使用代碼來定義為組織的應用程式提供執行階段環境的基礎架構。

--

--

運用"雲端服務"加速企業的數位轉型願景
運用"雲端服務"加速企業的數位轉型願景

Written by 運用"雲端服務"加速企業的數位轉型願景

我們協助您駕馭名為"雲端運算"的怪獸,馴服它為您所用。諮詢請來信jason.kao@suros.com.tw. https://facebook.com/jason.kao.for.cloud

No responses yet