網站首頁 編程語言 正文
這幾年云原生的熱度久高不下,許多大廠紛紛擁抱云原生。提到云原生,不少開發者可能會想到Kubernetes,也稱為K8s,是一個用于自動部署、擴展和管理“容器化(containerized)應用程序”的開源系統。作為云原生的重要代表之一,它真的很不錯。但也有不少開發者抱怨Kubernetes太復雜了。
近日,在國外知名的技術論壇網站Hacker News上,就有一位用戶對Kubernetes為什么這么復雜做出了自己的見解。
為什么Kubernetes這么復雜?
Kubernetes相比其他系統來說,確實要更大,更復雜。相信不少人在使用它的過程中都曾試圖了解它為什么這樣。該用戶也是這樣,并將自己的理解寫了出來。
Kubernetes是一個集群操作系統
Kubernetes更像是一個通用的集群操作系統內核。傳統操作系統的工作是將一臺計算機及其所有相關硬件的接口暴露出來,讓應用程序可以訪問這些接口。具體細節我們不明確,但這些接口都有相應的設計目標。
- ? ? 資源共享——將一臺物理計算機的資源細分給多個程序,使它們在某種程度上相互隔離;
- ? ? 可移植性——在一定程度上抽象出底層硬件的精確細節,這樣同一程序就可以在不同的硬件上運行而無需修改,或者只需稍加修改;
- ? ? 通用性——當有新的硬件插入計算機時,能夠以漸進的方式將這些硬件納入抽象和接口,最好是在不大幅改變任何接口或破壞任何不使用該硬件的現有軟件的情況下。
- ? ? 整體性——與通用性相關,操作系統能夠調解對硬件的所有訪問:軟件應該很少或者不可能完全繞過操作系統的內核。軟件可以使用操作系統內核來建立與硬件的直接連接,從而使未來
- 的交互直接發生(例如建立一個內存映射的命令管道),但最初的分配和配置仍然在操作系統的監督之下。
- ? ? 性能——與 "直接編寫一個特殊用途的軟件,直接在硬件上運行,并對硬件有獨占的直接訪問權(如unikernel)”相比,希望擁有這種一個可接受的小的性能成本。在某些情況下,通過提供像I/O調度器或緩存層這樣的優化,在實踐中達到比這樣的系統更高的性能。
操作系統內核通常是圍繞上述目標設計,然后編寫用戶空間庫,將低級的、通用的、高性能的接口包裝成更容易使用的抽象概念。操作系統開發者往往更關心的是怎么讓應用運行的更快,而不是應用在我的系統上運行時代碼更少。
Kubernetes與上述設計理念非常類似,它的目標是抽象出一整個數據中心或云。這個觀點有助于理解Kubernetes。它指出了Kubernetes為什么非常靈活。Kubernetes希望自己能擁有普遍性并獲得更強大的功能,它能夠在任何類型的硬件或虛擬機實例上部署任何類型的應用程序。并且還不需要脫離Kubernetes的界面。不論它是否真的能實現這一目標,這樣的設計都很有意義。
上述視角所解釋的設計選擇是Kubernetes的可插拔性和可配置性。一般來說,在不付出奢侈的性能成本下,做不到對所有人都適用的選擇。在現代云環境中,應用程序的類型和部署的硬件類型有很大不同,尤其是要求可以在不同位置快速部署時。這也就意味著,如果一個系統想讓所有人都適用,它就需要強大的快速配置性能。做到這一點確實會搭建出一個強大的系統,但缺點就是它會變得非常復雜。
許多用戶認為Kubernetes本質上是一個“Heroku”,即作為一個部署應用程序的平臺,去抽象出大多數傳統的底層操作系統和分布式系統的細節。Kubernetes認為自己解決的問題更接近于 "CloudFormation",在這個意義上,它希望足以定義整個基礎設施,它還試圖以一種在底層云提供商或硬件上都通用的方式做到這一點。
Kubernetes中的一切是一個控制循環
想象一個非常必要的 "集群操作系統",就像上面描述的那樣,它暴露了 "分配5個CPU的計算量 " 或 "創建一個新的虛擬網絡 "這樣的基元,這些基元反過來又支持系統內部抽象的配置變化或對EC2 API(或其他基礎云提供商)的調用。
但Kubernetes并非是這樣進行工作的,相反,Kubernetes的核心設計決定了所有的配置都是聲明性的,并且都是通過作為控制循環"操作者 "的方式實現。他們不斷地將期望的配置與現實的狀態進行比較,并修改現實狀態,達到與期望狀態一致。
這是一個非常慎重且理由充分的設計抉擇。一般來說,任何沒有被設計成控制循環的系統都將不可避免地偏離期望配置,因此,需要有人來編寫控制循環并通過內部化來進行控制。Kubernetes希望能讓大多數核心控制環路只寫一次,而且是由領域專家來寫,從而使在其上構建可靠的系統變得更加容易。這也是一個系統的自然選擇,因為它的本質是分布式的,而且是為構建分布式系統而設計的。分布式系統的決定性性質是排除部分可能性的故障,這就要求超過一定規模的系統能夠自我修復,并收斂于正確的狀態,而不考慮局部故障。
然而,這種設計也帶來了系統的復雜性和一定幾率的混亂。挑兩個具體的例子。
第一:錯誤延遲, 在Kubernetes中創建一個對象(例如一個pod),這只是在配置存儲中創建一個對象,斷言該對象的預期存在。如果由于資源限制(集群的容量),或者由于對象在某些方面內部不一致(比如引用的容器鏡像不存在),系統在實際分配上不可能滿足該請求,但用戶在創建時無法看到系統的實際情況。事實上,只有當開發者要修改創建對象時,系統才會產生錯誤提示。
這種情況使得一切都更難調試和推理,因為你不能用"創建成功 "作為 "結果對象存在 "的一個速記。這也意味著,與失敗有關的日志信息或調試輸出信息不會出現在創建對象的進程中。一個代碼完整,功能強大的控制器,系統會解釋正在發生的事情,或以其他方式注釋有問題的對象;但對于較差的控制器,控制器的日志中只能找到日志垃圾。而且有些變化可能涉及到多個控制器,它們有時獨立行動,有時聯合行動,這就很難去追蹤發生故障的代碼。
聲明式的控制循環模式提供了一個隱含的承諾:用戶不需要擔心如何從狀態A到狀態B,只需要把狀態B寫進配置數據庫,然后等待。當它的代碼運行良好時,從狀態A自然就進入到狀態B了。這是一個巨大的簡化。
但有時也會失誤,無法或需要等待很長時間從狀態A到狀態B,即使狀態B本身可以實現。這是一個罕見的例子,控制器的作者可能忘記實現它了。Kubernetes中的核心內置基元經過很多測試和使用,以此來一直保持正常工作。但當用戶開始添加第三方資源,比如以管理TLS證書、云負載均衡器、托管數據庫或外部DNS名稱等去運行系統時,程序就會偏離軌道,變得不能清楚的知道路徑是怎么經過測試的。這個故障模式和延遲錯誤一樣微妙。很難區分“變化被接受”和“變化永遠不會被接受”的區別
結論
以上就是來自Hacker News的博主分享的他對Kubernetes為什么這么復雜的看法。該博主認為,對Kubernetes本身、其復雜性以及對其服務的目標有個很好地理解,是一件非常有意義的事。希望這篇文章對剛開始使用Kubernetes的人能有一定幫助。
原文鏈接:https://blog.csdn.net/qq_43529978/article/details/122811846
相關推薦
- 2022-12-27 Qt實現UDP通信的示例代碼_C 語言
- 2022-12-11 React?狀態的不變性實例詳解_React
- 2022-11-05 一篇文章說清楚?go?get?使用私有庫的方法_Golang
- 2022-03-14 軟件文檔編寫規范(技術文件編寫規范)
- 2023-04-24 Numpy創建NumPy矩陣的簡單實現_python
- 2022-03-27 Docker下安裝Mongo4.2及客戶端工具連接Mongo_docker
- 2022-09-27 Swift超詳細講解指針_Swift
- 2022-07-11 gstreamer的消息傳遞機制
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支