Kubernetes架構基礎知識

Kubernetes是擁有大量代碼和功能的大型開源項目。讀者可能閱讀過Kubernetes的相關文章,或在其他項目中涉足這一領域,甚至在工作中使用過Kubernetes。但若想深入理解並有效使用Kubernetes,將其更好地應用於實踐,則需要對其有更深入的瞭解。本章將構建Kubernetes的基本框架,首先,我們將理解容器編排(Container Orchestration)的含義;接着解釋幾個與Kubernetes相關的重要概念,這些概念將貫穿於全書;之後,深入介紹Kubernetes的體系架構,瞭解如何將Kubernetes的所有功能提供給用戶;緊接着將介紹Kubernetes支持的各種運行時和容器引擎(Docker便是其中之一);最後,對Kubernetes在全連續集成(Full Continuous Integration)和部署管道(Deployment Pipeline)中的作用進行探討。

本章將重點介紹以下幾個方面:容器編排、Kubernetes適用條件、Kubernetes設計原理和體系結構以及Kubernetes支持的不同運行時環境。讀者將熟悉開源倉庫的整體結構,併爲解決其餘問題打好基礎。

1.1 理解容器編排

Kubernetes的主要功能是容器編排,是指確保所有容器都按照計劃運行在物理機或虛擬機上。這些容器在部署環境和集羣配置的約束下被打包執行大量工作負載。此外,Kubernetes必須密切關注所有運行中的容器,替換運行中止、無響應或其他非正常狀態的容器。後續章節將會介紹Kubernetes的更多功能,本節將重點介紹容器及其編排。

1.1.1 物理機、虛擬機和容器

硬件貫穿於容器編排的始終。運行工作負載需要一些真正的硬件配置,包括具有計算能力(CPU或核心)、內存和一些本地持久存儲(機械硬盤或SSD)的實體物理機。此外,需要一些共享的持久存儲,並使用網絡連接所有物理機,以便於其互相查找和信息互通。此時,可在物理機上運行多個虛擬機或單純保持裸金屬狀態。Kubernetes可部署在實體硬件或虛擬機集羣上,同時也可以直接在實體硬件或虛擬機上管理容器。理論上,一個Kubernetes集羣可以由物理機和虛擬機組合而成,但這並不常見。

1.1.2 雲端容器

容器是封裝微服務的理想選擇,因爲它們不僅爲微服務提供隔離,並且非常輕量,且在部署多個微服務時不會像使用虛擬機時那樣產生大量開銷。這使得容器非常適合於雲部署,因爲爲每個微服務分配整個虛擬機的成本非常高。

現在主要的雲提供商(如AWS、GCE和Azure)都提供容器託管服務,其中一些便是基於Kubernetes(如Google的GKE);另外諸如Microsoft Azure的容器服務,則是基於Apache Mesos等其他解決方案。此外,AWS將ECS(EC2上的容器服務)作爲其自有的編排解決方案。Kubernetes的強大之處在於,它可以部署在上述這些雲服務器上。Kubernetes有一個雲提供商接口,允許任何雲提供商執行並無縫集成Kubernetes。

1.1.3 服務器運行模式

過去系統規模很小,每個服務器都有一個名字。開發人員和用戶確切地知道每臺機器上運行的是什麼軟件。我工作過的許多公司都進行過數日討論,來決定服務器的命名主題。例如,作曲家和希臘神話人物是受歡迎的選擇。開發人員像對待自己摯愛的寵物一樣對待服務器。如果一臺服務器發生故障,這將是重大的危機,所有人都需投入全部精力完成這3件事情:更換一臺新的服務器;確認發生故障的服務器上還運行着哪些數據;如何讓這些數據在新服務器上運行。如果發生故障的服務器存儲了一些重要的數據,那隻能寄希望於備份數據和數據恢復。

顯然,這種方法並不合適,當有幾十個甚至上百個服務器時,必須像對待牲畜一樣對待它們,此時需考慮的是集體而非個體。或許此時構建機器時仍需要像對待寵物一樣處理,但對於網絡服務器來講,只能像對待牲畜一樣去處理。

Kubernetes把這一方法推向極致,它承擔了將容器分配給特定機器的全部任務。無須花費大量時間與各個機器(節點)交互。這對於無狀態工作負載來說是最好的。對於有狀態應用程序,情況稍有不同,但Kubernetes提供了一個名爲StatefulSet的解決方案,我們接下來將對其進行討論。

