好文推荐 | etcd 问题、调优、监控
點擊上方“朱小廝的博客”,選擇“設為星標”
后臺回復"加群",加入新技術
來源:www.xuyasong.com/?p=1983
etcd 原理解析:讀《etcd 技術內幕》這篇文章主要是原理性的內容,本文主要是實踐角度,談談平時用到的一些操作和監控。
高可用
etcd 是基于 raft算法的分布式鍵值數據庫,生來就為集群化而設計的,由于Raft算法在做決策時需要超半數節點的投票,所以etcd集群一般推薦奇數節點,如3、5或者7個節點構成一個集群。
以上是etcd集群部署的基礎概念,但是還需要注意以下問題:
選主過程
etcd 是高可用的,允許部分機器故障,以標準的3 節點etcd 集群,最大容忍1臺機器宕機,下面以最簡單的leader宕機來演示raft 的投票邏輯,以實際的運行日志來驗證并理解。更多的場景可以看之前的原理解析
場景:正常運行的三臺etcd:100、101、102。當前任期為 7,leader 為 101機器。現在使101 宕機
宕機前:101 為 leader,3 個 member
宕機后:102 成為新 leader,2 個 member
過程:
將 101 機器的 etcd 停止,此時只剩 2 臺,但總數為 3
101停止etcd 的運行
102(91d63231b87fadda) 收到消息,發現101(8a4bb0af2f19bd46)心跳超時,于是發起了新一輪選舉,任期為 7+1=8
102(91d63231b87fadda)成為新一任的候選人,然后自己投給了自己,獲得 1 票
102(91d63231b87fadda)發送給 掛掉的101 和 另一個100,希望他們也投給自己
102 肯定收不到 101 的回應,因為 101 已經掛掉
100 (9feab580a25dd270)收到了 102 的拉票消息,因為任期 8 大于當前100機器所處的 7,于是知道是發起了新的一輪選舉,因此回應 101,我給你投票。這里任期term是關鍵,也就是說,100 和 102 誰先感受到 101 宕機,發起投票,誰就是新的 leader,這個也和進程初始的啟動時間有關。
102 獲得了 2 票,一票是自己,一票是 100,超過半數,成為新的 leader。任期為 8
更換完成
必須是奇數節點嗎
etcd官方推薦3、5、7個節點,雖然raft算法也是半數以上投票才能有 leader,但奇數只是推薦,其實偶數也是可以的。如 2、4、8個節點。分情況說明:
1 個節點:就是單實例,沒有集群概念,不做討論
2 個節點:是集群,但沒人會這么配,這里說點廢話:雙節點的etcd能啟動,啟動時也能有主,可以正常提供服務,但是一臺掛掉之后,就選不出主了,因為他只能拿到1票,剩下的那臺也無法提供服務,也就是雙節點無容錯能力,不要使用。
2節點正常運行:
1臺宕機后:
3 節點:標準的3 節點etcd 集群只能容忍1臺機器宕機,掛掉 1 臺的邏輯上邊已經演示過,如果再掛 1 臺,就和 2節點的情形一致了,一直選,一直增加任期,但就是選不出來,服務也就不可用了
4 節點:最大容忍1 臺
5 節點:最大容忍 2 臺
6 節點:最大容忍 2 臺
你會發現偶數節點雖然多了一臺機器,但是容錯能力是一樣的,也就是說,你可以設置偶數節點,但沒增加什么能力,還浪費了一臺機器。同時etcd 是通過復制數據給所有節點來達到一致性,因此偶數的多一臺機器增加不了性能,反而會拉低寫入速度。
機器越多越好嗎
etcd 集群是一個 Raft Group,沒有 shared。所以它的極限有兩部分,一是單機的容量限制,內存和磁盤;二是網絡開銷,每次 Raft 操作需要所有節點參與,每一次寫操作需要集群中大多數節點將日志落盤成功后,Leader 節點才能修改內部狀態機,并將結果返回給客戶端。因此節點越多性能越低,所以擴展很多 etcd 節點是沒有意義的,一般是 3、5、7, 7 個也足夠了。
在 k8s 中一般是3*master機器做高可用,也就是 3節點的 etcd。也有人將 etcd獨立于 k8s集群之外,來更好地擴展 etcd 集群,或者根據 k8s 的資源來拆分 etcd,如 events 放在單獨的 etcd 集群中。不同的副本數視業務規模而定,3,5,7 都可以。
腦裂問題
集群化的軟件總會提到腦裂問題,如ElasticSearch、Zookeeper集群,腦裂就是同一個集群中的不同節點,對于集群的狀態有了不一樣的理解。
etcd 中有沒有腦裂問題?答案是:沒有
The majority side becomes the available cluster and the minority side is unavailable; there is no “split-brain” in etcd.以網絡分區導致腦裂為例,一開始有5個節點, Node 5 為 Leader
由于出現網絡故障,124 成為一個分區,35 成為一個分區, Node 5 的 leader 任期還沒結束的一段時間內,仍然認為自己是當前leader,但是此時另外一邊的分區,因為124無法連接 5,于是選出了新的leader 1,網絡分區形成。
35分區是否可用?如果寫入了1而讀取了 5,是否會讀取舊數據(stale read)?
答:35分區屬于少數派,被認為是異常節點,無法執行寫操作。寫入 1 的可以成功,并在網絡分區恢復后,35 因為任期舊,會自動成為 follower,異常期間的新數據也會從 1 同步給 35。
而 5 的讀請求也會失敗,etcd 通過ReadIndex、Lease read保證線性一致讀,即節點5在處理讀請求時,首先需要與集群多數節點確認自己依然是Leader并查詢 commit index,5做不到多數節點確認,因此讀失敗。
因此 etcd 不存在腦裂問題。線性一致讀的內容下面會提到。
etcd 是強一致性嗎
是強一致性,讀和寫都可以保證線性一致,關于一致性的分析可以看?這篇文章
線性一致讀
線性一致性讀需要在所有節點走一遍確認,查詢速度會有所降低,要開啟線性一致性讀,在不同的 client是有所區別的:
v2 版本:通過 sdk訪問時,quorum=true 的時候讀取是線性一致的,通過etcdctl訪問時,該參數默認為true。
v3 版本:通過 sdk訪問時,WithSerializable=true 的時候讀取是線性一致的,通過etcdctl訪問時consistency=“l”表示線性(默認為 l,非線性為 s)
為了保證線性一致性讀,早期的 etcd(_etcd v3.0 _)對所有的讀寫請求都會走一遍 Raft 協議來滿足強一致性。然而通常在現實使用中,讀請求占了 etcd 所有請求中的絕大部分,如果每次讀請求都要走一遍 raft 協議落盤,etcd 性能將非常差。
因此在 etcd v3.1 版本中優化了讀請求(PR#6275),使用的方法滿足一個簡單的策略:每次讀操作時記錄此時集群的 commit index,當狀態機的 apply index 大于或者等于 commit index 時即可返回數據。由于此時狀態機已經把讀請求所要讀的 commit index 對應的日志進行了 apply 操作,符合線性一致讀的要求,便可返回此時讀到的結果。
部署
介紹下 etcd 的完整安裝過程。下載 etcd3.4 的 release 包
生成證書
1.ca-config.json
創建用來生成 CA 文件的 JSON 配置文件,這個文件后面會被各種組件使用,包括了證書過期時間的配置,expiry字段
{"signing": {"default": {"expiry": "87600h"},"profiles": {"demo": {"usages": ["signing","key encipherment","server auth","client auth"],"expiry": "87600h"}}}}2.ca-csr.json
創建用來生成 CA 證書簽名請求(CSR)的 JSON 配置文件
{"CN": "demo","key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","ST": "BeiJing","L": "BeiJing","O": "demo","OU": "cloudnative"}]}3.生成基礎 ca 證書
cfssl gencert -initca ca-csr.json | cfssljson -bare ca執行后會生成三個文件:
ca.csr:證書簽名請求,一般用于提供給證書頒發機構,自簽就不需要了
ca.pem:證書,公共證書
ca-key.pem:CA密鑰
生成 etcd 證書
增加etcd-csr.json文件,ip 需要填寫三臺 etcd 機器的 ip
{"CN": "demo","hosts": ["127.0.0.1","ip1","ip2","ip3"],"key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","ST": "BeiJing","L": "BeiJing","O": "demo","OU": "cloudnative"}]}這里的hosts字段中指定了授權使用該證書的IP和域名列表,因為現在要生成的證書需要被etcd集群各個節點使用,所以這里指定了各個節點的IP
生成證書:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=jpaas etcd-csr.json | cfssljson -bare etcd創建etcd 的 CA 證書:這里需要4 個文件
etcd-csr.json:etcd的證書配置
ca.pem:基礎公鑰
ca-key.pem:基礎私鑰
ca-config.json:配置文件,如過期時間
執行后會生成三個文件:
etcd.csr
etcd.pem
etcd-key.pem
在一臺機器上做證書生成,生成后將這三個文件拷貝到其他幾臺機器。
部署集群
etcd 啟動配置示例
./etcd \ --name=etcd-0 \ --client-cert-auth=true \ --cert-file=/etc/etcd/ssl/etcd.pem \ --key-file=/etc/etcd/ssl/etcd-key.pem \ --peer-cert-file=/etc/etcd/ssl/etcd.pem \ --peer-key-file=/etc/etcd/ssl/etcd-key.pem \ --trusted-ca-file=/etc/etcd/ssl/ca.pem \ --peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \ --initial-advertise-peer-urls https://100.0.0.0:2380 \--listen-peer-urls https://100.0.0.0:2380 \--listen-client-urls https://100.0.0.0:2379,https://127.0.0.1:2379 \--advertise-client-urls https://100.0.0.0:2379 \--initial-cluster-token etcd-cluster \ --initial-cluster etcd-0=https://100.0.0.0:2380,etcd-1=https://100.0.0.1:2380,etcd-2=https://100.0.0.2:2380 \--initial-cluster-state new \ --quota-backend-bytes=8589934592 \ --auto-compaction-retention=10 \ --enable-pprof=true \ --data-dir=/var/lib/etcdetcdctl 命令
因為我們的 etcd 配置了證書,所有的命令都要帶上證書訪問,如:
ETCDCTL_API=3 ./etcdctl --endpoints=https://0:2379,https://1:2379,https://2:2379 --cacert /etc/etcd/ssl/ca.pem --cert /etc/etcd/ssl/etcd.pem --key /etc/etcd/ssl/etcd-key.pem endpoint status --write-out=tableetcd 版本為 3.4,可以ETCDCTL_API=3,或ETCDCTL_API=2,默認情況下用的就是v3了,可以不用聲明ETCDCTL_API
證書太長就不寫了,以下命令均為無證書版:
version: 查看版本
member list: 查看節點狀態,learner 情況
endpoint status: 節點狀態,leader 情況
endpoint health: 健康狀態與耗時
alarm list: 查看警告,如存儲滿時會切換為只讀,產生 alarm
alarm disarm:清除所有警告
set app demo: 寫入
get app: 獲取
update app demo1:更新
rm app: 刪除
mkdir demo 創建文件夾
rmdir dir 刪除文件夾
backup 備份
compaction:壓縮
defrag:整理碎片
watch key 監測 key 變化
get / –prefix –keys-only: 查看所有 key
–write-out= tables,可以用表格形式輸出更清晰,注意有些輸出并不支持tables
注意,member list并沒有展示 leader 信息,展示的是 learner,learner的含義后面會解釋
參數配置
版本建議使用 3.4 及以上,3.4存儲容量做了提升,降低了讀寫延遲。
etcd 的配置參數有很多,如果你覺得自己的etcd遇到了瓶頸,先不要急著提 issue 改代碼,先看下這些參數的含義,也許調一下配置就能解決。
etcd 的配置遇到按照功能來劃分:
代理功能
etcd gateway
etcd grpc-proxy
每個訪問 etcd 的應用都要有 etcd 集群的 endpoints。如果在同一臺服務器上的多個應用訪問同一個 etcd 集群,大家都得配置一樣的endpoints。如果這個時候 etcd 集群更換了集群或者 ip,每個應用都需要更新它的終端列表,這種重新配置是繁瑣且容易出錯的。
這里提一下,etcd 的 client 使用的是 grpc 訪問,client會根據傳入的 endpoints 做客戶端負載均衡。
etcd gateway就是一個典型的轉發代理,屏蔽掉后面的endpoints 信息。不過需要注意的是,etcd gateway在 TCP 層,不支持 https 類型的 endpoints。
成員配置
–data-dir: 數據目錄
–snapshot-count: 最大快照次數,默認10萬
–heartbeat-interval: 心跳周期默認 100ms
–election-timeout: 選舉超時1s
–max-snapshots: 最大保留快照數,默認 5 個
–quota-backend-bytes: DB 數據大小,比如 10G,50G。
–auto-compaction-retention: 自動壓縮,默認為 0 不開啟,k8s中 apiserver會開啟這個壓縮,5 分鐘一次。如果你的 etcd 還被其他人使用,這里也可以設置下時間
–enable-pprof: 開啟pprof分析
–metrics: 默認為basic模式,extensive代表暴露histogram類型 metric
–log-level: 日志等級。info, warn, error, panic, or fatal
證書配置
--client-cert-auth=true \ --cert-file=/etc/etcd/ssl/etcd.pem \ --key-file=/etc/etcd/ssl/etcd-key.pem \ --peer-cert-file=/etc/etcd/ssl/etcd.pem \ --peer-key-file=/etc/etcd/ssl/etcd-key.pem \ --trusted-ca-file=/etc/etcd/ssl/ca.pem \ --peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \集群配置
--peer-trusted-ca-file=/etc/etcd/ssl/ca.pem \ --initial-advertise-peer-urls https://100.0.0.0:2380 \--listen-peer-urls https://100.0.0.0:2380 \--listen-client-urls https://100.0.0.0:2379,https://127.0.0.1:2379 \--advertise-client-urls https://100.0.0.0:2379 \--initial-cluster-token etcd-cluster \ --initial-cluster etcd-0=https://100.0.0.0:2380,etcd-1=https://100.0.0.1:2380,etcd-2=https://100.0.0.2:2380 \--initial-cluster-state new \配置調優
一般情況下,etcd 默認模式不會有什么問題,影響 etcd 的因素一般是網絡和存儲延時,尤其是跨地域、跨機房的集群。
網絡延遲
因為 leader 和 member 之間有頻繁的心跳和數據復制,因此網絡擁塞影響會很大,當然長時間失敗會無響應會導致 etcd 集群不可用。一般是將 etcd 集群規劃在一個地域或一個機房內,并且使用tc提高帶寬和優先級。
心跳間隔
etcd 的一致性協議依賴兩個時間參數。
–heartbeat-interval:心跳間隔,即 leader 通知member 并保證自己 leader 地位的心跳,默認是 100ms,這個應該設置為節點間的 RTT 時間。
–election-timeout:選舉超時時間,即 member 多久沒有收到 leader 的回應,就開始自己競選 leader,默認超時時間為 1s
默認值有可能不滿足你的需求,如你的網絡延遲較高,RTT 大于 100,就應該按真實延遲來,比如這個 issue,官方文檔也對心跳的設置給了詳細的解釋和配置建議:https://github.com/etcd-io/etcd/blob/master/Documentation/tuning.md
如果心跳間隔太短,則 etcd 將發送不必要的消息,從而增加 CPU 和網絡資源的使用。另一方面,心跳間隔過長會導致選舉超時。較高的選舉超時時間需要更長的時間來檢測領導者失敗。測量往返時間(RTT)的最簡單方法是使用PING。
磁盤 IO
除了網絡延遲,磁盤 IO 也嚴重影響 etcd 的穩定性, etcd需要持久化數據,對磁盤速度很敏感,強烈建議對 ETCD 的數據掛 SSD。
另外,要確認機器上沒有其他高 IO 操作,否則會影響 etcd 的 fsync,導致 etcd 丟失心跳,leader更換等。一般磁盤有問題時,報錯的關鍵字類似于:
took too long (1.483848046s) to executeetcdserver: failed to send out heartbeat on time磁盤 IO 可以通過監控手段提前發現,并預防這類問題的出現
快照
etcd的存儲分為內存存儲和持久化(硬盤)存儲兩部分,內存中的存儲除了順序化的記錄下所有用戶對節點數據變更的記錄外,還會對用戶數據進行索引、建堆等方便查詢的操作。而持久化則使用預寫式日志(WAL:Write Ahead Log)進行記錄存儲。
在WAL的體系中,所有的數據在提交之前都會進行日志記錄。在etcd的持久化存儲目錄中,有兩個子目錄。一個是WAL,存儲著所有事務的變化記錄;另一個則是snapshot,用于存儲某一個時刻etcd所有目錄的數據。通過WAL和snapshot相結合的方式,etcd可以有效的進行數據存儲和節點故障恢復等操作。
既然有了WAL實時存儲了所有的變更,為什么還需要snapshot呢?隨著使用量的增加,WAL存儲的數據會暴增,為了防止磁盤很快就爆滿,etcd默認每10000條記錄做一次snapshot,經過snapshot以后的WAL文件就可以刪除。而通過API可以查詢的歷史etcd操作默認為1000條。
客戶端優化
etcd 的客戶端應該避免一些頻繁操作或者大對象操作,如:
put 時避免大 value,精簡再精簡(例如 k8s 中 crd 使用)
避免創建頻繁變化的 kv(例如 k8s 中 node 信息匯報),如 node-lease
避免創建大量 lease,盡量選擇復用(例如 k8s 中 event 數據管理)
合理利用 apiserver 中的緩存,避免大量請求打到 etcd上,如集群異常恢復后大量 pod同步
其他
你可能還看到過lease revoke 、boltdb、內存優化等方式,這些已經合入了最新的 etcd3.4版本,因此選擇最新的 release 版本也是提高穩定性的一種方式。
壓縮機制
Etcd作為 KV 存儲,會為每個 key 都保留歷史版本,比如用于發布回滾、配置歷史等。
對 demo 寫入值為 101,然后更為為 102,103。-w json 可以輸出這次寫入的 revision
etcdctl put demo 101 -w json etcdctl put demo 102 -w json etcdctl put demo 103 -w json返回類似:{"header":{"cluster_id":4871617780647557296,"member_id":3135801277950388570,"revision":434841,"raft_term":2}}取值:
etcdctl get demo 默認 --rev=0即最新值=103如果要拿到歷史值,需要制定 rev 版本 etcdctl get demo --rev=434841,得到 102觀察 key的變化:
etcdctl watch foo --rev=0歷史版本越多,存儲空間越大,性能越差,直到etcd到達空間配額限制的時候,etcd的寫入將會被禁止變為只讀,影響線上服務,因此這些歷史版本需要進行壓縮。
數據壓縮并不是清理現有數據,只是對給定版本之前的歷史版本進行清理,清理后數據的歷史版本將不能訪問,但不會影響現有最新數據的訪問。
手動壓縮
etcdctl compact 5。 在 5 之前的所有版本都會被壓縮,不可訪問如果 etcdctl get --rev=4 demo,會報錯Error: rpc error: code = 11 desc = etcdserver: mvcc: required revision has been compacted手動操作畢竟繁瑣,Etcd提供了啟動參數 “–auto-compaction-retention” 支持自動壓縮 key 的歷史版本,以小時為單位
etcd --auto-compaction-retention=1 代表 1 小時壓縮一次v3.3之上的版本有這樣一個規則:
如果配置的值小于1小時,那么就嚴格按照這個時間來執行壓縮;如果配置的值大于1小時,會每小時執行壓縮,但是采樣還是按照保留的版本窗口依然按照用戶指定的時間周期來定。
k8s api-server支持定期執行壓縮操作,其參數里面有這樣的配置:
– etcd-compaction-interval 即默認 5 分鐘一次你可以在 etcd 中看到這樣的壓縮日志,5 分鐘一次:
Apr 25 11:05:20 etcd[2195]: store.index: compact 433912Apr 25 11:05:20 etcd[2195]: finished scheduled compaction at 433912 (took 1.068846ms)Apr 25 11:10:20 etcd[2195]: store.index: compact 434487Apr 25 11:10:20 etcd[2195]: finished scheduled compaction at 434487 (took 1.019571ms)Apr 25 11:15:20 etcd[2195]: store.index: compact 435063Apr 25 11:15:20 etcd[2195]: finished scheduled compaction at 435063 (took 1.659541ms)Apr 25 11:20:20 etcd[2195]: store.index: compact 435637Apr 25 11:20:20 etcd[2195]: finished scheduled compaction at 435637 (took 1.676035ms)Apr 25 11:25:20 etcd[2195]: store.index: compact 436211Apr 25 11:25:20 etcd[2195]: finished scheduled compaction at 436211 (took 1.17725ms)碎片整理
進行壓縮操作之后,舊的revision被清理,會產生內部的碎片,內部碎片是指空閑狀態的,能被etcd使用但是仍然消耗存儲空間的磁盤空間,去碎片化實際上是將存儲空間還給文件系統。
# defrag命令默認只對本機有效 etcdctl defrag# 如果帶參數--endpoints,可以指定集群中的其他節點也做整理 etcdctl defrag --endpoints如果etcd沒有運行,可以直接整理目錄中db的碎片
etcdctl defrag --data-dir <path-to-etcd-data-dir>碎片整理會阻塞對etcd的讀寫操作,因此偶爾一次大量數據的defrag最好逐臺進行,以免影響集群穩定性。
etcdctl執行后的返回?Finished defragmenting etcd member[https://127.0.0.1:2379]
存儲空間
Etcd 的存儲配額可保證集群操作的可靠性。如果沒有存儲配額,那么 Etcd 的性能就會因為存儲空間的持續增長而嚴重下降,甚至有耗完集群磁盤空間導致不可預測集群行為的風險。一旦其中一個節點的后臺數據庫的存儲空間超出了存儲配額,Etcd 就會觸發集群范圍的告警,并將集群置于接受讀 key 和刪除 key 的維護模式。只有在釋放足夠的空間和消除后端數據庫的碎片之后,清除存儲配額告警,集群才能恢復正常操作。
啟動 etcd 時。–quota-backend-bytes 默認為 2G,2G 一般情況下是不夠用的,
你可以通過 etcdctl endpoint status 命令來查看當前的存儲使用量
在 3.4 版本中,etcd 的存儲容量得到了提高,你可以設置 100G 的存儲空間,當然并不是越大越好,key 存儲過多性能也會變差,根據集群規模適當調整。
另外,–max-request-bytes 限制了請求的大小,默認值是1572864,即1.5M。在某些場景可能會出現請求過大導致無法寫入的情況,可以調大到10485760即10M。
如果遇到空間不足,可以這樣操作:
# 獲取當前版本號 $ rev=$(ETCDCTL_API=3 etcdctl endpoint status --write-out="json" | egrep -o '"revision":[0-9]*' | egrep -o '[0-9]*')# 壓縮所有舊版本 $ ETCDCTL_API=3 etcdctl compact $rev# 去碎片化 $ ETCDCTL_API=3 etcdctl defrag # 取消警報 $ ETCDCTL_API=3 etcdctl alarm disarm # 測試通過 $ ETCDCTL_API=3 etcdctl put key0 1234快照備份
etcd可以定期做備份、以保證數據更好的持久化。通過加載備份數據,etcd可以將集群恢復到具有已知良好狀態的時間點。
使用命令etcdctl:
etcdctl snapshot save backup.dbetcdctl --write-out=table snapshot status backup.db+----------+----------+------------+------------+| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |+----------+----------+------------+------------+| fe01cf57 | 10 | 7 | 2.1 MB |+----------+----------+------------+------------+learner 角色
learner 是 etcd 3.4 版本中增加的新角色,類似于 zookeeper 的 observer, 不參與 raft 投票選舉。通過這個新角色的引入,降低了加入新節點時給老集群的額外壓力,增強了集群的穩定性。除此之外還可以使用它作為集群的熱備或服務一些讀請求。
舉例,如果 etcd集群需要加入一個新節點,新加入的 etcd 成員因為沒有任何數據,因此需要從 leader 那里同步數據,直到趕上領導者的日志為止。這樣就會導致 leader 的網絡過載,導致 leader 和 member 之間的心跳可能阻塞。然后就開始了新的leader選舉,也就是說,具有新成員的集群更容易受到領導人選舉的影響。領導者的選舉以及隨后向新成員的更新都容易導致一段時間的群集不可用,這種是不符合預期,風險也是很大的。
因此為了解決這個問題,raft 4.2.1 論文中介紹了一種新的節點角色:Learner。加入集群的節點不參與投票選舉,只接收 leader 的 replication message,直到與 leader 保持同步為止。
learner 在網絡分區等場景下的處理,可以詳細參考:https://etcd.io/docs/v3.3.12/learning/learner/
具體操作:
# 增加一個節點作為learner member add --learner# 當learner的日志趕上了leader的進度時,將learner提升為有投票權的成員,然后該成員將計入法定人數 member promoteetcd server 會驗證 promote 請求以確保真實在提升之前,learner僅充當備用節點,leader無法轉移給learner。learner拒絕客戶端讀寫(客戶端平衡器不應將請求路由到learner)
另外,etcd限制了集群可以擁有的learner總數,并避免了日志復制導致領導者過載。learner永遠不會自我提升。
etcd client v3
Etcd client v3是基于grpc實現的,而grpc又是基于http2.0實現的,借用了很多 http2的優勢如二進制通訊、多路復用等,因此整體上借用grpc的框架做地址管理、連接管理、負載均衡等,而底層對每個Etcd的server只需維持一個http2.0連接。
Etcd client v3實現了grpc中的Resolver接口,用于Etcd server地址管理。當client初始化或者server集群地址發生變更(可以配置定時刷新地址)時,Resolver解析出新的連接地址,通知grpc ClientConn來響應變更。
client v3的原理解析可以看這篇文章:https://www.jianshu.com/p/281b80ae619b
我們是用etcd client做應用的選主操作,可以看下這篇
這里提一下,最早的時候以為 kubernetes 中的 scheduler、controller-manager是基于 etcd 做選主的,client拿來直接用很方便。后來發現不是,kubernetes 是用搶占 endpoint 資源的方式實現選主邏輯,不依賴外部 etcd,這么想來也合理,嚴格來講,etcd 不是kubernetes的東西,不應該有太多依賴。
k8s 中 scheduler 的選主邏輯可以看這篇文章
問題排查
列幾個常遇到的 etcd 問題,后面監控部分會提到如何監測、預防這類問題
一個節點宕機
一個節點宕機,并不會影響整個集群的正常工作,慢慢修復。
移出該節點:etcdctl member remove xx
修復機器問題,刪除舊的數據目錄,重新啟動 etcd 服務
因為 etcd 的證書需要簽入所有節點 ip,因此這里的節點不能更改 ip,否則要全部重簽證書,重啟服務
重啟啟動 etcd 時,需要將配置中的 cluster_state改為:existing,因為是加入已有集群,不能用 new
加入 memeber:etcdctl member add xxx –peer-urls=https://x.x.x.x:2380
驗證:etcdctl endpoint status
遷移數據
如果你的集群需要更換所有的機器,包括更換 IP,那就得通過快照恢復的方式了
使用 etcdctl snapshot save 來保存現有數據,新集群更換后,使用 restore 命令恢復數據,在執行快照時會產生一個 hash 值,來標記快照內容后面恢復時用于校驗,如果你是直接復制的數據文件,可以–skip-hash-check 跳過這個檢查。
遷移集群會更換證書和端點,因此一定會影響上層服務,在遷移之前一定要做好新舊切換,如 apiserver 分批升級(會有部分數據不一致)、避免服務宕機時間過長等
failed to send out heartbeat on time
這個前面已經提過,大概率是因為磁盤性能不足,導致心跳失敗,更換 SSD 或者排查機器上高 IO 的進程
詳細可以查看這個:https://github.com/etcd-io/etcd/blob/master/Documentation/faq.md#what-does-the-etcd-warning-failed-to-send-out-heartbeat-on-time-mean
request ... took too long to execute?這類報錯也是同理
mvcc: database space exceeded
存儲空間不足,參考上面提到的清理和恢復步驟,或者提高存儲空間
endpoints問題
盡量不要使用lb 作為 etcd endpoints 配置,etcd client 是 grpc 訪問,請使用默認的 全量list ,客戶端做負載均衡的方式。詳細內容可以參考 grpc 負載均衡場景解析
監控
etcd 默認以/metrics的 path 暴露了監控數據,數據為 prometheus 標準格式。
通過 metric 數據可以配置出如下面板,一般我們關心的數據,或者說需要配置報警的內容:
是否有 leader:集群就不可用了
leader 更換次數:一定時間內頻率過高一般是有問題,且leader 更換會影響到上層服務
rpc 請求速率:即 qps,可以評估當前負載
db 總大小:用于評估數據量、壓縮策略等
磁盤讀寫延遲:這個很關鍵,延遲過高會導致集群出現問題
后記
etcd 可以很簡單,畢竟只是 KV 存儲,也可以很復雜,代表了云原生時代分布式存儲的基石,本文中的內容只是工作中的問題描述,淺嘗輒止,不足之處,歡迎指正。
參考
https://ms2008.github.io/2019/12/04/etcd-rumor/
ReadIndex:https://zhuanlan.zhihu.com/p/31050303
LeaseRead:https://zhuanlan.zhihu.com/p/31118381
線性一致讀:https://zhengyinyong.com/post/etcd-linearizable-read-implementation/
https://juejin.im/post/5d843b995188257e8e46e25d
https://skyao.io/learning-etcd3/documentation/op-guide/gateway.html
https://github.com/etcd-io/etcd/issues/7522
https://github.com/etcd-io/etcd/blob/master/Documentation/learning/design-learner.md
想知道更多?掃描下面的二維碼關注我
后臺回復”加群“獲取公眾號專屬群聊入口
當當618圖書優惠活動,每滿100-50,我這里還有一批“實付滿200再減30”的優惠碼TEGNC6?,囤書薅羊毛再走一波~~(使用時間:5月18~6月1日,使用渠道:當當小程序或當當APP)
【原創系列 | 精彩推薦】
Paxos、Raft不是一致性算法嘛?
越說越迷糊的CAP
分布式事務科普——初識篇
分布式事務科普——終結篇
面試官居然問我Raft為什么會叫做Raft!
面試官給我挖坑:URI中的//有什么用
面試官給我挖坑:a[i][j]和a[j][i]有什么區別?
面試官給我挖坑:單機并發TCP連接數到底有多少?
網關Zuul科普
網關Spring Cloud?Gateway科普
Nginx架構原理科普
OpenResty概要及原理科普
微服務網關 Kong 科普
云原生網關Traefik科普
點個在看少個 bug?????
總結
以上是生活随笔為你收集整理的好文推荐 | etcd 问题、调优、监控的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 这是我看过关于 volatile 最好的
- 下一篇: JAVA 泛型中的通配符 T,E,K,V