
本文主要介紹什么是k8s以及k8s的基本架構(gòu)和相關(guān)基礎(chǔ)概念。
Kubernetes 一詞源于希臘語,意為“舵手”或“飛行員”,作為一個可移植、可擴展的開源平臺,k8s可以使用聲明式配置來管理編排容器服務(wù)并且提高自動化水平和效率。同時,得益于龐大且仍不斷在增長的生態(tài)系統(tǒng)支撐,k8s擁有海量可用的周邊服務(wù)、工具和生態(tài)支持。
kubernetes官網(wǎng)上給出的定義如下:Kubernetes是用于自動部署,擴展和管理容器化應(yīng)用程序的開源系統(tǒng)。(Kubernetes, also known as K8s, is an open-source system for automating deployment, scaling, and management of containerized applications.)它將組成應(yīng)用程序的容器組合成邏輯單元(pod),以便于管理和服務(wù)發(fā)現(xiàn)。Kubernetes 源自Google 15 年生產(chǎn)環(huán)境的運維經(jīng)驗,同時凝聚了社區(qū)的最佳創(chuàng)意和實踐。
1、軟件部署的迭代進程
一般來說,我們可以把軟件部分分為三個階段:傳統(tǒng)部署、虛擬化部署、容器化部署。
注意容器化雖然也屬于虛擬化的一種,但是這里所指的虛擬化部署指的是通過KVM等虛擬化方式創(chuàng)建的虛擬機來部署應(yīng)用。

