㈠ etcd是什麼東西它和ZooKeeper有什麼區別
etcd是一個高可用的鍵值存儲系統,主要用於共享配置和服務發現。etcd是由CoreOS開發並維護的,靈感來自於 ZooKeeper 和 Doozer,它使用Go語言編寫,並通過Raft一致性演算法處理日誌復制以保證強一致性。Raft是一個來自Stanford的新的一致性演算法,適用於分布式系統的日誌復制,Raft通過選舉的方式來實現一致性,在Raft中,任何一個節點都可能成為Leader。Google的容器集群管理系統Kubernetes、開源PaaS平台Cloud Foundry和CoreOS的Fleet都廣泛使用了etcd。
etcd 集群的工作原理基於 raft 共識演算法 (The Raft Consensus Algorithm)。etcd 在 0.5.0 版本中重新實現了 raft 演算法,而非像之前那樣依賴於第三方庫 go-raft 。raft 共識演算法的優點在於可以在高效的解決分布式系統中各個節點日誌內容一致性問題的同時,也使得集群具備一定的容錯能力。即使集群中出現部分節點故障、網路故障等問題,仍可保證其餘大多數節點正確的步進。甚至當更多的節點(一般來說超過集群節點總數的一半)出現故障而導致集群不可用時,依然可以保證節點中的數據不會出現錯誤的結果。
㈡ 筆記本etcd什麼意思
鍵值存儲倉庫,用於配置共享和服務發現。
擴展知識:etcd(讀作 et-see-dee)是一種開源的分布式統一鍵值存儲,用於分布式系統或計算機集群的共享配置、服務發現和的調度協調。etcd 有助於促進更加安全的自動更新,協調向主機調度的工作,並幫助設置容器的覆蓋網路。
etcd 是許多其他項目的核心組件。最值得注意的是,它是 Kubernetes 的首要數據存儲,也是容器編排的實際標准系統。使用 etcd, 雲原生應用可以保持更為一致的運行時間,而且在個別伺服器發生故障時也能正常工作。應用從 etcd 讀取數據並寫入到其中;通過分散配置數據,為節點配置提供冗餘和彈性。
㈢ kubernetes控制平面組件:etcd
--listen-peer-urls
--listen-client-urls
--initial-advertise-peer-urls
--initial-cluster
--initial-cluster-state
--advertise-client-urls
1.code
headless svc, 像DNS RR ClusterIP:None
kubectl -n stg1 get endpoints
client 怎麼訪問:
2.配置文件
3.apply
官方的code有兩個問題
本地訪問
擴容
利用反親和性 分布etcd pod到不同節點
~ ❯❯❯ etcdctl get / --prefix
從 etcd 的架構圖中我們可以看到,etcd 主要分為四個部分。
etcd 目前支持 V2 和 V3 兩個大版本,這兩個版本在實現上有比較大的不同,一方面是對外提供介面的方式,另一方面就是底層的存儲引擎,V2 版本的實例是一個純內存的實現,所有的數據都沒有存儲在磁碟上,而 V3 版本的實例就支持了數據的持久化。
v3默認boltdb
consortium etcd2+mysql
數據默認會存放在 /var/lib/etcd/default/ 目錄。我們會發現數據所在的目錄,會被分為兩個文件夾中,分別是 snap 和 wal目錄。
解決三個問題:節點選舉、日誌復制以及安全性 。
每一個 Raft 集群中都包含多個伺服器,在任意時刻,每一台伺服器只可能處於 Leader 、 Follower 以及 Candidate 三種狀態;在處於正常的狀態時,集群中只會存在一個 Leader 狀態,其餘的伺服器都是 Follower 狀態。
所有的 Follower 節點都是被動的,它們不會主動發出任何的請求 ,只會響應 Leader 和 Candidate 發出的請求。對於每一個用戶的可變操作,都會被路由給 Leader 節點進行處理,除了 Leader 和 Follower 節點之外,Candidate 節點其實只是集群運行過程中的一個臨時狀態。
每一個伺服器都會存儲當前集群的最新任期,它就像是一個單調遞增的邏輯時鍾,能夠同步各個節點之間的狀態,當前節點持有的任期會隨著每一個請求被傳遞到其他的節點上。Raft 協議在每一個任期的開始時都會從一個集群中選出一個節點作為集群的 Leader 節點,這個節點會負責集群中的日誌的復制以及管理工作。
客戶端通過 監聽指定的key可以迅速感知key的變化並作出相應處理 ,watch機制的實現依賴於 資源版本號revision的設計 ,每一次key的更新都會使得revision原子遞增,因此根據不同的版本號revision的對比就可以感知新事件的發生。etcd watch機制有著廣泛的應用,比如利用etcd實現分布式鎖; k8s中監聽各種資源的變化 ,從而實現各種controller邏輯等。
watch機制的實現主要可分為三個部分
client使用 watchClient 的watch介面發起watch請求,與server端建立一個 gRPCStream 連接。
server端會為每個client生成唯一一個watch id,並記錄每個client也就是watcher監聽的key或者key range,通過recvLoop接收client請求,通過sendLoop發送請求,server端只負責收發請求和響應。
主要的實現都放在了watchalbStore層,watchalbStore會監聽key的變化,然後通過syncWatchersLoop和syncVictimsLoop兩個處理流程將key的更新變化包裝成event,通過channel發送給gRPC server。
MVCC(Multiversion Concurrency Control)多版本並發控制機制
場景1:
這就是悲觀鎖
悲觀鎖:悲觀得認為並發事務會沖突,所以要先拿鎖,拿到鎖的作修改操作
場景2
資料庫:寫回磁碟,A寫好了。哎,B和C都是version 13,我咋寫?算了,報錯吧。。
就是樂觀鎖,默認不加鎖,你盡管寫,沖突我認慫!樂觀鎖其實不是鎖,只是相對悲觀鎖來定義,適合讀多寫少。
樂觀鎖:樂觀得認為數據不會沖突,但發生沖突時要能檢測到。
場景3
這就是MVCC,在 MVCC 資料庫中,你更新一個 key-value 數據的時候,它並不會直接覆蓋原數據,而是 新增一個版本來存儲新的數據,每個數據都有一個版本號 ,版本號是一個邏輯時鍾,不會因為伺服器時間的差異而受影響。
MVCC不等於樂觀鎖!
--rev 查的是main
在底層boltdb里,實際分布是這樣的:
底層的key是revision,/奧特曼是用戶key,「他很帥」就是用戶value
刪除
之前有delete動作,但是依然有版本記錄。為什麼?
刪除這個動作,其實etcd是在blotdb里寫了一條,「刪除用戶/奧特曼」
此時有個問題:用戶說我的確刪除了啊,真的不要了!請把空間還給我啊!
回收 compact(壓縮)
etcdctl compact {version}
compact 需要一個版本號。這個版本號就是寫事務遞增的那個版本號,compact 12345,就是說把版本12345以前的 標記刪除了的數據 釋放掉,用戶沒刪除的數據肯定不能回收。
如何壓縮:
注意修改go.mod
Watch
服務發現要解決的也是分布式系統中最常見的問題之一,即在同一個分布式集群中的進程或服務,要如何才能找到對方並建立連接。本質上來說,服務發現就是想要了解集群中是否有進程在監聽 udp 或 tcp 埠,並且通過名字就可以查找和連接。
需要實現的功能;
discover.go
eBay payment
ebay kubernetes 控制面架構
問題
㈣ k8s etcd 與持久化存儲
1、是什麼
2、etcd架構及工作原理
(1) 數據流程
一個用戶的請求發送過來,會經過HTTP Server轉發給store進行具體事務處理,如果涉及到節點的修改,則需要交給raft模塊進行狀態的變更,日誌的記錄,然後再同步給別的etcd節點確認數據提交,最後進行數據提交,再次同步
(2)工作原理
Etcd使用 Raft協議 來維護集群內各個節點狀態的 一致性 。簡單說,ETCD集群是一個分布式系統,由多個節點相互通信構成整體對外服務, 每個節點都存儲了完整的數據 ,並且通過Raft協議保證每個節點維護的數據是一致的
(3) 主要組成部分
(4)etcd集群中的術語
3、k8s中的etcd
(1)etcd在k8s中的作用: etcd在kubernetes集群是用來存放數據並通知變動的
(2)為什麼k8s選擇etcd:
PV 目前支持的類型包括:gcePersistentDisk 、AWSElasticBlockStore 、AzureFile 、AzureDisk 、FC ( Fibre Channel ) 、Flocker、NFS 、iSCSI 、RBD (Rados Block Device )、CephFS 、Cinder、GlusterFS 、V sphere Volume 、Quobyte Volumes 、VMware Photon 、Portwonc
Volumes 、ScaleIO Volumes 和HostPath (僅供單機測試)。
如果某個Pod 想申請某種類型的PY ,則首先需要定義一個PersistentVolurneClaim ( PVC )對象,然後,在Pod 的Volume 定義中引用上述PVC 即可:
㈤ etcd的應用場景
提到etcd很多人第一反應就是一個鍵值存儲倉庫。不過etcd官方文檔的定義卻是這樣的:
etcd作為一個受到ZooKeeper與doozer啟發而催生的項目,除了擁有與之類似的功能外,更專注於以下四點。
接下來將針對剖析一些etcd的經典使用場景,來看看etcd這個基於Raft強一致性演算法的分布式存儲倉庫能給我們帶來哪些幫助。
在分布式系統中「服務發現」也是比較常見的問題:在同一個集群環境中不同的應用或服務,如何能夠找到對方並建立連接,來完成後續的行為。本質上來說,服務發現就是想要知道集群中是否有進程在監聽udp或tcp埠,並能通過名字就可以查找和連接。而要解決服務發現的問題,需要滿足如下三個方面,缺一不可。
來看服務發現對應的具體場景:
在分布式系統中,最適用的一種組件間通信方式就是消息發布與訂閱。即構建一個配置共享中心,數據提供者在這個配置中心發布消息,而消息使用者則訂閱他們關心的主題,一旦主題有消息發布,就會實時通知訂閱者。通過這種方式可以做到分布式系統配置的集中式管理與動態更新。
在場景一中也提到了負載均衡,本文所指的負載均衡均為軟負載均衡。分布式系統中,為了保證服務的高可用以及數據的一致性,通常都會把數據和服務部署多份,以此達到對等服務,即使其中的某一個服務失效了,也不影響使用。由此帶來的壞處是數據寫入性能下降,而好處則是數據訪問時的負載均衡。因為每個對等服務節點上都存有完整的數據,所以用戶的訪問流量就可以分流到不同的機器上。
這里說到的分布式通知與協調,與消息發布和訂閱有些相似。都用到了etcd中的Watcher機制,通過注冊與非同步通知機制,實現分布式環境下不同系統之間的通知與協調,從而對數據變更做到實時處理。實現方式通常是這樣:不同系統都在etcd上對同一個目錄進行注冊,同時設置Watcher觀測該目錄的變化(如果對子目錄的變化也有需要,可以設置遞歸模式),當某個系統更新了etcd的目錄,那麼設置了Watcher的系統就會收到通知,並作出相應處理。
因為etcd使用Raft演算法保持了數據的強一致性,某次操作存儲到集群中的值必然是全局一致的,所以很容易實現分布式鎖。鎖服務有兩種使用方式,一是保持獨占,二是控制時序。
分布式隊列的常規用法與場景五中所描述的分布式鎖的控制時序用法類似,即創建一個先進先出的隊列,保證順序。
另一種比較有意思的實現是在保證隊列達到某個條件時再統一按順序執行。這種方法的實現可以在/queue這個目錄中另外建立一個/queue/condition節點。
通過etcd來進行監控實現起來非常簡單並且實時性強。
這樣就可以第一時間檢測到各節點的健康狀態,以完成集群的監控要求。
另外,使用分布式鎖,可以完成Leader競選。這種場景通常是一些長時間CPU計算或者使用IO操作的機器,只需要競選出的Leader計算或處理一次,就可以把結果復制給其他的Follower。從而避免重復勞動,節省計算資源。
這個的經典場景是搜索系統中建立全量索引。如果每個機器都進行一遍索引的建立,不但耗時而且建立索引的一致性不能保證。通過在etcd的CAS機制同時創建一個節點,創建成功的機器作為Leader,進行索引計算,然後把計算結果分發到其它節點。
etcd實現的這些功能,ZooKeeper都能實現。那麼為什麼要用etcd而非直接使用ZooKeeper呢?
相較之下,ZooKeeper有如下缺點:
而etcd作為一個後起之秀,其優點也很明顯。
最後,etcd作為一個年輕的項目,真正告訴迭代和開發中,這既是一個優點,也是一個缺點。優點是它的未來具有無限的可能性,缺點是無法得到大項目長時間使用的檢驗。然而,目前CoreOS、Kubernetes和CloudFoundry等知名項目均在生產環境中使用了etcd,所以總的來說,etcd值得你去嘗試。
從etcd的架構圖中我們可以看到,etcd主要分為四個部分。
通常,一個用戶的請求發送過來,會經由HTTP Server轉發給Store進行具體的事務處理,如果涉及到節點的修改,則交給Raft模塊進行狀態的變更、日誌的記錄,然後再同步給別的etcd節點以確認數據提交,最後進行數據的提交,再次同步。
㈥ 【K8s 精選】CKA - 管理高可用性 Kubernetes 集群
創建 HA 集群的一般步驟:
● 設置負載均衡器。有許多開源選項可用於負載均衡:HAproxy、Envoy 或來自雲提供商的類似負載均衡器效果很好。
● 在第一個控制平面節點上運行 kubeadm init ,並進行以下修改:
① 創建 kubeadm 配置文件
② 在配置文件中,將 controlPlaneEndpoint 欄位設置為可以訪問負載均衡器的位置。
③ 運行 init,帶有如下 --upload-certs 標志: sudo kubeadm init --config=kubeadm-config.yaml --upload-certs
● kubeadm join –control-plane 在您想要擴展控制平面節點集時隨時運行。控制平面和普通節點可以隨時以任何順序加入。
① 3 台機器作為控制面節點、3 台機器作為工作節點、3 台機器作為外部 etcd 集群(外部 etcd 拓撲方案)
② 在集群中,確保所有計算機之間存在全網路連接(公網或私網)
③ 在所有機器上具有 sudo 許可權
④ 從某台設備通過 ssh 訪問系統中所有節點的能力
⑤ 所有機器上已經安裝 kubeadm 和 kubelet , kubectl 是可選的
每個控制平面節點創建一個本地 etcd 成員(member) 。該 etcd 成員只與該節點的 kube-apiserver 、 kube-controller-manager 、 kube-scheler 實例通信。
堆疊(stacked) etcd 方案,在控制平面設置負載均衡後,自動管理 etcd 的 external 對象下帶有 endpoints 的配置文件。
etcd 分布式數據存儲集群在獨立於控制平面節點的其他節點上運行 。每個控制平面節點都運行 kube-apiserver , kube-scheler 和 kube-controller-manager 實例。 每個 etcd 主機與每個控制平面節點的 kube-apiserver 通信 。
● 利用 kubeadm 創建高可用 etcd 集群
● 配置 SSH 。
● 將以下文件從集群中的任何 etcd 節點復制到第一個控制平面節點:
㈦ kubernetes的master節點和node節點
kubernetes集群中的master節點是集群的控制節點, 負責整個集群的管理和控制。執行的控制命令都是發送給master節點。 Master節點上運行的主要組件如下:
Node節點時kubernetes集群中的工作負責節點,Node上的工作負載由master分配, 當某個Node宕機時,Master會將上面的工作負載轉移到其他節點上去, Node節點上運行的主要組件如下:
上圖為kubernetes中所有組件一起工作時的示意圖,由此我們可以得出以下幾個通信流程,
根據上面節點通信的介紹我們會產生一個疑問, 這個看起來好復雜的樣子。 臣妾看不懂呀。 如果想進一步了解集群中詳細的工作流程請移駕 kubectl創建pod背後發生了什麼 探索背後的秘密
要求結果為所有的 Kubernetes Master 伺服器沒有單點故障,任何一台伺服器當機均不影響Kubernetes的正常工作。
為了實現沒有單點故障的目標,需要為以下幾個組件建立高可用方案:
etcd是Kubernetes當中唯一帶狀態的服務,也是高可用的難點。Kubernetes選用etcd作為它的後端數據存儲倉庫正是看重了其使用分布式架構,沒有單點故障的特性。
雖然單節點的etcd也可以正常運行。但是推薦的部署方案均是採用3個或者5個節點組成etcd集群,供Kubernetes使用。
etcd的高可用基本有三種思路:
一是使用獨立的etcd集群,使用3台或者5台伺服器只運行etcd,獨立維護和升級。甚至可以使用CoreOS的 update-engine 和 locksmith ,讓伺服器完全自主的完成升級。這個etcd集群將作為基石用於構建整個集群。 採用這項策略的主要動機是etcd集群的節點增減都需要顯式的通知集群,保證etcd集群節點穩定可以更方便的用程序完成集群滾動升級,減輕維護負擔。
二是在Kubernetes Master上用static pod的形式來運行etcd,並將多台Kubernetes Master上的etcd組成集群。 在這一模式下,各個伺服器的etcd實例被注冊進了Kubernetes當中,雖然無法直接使用 kubectl 來管理這部分實例,但是監控以及日誌搜集組件均可正常工作。在這一模式運行下的etcd可管理性更強。
三是使用CoreOS提出的 self-hosted etcd方案 ,將本應在底層為Kubernetes提供服務的etcd運行在Kubernetes之上。 實現Kubernetes對自身依賴組件的管理。在這一模式下的etcd集群可以直接使用 etcd-operator 來自動化運維,最符合Kubernetes的使用習慣。
這三種思路均可以實現etcd高可用的目標,但是在選擇過程中卻要根據實際情況做出一些判斷。簡單來講預算充足但保守的項目選方案一, 想一步到位並願意承擔一定風險的項目選方案三。折中一點選方案二。各個方案的優劣以及做選擇過程中的取捨在這里就不詳細展開了,對這塊有疑問的朋友可以私下聯系交流。
apiserver本身是一個無狀態服務,要實現其高可用相對要容易一些,難點在於如何將運行在多台伺服器上的apiserver用一個統一的外部入口暴露給所有Node節點。
說是難點,其實對於這種無狀態服務的高可用,我們在設計業務系統的高可用方案時已經有了相當多的經驗積累。需要注意的是apiserver所使用的SSL證書要包含外部入口的地址,不然Node節點無法正常訪問apiserver。
apiserver的高可用也有三種基本思路:
一是使用外部負載均衡器,不管是使用公有雲提供的負載均衡器服務或是在私有雲中使用 LVS 或者 HaProxy 自建負載均衡器都可以歸到這一類。 負載均衡器是非常成熟的方案,在這里略過不做過多介紹。如何保證負載均衡器的高可用,則是選擇這一方案需要考慮的新問題。
二是在網路層做負載均衡。比如在Master節點上用 BGP 做 ECMP ,或者在Node節點上用 iptables 做NAT都可以實現。採用這一方案不需要額外的外部服務,但是對網路配置有一定的要求。
三是在Node節點上使用反向代理對多個Master做負載均衡。這一方案同樣不需要依賴外部的組件,但是當Master節點有增減時,如何動態配置Node節點上的負載均衡器成為了另外一個需要解決的問題。
從目前各個集群管理工具的選擇來看,這三種模式都有被使用,目前還沒有明確的推薦方案產生。建議在公有雲上的集群多考慮第一種模式,在私有雲環境中由於維護額外的負載均衡器也是一項負擔,建議考慮第二種或是第三種方案。
這兩項服務是Master節點的一部分,他們的高可用相對容易,僅需要運行多份實例即可。這些實例會通過向apiserver中的 Endpoint 加鎖的方式來進行leader election, 當目前拿到leader的實例無法正常工作時,別的實例會拿到鎖,變為新的leader。
嚴格來說kube-dns並不算是Master組件的一部分,因為它是可以跑在Node節點上,並用 Service 向集群內部提供服務的。但在實際環境中, 由於默認配置只運行了一份kube-dns實例,在其升級或是所在節點當機時,會出現集群內部dns服務不可用的情況,嚴重時會影響到線上服務的正常運行。
為了避免故障,請將kube-dns的 replicas 值設為2或者更多,並用 anti-affinity 將他們部署在不同的Node節點上。這項操作比較容易被疏忽,直到出現故障時才發現原來是kube-dns只運行了一份實例導致的故障。
上面介紹了Kubernetes Master各個組件高可用可以採用的策略。其中etcd和kube-apiserver的高可用是整個方案的重點。由於存在多種高可用方案,集群管理員應當根據集群所處環境以及其他限制條件選擇適合的方案。
這種沒有絕對的通用方案,需要集群建設者根據不同的現狀在多個方案中做選擇的情況在Kubernetes集群建設過程中頻頻出現, 也是整個建設過程中最有挑戰的一部分。容器網路方案的選型作為Kubernetes建設過程中需要面對的另外一個大問題也屬於這種情況,今後有機會再來分享這個話題。
在實際建設過程中,在完成了上述四個組件的高可用之後,最好採取實際關機檢驗的方式來驗證高可用方案的可靠性,並根據檢驗的結果不斷調整和優化整個方案。
此外將高可用方案與系統自動化升級方案結合在一起考慮,實現高可用下的系統自動升級,將大大減輕集群的日常運維負擔,值得投入精力去研究。
雖然本篇主要在講Kubernetes Master高可用的方案,但需要指出的是,高可用也並不是必須的,為了實現高可用所付出的代價並不低, 需要有相應的收益來平衡。對於大量的小規模集群來說,業務系統並沒有實現高可用,貿然去做集群的高可用收益有限。這時採用單Master節點的方案,做好etcd的數據備份,不失為理性的選擇。
㈧ 【知識總結】6.服務注冊發現框架比較(Consul/Zookeeper/etcd/Eureka)
服務發現就是服務提供者將自己提供的地址post或者update到服務中介,服務消費者從服務中介那裡get自己想要的服務的地址。
但是有兩個問題:
第一個問題:如果有一個服務提供者宕機,那麼中介的key/value中會有一個不能訪問的地址,該怎麼辦?
心跳機制: 服務提供者需要每隔5秒左右向服務中介匯報存活,服務中介將服務地址和匯報時間記錄在zset數據結構的value和score中。服務中介需要每隔10秒左右檢查zset數據結構,踢掉匯報時間嚴重落後的地址。這樣就可以保證服務列表中地址的有效性。
第二個問題是服務地址變動時如何通知消費者。有兩種解決方案。
第一種是輪詢,消費者每隔幾秒查詢服務列表是否有改變。如果服務地址很多,查詢會很慢。這時候可以引入服務版本號機制,給每個服務提供一個版本號,在服務變動時,遞增這個版本號。消費者只需要輪詢這個版本號的變動即可知道服務列表是否發生了變化。
第二種是採用pubsub。這種方式及時性要明顯好於輪詢。缺點是每個pubsub都會佔用消費者一個線程和一個額外的連接。為了減少對線程和連接的浪費,我們使用單個pubsub廣播全局版本號的變動。所謂全局版本號就是任意服務列表發生了變動,這個版本號都會遞增。接收到版本變動的消費者再去檢查各自的依賴服務列表的版本號是否發生了變動。這種全局版本號也可以用於第一種輪詢方案。
CAP理論
CAP理論是分布式架構中重要理論
關於P的理解,我覺得是在整個系統中某個部分,掛掉了,或者宕機了,並不影響整個系統的運作或者說使用,而可用性是,某個系統的某個節點掛了,但是並不影響系統的接受或者發出請求,CAP 不可能都取,只能取其中2個。原因是
(1)如果C是第一需求的話,那麼會影響A的性能,因為要數據同步,不然請求結果會有差異,但是數據同步會消耗時間,期間可用性就會降低。
(2)如果A是第一需求,那麼只要有一個服務在,就能正常接受請求,但是對與返回結果變不能保證,原因是,在分布式部署的時候,數據一致的過程不可能想切線路那麼快。
(3)再如果,同事滿足一致性和可用性,那麼分區容錯就很難保證了,也就是單點,也是分布式的基本核心,好了,明白這些理論,就可以在相應的場景選取服務注冊與發現了。
平時經常用到的服務發現的產品進行下特性的對比,首先看下結論:
補充:
(1)運維和開發如果是 Java 更熟,也更多 Java 的應用,那毫無疑問應該用 ZK;如果是搞 Go 的,那麼還是 etcd 吧,畢竟有時候遇到問題還是要看源碼的。
(2)在創建一百萬個或更多鍵時,etcd可以比Zookeeper或Consul穩定地提供更好的吞吐量和延遲。此外,它實現了這一目標,只有一半的內存,顯示出更高的效率。但是,還有一些改進的餘地,Zookeeper設法通過etcd提供更好的最小延遲,代價是不可預測的平均延遲。
(3)
一致性協議: etcd 使用 Raft 協議,Zookeeper 使用 ZAB(類PAXOS協議),前者容易理解,方便工程實現;
運維方面:etcd 方便運維,Zookeeper 難以運維;
數據存儲:etcd 多版本並發控制(MVCC)數據模型 , 支持查詢先前版本的鍵值對
項目活躍度:etcd 社區與開發活躍,Zookeeper 感覺已經快死了;
API:etcd 提供 HTTP+JSON, gRPC 介面,跨平台跨語言,Zookeeper 需要使用其客戶端;
訪問安全方面:etcd 支持 HTTPS 訪問,Zookeeper 在這方面缺失;
與 Eureka 有所不同,Apache Zookeeper 在設計時就緊遵CP原則,即任何時候對 Zookeeper 的訪問請求能得到一致的數據結果,同時系統對網路分割具備容錯性,但是 Zookeeper 不能保證每次服務請求都是可達的。
從 Zookeeper 的實際應用情況來看,在使用 Zookeeper 獲取服務列表時,如果此時的 Zookeeper 集群中的 Leader 宕機了,該集群就要進行 Leader 的選舉,又或者 Zookeeper 集群中半數以上伺服器節點不可用(例如有三個節點,如果節點一檢測到節點三掛了 ,節點二也檢測到節點三掛了,那這個節點才算是真的掛了),那麼將無法處理該請求。所以說,Zookeeper 不能保證服務可用性。
當然,在大多數分布式環境中,尤其是涉及到數據存儲的場景,數據一致性應該是首先被保證的,這也是 Zookeeper 設計緊遵CP原則的另一個原因。
但是對於服務發現來說,情況就不太一樣了,針對同一個服務,即使注冊中心的不同節點保存的服務提供者信息不盡相同,也並不會造成災難性的後果。
因為對於服務消費者來說,能消費才是最重要的,消費者雖然拿到可能不正確的服務實例信息後嘗試消費一下,也要勝過因為無法獲取實例信息而不去消費,導致系統異常要好(淘寶的雙十一,京東的618就是緊遵AP的最好參照)。
當master節點因為網路故障與其他節點失去聯系時,剩餘節點會重新進行leader選舉。問題在於,選舉leader的時間太長,30~120s,而且選舉期間整個zk集群都是不可用的,這就導致在選舉期間注冊服務癱瘓。
在雲部署環境下, 因為網路問題使得zk集群失去master節點是大概率事件,雖然服務能最終恢復,但是漫長的選舉事件導致注冊長期不可用是不能容忍的。
Spring Cloud Netflix 在設計 Eureka 時就緊遵AP原則。Eureka是在Java語言上,基於Restful Api開發的服務注冊與發現組件,由Netflix開源。遺憾的是,目前Eureka僅開源到1.X版本,2.X版本已經宣布閉源。
Eureka Server 也可以運行多個實例來構建集群,解決單點問題,但不同於 ZooKeeper 的選舉 leader 的過程,Eureka Server 採用的是Peer to Peer 對等通信。這是一種去中心化的架構,無 master/slave 之分,每一個 Peer 都是對等的。在這種架構風格中,節點通過彼此互相注冊來提高可用性,每個節點需要添加一個或多個有效的 serviceUrl 指向其他節點。每個節點都可被視為其他節點的副本。
在集群環境中如果某台 Eureka Server 宕機,Eureka Client 的請求會自動切換到新的 Eureka Server 節點上,當宕機的伺服器重新恢復後,Eureka 會再次將其納入到伺服器集群管理之中。當節點開始接受客戶端請求時,所有的操作都會在節點間進行復制(replicate To Peer)操作,將請求復制到該 Eureka Server 當前所知的其它所有節點中。
當一個新的 Eureka Server 節點啟動後,會首先嘗試從鄰近節點獲取所有注冊列表信息,並完成初始化。Eureka Server 通過 getEurekaServiceUrls() 方法獲取所有的節點,並且會通過心跳契約的方式定期更新。
默認情況下,如果 Eureka Server 在一定時間內沒有接收到某個服務實例的心跳(默認周期為30秒),Eureka Server 將會注銷該實例(默認為90秒, eureka.instance.lease-expiration-ration-in-seconds 進行自定義配置)。
當 Eureka Server 節點在短時間內丟失過多的心跳時,那麼這個節點就會進入自我保護模式。
Eureka的集群中,只要有一台Eureka還在,就能保證注冊服務可用(保證可用性),只不過查到的信息可能不是最新的(不保證強一致性)。除此之外,Eureka還有一種自我保護機制,如果在15分鍾內超過85%的節點都沒有正常的心跳,那麼Eureka就認為客戶端與注冊中心出現了網路故障,此時會出現以下幾種情況:
Eureka不再從注冊表中移除因為長時間沒有收到心跳而過期的服務;
Eureka仍然能夠接受新服務注冊和查詢請求,但是不會被同步到其它節點上(即保證當前節點依然可用);
當網路穩定時,當前實例新注冊的信息會被同步到其它節點中;
因此,Eureka可以很好的應對因網路故障導致部分節點失去聯系的情況,而不會像zookeeper那樣使得整個注冊服務癱瘓。
Consul 是 HashiCorp 公司推出的開源工具,用於實現分布式系統的服務發現與配置。Consul 使用 Go 語言編寫,因此具有天然可移植性(支持Linux、windows和Mac OS X)。
Consul採用主從模式的設計,使得集群的數量可以大規模擴展,集群間通過RPC的方式調用(HTTP和DNS)。
Consul 內置了服務注冊與發現框架、分布一致性協議實現、健康檢查、Key/Value 存儲、多數據中心方案,不再需要依賴其他工具(比如 ZooKeeper 等),使用起來也較為簡單。
Consul 遵循CAP原理中的CP原則,保證了強一致性和分區容錯性,且使用的是Raft演算法,比zookeeper使用的Paxos演算法更加簡單。雖然保證了強一致性,但是可用性就相應下降了,例如服務注冊的時間會稍長一些,因為 Consul 的 raft 協議要求必須過半數的節點都寫入成功才認為注冊成功 ;在leader掛掉了之後,重新選舉出leader之前會導致Consul 服務不可用。
默認依賴於SDK
Consul本質上屬於應用外的注冊方式,但可以通過SDK簡化注冊流程。而服務發現恰好相反,默認依賴於SDK,但可以通過Consul Template(下文會提到)去除SDK依賴。
Consul Template
Consul,默認服務調用者需要依賴Consul SDK來發現服務,這就無法保證對應用的零侵入性。
所幸通過 Consul Template ,可以定時從Consul集群獲取最新的服務提供者列表並刷新LB配置(比如nginx的upstream),這樣對於服務調用者而言,只需要配置一個統一的服務調用地址即可。
Consul強一致性(C)帶來的是:
Eureka保證高可用(A)和最終一致性:
其他方面,eureka就是個servlet程序,跑在servlet容器中; Consul則是go編寫而成。
etcd是一個採用http協議的分布式鍵值對存儲系統,因其易用,簡單。很多系統都採用或支持etcd作為服務發現的一部分,比如kubernetes。但正事因為其只是一個存儲系統,如果想要提供完整的服務發現功能,必須搭配一些第三方的工具。
比如配合etcd、Registrator、confd組合,就能搭建一個非常簡單而強大的服務發現框架。但這種搭建操作就稍微麻煩了點,尤其是相對consul來說。所以etcd大部分場景都是被用來做kv存儲,比如kubernetes。
etcd 比較多的應用場景是用於服務發現,服務發現 (Service Discovery) 要解決的是分布式系統中最常見的問題之一,即在同一個分布式集群中的進程或服務如何才能找到對方並建立連接。和 Zookeeper 類似,etcd 有很多使用場景,包括:
配置管理
服務注冊發現
選主
應用調度
分布式隊列
分布式鎖
按照官網給出的數據, 在 2CPU,1.8G 內存,SSD 磁碟這樣的配置下,單節點的寫性能可以達到 16K QPS, 而先寫後讀也能達到12K QPS。這個性能還是相當可觀。
etcd 提供了 etcdctl 命令行工具 和 HTTP API 兩種交互方法。etcdctl命令行工具用 go 語言編寫,也是對 HTTP API 的封裝,日常使用起來也更容易。所以這里我們主要使用 etcdctl 命令行工具演示。
(1)注冊中心ZooKeeper、Eureka、Consul 、Nacos對比
https://zhuanlan.hu.com/p/165217227?utm_source=wechat_session
(2)常用的服務發現對比(Consul、zookeeper、etcd、eureka)
https://blog.csdn.net/gaohe7091/article/details/101197107
㈨ ETCD——基礎原理
一個ETCD集群一般由3個或者5個節點組成,兩個quorum一定存在交集,則
即:3個節點容忍1個節點故障,5個節點容忍2個節點故障,以此類推。
首先,所有的數據都保存在B+樹(灰色),當我們指定了版本信息之後,會直接到灰色B+樹中去獲取相關的數據;同時,還有另外一個B+樹,它維護了key和revions的映射關系,查詢key的數據時候,會根據key查詢到revision,再通過revision查詢到相應的key。
etcd 使用 raft 協議來維護集群內各個節點狀態的一致性。簡單說,etcd 集群是一個分布式系統,由多個節點相互通信構成整體對外服務,每個節點都存儲了完整的數據,並且通過 Raft 協議保證每個節點維護的數據是一致的。
每個 etcd 節點都維護了一個狀態機,並且,任意時刻至多存在一個有效的主節點。主節點處理所有來自客戶端寫操作,通過 Raft 協議保證寫操作對狀態機的改動會可靠的同步到其他節點。
etcd 的設計目標是用來存放非頻繁更新的數據,提供可靠的 Watch插件,它暴露了鍵值對的歷史版本,以支持低成本的快照、監控歷史事件。這些設計目標要求它使用一個持久化的、多版本的、支持並發的數據數據模型。
當 etcd 鍵值對的新版本保存後,先前的版本依然存在。從效果上來說,鍵值對是不可變的,etcd 不會對其進行 in-place 的更新操作,而總是生成一個新的數據結構。為了防止歷史版本無限增加,etcd 的存儲支持壓縮(Compact)以及刪除老舊版本。
邏輯視圖
從邏輯角度看,etcd 的存儲是一個扁平的二進制鍵空間,鍵空間有一個針對鍵(位元組字元串)的詞典序索引,因此范圍查詢的成本較低。
鍵空間維護了多個修訂版本(Revisions),每一個原子變動操作(一個事務可由多個子操作組成)都會產生一個新的修訂版本。在集群的整個生命周期中,修訂版都是單調遞增的。修訂版同樣支持索引,因此基於修訂版的范圍掃描也是高效的。壓縮操作需要指定一個修訂版本號,小於它的修訂版會被移除。
一個鍵的一次生命周期(從創建到刪除)叫做 「代 (Generation)」,每個鍵可以有多個代。創建一個鍵時會增加鍵的版本(version),如果在當前修訂版中鍵不存在則版本設置為1。刪除一個鍵會創建一個墓碑(Tombstone),將版本設置為0,結束當前代。每次對鍵的值進行修改都會增加其版本號 — 在同一代中版本號是單調遞增的。
當壓縮時,任何在壓縮修訂版之前結束的代,都會被移除。值在修訂版之前的修改記錄(僅僅保留最後一個)都會被移除。
物理視圖
etcd 將數據存放在一個持久化的 B+ 樹中,處於效率的考慮,每個修訂版僅僅存儲相對前一個修訂版的數據狀態變化(Delta)。單個修訂版中可能包含了 B+ 樹中的多個鍵。
鍵值對的鍵,是三元組(major,sub,type)
鍵值對的值,包含從上一個修訂版的 Delta。B+ 樹 —— 鍵的詞法位元組序排列,基於修訂版的范圍掃描速度快,可以方便的從一個修改版到另外一個的值變更情況查找。
etcd 同時在內存中維護了一個 B 樹索引,用於加速針對鍵的范圍掃描。索引的鍵是物理存儲的鍵面向用戶的映射,索引的值則是指向 B+ 樹修該點的指針。
元數據存儲——Kubernetes
Service Discovery(Name Service)
Distributed Coordination: Leader Election
㈩ etcd工作原理和部署指南
etcd是由CoreOS團隊發的一個分布式一致性的KV存儲系統,可用於服務注冊發現和共享配置,隨著CoreOS和Kubernetes等項目在開源社區日益火熱,它們項目中都用到的etcd組件作為一個高可用強一致性的服務發現存儲倉庫,漸漸為開發人員所關注。在雲計算時代,如何讓服務快速透明地接入到計算集群中,如何讓共享配置信息快速被集群中的所有機器發現,更為重要的是,如何構建這樣一套高可用、安全、易於部署以及響應快速的服務集群,已經成為了迫切需要解決的問題。etcd為解決這類問題帶來了福音,本文將從etcd的應用場景開始,深入解讀etcd的實現方式,以供開發者們更為充分地享用etcd所帶來的便利。
etcd推薦使用奇數作為集群節點個數。因為奇數個節點和其配對的偶數個節點相比,容錯能力相同,卻可以少一個節點。綜合考慮性能和容錯能力,etcd官方文檔推薦的etcd集群大小是3,5,7。由於etcd使用是Raft演算法,每次寫入數據需要有2N+1個節點同意可以寫入數據,所以部分節點由於網路或者其他不可靠因素延遲收到數據更新,但是最終數據會保持一致,高度可靠。隨著節點數目的增加,每次的寫入延遲會相應的線性遞增,除了節點數量會影響寫入數據的延遲,如果節點跟接節點之間的網路延遲,也會導致數據的延遲寫入。
結論:
1.節點數並非越多越好,過多的節點將會導致數據延遲寫入。
2.節點跟節點之間的跨機房,專線之間網路延遲,也將會導致數據延遲寫入。
3.受網路IO和磁碟IO的延遲
4.為了提高吞吐量,etcd通常將多個請求一次批量處理並提交Raft,
5.增加節點,讀性能會提升,寫性能會下降,減少節點,寫性能會提升。
參數說明:
這種方式就是 利用一個已有的 etcd 集群來提供 discovery 服務,從而搭建一個新的 etcd 集群。
假設已有的 etcd 集群的一個訪問地址是: myetcd.local ,那麼我們首先需要在已有 etcd 中創建一個特殊的 key,方法如下:
其中 value=3 表示本集群的大小,即: 有多少集群節點。而 就是用來做 discovery 的 token。
接下來你在 3 個節點上分別啟動 etcd 程序,並加上剛剛的 token。
加 token 的方式同樣也有 命令行參數 和 環境變數 兩種。
命令行參數:
環境變數
以 命令行參數 啟動方式為例:
可以使用etcd附帶的 基準 CLI工具完成基準測試etcd性能。
對於一些基準性能數字,我們考慮具有以下硬體配置的三個成員的etcd集群:
有了這個配置,etcd可以大致寫出:
示例命令是:
可線性讀取請求通過集群成員的法定人數達成一致以獲取最新數據。可序列化的讀取請求比線性讀取要便宜,因為它們由任何單個etcd成員提供,而不是成員法定人數,以換取可能的陳舊數據。etcd可以閱讀:
示例命令是:
我們鼓勵在新環境中首次安裝etcd集群時運行基準測試,以確保集群達到足夠的性能; 群集延遲和吞吐量可能會對較小的環境差異敏感。
以上測試部分翻譯自官方文檔( https://coreos.com/etcd/docs/latest/op-guide/performance.html )