在本節中,講述了容器編排的概念,討論了主機(物理機或虛擬機)和容器之間的關係,以及在雲端運行容器的優勢,最後以牲畜和寵物作爲類比探討服務器的運行模式。1.2節將進入Kubernetes的世界,瞭解與之相關的概念和術語。

1.2 Kubernetes的相關概念

本節將簡要介紹許多與Kubernetes相關的重要概念,並提供一些案例來說明這些概念的重要性和相互間的關係,以便熟悉這些術語和概念。接着,介紹如何將這些概念編排在一起以實現令人敬畏的效果。讀者可將其中的許多概念視爲構建塊。一些概念被視作一個Kubernetes組件來執行,如節點和主節點。這些組件處於不同的抽象級,這將在1.5節中進行詳細討論。

圖1.1是著名的Kubernetes架構。

圖1.1 Kubernetes架構

1.2.1 集羣

集羣是主機存儲和網絡資源的集合,Kubernetes使用集羣來運行組成系統的各種工作負載。一個完整的系統可以由多個集羣組成。之後會詳細討論集羣聯邦的高級用例。

1.2.2 節點

節點是單個主機,它可以是物理機或虛擬機,職責是運行Pod。每個Kubernetes節點運行多個Kubernetes組件,如Kuberlet和Kube代理。節點由Kubernetes主控制器管理,這些節點類似於Kubernetes的工蜂,肩負重擔,過去它們被稱爲下屬(Minion)。如果讀者曾閱讀過以往的文獻資料,請不要被混淆,下屬即指節點。

1.2.3 主節點

主節點是Kubernetes的控制面板,由幾個組件組成,包含API服務器、調度器和控制器管理器。主節點負責節點在全局、集羣水平的調度和事件處理。通常,所有的主控制器組件都設置在一個單一主機上,在考慮到高可用性場景或大型集羣時,會傾向於採用多個主節點。在第4章中將詳細說明高可用性集羣。

1.2.4 Pod

Pod是Kubernetes的工作單元,每個Pod包含一個或多個容器,Pod通常在同一臺機器上運行並一起調度。Pod中的所有容器具有相同的IP地址和端口空間,它們可通過本地主機或標準進程進行通信。此外,Pod中的所有容器都可以訪問承載於Pod的節點上的本地共享存儲,共享存儲會存在於每個容器上。Pod是Kubernetes的重要特徵,通過作爲運行於多個進程的主Docker應用程序的超級管理員,可以實現在單個Docker容器中運行多個應用程序,但出於以下幾點,並不鼓勵這種做法。

  • 透明性:使Pod內的容器對基礎設施可見,使得基礎設施能夠向這些容器提供服務,例如流程管理和資源監控,這爲用戶提供了許多便利。
  • 解耦軟件依賴:可以獨立地對單個容器進行版本化、重建和重新部署。Kubernetes甚至有望支持單個容器的實時更新。
  • 易用性:用戶無須運行自有進程管理器,也不需要擔心信號和退出代碼的事務傳播等。
  • 效率:由於基礎設施將承擔更多的職責,因此容器可以更加輕量。

對於相互依賴且需要在同一主機上協作以實現其目標的容器組,Pod提供了很好的解決方案。切記,Pod被認爲是臨時、可替代的實體,需要的話可以被丟棄和替換,Pod可破壞任何Pod存儲。每個Pod都有一個唯一的ID(UID),因此,區分它們仍是可實現的。

1.2.5 標籤

標籤是用來組合對象集合(通常是Pod)的鍵值對。這對於其他幾個概念非常重要,例如副本控制器、副本集以及需要在對象動態組上進行操作、標識組成員的服務。對象和標籤之間存在N×N的關係,每個對象可以具有多個標籤,並且每個標籤可以應用於不同的對象。標籤的設計有一定的限制,對象上的每個標籤都必須且有唯一密鑰,標籤密鑰必須遵守嚴格的語法。它的語法包含兩個部分:前綴和名稱。前綴是可選的,如果它存在,則通過前斜槓(/)與名稱分離,並且必須是有效的DNS子域,前綴最多包含253個字符。名稱是強制的,最多包含63個字符。名稱必須以字母、數字、字符(a~z、A~Z、0~9)開頭和結尾,並且只包含字母、數字、字符、點、破折號和下劃線。值的規則與名稱相同。需注意的是,標籤只用於標識對象,而不會將任何元數據附加到對象中。這便是註解的目的(參見1.2.6節)。

