作者:肥嘟嘟左衛門熊
前言
今天簡單聊一聊一個小問題,即為什么k8s的集群主節點數量通常是奇數,且3或5個居多?
我們先拋出答案
- 2467等數量的主節點也是可以的,但是不推薦的的原因如下
1. 奇數的原因是防止資源的浪費
k8s的一致性算法RAFT,要求集群需要數量
大於(n/2)
的正常主節點才能提供服務(n為主節點數)
因此3個主節點有1個節點的容錯率,而4個主節點也只有1個節點的容錯率
2. 三個或五個也是平衡的考慮
3或5則是因為1個沒有容錯率,7個主節或更多將導致確定集群成員和仲裁的開銷加大,不建議這樣做
腦裂現象?
這是在Elasticsearch、ZooKeeper、k8s集群都會出現的現象
集群中的Master或Leader節點往往是通過選舉產生的。
在網絡正常的情況下,可以順利的選舉出Leader
。但當兩個機房之間的網絡通信出現故障時,選舉機制就有可能在不同的網絡分區中選出兩個Leader
。當網絡恢復時,這兩個Leader
該如何處理數據同步?又該聽誰的?這也就出現了“腦裂”現象。
舉例
某公司有機房如下
如果當有一天電纜被挖懷了,上海的機房和昆明的機房沒法連通了,會存在什么情況呢?
情況一:原來的leader是在上海的服務器
我們假設原來的leader是在上海的服務器,那么昆明的兩台服務器由於電纜被挖斷,無法與leader建立連接,那么昆明的兩台服務器就會認為主節點掛了,開始選舉leader,2台服務器會把票投給其中的一台,2<5/2,不滿足集群中存活的節點數必須要超過總節點數的半數才能繼續提供服務的規定,所以昆明的機房是不能繼續提供服務的。上海機房的存活數量為3台,組成了一個只有3個節點的小集群,3>5/2,所以上海的機房能繼續提供服務。
情況二:原來的leader是在昆明的服務器
我們假設原來的leader是在昆明的服務器,那么上海的機房由於和leader斷開,上海的機房會開始重新選舉leader,上海機房的存活數量為3台,組成了一個只有3個節點的小集群,3>5/2,所以上海的機房能繼續提供服務。昆明只剩下兩台服務器,不滿足集群中存活的節點數必須要超過總節點數的半數才能繼續提供服務的規定,昆明機房是不能繼續提供服務。
也就是說,即使出現兩個機房網絡通信斷開的情況,ZK由於集群中存活的節點數必須要超過總節點數的半數才能繼續提供服務這個規定,也只會有一個leader對外服務,不會出現各個機房分選出自己的leader的情況,這樣就避免了腦裂(多個主節點)的問題。
我們設想一下如果沒有集群中存活的節點數必須要超過總節點數的半數才能繼續提供服務這個規定,當出現故障的時候就可能會存在多個leader,就會造成數據不一致,各個機房自己玩自己的,而這是很致命的。
那么為什么一定要是超過半數,不能是等於半數呢?
我們還是以上面的圖來說,如果上海和昆明各有3台服務器,總數是6台服務器。兩個機房網絡斷開的時候,如果是等於半數,就會分選出各自的leader,出現腦裂的問題。
腦裂現象總結
為了避免腦裂的問題,給出了一個規定:集群中存活的節點數必須要超過總節點數的半數才能繼續提供服務,而正是由於這個規定,導致集群中n台和n+1台你的容災能力是一樣的(n為奇數),都只能壞一台。
k8s的一致性算法(consensus algorithm)
k8s使用RAFT作為它的一致性算法,使用該算法的還有etcd等。目的是實現分布式系統所需要的特性。(見下面條目分布式系統的挑戰)
RAFT 算法只能容錯故障節點,並且最大容錯節點數為(n-1)/2
。
分布式系統的挑戰
- 一致性
- 時序性
- 並發性
- 健壯性
有哪些一致性
- 邏輯時間的一致性:決定事件發生的順序
- 互斥性的一致性:訪問資源的所有權
- 協調者的共識:誰是當前的leader
為什么分布式系統需要leader?
分布式系統中很多類任務都需要單個進程(或實例或節點)扮演居中協調的協調者角色(coordinator),比如數據備份管理、組成員通信或原子性提交協議制定等,這個協調者角色就是leader或master。
選舉
在RAFT算法里,有如下的概念
名詞解釋
- term 任期:數字越大表示是越新的任期
- requestVote:當node被索要投票時,如果沒有投給別人就會投給索要的人
比如NodeA的term是1,向term為0的NodeB和NodeC索要投票,此時NodeB和NodeC的term會變成1,一個term內只能投票一次
- log entry: 操作條目日志
- appending entry:追加條目,即集群進行的操作
- 平票情況:平票時,節點會震盪直到有一個leader產生,由於timeout是一個隨機數,所以很少會出現平票
兩個timeout
- election timeout: 競選倒計時,沒有在倒計時前收到leader消息就會轉為candidate
- heartbeat timeout:leader間斷性的發送心跳,表明自己正常
日志復制(log replication)
之所以需要log replication,為了即使leader掛了,剩下的node也可以恢復日志,是一個容錯機制
日志復制過程
- 系統的所有更改現在都通過領導者,每次更改都在節點日志中的添加記錄
- 客戶端發送一個變更請求
- 該日志記錄當前沒有提交,所以不會更新節點的值。
- 要提交記錄,節點首先將其復制到follower節點...
- 然后leader等待,直到大多數節點都記完了這條記錄
- leader得到反饋后,記錄已commit到領導者節點上,並且節點狀態為“ 5 ”
- 然后領導者通知跟隨者該記錄已commit
- 現在,集群已就系統狀態達成共識
要求節點數大於2n的原因
當一個請求進入時,leader會同步到所有node,當大多數node認可時,才會執行commit
所以當5個節點因網絡問題被為2和3時,由於2個節點的集群無法得到大多數節點的認可,因此無法commit
而如果3集群選舉出了新節點,那么可以繼續提供服務,網絡問題修復后,由於3是新選舉出的節點,因此3的term更高,2節點會被同步3節點的信息