天天看點

[K8s]何為Kubernetes?

Kubernetes 是一個可移植的、可擴充的開源平台,用于管理容器化的工作負載和服務,可促進聲明式配置和自動化。 Kubernetes 擁有一個龐大且快速增長的生态系統。Kubernetes 的服務、支援和工具廣泛可用。

Kubernetes 這個名字源于希臘語,意為“舵手”或“飛行員”。k8s 這個縮寫是因為 k 和 s 之間有八個字元的關系。 Google 在 2014 年開源了 Kubernetes 項目。Kubernetes 建立在Google 在大規模運作生産工作負載方面擁有十幾年的經驗的基礎上,結合了社群中最好的想法和實踐。

讓我們回顧一下為什麼 Kubernetes 如此有用。

[K8s]何為Kubernetes?

早期,各個組織機構在實體伺服器上運作應用程式。無法為實體伺服器中的應用程式定義資源邊界,這會導緻資源配置設定問題。

例如,如果在實體伺服器上運作多個應用程式,則可能會出現一個應用程式占用大部分資源的情況,結果可能導緻其他應用程式的性能下降。一種解決方案是在不同的實體伺服器上運作每個應用程式,但是由于資源利用不足而無法擴充,并且維護許多實體伺服器的成本很高。

作為解決方案,引入了虛拟化。虛拟化技術允許你在單個實體伺服器的 CPU 上運作多個虛拟機(VM)。 虛拟化允許應用程式在 VM 之間隔離,并提供一定程度的安全,因為一個應用程式的資訊 不能被另一應用程式随意通路。

虛拟化技術能夠更好地利用實體伺服器上的資源,并且因為可輕松地添加或更新應用程式 而可以實作更好的可伸縮性,降低硬體成本等等。

每個 VM 是一台完整的計算機,在虛拟化硬體之上運作所有元件,包括其自己的作業系統。

容器類似于 VM,但是它們具有被放寬的隔離屬性,可以在應用程式之間共享作業系統(OS)。 是以,容器被認為是輕量級的。容器與 VM 類似,具有自己的檔案系統、CPU、記憶體、程序空間等。 由于它們與基礎架構分離,是以可以跨雲和 OS 發行版本進行移植。

容器因具有許多優勢而變得流行起來。下面列出的是容器的一些好處:

靈活應用程式的建立和部署:與使用 VM 鏡像相比,提高了容器鏡像建立的簡便性和效率。

持續開發、內建和部署:通過快速簡單的復原(由于鏡像不可變性),支援可靠且頻繁的 容器鏡像建構和部署。

關注開發與運維的分離:在建構/釋出時而不是在部署時建立應用程式容器鏡像, 進而将應用程式與基礎架構分離。

可觀察性:不僅可以顯示作業系統級别的資訊和名額,還可以顯示應用程式的運作狀況和其他名額信号。

跨開發、測試和生産的環境一緻性:在便攜式計算機上與在雲中相同地運作。

跨雲和作業系統發行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方運作。

以應用程式為中心的管理:提高抽象級别,從在虛拟硬體上運作 OS 到使用邏輯資源在 OS 上運作應用程式。

松散耦合、分布式、彈性、解放的微服務:應用程式被分解成較小的獨立部分, 并且可以動态部署和管理 - 而不是在一台大型單機上整體運作。

資源隔離:可預測的應用程式性能。

資源利用:高效率和高密度。

容器是打包和運作應用程式的好方式。在生産環境中,你需要管理運作應用程式的容器,并確定不會停機。 例如,如果一個容器發生故障,則需要啟動另一個容器。如果系統處理此行為,會不會更容易?

這就是 Kubernetes 來解決這些問題的方法! Kubernetes 為你提供了一個可彈性運作分布式系統的架構。 Kubernetes 會滿足你的擴充要求、故障轉移、部署模式等。 例如,Kubernetes 可以輕松管理系統的 Canary 部署。

Kubernetes 為你提供:

服務發現和負載均衡

Kubernetes 可以使用 DNS 名稱或自己的 IP 位址公開容器,如果進入容器的流量很大, Kubernetes 可以負載均衡并配置設定網絡流量,進而使部署穩定。

存儲編排

Kubernetes 允許你自動挂載你選擇的存儲系統,例如本地存儲、公共雲提供商等。

