1. 程式人生 > >應用容器化和與Kubernetes適配的7條軍規_Kubernetes中文社群

應用容器化和與Kubernetes適配的7條軍規_Kubernetes中文社群

導讀

本文來自於Red Hat諮詢顧問Bilgin Ibryam所編寫的一篇白皮書,名為《PRINCIPLES OF CONTAINER-BASED APPLICATION DESIGN》。已被被Kubernetes官網轉載。白皮書在Red Hat官網的下載地址:https://www.redhat.com/en/resources/cloud-native-container-design-whitepaper 本微信文章是我是對這篇文章的學習和整理。

先回顧經典的軟體設計原則:

  • 保持簡單,愚蠢(KISS)
  • 不要重複自己(DRY)
  • 適可而止 (YAGNI)
  • 關注點分離(SoC)
  • 單一責任, 開放封閉, 里氏替換, 迪米特法則,介面分離, 依賴倒置(SOLID)

然後是Red Hat的雲原生容器設計原則:

  1. 單一關注性原則(SCP)
  2. 高度可觀測性原則(HOP)
  3. 生命週期一致性原則(LCP)
  4. 映象不可變性原則(IIP)
  5. 程序可處置性原則(PDP)
  6. 自包含性原則(S-CP)
  7. 執行時約束性原則(RCP)

很多組織都理解雲原生的重要性和必要性,但是並不知道從哪裡開始。那麼請確保:雲原生平臺和容器化應用能無縫的執行在一起,並且具備抵禦故障的能力,甚至在底層的基礎架構出現宕機的時候,也能通過過彈性擴充套件的方式表現出可靠性。本文描述了容器化應用時需要遵循的基本準則,實施這些原則有助於使之與雲原生平臺Kubernetes更加適配。

1、單一關注性原則

SINGLE CONCERN PRINCIPLE(SCP)

在許多方面,單一關注性原則與來自SOLID的SRP是類似的,它建議一個類應該只有一個責任。SRP背後的動機是每個責任是變更的一個軸心,一個類應該有,且也只有一個需要改變的理由。SCP原則中的“關注”一詞強調關注是一種更高層次的抽象的責任,而且它更好地將範圍描述為一個容器而不是一個類。雖然SRP的主要動機是變化原因的唯一性,而SCP的主要動機是容器映象重用和可替換性。如果你建立一個解決單個問題的容器,並且以功能完整的方式來實現,不同應用程式中的容器映象重用的可能性就會更高。

因此,SCP原則規定每個集容器都應該解決一個問題,並做得很好。 實現這一點,通常比在面向物件的世界中實現SRP更容易,容器通常管理的一個單一的程序,大多數情況下一個程序解決一個問題。

如果你的容器化微服務需要解決多個問題,它可以使用這樣的模式,將多個容器用sidecar和init-containers的模式合併成一個部署單元(pod),這樣每個容器仍然是處理單個問題。同樣,您可以替換處理同樣問題的容器。 例如,將Web伺服器容器或佇列實現容器,更新為更具可擴充套件性的容器。

2、高度可觀測性原則

HIGH OBSERVABILITY PRINCIPLE(HOP)

容器提供了一種統一的方式來打包和執行應用程式,將它們視為一個黑盒子物件。 但任何旨在成為雲原生公民的容器都必須提供API支援,要為執行時環境編寫介面(API),以觀察容器的健康狀況和行為。 這是自動化容器更新和生命週期回收的基本先決條件和統一的方式,從而提高系統的彈性和使用者體驗。

實際上,您的容器化應用程式必須至少為其提供不同型別的健康檢查的API–活動和就緒等狀態。更好的應用程式的行為則必須提供其他手段來觀察容器化應用程式的狀態。應用程式應該將重要事件記錄到標準錯誤(STDERR)和標準輸出(STDOUT)中,從而通過統一的日誌聚合工具(諸如Fluentd和Logstash之類的工具)進行分析,並與跟蹤和指標收集庫相結合,例如OpenTracing,Prometheus等。

將您的應用程式視為黑盒子,但實施所有必要的API以幫助平臺對其進行觀測,並以最佳方式管理您的應用程式。

 3、生命週期一致性原則

LIFE-CYCLE CONFORMANCE PRINCIPLE(LCP)

HOP規定了你的容器提供供平臺觀測的API。 LCP則規定:您的應用程式有辦法讀取來自平臺的事件。 此外,除了獲得事件以外,容器還應該對這些事件相應地作出反應。這就是此原則名字由來。這幾乎就像在應用程式通過一個“寫入API”與平臺進行互動。

來自管理平臺的各種事件都是為了幫助您管理您的容器的生命週期的。決定處理哪些事件取決於您的應用程式 以及是否對這些事件做出反應。

但有些事件比其他事件更重要。例如,任何需要一個乾淨的關閉程序,這就需要捕獲訊號:終止(SIGTERM)訊息,並儘可能迅速關閉。 這是為了避免通過強制關閉訊號:kill(SIGKILL),之後跟隨一個SIGTERM。

還有其他事件,例如PostStart和PreStop,可能對您的應用程式生命週期管理也非常重要。 例如,某些應用程式需要在服務之前進行預熱請求和一些需要在關閉乾淨之前釋放資源。

 4、映象不可變性原則

IMAGE IMMUTABILITY PRINCIPLE(IIP)

容器化的應用程式是不可變更的,映象一旦完成了構建,預計在不同的環境中執行都不會改變。這意味著在因外部環境的不同,在需要的時候需要使用外部手法處理所依賴的外部配置資料,而不是每個環境修改或者構建不同的容器。而容器應用程式中的任何變更,都應該因此觸發構建新的容器映像,並在所有環境中重用它。相同於這個原理的,不可變伺服器和不可變基礎架構的概念也很受歡迎,並且對於伺服器/主機管理也是如此。

在遵循IIP原則的情況下,應該防止為不同的環境建立相似的容器映象,要始終堅持為所有環境只配置一個容器映像。 這個原則允許在應用程式更新期間,採用自動回滾和前滾等做法,這是雲原生自動化的重要方面。

 5、程序可處置性原則

PROCESS DISPOSABILITY PRINCIPLE(PDP)

遷移到容器應用程式的主要動機之一是:容器需要儘可能做到臨時性,並做好在任何時候被另一個容器例項替換的準備。需要更換容器的原因有很多,比如:健康檢查失敗、縮容、應用程式將容器遷移到不同的主機,平臺資源匱乏或其它的問題。

這意味著容器化的應用程式必須保持其狀態為向外擴充套件的或分散式和冗餘的。這也意味著應用程式應該快速啟動和關閉,甚至為徹底的硬體故障做好準備。 實施這一原則的另一個有用的做法是建立小容器。 容器在雲原生環境可以自動排程並在不同的主機上啟動。較小的容器可以實現更快啟動時間,因為在重新啟動之前容器映象需要被物理地複製到主機系統。

 6、自包含性原則

SELF-CONTAINMENT PRINCIPLE(S-CP)

這個原則規定一個容器應該在構建時包含所有需要的東西。容器的存在應該僅僅依賴於Linux®核心,在並新增相關額外的庫,在容器構建時加入它們。除了庫之外,它還應該包含語言執行時,應用程式平臺(如果需要),以及執行所需的其他依賴關係,等執行容器化應用所需要的諸如此類的東西。

唯一的例外是:由於不同環境之間差異,並且只能在執行時提供的配置; 例如,通過Kubernetes提供的ConfigMap。

某些應用程式由多個容器元件組成。 例如,容器化的Web應用程式也可能需要資料庫容器。 根據這個原則,並不建議合併兩個容器。相反,它建議的是資料庫容器只包含執行資料庫所需的所有內容,Web應用程式容器只包含執行Web應用程式所需的所有內容,如Web伺服器。 在執行時,Web應用程式容器將根據需要依賴於並訪問資料庫容器。

 7、執行時約束性原則

RUNTIME CONFINEMENT PRINCIPLE(RCP)

S-CP從構建時的角度檢視容器,並關注於生成的二進位制檔案及其內容。但是容器不僅僅是磁碟上一個只有尺寸大小的單一維度的黑盒子。 容器執行時有多個維度,例如記憶體使用維度,CPU使用維度等資源消耗維度。

這個RCP原則建議每個容器申報資源需求,併發送資訊到平臺。它應該分享容器的資源配置檔案,從CPU,記憶體,網路,磁碟的角度宣告。這影響到平臺如何執行排程,自動擴充套件,容量 管理以及容器常規的服務級別協議(SLA)等。

除了向平臺宣告容器的資源需求之外,還有一點也很重要, 應用被約束在使用所宣告的資源需求內。如果應用程式對資源的使用保持在約束的範圍內,則當資源匱乏發生時,平臺不太可能將其終止和遷移。

8、結論

雲原生不僅僅是一種最終狀態 – 它也是一種工作方式。 本份白皮書描述了一系列容器應用的基本原則,必須遵守才能成為優秀的雲原生公民。

除了這些原則之外,建立良好的容器應用程式還需要熟悉其他容器相關的最佳實踐和技術。 儘管上述原則非常根本,適用於大多數用例,下面列出的最佳實踐在應用和不應用的時候,則需要判斷力。以下是一些與容器相關的更常見的最佳實踐:

  • 映象要儘可能的小。 通過清理臨時檔案,並避免安裝不必要的軟體包來構建小尺寸映象。 這減少了容器的尺寸,構建時間和複製容器映象的網路傳輸時間。
  • 支援任意使用者ID。 避免使用sudo命令或要求特定使用者名稱執行你的容器。
  • 標記重要的埠。 雖然可以在執行時指定埠號,然而使用EXPOSE命令在執行的時候指定,則可以讓映象的使用者更輕鬆。
  • 為持久資料使用卷。 在容器摧毀之後還需要儲存的容器資料的,必須將資料寫入一個數據卷。
  • 設定映象元資料。 以標籤和註釋形式存在的映象元資料可以使您的容器映象更加實用,從而為使用您的容器的開發人員提供了更好的體驗。
  • 使主機和映象同步。 一些容器應用需要容器在某些屬性(如時間和機器ID)上與主機同步。

這裡是指向各種模式和最佳實踐的資源的連結,以幫助您能有效地實現上述目標:

  • https://www.slideshare.net/luebken/container-patterns
  • https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices
  • http://docs.projectatomic.io/container-best-practices
  • https://docs.openshift.com/enterprise/3.0/creating_images/guidelines.html
  • https://www.usenix.org/system/files/conference/hotcloud16/hotcloud16_burns.pdf
  • https://leanpub.com/k8spatterns/
  • https://12factor.net