1.2.6 註解

註解可使任意元數據與Kubernetes對象關聯。Kubernetes只存儲註解並使其元數據可用。與標籤不同的是,它對字符類型和大小沒有嚴格要求。複雜的系統通常需要這樣的元數據,而Kubernetes可識別這樣的需求並提供開箱即用的元數據,這樣用戶則不必提取自己單獨的元數據存儲進行映射。

這裏已涵蓋了大部分Kubernetes的概念,也對其進行了簡要概括。在1.2.7節中,將從其設計動機、內部結構與實現、源代碼方面繼續研究Kubernetes的體系結構。

1.2.7 標籤選擇器

標籤選擇器根據標籤選擇對象,基於相等的選擇器指定鍵名和值。基於值的等式或不等式,它有兩個運算符:=(或==)和!=,代碼如下。

role = webserver

這將選擇所有具有該標籤鍵和值的對象。

標籤選擇器可以用多個逗號分隔,代碼如下。

role = webserver, application != foo

基於集合的選擇器擴展性能並允許基於多個值進行選擇,代碼如下。

role in (webserver, backend)

1.2.8 副本控制器和副本集

副本控制器和副本集管理由標籤選擇器標識的一組Pod,確保一定數量的Pod始終運行。它們之間的主要區別在於,副本控制器通過名稱匹配來測試成員資格,副本集則通過基於集合的選擇器。副本集更新,並被指定爲下一代副本控制器。它還處於測試階段,且在編寫時不能被所有工具支持。但也許讀者在讀到這本書時,它已完全成熟。

Kubernetes會保證在副本控制器或副本集中保持相同數量的Pod運行。在因主機節點或Pod本身的問題而導致數量下滑時,Kubernetes將啓動新的用例。需注意的是,如果人爲啓動Pod並超過指定數量,則副本控制器將結束多餘Pod的進程。

副本控制器曾經是許多工作流的中心,例如滾動更新和運行一次性作業。隨着Kubernetes的發展,它引入了對很多類似工作流的直接支持,例如Deployment、Job和DaemonSet等專用對象。這些將在下面的章節中提到。

1.2.9 服務

服務向用戶或其他服務暴露一些功能。它們通常包含一組Pod,由標籤進行區分。服務可提供對外部資源的訪問路徑,或者直接控制虛擬IP的Pod。本地Kubernetes服務器通過便捷的端點暴露功能。需注意的是,服務在第3層(TCP/UDP)進行。Kubernetes 1.2添加了入口對象,該對象提供對HTTP對象的訪問,後續會對這一部分展開詳談。服務可通過以下兩種機制之一被髮布或發現:DNS或環境變量。服務可以由Kubernetes均衡負載。但當服務使用外部資源或需要特殊處理時,開發人員可自行管理和均衡負載。

與IP地址、虛擬IP地址和端口空間相關的細節,都將在之後的章節中深入討論。

1.2.10 存儲卷

Pod上的存儲是臨時的,會隨Pod一起消失。如果只是在節點的容器間交換數據,這已經足夠,但有時數據需要在Pod上存儲更長的時間,或在Pod間傳遞數據,存儲卷的概念便支持了這種需求。需注意的是,雖然Docker中也有存儲卷的概念,但它仍比較有限(儘管功能越來越強大)。Kubernetes使用自有的存儲卷,並且支持額外的容器類型(如rkt),因此在根本上它獨立於Docker的存儲卷。

存儲卷類型有多種,Kubernetes目前直接支持所有類型。如果可添加間接層,則抽象存儲卷插件也許會被開發。emptyDir存儲卷類型會在每個容器上安裝一個卷,該卷會默認在宿主機器的任意可用容器上備份。如果需要,可以請求存儲介質。當Pod由於任何原因終止時,此存儲會被刪除。對於特定的雲環境、各種聯網的文件系統,甚至Git存儲庫,都有許多存儲卷類型。一個比較有意思的存儲卷類型是PersistentDiskClaim,它概括了部分細節,並在開發者的雲提供商環境中使用默認的持久存儲。

1.2.11 有狀態服務集