-
傳統(tǒng)部署
在傳統(tǒng)部署時代,所有的應(yīng)用都運行在同一臺物理機上面。這給資源的隔離帶來了很大的困擾,不同的應(yīng)用會因為爭奪系統(tǒng)資源而降低性能表現(xiàn),也有可能會出現(xiàn)一個應(yīng)用占用了大部分資源而另一個應(yīng)用無資源可用的情況。同時,運維人員維護如此多的運行不同應(yīng)用的物理機也是相當(dāng)麻煩的。
-
虛擬化部署
在虛擬化部署時代,通過在操作系統(tǒng)中加入了Hypervisor,以及CPU等硬件的更新迭代支持,可以在一臺物理機上面通過虛擬化的方式創(chuàng)建多臺虛擬機Virtual Machines (VMs)。每臺虛擬機都是一個獨立的操作系統(tǒng),擁有自己的文件系統(tǒng)和各種資源以及虛擬化的硬件。運維人員只需要維護各種虛擬機鏡像鏡像即可。
-
容器化部署
前面我們說過容器化嚴(yán)格來說也是虛擬化的一種,只不過容器化更進一步,通過容器運行時(Container Runtime),可以讓不同的容器共享底層宿主機的操作系統(tǒng),因為容器化被視為是一種輕量的虛擬化技術(shù)。同時,和虛擬機一樣,容器也有自己的文件系統(tǒng)、CPU、內(nèi)存、進程空間等資源。而且由于容器和底層的操作系統(tǒng)分離,一個容器可以運行在不同操作系統(tǒng)和云環(huán)境上。容器化技術(shù)的一些特點如下:
解耦了應(yīng)用的創(chuàng)建和部署過程:對比虛擬機,可以提供更高的易用性和效率
持續(xù)開發(fā)、集成、部署(CI/CD):得益于容器鏡像的不變性,容器化技術(shù)可以高效快速地頻繁創(chuàng)建高質(zhì)量的容器鏡像用于部署和回滾
開發(fā)和運維分離:創(chuàng)建應(yīng)用容器鏡像和部署應(yīng)用的時空連續(xù)性被打斷,創(chuàng)建之后不需要立即部署,而是使用容器作為中介將其保存起來,從而使得應(yīng)用和底層的基礎(chǔ)架構(gòu)解耦
出色的可觀察性:不僅僅是系統(tǒng)層面的指標(biāo)信息,包括應(yīng)用的健康狀態(tài)和其他變量也能夠展示出來
環(huán)境一致性:開發(fā)、測試和生產(chǎn)環(huán)境只要使用同樣的鏡像,就可以保證環(huán)境的一致性
跨云和操作系統(tǒng):容器可以運行在各種云環(huán)境和不同的操作系統(tǒng)上
以應(yīng)用為中心進行管理:容器的抽象層級上升到了應(yīng)用級別,因此可以從應(yīng)用的邏輯資源層面進行調(diào)度分配和管理
松散耦合、分布式、彈性、解放的微服務(wù):應(yīng)用程序被分解成較小的獨立部分, 并且可以動態(tài)部署和管理,而不是在一臺大型的物理機或虛擬機上整體運行
資源隔離:可預(yù)測的應(yīng)用程序性能
資源利用:高效率和高密度
2、k8s的優(yōu)勢
容器無疑是一種運行和管理應(yīng)用的良方。在生產(chǎn)環(huán)境中,我們需要保證每一個容器服務(wù)都正常運行,如果某個容器宕掉了,需要重啟一個新的容器來進行替補。如果上述的操作能夠被某個系統(tǒng)自動實現(xiàn)呢?這時候k8s的優(yōu)勢就展現(xiàn)出來了。k8s提供了一個彈性的分布式系統(tǒng)框架,它照顧到了應(yīng)用擴容、故障轉(zhuǎn)移和部署模式等多個方面。k8s的一些主要特性有:
服務(wù)發(fā)現(xiàn)和負載均衡:k8s可以通過DNS或者是IP地址來暴露容器中的服務(wù)。如果某個容器的流量/請求特別高,k8s能夠主動實現(xiàn)負載均衡來降低該容器的流量/請求從而保證容器的穩(wěn)定運行
存儲編排:k8s允許我們根據(jù)自己的實際需求和選擇來掛載存儲系統(tǒng),支持但不限于本地存儲、云存儲等各種方式
自動部署和回滾:我們可以使用k8s來聲明已經(jīng)部署的容器的期望狀態(tài),它可以以受控的速率將實際狀態(tài)切換到期望狀態(tài)。例如我們可以聲明某個容器的運行數(shù)量的期望值為10,k8s會自動將容器的數(shù)量調(diào)整到該期望狀態(tài);我們還可以使用自動化 Kubernetes 來為部署創(chuàng)建新容器, 刪除現(xiàn)有容器并將它們的所有資源用于新容器
自動裝箱計算:我們可以在k8s中指定每個容器所需 CPU 和內(nèi)存(RAM)。 當(dāng)容器指定了資源請求時,k8s會根據(jù)每個node節(jié)點的狀態(tài)和每個容器所需要的資源來進行智能調(diào)度,確保資源的最大化利用
-
自我修復(fù)
k8s能夠自動重啟運行失敗的容器、替換容器、殺死不響應(yīng)
用戶定義的運行狀況檢查的容器,并且在準(zhǔn)備好服務(wù)之前不將其通告給客戶端,從而保證客戶端的請求不會被分發(fā)到有問題的容器中 -
密鑰與配置管理
k8s允許我們存儲和管理如密碼、OAuth 令牌和 ssh 密鑰等敏感信息,我們可以在不重建容器鏡像的情況下部署和更新密鑰和應(yīng)用程序配置,也不需要在配置中暴露密鑰等敏感信息
3、k8s不是什么
官方一直在強調(diào)這個觀點:k8s并不是一個傳統(tǒng)的包羅萬象的PaaS平臺,它的設(shè)計思想是提供最核心的基礎(chǔ)框架和必要的核心功能,而在其他的選擇上盡可能保證多樣的兼容性和靈活性。盡管因為操作在容器級別層面而不是硬件層面,使得k8s提供了一些如部署、擴容、負載均衡等和PaaS平臺類似的特性,但是對于日志、存儲、報警、監(jiān)控、CI/CD等其他諸多方面,k8s選擇了將選擇權(quán)交給使用者,這也是構(gòu)建k8s豐富的生態(tài)中的重要一環(huán)。
k8s不限制支持的應(yīng)用類型:包括無狀態(tài)(nginx等)、有狀態(tài)(數(shù)據(jù)庫等)和數(shù)據(jù)處理(AI、大數(shù)據(jù)、深度學(xué)習(xí)等)各種各樣的應(yīng)用類型,基本上能在容器中運行的應(yīng)用都能在k8s中運行,而事實上絕大多數(shù)應(yīng)用都能在容器中運行,因此絕大多數(shù)應(yīng)用都能在k8s中運行
不負責(zé)部署源代碼、不構(gòu)建程序、沒有CI/CD:k8s并不涉及這些部分,使用者可以根據(jù)自己的偏好來選擇合適的解決方案
不提供應(yīng)用級別的服務(wù):不提供中間件、數(shù)據(jù)庫、數(shù)據(jù)存儲集群等作為內(nèi)置服務(wù),但是它們都能夠很好地運行在k8s中,也能通過各種方式將服務(wù)暴露出去使用
不提供日志、監(jiān)控和報警等解決方案,但是提供了一些概念和指標(biāo)數(shù)據(jù)等用于收集導(dǎo)出機制
不提供或不要求配置語言/系統(tǒng)(例如 jsonnet),它提供了可以由任意形式的聲明性規(guī)范所構(gòu)成的聲明性 API
不提供也不采用任何全面的機器配置、維護、管理或自我修復(fù)系統(tǒng)
此外,Kubernetes 不僅僅是一個編排系統(tǒng),實際上它消除了編排的需要。 編排的技術(shù)定義是執(zhí)行已定義的工作流程:首先執(zhí)行 A,然后執(zhí)行 B,再執(zhí)行 C。 相比之下,Kubernetes 包含一組獨立的、可組合的控制過程, 這些過程連續(xù)地將當(dāng)前狀態(tài)驅(qū)動到所提供的所需狀態(tài)。 如何從 A 到 C 的方式無關(guān)緊要,也不需要集中控制,這使得系統(tǒng)更易于使用 且功能更強大、系統(tǒng)更健壯、更為彈性和可擴展。
4、k8s基本架構(gòu)
我們先來看看官方給出的基本架構(gòu)圖。下圖只包含了非常基礎(chǔ)的k8s架構(gòu)組件。我們先從這里開始。

首先上圖灰色區(qū)域表示的是一整個k8s集群,整個k8s的架構(gòu)其實和我們常見的master-worker模型非常相似,只不過由于這是分布式的集群,要更復(fù)雜一些。
4.1 Control Plane
首先我們看到藍色框內(nèi)的Control Plane,這個是整個集群的控制平面,相當(dāng)于是master進程的加強版。k8s中的Control Plane一般都會運行在Master節(jié)點上面。在默認(rèn)情況下,Master節(jié)點并不會運行應(yīng)用工作負載,所有的應(yīng)用工作負載都交由Node節(jié)點負責(zé)。
控制平面中的Master節(jié)點主要運行控制平面的各種組件,它們主要的作用就是維持整個k8s集群的正常工作、存儲集群的相關(guān)信息,同時為集群提供故障轉(zhuǎn)移、負載均衡、任務(wù)調(diào)度和高可用等功能。對于Master節(jié)點一般有多個用于保證高可用,而控制平面中的各個組件均以容器的Pod形式運行在Master節(jié)點中,大部分的組件需要在每個Master節(jié)點上都運行,少數(shù)如DNS服務(wù)等組件則只需要保證足夠數(shù)量的高可用即可。
4.1.1 kube-apiserver
k8s集群的控制平面的核心是API服務(wù)器,而API服務(wù)器主要就是由kube-apiserver組件實現(xiàn)的,它被設(shè)計為可水平擴展,即通過部署不同數(shù)量的實例來進行縮放從而適應(yīng)不同的流量。API服務(wù)器作為整個k8s控制平面的前端,負責(zé)提供 HTTP API,以供用戶、集群中的不同部分組件和集群外部組件相互通信。
并且kubernetes api在設(shè)計的時候是遵循REST思想的,我們可以通過kubeadm或者kubectl這類的CLI工具來操控API從而控制整個k8s集群,也可以通過其他的Web UI來進行操控。
4.1.2 kube-scheduler
主節(jié)點上的組件,該組件監(jiān)視那些新創(chuàng)建的未指定運行節(jié)點的 Pod,并選擇節(jié)點讓 Pod 在上面運行。
調(diào)度決策考慮的因素包括單個 Pod 和 Pod 集合的資源需求、硬件/軟件/策略約束、親和性和反親和性規(guī)范、數(shù)據(jù)位置、工作負載間的干擾和最后時限。
4.1.3 kube-controller-manager
在主節(jié)點上運行 控制器 的組件。
從邏輯上講,每個控制器都是一個單獨的進程, 但是為了降低復(fù)雜性,它們都被編譯到同一個可執(zhí)行文件,并在一個進程中運行。
這些控制器包括:
- 節(jié)點控制器(Node Controller): 負責(zé)在節(jié)點出現(xiàn)故障時進行通知和響應(yīng)。
- 副本控制器(Replication Controller): 負責(zé)為系統(tǒng)中的每個副本控制器對象維護正確數(shù)量的 Pod。
- 端點控制器(Endpoints Controller): 填充端點(Endpoints)對象(即加入 Service 與 Pod)。
- 服務(wù)帳戶和令牌控制器(Service Account & Token Controllers): 為新的命名空間創(chuàng)建默認(rèn)帳戶和 API 訪問令牌.
4.1.4 etcd
etcd 是兼具一致性和高可用性的鍵值key-value數(shù)據(jù)庫,可以作為保存 Kubernetes 所有集群數(shù)據(jù)的后臺數(shù)據(jù)庫,負責(zé)保存Kubernetes Cluster的配置信息和各種資源的狀態(tài)信息,當(dāng)數(shù)據(jù)發(fā)生變化時,etcd 會快速地通知Kubernetes相關(guān)組件。
Kubernetes 集群的 etcd 數(shù)據(jù)庫通常需要有個備份計劃。此外還有一種k8s集群部署的高可用方案是將etcd數(shù)據(jù)庫從容器中抽離出來,單獨作為一個高可用數(shù)據(jù)庫部署,從而為k8s提供穩(wěn)定可靠的高可用數(shù)據(jù)庫存儲。
4.1.5 cloud-controller-manager
cloud-controller-manager 僅運行特定于云平臺的控制回路。 如果你在自己的環(huán)境中運行 Kubernetes,或者在本地計算機中運行學(xué)習(xí)環(huán)境, 所部署的環(huán)境中不需要云控制器管理器。因此可以將其理解為云服務(wù)廠商專用的kube-controller-manager,這里不作贅述。
4.1.6 DNS
DNS雖然在k8s的官方文檔被劃分為插件部分,但是從k8s的原理中我們不難看出其重要性,因此幾乎所有 Kubernetes 集群都應(yīng)該有集群 DNS, 因為很多示例都需要 DNS 服務(wù)。
集群 DNS 是一個 DNS 服務(wù)器,和環(huán)境中的其他 DNS 服務(wù)器一起工作,它為 Kubernetes 服務(wù)提供 DNS 記錄。Kubernetes 啟動的容器自動將此 DNS 服務(wù)器包含在其 DNS 搜索列表中。
k8s默認(rèn)使用的是coreDNS組件。
4.2 Worker Node
Worker Node的概念是和前面的Control Plane相對立的,集群中的節(jié)點基本都可以分為控制節(jié)點(Control Plane/master)和工作節(jié)點(Worker Node/worker)兩大類。一般來說集群中的主要工作負載都是運行在Worker Node上面的,Master節(jié)點默認(rèn)情況下不參與工作負載,但是可以手動設(shè)置為允許參與工作負載。
4.3.1 Pod
Pod是k8s集群中最小的工作單元,和docker里面的單個運行的容器不同,Pod中可以包含多個容器,它們共享相同的計算、網(wǎng)絡(luò)和存儲等資源(相當(dāng)于在一臺機器上運行多個應(yīng)用)
4.3.2 kubelet
kubelet是k8s集群中的每個節(jié)點上(包括master節(jié)點)都會運行的代理。 它能夠保證容器都運行在 Pod 中。kubelet 只會管理由 Kubernetes 創(chuàng)建的容器。
kubelet 接收一組通過各類機制提供給它的 PodSpecs,確保這些 PodSpecs 中描述的容器處于運行狀態(tài)且健康。 當(dāng)Scheduler確定在某個Node上運行Pod后,會將Pod的具體配置信息(image、volume等)發(fā)送給該節(jié)點的kubelet,kubelet根據(jù)這些信息創(chuàng)建和運行容器,并向Master報告運行狀態(tài)。
4.3.3 kube-proxy
kube-proxy 是集群中每個節(jié)點上運行的網(wǎng)絡(luò)代理, kube-proxy通過維護主機上的網(wǎng)絡(luò)規(guī)則并執(zhí)行連接轉(zhuǎn)發(fā),實現(xiàn)了Kubernetes服務(wù)抽象。
service在邏輯上代表了后端的多個Pod,外界通過service訪問Pod。service接收到的請求就是通過kube-proxy轉(zhuǎn)發(fā)到Pod上的,kube-proxy服務(wù)負責(zé)將訪問service的TCP/UDP數(shù)據(jù)流轉(zhuǎn)發(fā)到后端的容器。如果有多個副本,kube-proxy會實現(xiàn)負載均衡。