[K8s]何為Kubernetes?


Kubernetes 是什么?

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

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

時光回溯

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

image

傳統部署時代:

早期,各個組織機構在物理服務器上運行應用程序。無法為物理服務器中的應用程序定義資源邊界,這會導致資源分配問題。

例如,如果在物理服務器上運行多個應用程序,則可能會出現一個應用程序占用大部分資源的情況,結果可能導致其他應用程序的性能下降。一種解決方案是在不同的物理服務器上運行每個應用程序,但是由於資源利用不足而無法擴展,並且維護許多物理服務器的成本很高。

虛擬化部署時代:

作為解決方案,引入了虛擬化。虛擬化技術允許你在單個物理服務器的 CPU 上運行多個虛擬機(VM)。 虛擬化允許應用程序在 VM 之間隔離,並提供一定程度的安全,因為一個應用程序的信息 不能被另一應用程序隨意訪問。

虛擬化技術能夠更好地利用物理服務器上的資源,並且因為可輕松地添加或更新應用程序 而可以實現更好的可伸縮性,降低硬件成本等等。

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

容器部署時代:

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

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

  • 敏捷應用程序的創建和部署:與使用 VM 鏡像相比,提高了容器鏡像創建的簡便性和效率。
  • 持續開發、集成和部署:通過快速簡單的回滾(由於鏡像不可變性),支持可靠且頻繁的 容器鏡像構建和部署。
  • 關注開發與運維的分離:在構建/發布時而不是在部署時創建應用程序容器鏡像, 從而將應用程序與基礎架構分離。
  • 可觀察性:不僅可以顯示操作系統級別的信息和指標,還可以顯示應用程序的運行狀況和其他指標信號。
  • 跨開發、測試和生產的環境一致性:在便攜式計算機上與在雲中相同地運行。
  • 跨雲和操作系統發行版本的可移植性:可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方運行。
  • 以應用程序為中心的管理:提高抽象級別,從在虛擬硬件上運行 OS 到使用邏輯資源在 OS 上運行應用程序。
  • 松散耦合、分布式、彈性、解放的微服務:應用程序被分解成較小的獨立部分, 並且可以動態部署和管理 - 而不是在一台大型單機上整體運行。
  • 資源隔離:可預測的應用程序性能。
  • 資源利用:高效率和高密度。

為什么需要 Kubernetes,它能做什么?

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

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

Kubernetes 為你提供:

  • 服務發現和負載均衡
    Kubernetes 可以使用 DNS 名稱或自己的 IP 地址公開容器,如果進入容器的流量很大, Kubernetes 可以負載均衡並分配網絡流量,從而使部署穩定。

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

  • 自動部署和回滾
    你可以使用 Kubernetes 描述已部署容器的所需狀態,它可以以受控的速率將實際狀態 更改為期望狀態。例如,你可以自動化 Kubernetes 來為你的部署創建新容器, 刪除現有容器並將它們的所有資源用於新容器。

  • 自動完成裝箱計算
    Kubernetes 允許你指定每個容器所需 CPU 和內存(RAM)。 當容器指定了資源請求時,Kubernetes 可以做出更好的決策來管理容器的資源。

  • 自我修復
    Kubernetes 重新啟動失敗的容器、替換容器、殺死不響應用戶定義的 運行狀況檢查的容器,並且在准備好服務之前不將其通告給客戶端。

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

Kubernetes 不是什么

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 集群由一組被稱作節點的機器組成。這些節點上運行 Kubernetes 所管理的容器化應用。集群具有至少一個工作節點。

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

本文檔概述了交付正常運行的 Kubernetes 集群所需的各種組件。

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

image

控制平面組件(Control Plane Components)

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

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

kube-apiserver

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

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

etcd

etcd 是兼具一致性和高可用性的鍵值數據庫,可以作為保存 Kubernetes 所有集群數據的后台數據庫。

您的 Kubernetes 集群的 etcd 數據庫通常需要有個備份計划。

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

kube-scheduler

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

調度決策考慮的因素包括單個 Pod 和 Pod 集合的資源需求、硬件/軟件/策略約束、親和性和反親和性規范、數據位置、工作負載間的干擾和最后時限。

kube-controller-manager

運行控制器進程的控制平面組件。