如果關注Pod上的數據,則可以使用持久化存儲。但若需要Kubernetes管理諸如Kubernetes或MySQL Galera分佈式數據存儲庫,便不能用常規的Pod和服務來模擬它,因爲這些集羣存儲使數據分佈在唯一的節點上。說回有狀態服務集,前文討論了寵物與牲畜的關係,以及牲畜是如何管理和執行的。有狀態服務集介於二者之間。有狀態服務集能夠確保給定數量的具有唯一標識的寵物在任意給定時間運行(類似於複製控制器)。寵物具有以下特性。

  • 在DNS中可用的穩定主機名。
  • 序數索引。
  • 與序數和主機名相連接的穩定存儲。

有狀態服務集可以幫助對等體發現、添加或移除寵物。

1.2.12 密鑰對象

密鑰對象是包含敏感信息的小型對象,如憑據和令牌。它們以明文的形式存儲在etcd中,可通過Kubernetes API服務器訪問,並在需要訪問時作爲文件裝入Pod中(使用負載於常規容量上的專用密鑰對象容量)。相同的密鑰對象可被安裝到多個Pod中。Kubernetes本身已爲它的組件加密,開發者也可以創造自有密鑰對象。另一種方法是使用密鑰對象作爲環境變量。需注意的是,爲獲得更好的安全性,在預製密鑰對象的情況下,Pod中的密鑰對象一般存儲於tmpfs內存中。

1.2.13 名稱

Kubernetes中的每個對象都由UID和名稱標識,該名稱用於引用API調用中的對象。名稱應不超過253個字符,並使用小寫字母數字字符、下劃線(_)和圓點(.)。如果刪除對象,則可以創建與已刪除對象具有相同名稱的另一對象,但UID在集羣生命週期中必須是唯一的。UID由Kubernetes生成,因此無須擔心其重複。

1.2.14 命名空間

命名空間是一個虛擬集羣。由命名空間分隔的多個虛擬集羣可組成一個單獨的物理集羣。每個虛擬集羣與其他虛擬集羣完全隔離,它們只能通過公共接口交換信息。需注意的是,節點對象和持久化存儲卷不存在於命名空間中。Kubernetes可以調度來自不同命名空間的Pod在同一節點運行。同樣,來自不同命名空間的Pod可以使用相同的持久存儲。

在使用命名空間時,必須考慮網絡策略和資源配額,以確保物理集羣資源的正確訪問和分配。

1.3 深入瞭解Kubernetes架構

Kubernetes有非常宏大的目標,它致力於管理並簡化跨環境和雲提供商的分佈式系統的編排、部署和管理。它提供了許多功能和服務,這些功能和服務應當適應於各種情境,並不斷衍化和保持足夠簡單以供大部分用戶使用。這是一個艱鉅的任務。Kubernetes通過清晰的排布、高水平的設計和成熟的架構來實現這一點,該架構同時促進了系統的擴展性和靈活性。Kubernetes的許多部分仍是硬編碼或環境敏感的,但它們會被逐漸分解爲插件,並保持內核的通用性和概括性。在本節中,將對Kubernetes層層解剖,首先介紹各種分佈式系統設計模式以及Kubernetes如何對其進行支持;然後介紹Kubernetes外層,即它的API集;接下來會介紹組成Kubernetes的實際組件;最後,對源代碼樹進行簡要介紹,以對Kubernetes的結構進行進一步瞭解。

在本節的最後,讀者將對Kubernetes的架構、執行以及其部分設計決策有深入的理解。

分佈式系統設計模式

用托爾斯泰在《安娜·卡列尼娜》中的一句話來形容幸福的家庭(工作的分佈式系統)都是相似的。這意味着,所有設計良好的分佈式系統都必須遵循最佳實踐和原則,以使其功能正常運行。Kubernetes不僅是一個管理系統,它同時還可應用這些最佳實踐爲開發者和管理員提供高水平的服務。下面將介紹幾種設計模式。

1.邊車模式

邊車模式除主應用容器之外,還在Pod中共同定位另一個容器。應用容器並不知道邊車容器,只是單純執行自己的任務。中央日誌代理(Central Logging Agent)就是一個很好的例子。主容器只將日誌記錄到stdout,但邊車容器會將所有日誌發送到一箇中央日誌服務,這些日誌將在此處聚合整個系統的日誌。使用邊車容器相較於將中央日誌添加到主應用容器有巨大的優勢,應用不再受到中央日誌的負擔,如果要升級或更改中央日誌記錄策略或切換到新的提供商,只需更新並部署邊車容器,應用容器並沒有任何改變,因此不會由於意外情況而遭到破壞。

2.外交官模式

外交官模式是指將遠程服務當作本地服務,並使其強制執行部分策略。外交官模式的一個很好的例子是,如果有一個Redis集羣,該集羣中一個主機用於編寫,其餘副本用於讀取,則本地外交官容器可作爲代理,並將Redis暴露給本地主機上的主應用容器。主應用容器簡單地連接到localhost:6379(Redis缺省端口)上的Redis,但是它其實只是連接到在相同Pod中運行的外交官容器,該容器過濾請求,將編寫請求發送到真正的Redis主機,並將讀取請求隨機發送到其中一個讀取副本上,與挎鬥模式類似,主應用在這期間並不瞭解運行過程。當測試真正的本地Redis集羣時,這會有很大的幫助。此外,如果Redis集羣配置發生改變,則只需要修改外交官容器,主應用同樣不瞭解這一運行過程。

3.適配器模式

適配器模式是關於主應用容器的標準化輸出。逐步推出的服務可能會面臨如下問題:服務可能會生成不符合先前版本的格式報表,而其他使用該輸出的服務和應用還未升級。適配器容器可以與新的應用容器共同部署在同一Pod上,並將其輸出與舊版本相匹配,直到所有的用戶都被升級。適配器容器與主應用程序容器共享文件系統,以此監控本地文件系統,每當新應用寫入某個文件時,適配器容器將立即進行適配。

4.多節點模式

單節點模式都是直接由Kubernetes通過Pod直接進行支持的。而多節點模式並不被直接支持,例如負責人選舉、工作隊列和分散收集等,但使用標準接口組合Pod可實現Kubernetes支持。

1.4 Kubernetes API

若想了解一個系統的功能及其提供的服務,需要關注它的API。API爲使用該系統的用戶提供了一個全局圖。Kubernetes從多角度爲開發者提供多組REST API。有些API需通過工具使用,有些則可以被開發者直接使用。API的一個重要方面在於它們也在不斷地發展,Kubernetes開發者通過嘗試擴展(向現有對象添加新對象和新字段),避免重命名或刪除現有對象和字段來保持其可管理性。此外,所有API端點都是版本化的,通常也包含Alpha或Beta記法。代碼如下。

/api/v1
/api/v2alpha1

通過基於客戶端庫的kubectl CLI,或者直接調用REST API,可以訪問API。下面的章節會對認證和授權機制進行詳細介紹。由此,讀者可對API有初步的認識。

1.4.1 Kubernetes API

這是Kubernetes的主要API,它非常龐大。前文所講的所有概念以及許多輔助概念,都有相應的API對象和運算。若有正確的權限,則可列出、獲取、創建和更新對象。下面是一個常見操作的詳細文檔,可以得到所有的Pod列表。

GET /api/v1/pods

它支持各種可選參數。

  • pretty:如果爲true,輸出則用pretty打印。
  • labelSelector:用於限制結果的選擇器表達。
  • watch:如果爲true,則觀察變化並返回事件流。
  • resourceVersion:使用watch,只返回該版本之後發生的事件。
  • timeoutSeconds:列表或監控器的超時時長。 


1.4.2 自動伸縮 API

自動伸縮API非常聚焦,允許控制同級別的Pod自動縮放器。該自動縮放器基於CPU利用率,甚至特定於應用的度量來管理一組Pod。它可以用/apis/autoscaling/v1端點來列出、查詢、創建、更新和銷燬自動縮放器對象。

批處理API

批處理API用來管理作業。作業是執行和終止某些活動的Pod。與副本控制器管理的常規Pod不同,它們在作業完成時就應該終止。批處理API使用Pod模板指定作業,然後在大部分情況下,允許通過/apis/batch/v1端點列出、查詢、創建和刪除作業。

1.5 Kubernetes組件

Kubernetes集羣具有幾個用於控制集羣的主組件,以及在每個集羣節點上運行的節點組件。這一部分將介紹這些組件,並解釋它們是如何協同工作的。

1.5.1 主組件

主組件通常在一個節點上運行,但在高可用性集羣或大型集羣上,它們可以分佈在多個節點上。

1.API服務器

Kube API服務器(Kube-API Server)提供Kubernetes REST API。由於其具有無狀態性,因此它可以很輕鬆地水平縮放。它的所有數據都存儲在etcd集羣中。API服務器是Kubernetes控制平面的體現。

2.etcd

etcd是一種非常可靠的分佈式數據存儲。Kubernetes使用它來存儲整個集羣狀態。在小型的瞬態集羣中,單個etcd可以與所有其他主組件在同一節點上運行。但考慮到冗餘和高可用性,更大型的集羣通常包含3個,甚至5個etcd集羣。

3.控制器管理器

控制器管理器是各種管理器的集合,這些管理器被打包成一個二進制文件。它包含副本控制器、Pod控制器、服務控制器和端點控制器等。所有這些控制器通過API監控集羣狀態,它們的任務是將集羣控制在目標狀態。

4.調度器

Kube調度器負責將Pod調度到節點中。這是一個非常複雜的任務,因爲它需要考慮多個相互作用的因素,例如以下幾點。

  • 資源需求。
  • 服務要求。
  • 硬/軟件策略約束。
  • 親和性和反親和性規範。
  • 數據局部性。
  • 截止日期。

5.DNS

從Kubernetes 1.3開始,DNS服務便成爲標準Kubernetes集羣的一部分。它被調度成一個普通的Pod。除Headless服務外的每個服務都會接收DNS名稱,Pod也可以接收DNS名稱,這對於自動化探索非常有用。

1.5.2 節點組件

集羣中的節點需要幾個組件與集羣主組件交互,接收要執行的工作負載,並根據它們的狀態更新集羣。

1.代理

Kube代理在每個節點上進行低水平的網絡維護,它用於呈現本地Kubernetes服務,可以執行TCP及UDP轉發,通過環境變量或DNS尋找集羣IP。

2.Kubelet

Kubelet是節點上Kubernetes的代表。它負責監控與主組件的通信並管理運行中的Pod,包括以下幾個方面的內容。

  • 從API服務器下載Pod機密。
  • 裝載卷。
  • 運行Pod的容器(Docker或Rkt)。
  • 報告節點和每個Pod的狀態。
  • 運行容器活性探針。

在本節中,我們通過Kubernetes的API以及用於控制管理集羣的組件,深入研究了它的內在構成,從宏觀的視角探討了它的體系結構及其所支持的設計模式。1.6節將介紹Kubernetes支持的運行時。

1.6 Kubernetes運行時

Kubernetes最初只支持Docker作爲容器運行時引擎,目前情況有所變化,Rkt成爲另一被支持的運行時引擎,也通過Hypernet與Hyper.sh容器工作進行了一些有趣的嘗試。一個較爲重要的設計策略是,Kubernetes本身應與特定的運行時完全脫離。Kubernetes與運行時的交互是通過運行時引擎必須執行的一個相對通用的接口實現的。大多數信息交換會通過Pod、容器概念以及可在容器上執行的操作來實現,每個運行時引擎負責保證Kubernetes運行時接口是兼容的。

在本節中,將深入介紹運行時接口,並細化到單個運行時引擎。閱讀完本節,讀者將能選擇適合實際用例的運行時引擎,並知曉在同一系統中切換或組合多個運行時的具體實用場景。

1.6.1 運行時接口

容器的運行時接口在GitHub的Kubernetes項目中有詳細介紹。Kubernetes是開源的,可以查看相關網址。

下面的代碼展示了該文件中沒有詳細註釋的部分片段。即便是對Go語言一無所知的入門級程序員,也能夠從Kubernetes的角度掌握運行時引擎的功能範圍。

type Runtime interface {
  Type() string
  Version() (Version, error)
  APIVersion() (Version, error)
  Status() error
  GetPods(all bool) ([]*Pod, error)
}

 

在此對Go語言進行簡要介紹,以幫助讀者更好地解析代碼——首先是方法名,接下來是括號中的方法參數。每個參數都是一對,由名稱和名稱類型組成。最後,指定返回值。Go語言允許多個返回類型。除返回實際結果之外,返回錯誤對象也很常見,如果一切正常,錯誤對象將爲nil。

事實上,這是一個意味着Kubernetes不執行任何操作的接口。第一組方法提供了運行時的基本信息:類型、版本、API版本和狀態。通過下面的代碼可以得到全部Pod。

SyncPod(pod *api.Pod, apiPodStatus api.PodStatus, podStatus
*PodStatus, pullSecrets []api.Secret, backOff
*flowcontrol.Backoff) PodSyncResult

KillPod(pod *api.Pod, runningPod Pod, gracePeriodOverride *int64)
error 

GetPodStatus(uid types.UID, name, namespace string) (*PodStatus,
error)

GetNetNS(containerID ContainerID) (string, error)

GetPodContainerID(*Pod) (ContainerID, error)