自動部署和復原

你可以使用 Kubernetes 描述已部署容器的所需狀态,它可以以受控的速率将實際狀态 更改為期望狀态。例如,你可以自動化 Kubernetes 來為你的部署建立新容器, 删除現有容器并将它們的所有資源用于新容器。

自動完成裝箱計算

Kubernetes 允許你指定每個容器所需 CPU 和記憶體(RAM)。 當容器指定了資源請求時,Kubernetes 可以做出更好的決策來管理容器的資源。

自我修複

Kubernetes 重新啟動失敗的容器、替換容器、殺死不響應使用者定義的 運作狀況檢查的容器,并且在準備好服務之前不将其通告給用戶端。

密鑰與配置管理

Kubernetes 允許你存儲和管理敏感資訊,例如密碼、OAuth 令牌和 ssh 密鑰。 你可以在不重建容器鏡像的情況下部署和更新密鑰和應用程式配置,也無需在堆棧配置中暴露密鑰。

Kubernetes 不是傳統的、包羅萬象的 PaaS(平台即服務)系統。 由于 Kubernetes 在容器級别而不是在硬體級别運作,它提供了 PaaS 産品共有的一些普遍适用的功能, 例如部署、擴充、負載均衡、日志記錄和監視。 但是,Kubernetes 不是單體系統,預設解決方案都是可選和可插拔的。 Kubernetes 提供了建構開發人員平台的基礎,但是在重要的地方保留了使用者的選擇和靈活性。

Kubernetes:

不限制支援的應用程式類型。 Kubernetes 旨在支援極其多種多樣的工作負載,包括無狀态、有狀态和資料處理工作負載。 如果應用程式可以在容器中運作,那麼它應該可以在 Kubernetes 上很好地運作。

不部署源代碼,也不建構你的應用程式。 持續內建(CI)、傳遞和部署(CI/CD)工作流取決于組織的文化和偏好以及技術要求。

不提供應用程式級别的服務作為内置服務,例如中間件(例如,消息中間件)、 資料處理架構(例如,Spark)、資料庫(例如,mysql)、緩存、叢集存儲系統 (例如,Ceph)。這樣的元件可以在 Kubernetes 上運作,并且/或者可以由運作在 Kubernetes 上的應用程式通過可移植機制(例如, 開放服務代理)來通路。

不要求日志記錄、監視或警報解決方案。 它提供了一些內建作為概念證明,并提供了收集和導出名額的機制。

不提供或不要求配置語言/系統(例如 jsonnet),它提供了聲明性 API, 該聲明性 API 可以由任意形式的聲明性規範所構成。

不提供也不采用任何全面的機器配置、維護、管理或自我修複系統。

此外,Kubernetes 不僅僅是一個編排系統,實際上它消除了編排的需要。 編排的技術定義是執行已定義的工作流程:首先執行 A,然後執行 B,再執行 C。 相比之下,Kubernetes 包含一組獨立的、可組合的控制過程, 這些過程連續地将目前狀态驅動到所提供的所需狀态。 如何從 A 到 C 的方式無關緊要,也不需要集中控制,這使得系統更易于使用 且功能更強大、系統更健壯、更為彈性和可擴充。

當你部署完 Kubernetes, 即擁有了一個完整的叢集。

一個 Kubernetes 叢集由一組被稱作節點的機器組成。這些節點上運作 Kubernetes 所管理的容器化應用。叢集具有至少一個工作節點。

工作節點托管作為應用負載的元件的 Pod 。控制平面管理叢集中的工作節點和 Pod 。 為叢集提供故障轉移和高可用性,這些控制平面一般跨多主機運作,叢集跨多個節點運作。

本文檔概述了傳遞正常運作的 Kubernetes 叢集所需的各種元件。

這張圖表展示了包含所有互相關聯元件的 Kubernetes 叢集。

[K8s]何為Kubernetes?

控制平面的元件對叢集做出全局決策(比如排程),以及檢測和響應叢集事件(例如,當不滿足部署的 replicas 字段時,啟動新的 pod)。

控制平面元件可以在叢集中的任何節點上運作。 然而,為了簡單起見,設定腳本通常會在同一個計算機上啟動所有控制平面元件, 并且不會在此計算機上運作使用者容器。 請參閱使用 kubeadm 建構高可用性叢集 中關于多 VM 控制平面設定的示例。

API 伺服器是 Kubernetes 控制面的元件, 該元件公開了 Kubernetes API。 API 伺服器是 Kubernetes 控制面的前端。

Kubernetes API 伺服器的主要實作是 kube-apiserver。 kube-apiserver 設計上考慮了水準伸縮,也就是說,它可通過部署多個執行個體進行伸縮。 你可以運作 kube-apiserver 的多個執行個體,并在這些執行個體之間平衡流量。

etcd 是兼具一緻性和高可用性的鍵值資料庫,可以作為儲存 Kubernetes 所有叢集資料的背景資料庫。

您的 Kubernetes 叢集的 etcd 資料庫通常需要有個備份計劃。

要了解 etcd 更深層次的資訊,請參考 etcd 文檔。

控制平面元件,負責監視新建立的、未指定運作節點(node)的 Pods,選擇節點讓 Pod 在上面運作。

排程決策考慮的因素包括單個 Pod 和 Pod 集合的資源需求、硬體/軟體/政策限制、親和性和反親和性規範、資料位置、工作負載間的幹擾和最後時限。

運作控制器程序的控制平面元件。

從邏輯上講,每個控制器都是一個單獨的程序, 但是為了降低複雜性,它們都被編譯到同一個可執行檔案,并在一個程序中運作。

這些控制器包括:

節點控制器(Node Controller): 負責在節點出現故障時進行通知和響應

任務控制器(Job controller): 監測代表一次性任務的 Job 對象,然後建立 Pods 來運作這些任務直至完成

端點控制器(Endpoints Controller): 填充端點(Endpoints)對象(即加入 Service 與 Pod)

服務帳戶和令牌控制器(Service Account & Token Controllers): 為新的命名空間建立預設帳戶和 API 通路令牌

雲控制器管理器是指嵌入特定雲的控制邏輯的控制平面元件。 雲控制器管理器使得你可以将你的叢集連接配接到雲提供商的 API 之上, 并将與該雲平台互動的元件同與你的叢集互動的元件分離開來。

cloud-controller-manager 僅運作特定于雲平台的控制回路。 如果你在自己的環境中運作 Kubernetes,或者在本地計算機中運作學習環境, 所部署的環境中不需要雲控制器管理器。

與 kube-controller-manager 類似,cloud-controller-manager 将若幹邏輯上獨立的 控制回路組合到同一個可執行檔案中,供你以同一程序的方式運作。 你可以對其執行水準擴容(運作不止一個副本)以提升性能或者增強容錯能力。

下面的控制器都包含對雲平台驅動的依賴:

節點控制器(Node Controller): 用于在節點終止響應後檢查雲提供商以确定節點是否已被删除

路由控制器(Route Controller): 用于在底層雲基礎架構中設定路由

服務控制器(Service Controller): 用于建立、更新和删除雲提供商負載均衡器

節點元件在每個節點上運作,維護運作的 Pod 并提供 Kubernetes 運作環境。

一個在叢集中每個節點(node)上運作的代理。 它保證容器(containers)都 運作在 Pod 中。

kubelet 接收一組通過各類機制提供給它的 PodSpecs,確定這些 PodSpecs 中描述的容器處于運作狀态且健康。 kubelet 不會管理不是由 Kubernetes 建立的容器。

kube-proxy 是叢集中每個節點上運作的網絡代理, 實作 Kubernetes 服務(Service) 概念的一部分。

kube-proxy 維護節點上的網絡規則。這些網絡規則允許從叢集内部或外部的網絡會話與 Pod 進行網絡通信。

如果作業系統提供了資料包過濾層并可用的話,kube-proxy 會通過它來實作網絡規則。否則, kube-proxy 僅轉發流量本身。

容器運作環境是負責運作容器的軟體。

Kubernetes 支援多個容器運作環境: Docker、 containerd、CRI-O 以及任何實作 Kubernetes CRI (容器運作環境接口)。

插件使用 Kubernetes 資源(DaemonSet、 Deployment等)實作叢集功能。 因為這些插件提供叢集級别的功能,插件中命名空間域的資源屬于 kube-system 命名空間。

下面描述衆多插件中的幾種。有關可用插件的完整清單,請參見 插件(Addons)。