從邏輯上講,每個控制器都是一個單獨的進程, 但是為了降低復雜性,它們都被編譯到同一個可執行文件,並在一個進程中運行。

這些控制器包括:

  • 節點控制器(Node Controller): 負責在節點出現故障時進行通知和響應
  • 任務控制器(Job controller): 監測代表一次性任務的 Job 對象,然后創建 Pods 來運行這些任務直至完成
  • 端點控制器(Endpoints Controller): 填充端點(Endpoints)對象(即加入 Service 與 Pod)
  • 服務帳戶和令牌控制器(Service Account & Token Controllers): 為新的命名空間創建默認帳戶和 API 訪問令牌

cloud-controller-manager

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

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

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

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

  • 節點控制器(Node Controller): 用於在節點終止響應后檢查雲提供商以確定節點是否已被刪除
  • 路由控制器(Route Controller): 用於在底層雲基礎架構中設置路由
  • 服務控制器(Service Controller): 用於創建、更新和刪除雲提供商負載均衡器

Node 組件

節點組件在每個節點上運行,維護運行的 Pod 並提供 Kubernetes 運行環境。

kubelet

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

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

kube-proxy

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

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

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

容器運行時(Container Runtime)

容器運行環境是負責運行容器的軟件。

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

插件(Addons)

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

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

DNS

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

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

Kubernetes 啟動的容器自動將此 DNS 服務器包含在其 DNS 搜索列表中。

Web 界面(儀表盤)

Dashboard 是 Kubernetes 集群的通用的、基於 Web 的用戶界面。 它使用戶可以管理集群中運行的應用程序以及集群本身並進行故障排除。

容器資源監控

容器資源監控 將關於容器的一些常見的時間序列度量值保存到一個集中的數據庫中,並提供用於瀏覽這些數據的界面。

集群層面日志

集群層面日志 機制負責將容器的日志數據 保存到一個集中的日志存儲中,該存儲能夠提供搜索和瀏覽接口。

Kubernetes API

Kubernetes 控制面 的核心是 API 服務器。 API 服務器負責提供 HTTP API,以供用戶、集群中的不同部分和集群外部組件相互通信。

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

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

如果你正在編寫程序來訪問 Kubernetes API,可以考慮使用 客戶端庫之一。

OpenAPI 規范

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

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

image

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

API 變更

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

一般而言,新的 API 資源和新的資源字段可以被頻繁地添加進來。 刪除資源或者字段則要遵從 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 版本參考。

API 擴展

有兩種途徑來擴展 Kubernetes API:

  1. 你可以使用自定義資源 來以聲明式方式定義 API 服務器如何提供你所選擇的資源 API。
  2. 你也可以選擇實現自己的 聚合層 來擴展 Kubernetes API。

理解 Kubernetes 對象

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

在 Kubernetes 系統中,Kubernetes 對象 是持久化的實體。 Kubernetes 使用這些實體去表示整個集群的狀態。特別地,它們描述了如下信息:

  • 哪些容器化應用在運行(以及在哪些節點上)
  • 可以被應用使用的資源
  • 關於應用運行時表現的策略,比如重啟策略、升級策略,以及容錯策略

Kubernetes 對象是 “目標性記錄” —— 一旦創建對象,Kubernetes 系統將持續工作以確保對象存在。 通過創建對象,本質上是在告知 Kubernetes 系統,所需要的集群工作負載看起來是什么樣子的, 這就是 Kubernetes 集群的 期望狀態(Desired State)。

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

對象規約(Spec)與狀態(Status)

幾乎每個 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 對象時,必須提供對象的規約,用來描述該對象的期望狀態, 以及關於對象的一些基本信息(例如名稱)。 當使用 Kubernetes API 創建對象時(或者直接創建,或者基於kubectl), API 請求必須在請求體中包含 JSON 格式的信息。 大多數情況下,需要在 .yaml 文件中為 kubectl 提供這些信息。 kubectl 在發起 API 請求時,將這些信息轉換成 JSON 格式。

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

application/deployment.yaml

image

使用類似於上面的 .yaml 文件來創建 Deployment的一種方式是使用 kubectl 命令行接口(CLI)中的 kubectl apply 命令, 將 .yaml 文件作為參數。下面是一個示例:

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

輸出類似如下這樣:

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 代碼的實現細節。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM