之前寫過一篇 k8s(kubernetes)簡介 同名的文章炮捧,但是剛開始不會(huì)使用簡書的編輯器慌随,現(xiàn)在重新研究了一下痴腌,把之前的文章更新了一下。
k8s(kubernetes)簡介
kubernetes能做什么
傳統(tǒng)部署時(shí)代:
早期此疹,各個(gè)組織機(jī)構(gòu)在物理服務(wù)器上運(yùn)行應(yīng)用程序甚颂。無法為物理服務(wù)器中的應(yīng)用程序定義資源邊界,這會(huì)導(dǎo)致資源分配問題秀菱。 例如振诬,如果在物理服務(wù)器上運(yùn)行多個(gè)應(yīng)用程序,則可能會(huì)出現(xiàn)一個(gè)應(yīng)用程序占用大部分資源的情況衍菱,結(jié)果可能導(dǎo)致其他應(yīng)用程序的性能下降赶么。 一種解決方案是在不同的物理服務(wù)器上運(yùn)行每個(gè)應(yīng)用程序,但是這樣會(huì)造成資源利用不足脊串,而且不易擴(kuò)展辫呻, 同時(shí)物理服務(wù)器的運(yùn)維成本很高。
虛擬化部署時(shí)代:
作為解決方案琼锋,引入了虛擬化放闺。虛擬化技術(shù)允許你在單個(gè)物理服務(wù)器的 CPU 上運(yùn)行多個(gè)虛擬機(jī)(VM)。 虛擬化允許應(yīng)用程序在 VM 之間隔離缕坎,并提供一定程度的安全怖侦,因?yàn)橐粋€(gè)應(yīng)用程序的信息不能被另一應(yīng)用程序隨意訪問。
虛擬化技術(shù)能夠更好地利用物理服務(wù)器上的資源谜叹,并且因?yàn)榭奢p松地添加或更新應(yīng)用程序而可以實(shí)現(xiàn)更好的可伸縮性匾寝,降低硬件成本。
每個(gè) VM 是一臺(tái)完整的計(jì)算機(jī)荷腊,在虛擬化硬件之上運(yùn)行所有組件艳悔,包括其自己的操作系統(tǒng)。所以女仰,VM本身會(huì)占用大量的硬件資源猜年。
容器部署時(shí)代:
容器類似于 VM,但是它們具有被放寬的隔離屬性疾忍,可以在應(yīng)用程序之間共享操作系統(tǒng)(OS)乔外。 因此,容器技術(shù)更加輕量級(jí)锭碳。容器與 VM 類似袁稽,具有自己的文件系統(tǒng)勿璃、CPU擒抛、內(nèi)存推汽、進(jìn)程空間等。 由于它們與基礎(chǔ)架構(gòu)分離歧沪,因此可以跨云和跨系統(tǒng)發(fā)行版本進(jìn)行移植歹撒。相比于VM,容器本身所需要的硬件資源小得多诊胞。
kubernetes部署時(shí)代:
容器是打包和運(yùn)行應(yīng)用程序的很好方式暖夭。在生產(chǎn)環(huán)境中,你只需要管理運(yùn)行應(yīng)用程序的容器撵孤,并確保不會(huì)停機(jī)迈着。 例如,如果一個(gè)容器發(fā)生故障邪码,則需要啟動(dòng)另一個(gè)容器裕菠。如果把容器的啟停交給軟件處理,會(huì)不會(huì)更容易闭专?這就是 kubernetes 解決的問題奴潘!
kubernetes 提供以下功能:
-
服務(wù)發(fā)現(xiàn)和負(fù)載均衡
kubernetes 可以使用 DNS 名稱或自己的 IP 地址公開容器,如果進(jìn)入容器的流量很大影钉, kubernetes 可以負(fù)載均衡并分配網(wǎng)絡(luò)流量画髓。
-
存儲(chǔ)編排
kubernetes 允許你自動(dòng)掛載你選擇的存儲(chǔ)系統(tǒng),例如本地存儲(chǔ)平委、網(wǎng)絡(luò)存儲(chǔ)奈虾。
-
自動(dòng)部署和回滾
你可以使用 kubernetes 描述已部署容器的所需狀態(tài),它可以以受控的速率將實(shí)際狀態(tài)更改為期望狀態(tài)廉赔。例如愚墓,你可以自動(dòng)化 kubernetes 來為你的部署創(chuàng)建新容器, 刪除現(xiàn)有容器并將它們的所有資源用于新容器昂勉。
-
自動(dòng)完成資源配置
kubernetes 允許你指定每個(gè)容器所需 CPU 和內(nèi)存(RAM)浪册。 當(dāng)容器指定了資源請(qǐng)求時(shí),kubernetes 可以做出更好的決策來管理容器的資源岗照。
-
自我修復(fù)
kubernetes 能重新啟動(dòng)失敗的容器村象、替換容器、殺死不響應(yīng)的容器攒至。
-
密鑰與配置管理
kubernetes 允許你存儲(chǔ)和管理敏感信息厚者,例如密碼和 ssh 密鑰。 你可以在不重建容器鏡像的情況下更新密鑰和應(yīng)用程序配置迫吐。
k8s集群架構(gòu)以及組成
控制平面(Control Plane)
控制平面對(duì)集群做出全局決策(比如調(diào)度)库菲,以及檢測(cè)和響應(yīng)集群事件(例如,當(dāng)容器數(shù)量不足時(shí)志膀,啟動(dòng)新的容器)熙宇。
控制平面可以在集群中的任何節(jié)點(diǎn)上運(yùn)行鳖擒。 但是,為了簡單起見烫止,控制平面通常在單獨(dú)的計(jì)算機(jī)上運(yùn)行蒋荚,并且不會(huì)在此計(jì)算機(jī)上運(yùn)行用戶容器。
apiserver
apiserver公開了 kubernetes的核心接口馆蠕。kubernetes的所有組件都要通過apiserver才能與其他組件進(jìn)行通信期升。例如:當(dāng)調(diào)度器scheduler將任務(wù)發(fā)給工作節(jié)點(diǎn)時(shí),不直接與節(jié)點(diǎn)通信互躬,而是將計(jì)劃告訴apiserver播赁,再由apiserver將任務(wù)發(fā)送給工作節(jié)點(diǎn)。
apiserver 設(shè)計(jì)上考慮了水平伸縮吼渡,也就是說行拢,它可通過部署多個(gè)實(shí)例進(jìn)行伸縮。 你可以運(yùn)行apiserver 的多個(gè)實(shí)例诞吱,并在這些實(shí)例之間平衡流量舟奠。
etcd
etcd 是兼具一致性和高可用性的鍵值數(shù)據(jù)庫,可以作為保存 kubernetes 所有集群數(shù)據(jù)的后臺(tái)數(shù)據(jù)庫房维,etcd保存了kubernetes的所有狀態(tài)信息沼瘫。
scheduler
scheduler負(fù)責(zé)調(diào)度新創(chuàng)建的pods,選擇節(jié)點(diǎn)讓 pod在上面運(yùn)行咙俩。
調(diào)度決策考慮的因素包括資源需求耿戚、硬件/軟件/策略約束、親和性和反親和性阿趁、數(shù)據(jù)位置膜蛔、工作負(fù)載間的干擾和時(shí)限等。
controller-manager
controller-manager包括:
節(jié)點(diǎn)控制器(Node Controller): 負(fù)責(zé)在節(jié)點(diǎn)出現(xiàn)故障時(shí)進(jìn)行通知和響應(yīng)
任務(wù)控制器(Job controller): 管理 job對(duì)象脖阵,然后創(chuàng)建 pods 來運(yùn)行這些job直至完成
端點(diǎn)控制器(Endpoints Controller): 填充端點(diǎn)(Endpoints)對(duì)象(即加入 Service 的 Pod)
服務(wù)帳戶和令牌控制器(Service Account & Token Controllers): 為新的命名空間創(chuàng)建默認(rèn)帳戶和 API 訪問令牌
Node 組件
node組件在每個(gè)節(jié)點(diǎn)上運(yùn)行皂股,包括控制平面節(jié)點(diǎn),維護(hù)運(yùn)行的 pod并提供 kubernetes 運(yùn)行環(huán)境命黔。
kubelet
在每個(gè)節(jié)點(diǎn)上運(yùn)行呜呐,保證容器都運(yùn)行在pod中。
kubelet 接收 PodSpecs(pod的運(yùn)行參數(shù))悍募,確保這些 PodSpecs 中描述的容器處于運(yùn)行狀態(tài)且健康蘑辑。 kubelet 不會(huì)管理不是由 kubernetes 創(chuàng)建的容器。
kube-proxy
kube-proxy是集群中每個(gè)節(jié)點(diǎn)上運(yùn)行的網(wǎng)絡(luò)代理坠宴,實(shí)現(xiàn) kubernetes中service概念的一部分洋魂。
kube-proxy 維護(hù)節(jié)點(diǎn)上的網(wǎng)絡(luò)規(guī)則。這些網(wǎng)絡(luò)規(guī)則允許從集群內(nèi)部或外部的網(wǎng)絡(luò)會(huì)話與pod進(jìn)行網(wǎng)絡(luò)通信。
如果操作系統(tǒng)提供了數(shù)據(jù)包過濾層并可用的話副砍,kube-proxy 會(huì)通過它來實(shí)現(xiàn)網(wǎng)絡(luò)規(guī)則衔肢。否則, kube-proxy 僅轉(zhuǎn)發(fā)流量本身址晕。
容器運(yùn)行環(huán)境(Container Runtime)
容器運(yùn)行環(huán)境是負(fù)責(zé)運(yùn)行容器的軟件膀懈,如docker顿锰。
kubernetes 支持多個(gè)容器運(yùn)行環(huán)境: Docker谨垃、 containerd、CRI-O 以及任何實(shí)現(xiàn) kubernetes CRI (容器運(yùn)行環(huán)境接口)的軟件硼控。
k8s高可用架構(gòu)
堆疊(Stacked) etcd 拓?fù)?/h2>
堆疊(Stacked) HA(High Availability )集群是一種這樣的拓?fù)?/a>刘陶,其中 etcd 分布式數(shù)據(jù)存儲(chǔ)集群堆疊在控制平面節(jié)點(diǎn)上,作為控制平面的一個(gè)組件運(yùn)行牢撼。
每個(gè)控制平面節(jié)點(diǎn)運(yùn)行 kube-apiserver
匙隔,kube-scheduler
和 kube-controller-manager
實(shí)例。
kube-apiserver
使用負(fù)載均衡器暴露給工作節(jié)點(diǎn)熏版。
每個(gè)控制平面節(jié)點(diǎn)創(chuàng)建一個(gè)本地 etcd 成員(member)纷责,這個(gè) etcd 成員只與該節(jié)點(diǎn)的 kube-apiserver
通信。這同樣適用于本地 kube-controller-manager
和 kube-scheduler
實(shí)例撼短。
這種拓?fù)鋵⒖刂破矫婧?etcd 成員耦合在同一節(jié)點(diǎn)上再膳。相對(duì)使用外部 etcd 集群,設(shè)置起來更簡單曲横,而且更易于副本管理喂柒。
然而,堆疊集群存在耦合失敗的風(fēng)險(xiǎn)禾嫉。如果一個(gè)節(jié)點(diǎn)發(fā)生故障灾杰,則 etcd 成員和控制平面實(shí)例都將丟失,因此熙参,應(yīng)該為 HA 集群運(yùn)行至少三個(gè)堆疊的控制平面節(jié)點(diǎn)艳吠。
這是 kubeadm 中的默認(rèn)拓?fù)洹.?dāng)使用 kubeadm init
和 kubeadm join --control-plane
時(shí)孽椰,在控制平面節(jié)點(diǎn)上會(huì)自動(dòng)創(chuàng)建本地 etcd 成員讲竿。
外部 etcd 拓?fù)?/h2>
具有外部 etcd 的 HA 集群是一種這樣的拓?fù)?/a>,其中 etcd 分布式數(shù)據(jù)存儲(chǔ)集群在獨(dú)立于控制平面節(jié)點(diǎn)的其他節(jié)點(diǎn)上運(yùn)行弄屡。
就像堆疊的 etcd 拓?fù)湟粯犹赓鳎獠?etcd 拓?fù)渲械拿總€(gè)控制平面節(jié)點(diǎn)都運(yùn)行 kube-apiserver
,kube-scheduler
和 kube-controller-manager
實(shí)例膀捷。同樣迈嘹, kube-apiserver
使用負(fù)載均衡器暴露給工作節(jié)點(diǎn)。但是,etcd 成員在不同的主機(jī)上運(yùn)行秀仲,每個(gè) etcd 主機(jī)與每個(gè)控制平面節(jié)點(diǎn)的 kube-apiserver
通信融痛。
這種拓?fù)浣Y(jié)構(gòu)解耦了控制平面和 etcd 成員。因此神僵,失去控制平面實(shí)例或者 etcd 成員的影響較小雁刷,并且不會(huì)像堆疊的 HA 拓?fù)淠菢佑绊懠喝哂唷?/p>
但是,此拓?fù)湫枰獌杀队诙询B HA 拓?fù)涞闹鳈C(jī)數(shù)量保礼。
具有此拓?fù)涞?HA 集群至少需要三個(gè)用于控制平面節(jié)點(diǎn)的主機(jī)和三個(gè)用于 etcd 節(jié)點(diǎn)的主機(jī)沛励。
etcd集群中的數(shù)據(jù)一致性
1、etcd是什么
etcd是一個(gè)鍵值存儲(chǔ)系統(tǒng)炮障,集群中的每一個(gè)成員都保持著全量的數(shù)據(jù)目派。
2、數(shù)據(jù)一致性--etcd集群選舉
etcd集群中的角色分為Leader, Follower, Candidate胁赢。同一時(shí)間只存在一個(gè)Leader企蹭,Leader處理所有來自客戶端寫(讀可由Follower處理)操作。
當(dāng)Follower在一定時(shí)間內(nèi)沒有收到來自主節(jié)點(diǎn)的心跳智末,會(huì)將自己角色改變?yōu)镃andidate(自封為候選人)谅摄,并發(fā)起一次選主投票;當(dāng)收到包括自己在內(nèi)超過半數(shù)節(jié)點(diǎn)贊成后系馆,選舉成功送漠;當(dāng)收到票數(shù)不足半數(shù)選舉失敗。若本輪未選出主節(jié)點(diǎn)它呀,將進(jìn)行下一輪選舉螺男。為了避免陷入選主失敗循環(huán),每個(gè)節(jié)點(diǎn)未收到心跳發(fā)起選舉的時(shí)間是一定范圍內(nèi)的隨機(jī)值纵穿,這樣能夠避免2個(gè)節(jié)點(diǎn)同時(shí)發(fā)起選主下隧。Candidate節(jié)點(diǎn)收到來自主節(jié)點(diǎn)的信息后,會(huì)立即終止選舉過程谓媒,進(jìn)入Follower角色淆院。
在選主邏輯中,為了保障數(shù)據(jù)是最新的句惯,對(duì)能夠成為主的節(jié)點(diǎn)加以限制土辩,確保選出的節(jié)點(diǎn)以已經(jīng)包含了集群已經(jīng)提交的所有日志。如果新選出的主節(jié)點(diǎn)已經(jīng)包含了集群所有提交的日志抢野,那就不需要從和其他節(jié)點(diǎn)比對(duì)數(shù)據(jù)了拷淘。簡化了流程,縮短了集群恢復(fù)服務(wù)的時(shí)間指孤。這里存在一個(gè)問題启涯,加以這樣限制之后贬堵,還能否選出主呢?答案是:只要仍然有超過半數(shù)節(jié)點(diǎn)存活结洼,這樣的主一定能夠選出肪获。因?yàn)橐呀?jīng)提交的日志必然被集群中超過半數(shù)節(jié)點(diǎn)持久化碌更。
3、數(shù)據(jù)一致性--節(jié)點(diǎn)數(shù)量
etcd使用RAFT協(xié)議保證各個(gè)節(jié)點(diǎn)之間的狀態(tài)一致尝盼。根據(jù)RAFT算法原理峰锁,節(jié)點(diǎn)數(shù)目越多氮发,會(huì)降低集群的寫性能盆犁。這是因?yàn)槊恳淮螌懖僮鞫切希枰褐写蠖鄶?shù)節(jié)點(diǎn)將日志落盤成功后,Leader節(jié)點(diǎn)才能將修改內(nèi)部狀態(tài)機(jī)叽掘,并返回將結(jié)果返回給客戶端楣铁。
也就是說在等同配置下玖雁,節(jié)點(diǎn)數(shù)越少更扁,集群性能越好。顯然赫冬,只部署1個(gè)節(jié)點(diǎn)是沒什么意義的浓镜。通常,按照需求將集群節(jié)點(diǎn)部署為3劲厌,5膛薛,7,9個(gè)節(jié)點(diǎn)补鼻。
4哄啄、數(shù)據(jù)一致性--數(shù)據(jù)讀寫
為了保證數(shù)據(jù)的強(qiáng)一致性,etcd 集群中所有的數(shù)據(jù)流向都是一個(gè)方向风范,從 Leader (主節(jié)點(diǎn))流向Follower咨跌,也就是所有 Follower 的數(shù)據(jù)必須與 Leader 保持一致,如果不一致會(huì)被覆蓋硼婿。
讀取: 由于集群所有節(jié)點(diǎn)數(shù)據(jù)是強(qiáng)一致性的锌半,讀取可以從集群中隨便哪個(gè)節(jié)點(diǎn)進(jìn)行讀取數(shù)據(jù)
寫入: etcd 集群有 leader,如果寫入往 leader 寫入寇漫,可以直接寫入刊殉,然后Leader節(jié)點(diǎn)會(huì)把寫入分發(fā)給所有 Follower。如果往 follower 寫入州胳,請(qǐng)求會(huì)路由到Leader记焊,然后Leader節(jié)點(diǎn)會(huì)把寫入分發(fā)給所有 Follower。
5栓撞、etcd讀寫性能
按照官網(wǎng)給出的資料遍膜,在2CPU,1.8G內(nèi)存,SSD磁盤這樣的配置下捌归,單節(jié)點(diǎn)的寫性能可以達(dá)到16K QPS,肛响,而先寫后讀也能達(dá)到12K QPS。這個(gè)性能還是相當(dāng)可觀的惜索。