盡管其他插件都并非嚴格意義上的必需元件,但幾乎所有 Kubernetes 叢集都應該 有叢集 DNS, 因為很多示例都需要 DNS 服務。

叢集 DNS 是一個 DNS 伺服器,和環境中的其他 DNS 伺服器一起工作,它為 Kubernetes 服務提供 DNS 記錄。

Kubernetes 啟動的容器自動将此 DNS 伺服器包含在其 DNS 搜尋清單中。

Dashboard 是 Kubernetes 叢集的通用的、基于 Web 的使用者界面。 它使使用者可以管理叢集中運作的應用程式以及叢集本身并進行故障排除。

容器資源監控 将關于容器的一些常見的時間序列路徑成本儲存到一個集中的資料庫中,并提供用于浏覽這些資料的界面。

叢集層面日志 機制負責将容器的日志資料 儲存到一個集中的日志存儲中,該存儲能夠提供搜尋和浏覽接口。

Kubernetes 控制面 的核心是 API 伺服器。 API 伺服器負責提供 HTTP API,以供使用者、叢集中的不同部分和叢集外部元件互相通信。

Kubernetes API 使你可以查詢和操縱 Kubernetes API 中對象(例如:Pod、Namespace、ConfigMap 和 Event)的狀态。

大部分操作都可以通過 kubectl 指令行接口或 類似 kubeadm 這類指令行工具來執行, 這些工具在背後也是調用 API。不過,你也可以使用 REST 調用來通路這些 API。

如果你正在編寫程式來通路 Kubernetes API,可以考慮使用 用戶端庫之一。

完整的 API 細節是用 OpenAPI 來表述的。

Kubernetes API 伺服器通過 /openapi/v2 末端提供 OpenAPI 規範。 你可以按照下表所給的請求頭部,指定響應的格式:

[K8s]何為Kubernetes?

Kubernetes 為 API 實作了一種基于 Protobuf 的序列化格式,主要用于叢集内部通信。 關于此格式的詳細資訊,可參考 Kubernetes Protobuf 序列化 設計提案。每種模式對應的接口描述語言(IDL)位于定義 API 對象的 Go 包中。

任何成功的系統都要随着新的使用案例的出現和現有案例的變化來成長和變化。 為此,Kubernetes 的功能特性設計考慮了讓 Kubernetes API 能夠持續變更和成長的因素。 Kubernetes 項目的目标是 不要 引發現有用戶端的相容性問題,并在一定的時期内 維持這種相容性,以便其他項目有機會作出适應性變更。

一般而言,新的 API 資源和新的資源字段可以被頻繁地添加進來。 删除資源或者字段則要遵從 API 廢棄政策。

關于什麼是相容性的變更、如何變更 API 等詳細資訊,可參考 API 變更。

為了簡化删除字段或者重構資源表示等工作,Kubernetes 支援多個 API 版本, 每一個版本都在不同 API 路徑下,例如 /api/v1 或 /apis/rbac.authorization.k8s.io/v1alpha1。

版本化是在 API 級别而不是在資源或字段級别進行的,目的是為了確定 API 為系統資源和行為提供清晰、一緻的視圖,并能夠控制對已廢止的和/或實驗性 API 的通路。

為了便于演化和擴充其 API,Kubernetes 實作了 可被啟用或禁用的 API 組。

API 資源之間靠 API 組、資源類型、名字空間(對于名字空間作用域的資源而言)和 名字來互相區分。API 伺服器可能通過多個 API 版本來向外提供相同的下層資料, 并透明地完成不同 API 版本之間的轉換。所有這些不同的版本實際上都是同一資源 的(不同)表現形式。例如,假定同一資源有 v1 和 v1beta1 版本, 使用 v1beta1 建立的對象則可以使用 v1beta1 或者 v1 版本來讀取、更改 或者删除。

關于 API 版本級别的詳細定義,請參閱 API 版本參考。

有兩種途徑來擴充 Kubernetes API:

你可以使用自定義資源 來以聲明式方式定義 API 伺服器如何提供你所選擇的資源 API。

你也可以選擇實作自己的 聚合層 來擴充 Kubernetes API。

Kubernetes 對象在 Kubernetes API 中是如何表示的,以及如何在 .yaml 格式的檔案中表示。

在 Kubernetes 系統中,Kubernetes 對象 是持久化的實體。 Kubernetes 使用這些實體去表示整個叢集的狀态。特别地,它們描述了如下資訊:

哪些容器化應用在運作(以及在哪些節點上)

可以被應用使用的資源

關于應用運作時表現的政策,比如重新開機政策、更新政策,以及容錯政策

Kubernetes 對象是 “目标性記錄” —— 一旦建立對象,Kubernetes 系統将持續工作以確定對象存在。 通過建立對象,本質上是在告知 Kubernetes 系統,所需要的叢集工作負載看起來是什麼樣子的, 這就是 Kubernetes 叢集的 期望狀态(Desired State)。

操作 Kubernetes 對象 —— 無論是建立、修改,或者删除 —— 需要使用 Kubernetes API。 比如,當使用 kubectl 指令行接口時,CLI 會執行必要的 Kubernetes API 調用, 也可以在程式中使用 用戶端庫直接調用 Kubernetes API。

幾乎每個 Kubernetes 對象包含兩個嵌套的對象字段,它們負責管理對象的配置: 對象 spec(規約) 和 對象 status(狀态) 。 對于具有 spec 的對象,你必須在建立對象時設定其内容,描述你希望對象所具有的特征: 期望狀态(Desired State) 。

status 描述了對象的 目前狀态(Current State),它是由 Kubernetes 系統群組件 設定并更新的。在任何時刻,Kubernetes 控制平面 都一直積極地管理着對象的實際狀态,以使之與期望狀态相比對。

例如,Kubernetes 中的 Deployment 對象能夠表示運作在叢集中的應用。 當建立 Deployment 時,可能需要設定 Deployment 的 spec,以指定該應用需要有 3 個副本運作。 Kubernetes 系統讀取 Deployment 規約,并啟動我們所期望的應用的 3 個執行個體 —— 更新狀态以與規約相比對。 如果這些執行個體中有的失敗了(一種狀态變更),Kubernetes 系統通過執行修正操作 來響應規約和狀态間的不一緻 —— 在這裡意味着它會啟動一個新的執行個體來替換。

關于對象 spec、status 和 metadata 的更多資訊,可參閱 Kubernetes API 約定。

建立 Kubernetes 對象時,必須提供對象的規約,用來描述該對象的期望狀态, 以及關于對象的一些基本資訊(例如名稱)。 當使用 Kubernetes API 建立對象時(或者直接建立,或者基于kubectl), API 請求必須在請求體中包含 JSON 格式的資訊。 大多數情況下,需要在 .yaml 檔案中為 kubectl 提供這些資訊。 kubectl 在發起 API 請求時,将這些資訊轉換成 JSON 格式。

這裡有一個 .yaml 示例檔案,展示了 Kubernetes Deployment 的必需字段和對象規約:

application/deployment.yaml

[K8s]何為Kubernetes?

使用類似于上面的 .yaml 檔案來建立 Deployment的一種方式是使用 kubectl 指令行接口(CLI)中的 kubectl apply 指令, 将 .yaml 檔案作為參數。下面是一個示例:

<code>kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record</code>

輸出類似如下這樣:

deployment.apps/nginx-deployment created

在想要建立的 Kubernetes 對象對應的 .yaml 檔案中,需要配置如下的字段:

apiVersion - 建立該對象所使用的 Kubernetes API 的版本

kind - 想要建立的對象的類别

metadata - 幫助唯一性辨別對象的一些資料,包括一個 name 字元串、UID 和可選的 namespace

spec - 你所期望的該對象的狀态

對象 spec 的精确格式對每個 Kubernetes 對象來說是不同的,包含了特定于該對象的嵌套字段。 Kubernetes API 參考 能夠幫助我們找到任何我們想建立的對象的規約格式。

例如,Pod 參考文檔詳細說明了 API 中 Pod 的 spec 字段, Deployment 的參考文檔則詳細說明了 Deployment 的 spec 字段。 在這些 API 參考頁面中,你将看到提到的 PodSpec 和 DeploymentSpec。 這些名字是 Kubernetes 用來實作其 API 的 Golang 代碼的實作細節。

k8s
上一篇: DOS/CMD Tips
下一篇: About LoadRunner

繼續閱讀