GetContainerLogs(pod *api.Pod, containerID ContainerID, logOptions
*api.PodLogOptions, stdout, stderr io.Writer) (err error)

DeleteContainer(containerID ContainerID) error

下一組方法主要處理Pod,因爲這是Kubernetes概念模型中的主要概念框架。然後是GetPodContainerID(),它將數據從容器傳輸到Pod。還有如下一些與容器相關的更多方法。

  • ContainerCommandRunner
  • ContainerAttacher
  • ImageService

ContainerCommandRunner、ContainerAttacher和ImageService是運行時接口繼承的接口。這意味着,任何需要執行運行時接口的人都需要執行這些接口方法。接口的定義存放在同一文件中,接口名稱已經提供了很多接口功能的信息。顯然,Kubernets需要在容器中執行命令,將容器附加到Pod並抽取容器映像。建議讀者搜索這個文件並熟悉代碼。

現在,讀者已經在代碼級別對作爲運行時引擎的Kubernetes有了初步的認知,接下來將對各個運行時的引擎進行介紹。

1.6.2 Docker

當然,Docker是舉足輕重的容器。Kubernetes在設計之初僅針對Docker容器,在Kubernetes 1.3中才首次加入多運行時功能。在此之前,Kubernetes只能管理Docker容器。

假定讀者在閱讀此書時對Docker非常熟悉並瞭解其功能,我們知道Docker飽受讚譽並歷經發展,但也受到一些批判,對它的批判主要針對以下幾個方面進行。

  • 安全性。
  • 難以建立多容器應用(特別是網絡)。
  • 開發、監測和日誌記錄。
  • Docker容器執行單個命令的侷限性。
  • 釋放Half-Based特徵過於迅速。

針對上述問題,Docker做出了一些改善,尤其針對Docker Swarm產品。Docker Swarm是一個對標Kubernetes的Docker本地編排解決方案,它使用起來比Kubernetes更簡單,但沒有Kubernetes強大和成熟。

 

從Docker 1.12開始,Docker Daemon進程中就自帶羣模式,但由於膨脹和範圍蠕變使部分用戶受挫。這反過來又使更多的人轉而將CoreOS Rkt作爲替代方案。

從2016年4月發佈的Docker 1.11開始,Docker已經改變了運行容器的方式。運行時現在用containerd和Runc在容器中運行開放容器倡議(OCI)鏡像,如圖1.2所示。

圖1.2 容器中運行開放容器倡議(OCI)鏡像

1.6.3 Rkt

Rkt是一個來自CoreOS的新型容器管理器(CoreOS Linux發行版、etcd、Flannel等)。Rkt運行時得益於其簡單性、安全性和隔離性。它沒有像Docker引擎那樣的Daemon進程,而是依賴於諸如Systemd的OS Init系統來啓動Rkt可執行文件。Rkt可以下載鏡像[無論是App容器(appc)鏡像,還是OCI鏡像]、驗證鏡像,並在容器中運行鏡像,它的體系結構要簡單得多。

1.App容器

CoreOS於2014年12月開始了標準化工作,名爲appc,包括標準鏡像格式(如ACI)、運行時、簽名和發現。幾個月後,Docker也開始了自己的OCI標準化工作。由此可見,所有成果都將匯聚。這是一個偉大的事情,因爲工具、鏡像和運行時都能夠自由地互相執行,然而,目前還未實現這一願景。

2.Rkrnetes

Rktnetes在Kubernetes引入Rkt作爲運行時引擎。Kubernetes仍抽象於運行時引擎進程中。Rktnetes並不是一個獨立的產品。從外部來看,只需在每個節點上使用幾個命令行交換機運行Kubelet。但由於Docker和Rkt之間存在根本性差異,因此實際中可能會遇到多種問題。

3.Rkt是否已爲生產使用做好準備

Rkt和Kubernetes的集成不是完美的,這其中仍存在一些缺陷。在目前階段(2016年底),若非有明確具體的原因而使用Rkt,仍然建議讀者首選Docker。若有重要用例需使用Rkt,那最好基於CoreOS建立,這樣便於找到與CoreOS集羣的最佳集成,以及最佳文檔和聯機支持。

1.6.4 Hyper Container

Hyper Container是另一種選擇。Hyper Container有一個輕量級的VM(它自己的客戶內核),它運行在裸金屬上,並且依賴於系統管理程序進行隔離,而非Linux Cgroup。這種方式相比建立起來很費力的標準裸金屬集羣,提供了一個更爲有趣的組合,並且公共雲容器可以部署在重量級VM上。

Hypernetes

Hypernetes是一個多租戶Kubernetes發行版,它使用Hyper Container以及一些OpenStack組件進行身份驗證、持續存儲和聯網,如圖1.3所示。由於容器不共享主機內核,因此在同一物理主機上運行不同租戶的容器是安全的。

本節介紹了Kubernetes支持的各種運行時引擎以及標準化和融合化的趨勢。1.7節將縱觀全局,瞭解Kubernetes如何適應CI/CD流水線。

圖1.3 Hypernetes

1.7 持續集成與部署

Kubernetes對於基於微服務的應用是一個很好的運行平臺。通常,大多數開發人員可能並不知道系統部署在Kubernetes上,但是Kubernetes可以使之前看起來非常困難的任務成爲可能。

本節將探討CI/CD流水線以及Kubernetes可以爲之帶來什麼。閱讀完本節,讀者將可以自行設計CI/CD流水線,該流水線利用Kubernetes特性(如易於伸縮和開發生產奇偶性)來提高日常開發和部署的效率和穩定性。

1.7.1 CI/CD流水線

CI/CD流水線是由開發人員或操作人員修改系統代碼、數據或配置,測試並將其部署到生產中的一系列步驟。有些流水線是完全自動化的,有些則是需人工覈查的半自動化的。在大型公司中,測試和預演環境可能是自動化部署的,但發佈到生產環境仍需人工干預。

值得一提的是,開發人員可以完全脫離生產基礎設施。他們的接口只是一個Git工作流,一個很好的例子是Deis工作流(Kubernetes上的PaaS,類似於Heroku),如圖1.4所示,描述了一個典型的傳輸過程。

圖1.4 Deis工作流

1.7.2 爲Kubernetes設計CI/CD流水線

當部署目標是Kubernetes集羣時,應該重新思考一些傳統的做法。首先,其包裝是不同的,需要爲容器打包鏡像,通過使用智能標記來恢復代碼的改變是非常簡單和快捷的。如果一個不好的變化通過測試,但能立即恢復到之前版本,這會給用戶很大的信心。但需要注意的是,模式更改和數據遷移不能自動回滾。Kubernetes的另一個獨特性在於,開發者可以在本地運行整個集羣。這在設計集羣時會耗費一些精力,但由於組成系統的微服務在容器中運行,且這些容器通過API進行交互,因此仍是可行的。通常,如果系統是數據驅動的,則需要提供開發者可用的數據快照和合成數據來適應這種情況。

1.8 總結

本章介紹了大量的基礎和知識,讀者可以瞭解Kubernetes的設計和架構。Kubernetes是運行在容器中、基於微服務的應用程序編排平臺,Kubernetes集羣有主節點和工作節點。容器在Pod內運行,每個Pod在單個物理機或虛擬機上運行。Kubernetes直接支持許多概念,例如服務、標籤和持續存儲。可以在Kubernetes上實現各種分佈式系統設計模式。容器本身可以是Docker、Rkt或Hyper Container。

本文摘自最新上架新書:《精通Kubernetes》

  • k8s初學者指南
  • 針對K8s1.10,具備豐富實操案例
  • 幫助讀者掌握在各種雲平臺上設計和部署大型集羣的技能

本書通過理論與實踐相結合,全方位地介紹Kubernetes這一容器編排的理想工具。本書共14章,涉及的主題包括理解Kubernetes架構,創建Kubernetes集羣,監控、日誌記錄和故障排除,高可用性和可靠性,配置Kubernetes安全、限制和賬戶,使用關鍵Kubernetes資源,管理Kubernetes存儲,使用Kubernetes運行有狀態應用程序,滾動更新、可伸縮性和配額,高級Kubernetes網絡,在雲平臺和集羣聯邦中運行Kubernetes,自定義Kubernetes API和插件,操作Kubernetes軟件包管理器以及Kubernetes的未來。本書綜合考慮不同環境和用例,使讀者瞭解如何創建大型系統並將其部署在Kubernetes上。在各章節主題中,讀者提供了豐富的實踐案例分析,娓娓道來,引人入勝。
 
本書可以作爲Kubernetes的實踐參考手冊,聚焦於設計和管理Kubernetes集羣,爲開發人員、運維工程師詳細介紹了Kubernetes所提供的功能和服務。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章