ETCD 问题、调优、监控
點擊上方“朱小廝的博客”,選擇“設(shè)為星標(biāo)”
后臺回復(fù)"書",獲取
后臺回復(fù)“k8s”,可領(lǐng)取k8s資料
來源:r6d.cn/ac6KT
高可用
etcd 是基于 raft算法的分布式鍵值數(shù)據(jù)庫,生來就為集群化而設(shè)計的,由于Raft算法在做決策時需要超半數(shù)節(jié)點的投票,所以etcd集群一般推薦奇數(shù)節(jié)點,如3、5或者7個節(jié)點構(gòu)成一個集群。
以上是etcd集群部署的基礎(chǔ)概念,但是還需要注意以下問題:
選主過程
etcd 是高可用的,允許部分機(jī)器故障,以標(biāo)準(zhǔn)的3 節(jié)點etcd 集群,最大容忍1臺機(jī)器宕機(jī),下面以最簡單的leader宕機(jī)來演示raft 的投票邏輯,以實際的運行日志來驗證并理解。更多的場景可以看之前的原理解析
場景:正常運行的三臺etcd:100、101、102。當(dāng)前任期為 7,leader 為 101機(jī)器?,F(xiàn)在使101 宕機(jī)
宕機(jī)前:101 為 leader,3 個 member
宕機(jī)后:102 成為新 leader,2 個 member
過程:
將 101 機(jī)器的 etcd 停止,此時只剩 2 臺,但總數(shù)為 3
101停止etcd 的運行
102(91d63231b87fadda) 收到消息,發(fā)現(xiàn)101(8a4bb0af2f19bd46)心跳超時,于是發(fā)起了新一輪選舉,任期為 7+1=8
102(91d63231b87fadda)成為新一任的候選人,然后自己投給了自己,獲得 1 票
102(91d63231b87fadda)發(fā)送給 掛掉的101 和 另一個100,希望他們也投給自己
102 肯定收不到 101 的回應(yīng),因為 101 已經(jīng)掛掉
100 (9feab580a25dd270)收到了 102 的拉票消息,因為任期 8 大于當(dāng)前100機(jī)器所處的 7,于是知道是發(fā)起了新的一輪選舉,因此回應(yīng) 101,我給你投票。這里任期term是關(guān)鍵,也就是說,100 和 102 誰先感受到 101 宕機(jī),發(fā)起投票,誰就是新的 leader,這個也和進(jìn)程初始的啟動時間有關(guān)。
102 獲得了 2 票,一票是自己,一票是 100,超過半數(shù),成為新的 leader。任期為 8
更換完成
必須是奇數(shù)節(jié)點嗎
etcd官方推薦3、5、7個節(jié)點,雖然raft算法也是半數(shù)以上投票才能有 leader,但奇數(shù)只是推薦,其實偶數(shù)也是可以的。如 2、4、8個節(jié)點。分情況說明:
1 個節(jié)點:就是單實例,沒有集群概念,不做討論
2 個節(jié)點:是集群,但沒人會這么配,這里說點廢話:雙節(jié)點的etcd能啟動,啟動時也能有主,可以正常提供服務(wù),但是一臺掛掉之后,就選不出主了,因為他只能拿到1票,剩下的那臺也無法提供服務(wù),也就是雙節(jié)點無容錯能力,不要使用。
2節(jié)點正常運行:
1臺宕機(jī)后:
3 節(jié)點:標(biāo)準(zhǔn)的3 節(jié)點etcd 集群只能容忍1臺機(jī)器宕機(jī),掛掉 1 臺的邏輯上邊已經(jīng)演示過,如果再掛 1 臺,就和 2節(jié)點的情形一致了,一直選,一直增加任期,但就是選不出來,服務(wù)也就不可用了
4 節(jié)點:最大容忍1 臺
5 節(jié)點:最大容忍 2 臺
6 節(jié)點:最大容忍 2 臺
你會發(fā)現(xiàn)偶數(shù)節(jié)點雖然多了一臺機(jī)器,但是容錯能力是一樣的,也就是說,你可以設(shè)置偶數(shù)節(jié)點,但沒增加什么能力,還浪費了一臺機(jī)器。同時etcd 是通過復(fù)制數(shù)據(jù)給所有節(jié)點來達(dá)到一致性,因此偶數(shù)的多一臺機(jī)器增加不了性能,反而會拉低寫入速度。
機(jī)器越多越好嗎
etcd 集群是一個 Raft Group,沒有 shared。所以它的極限有兩部分,一是單機(jī)的容量限制,內(nèi)存和磁盤;二是網(wǎng)絡(luò)開銷,每次 Raft 操作需要所有節(jié)點參與,每一次寫操作需要集群中大多數(shù)節(jié)點將日志落盤成功后,Leader 節(jié)點才能修改內(nèi)部狀態(tài)機(jī),并將結(jié)果返回給客戶端。因此節(jié)點越多性能越低,所以擴(kuò)展很多 etcd 節(jié)點是沒有意義的,一般是 3、5、7, 7 個也足夠了。
在 k8s 中一般是3*master機(jī)器做高可用,也就是 3節(jié)點的 etcd。也有人將 etcd獨立于 k8s集群之外,來更好地擴(kuò)展 etcd 集群,或者根據(jù) k8s 的資源來拆分 etcd,如 events 放在單獨的 etcd 集群中。不同的副本數(shù)視業(yè)務(wù)規(guī)模而定,3,5,7 都可以。
腦裂問題
集群化的軟件總會提到腦裂問題,如ElasticSearch、Zookeeper集群,腦裂就是同一個集群中的不同節(jié)點,對于集群的狀態(tài)有了不一樣的理解。
etcd 中有沒有腦裂問題?答案是:沒有
The majority side becomes the available cluster and the minority side is unavailable; there is no “split-brain” in etcd.以網(wǎng)絡(luò)分區(qū)導(dǎo)致腦裂為例,一開始有5個節(jié)點, Node 5 為 Leader
由于出現(xiàn)網(wǎng)絡(luò)故障,124 成為一個分區(qū),35 成為一個分區(qū), Node 5 的 leader 任期還沒結(jié)束的一段時間內(nèi),仍然認(rèn)為自己是當(dāng)前l(fā)eader,但是此時另外一邊的分區(qū),因為124無法連接 5,于是選出了新的leader 1,網(wǎng)絡(luò)分區(qū)形成。
35分區(qū)是否可用?如果寫入了1而讀取了 5,是否會讀取舊數(shù)據(jù)(stale read)?
答:35分區(qū)屬于少數(shù)派,被認(rèn)為是異常節(jié)點,無法執(zhí)行寫操作。寫入 1 的可以成功,并在網(wǎng)絡(luò)分區(qū)恢復(fù)后,35 因為任期舊,會自動成為 follower,異常期間的新數(shù)據(jù)也會從 1 同步給 35。
而 5 的讀請求也會失敗,etcd 通過ReadIndex、Lease read保證線性一致讀,即節(jié)點5在處理讀請求時,首先需要與集群多數(shù)節(jié)點確認(rèn)自己依然是Leader并查詢 commit index,5做不到多數(shù)節(jié)點確認(rèn),因此讀失敗。
因此 etcd 不存在腦裂問題。線性一致讀的內(nèi)容下面會提到。
etcd 是強(qiáng)一致性嗎
是強(qiáng)一致性,讀和寫都可以保證線性一致,關(guān)于一致性的分析可以看?這篇文章
線性一致讀
線性一致性讀需要在所有節(jié)點走一遍確認(rèn),查詢速度會有所降低,要開啟線性一致性讀,在不同的 client是有所區(qū)別的:
v2 版本:通過 sdk訪問時,quorum=true 的時候讀取是線性一致的,通過etcdctl訪問時,該參數(shù)默認(rèn)為true。
v3 版本:通過 sdk訪問時,WithSerializable=true 的時候讀取是線性一致的,通過etcdctl訪問時consistency=“l(fā)”表示線性(默認(rèn)為 l,非線性為 s)
為了保證線性一致性讀,早期的 etcd(_etcd v3.0 _)對所有的讀寫請求都會走一遍 Raft 協(xié)議來滿足強(qiáng)一致性。然而通常在現(xiàn)實使用中,讀請求占了 etcd 所有請求中的絕大部分,如果每次讀請求都要走一遍 raft 協(xié)議落盤,etcd 性能將非常差。
因此在 etcd v3.1 版本中優(yōu)化了讀請求(PR#6275),使用的方法滿足一個簡單的策略:每次讀操作時記錄此時集群的 commit index,當(dāng)狀態(tài)機(jī)的 apply index 大于或者等于 commit index 時即可返回數(shù)據(jù)。由于此時狀態(tài)機(jī)已經(jīng)把讀請求所要讀的 commit index 對應(yīng)的日志進(jìn)行了 apply 操作,符合線性一致讀的要求,便可返回此時讀到的結(jié)果。
部署
介紹下 etcd 的完整安裝過程。下載 etcd3.4 的 release 包
生成證書
1.ca-config.json
創(chuàng)建用來生成 CA 文件的 JSON 配置文件,這個文件后面會被各種組件使用,包括了證書過期時間的配置,expiry字段
{"signing": {"default": {"expiry": "87600h"},"profiles": {"demo": {"usages": ["signing","key encipherment","server auth","client auth"],"expiry": "87600h"}}}}2.ca-csr.json
創(chuàng)建用來生成 CA 證書簽名請求(CSR)的 JSON 配置文件
{"CN": "demo","key": {"algo": "rsa","size": 2048},"names": [{"C": "CN","ST": "BeiJing","L": "BeiJing","O": "demo","OU": "cloudnative"}]}3.生成基礎(chǔ) ca 證書
cfssl gencert -initca ca-csr.json | cfssljson -bare ca執(zhí)行后會生成三個文件:
ca.csr:證書簽名請求,一般用于提供給證書頒發(fā)機(jī)構(gòu),自簽就不需要了
ca.pem:證書,公共證書
ca-key.pem:CA密鑰
生成 etcd 證書
增加etcd-csr.json文件,ip 需要填寫三臺 etcd 機(jī)器的 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字段中指定了授權(quán)使用該證書的IP和域名列表,因為現(xiàn)在要生成的證書需要被etcd集群各個節(jié)點使用,所以這里指定了各個節(jié)點的IP
生成證書:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=jpaas etcd-csr.json | cfssljson -bare etcd創(chuàng)建etcd 的 CA 證書:這里需要4 個文件
etcd-csr.json:etcd的證書配置
ca.pem:基礎(chǔ)公鑰
ca-key.pem:基礎(chǔ)私鑰
ca-config.json:配置文件,如過期時間
執(zhí)行后會生成三個文件:
etcd.csr
etcd.pem
etcd-key.pem
在一臺機(jī)器上做證書生成,生成后將這三個文件拷貝到其他幾臺機(jī)器。
部署集群
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,默認(rèn)情況下用的就是v3了,可以不用聲明ETCDCTL_API
證書太長就不寫了,以下命令均為無證書版:
version: 查看版本
member list: 查看節(jié)點狀態(tài),learner 情況
endpoint status: 節(jié)點狀態(tài),leader 情況
endpoint health: 健康狀態(tài)與耗時
alarm list: 查看警告,如存儲滿時會切換為只讀,產(chǎn)生 alarm
alarm disarm:清除所有警告
set app demo: 寫入
get app: 獲取
update app demo1:更新
rm app: 刪除
mkdir demo 創(chuàng)建文件夾
rmdir dir 刪除文件夾
backup 備份
compaction:壓縮
defrag:整理碎片
watch key 監(jiān)測 key 變化
get / –prefix –keys-only: 查看所有 key
–write-out= tables,可以用表格形式輸出更清晰,注意有些輸出并不支持tables
注意,member list并沒有展示 leader 信息,展示的是 learner,learner的含義后面會解釋
參數(shù)配置
版本建議使用 3.4 及以上,3.4存儲容量做了提升,降低了讀寫延遲。
etcd 的配置參數(shù)有很多,如果你覺得自己的etcd遇到了瓶頸,先不要急著提 issue 改代碼,先看下這些參數(shù)的含義,也許調(diào)一下配置就能解決。
etcd 的配置遇到按照功能來劃分:
代理功能
etcd gateway
etcd grpc-proxy
每個訪問 etcd 的應(yīng)用都要有 etcd 集群的 endpoints。如果在同一臺服務(wù)器上的多個應(yīng)用訪問同一個 etcd 集群,大家都得配置一樣的endpoints。如果這個時候 etcd 集群更換了集群或者 ip,每個應(yīng)用都需要更新它的終端列表,這種重新配置是繁瑣且容易出錯的。
這里提一下,etcd 的 client 使用的是 grpc 訪問,client會根據(jù)傳入的 endpoints 做客戶端負(fù)載均衡。
etcd gateway就是一個典型的轉(zhuǎn)發(fā)代理,屏蔽掉后面的endpoints 信息。不過需要注意的是,etcd gateway在 TCP 層,不支持 https 類型的 endpoints。
成員配置
–data-dir: 數(shù)據(jù)目錄
–snapshot-count: 最大快照次數(shù),默認(rèn)10萬
–heartbeat-interval: 心跳周期默認(rèn) 100ms
–election-timeout: 選舉超時1s
–max-snapshots: 最大保留快照數(shù),默認(rèn) 5 個
–quota-backend-bytes: DB 數(shù)據(jù)大小,比如 10G,50G。
–auto-compaction-retention: 自動壓縮,默認(rèn)為 0 不開啟,k8s中 apiserver會開啟這個壓縮,5 分鐘一次。如果你的 etcd 還被其他人使用,這里也可以設(shè)置下時間
–enable-pprof: 開啟pprof分析
–metrics: 默認(rèn)為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 \配置調(diào)優(yōu)
一般情況下,etcd 默認(rèn)模式不會有什么問題,影響 etcd 的因素一般是網(wǎng)絡(luò)和存儲延時,尤其是跨地域、跨機(jī)房的集群。
網(wǎng)絡(luò)延遲
因為 leader 和 member 之間有頻繁的心跳和數(shù)據(jù)復(fù)制,因此網(wǎng)絡(luò)擁塞影響會很大,當(dāng)然長時間失敗會無響應(yīng)會導(dǎo)致 etcd 集群不可用。一般是將 etcd 集群規(guī)劃在一個地域或一個機(jī)房內(nèi),并且使用tc提高帶寬和優(yōu)先級。
心跳間隔
etcd 的一致性協(xié)議依賴兩個時間參數(shù)。
–heartbeat-interval:心跳間隔,即 leader 通知member 并保證自己 leader 地位的心跳,默認(rèn)是 100ms,這個應(yīng)該設(shè)置為節(jié)點間的 RTT 時間。
–election-timeout:選舉超時時間,即 member 多久沒有收到 leader 的回應(yīng),就開始自己競選 leader,默認(rèn)超時時間為 1s
默認(rèn)值有可能不滿足你的需求,如你的網(wǎng)絡(luò)延遲較高,RTT 大于 100,就應(yīng)該按真實延遲來,比如這個 issue,官方文檔也對心跳的設(shè)置給了詳細(xì)的解釋和配置建議:https://github.com/etcd-io/etcd/blob/master/Documentation/tuning.md
如果心跳間隔太短,則 etcd 將發(fā)送不必要的消息,從而增加 CPU 和網(wǎng)絡(luò)資源的使用。另一方面,心跳間隔過長會導(dǎo)致選舉超時。較高的選舉超時時間需要更長的時間來檢測領(lǐng)導(dǎo)者失敗。測量往返時間(RTT)的最簡單方法是使用PING。
磁盤 IO
除了網(wǎng)絡(luò)延遲,磁盤 IO 也嚴(yán)重影響 etcd 的穩(wěn)定性, etcd需要持久化數(shù)據(jù),對磁盤速度很敏感,強(qiáng)烈建議對 ETCD 的數(shù)據(jù)掛 SSD。
另外,要確認(rèn)機(jī)器上沒有其他高 IO 操作,否則會影響 etcd 的 fsync,導(dǎo)致 etcd 丟失心跳,leader更換等。一般磁盤有問題時,報錯的關(guān)鍵字類似于:
took too long (1.483848046s) to executeetcdserver: failed to send out heartbeat on time磁盤 IO 可以通過監(jiān)控手段提前發(fā)現(xiàn),并預(yù)防這類問題的出現(xiàn)
快照
etcd的存儲分為內(nèi)存存儲和持久化(硬盤)存儲兩部分,內(nèi)存中的存儲除了順序化的記錄下所有用戶對節(jié)點數(shù)據(jù)變更的記錄外,還會對用戶數(shù)據(jù)進(jìn)行索引、建堆等方便查詢的操作。而持久化則使用預(yù)寫式日志(WAL:Write Ahead Log)進(jìn)行記錄存儲。
在WAL的體系中,所有的數(shù)據(jù)在提交之前都會進(jìn)行日志記錄。在etcd的持久化存儲目錄中,有兩個子目錄。一個是WAL,存儲著所有事務(wù)的變化記錄;另一個則是snapshot,用于存儲某一個時刻etcd所有目錄的數(shù)據(jù)。通過WAL和snapshot相結(jié)合的方式,etcd可以有效的進(jìn)行數(shù)據(jù)存儲和節(jié)點故障恢復(fù)等操作。
既然有了WAL實時存儲了所有的變更,為什么還需要snapshot呢?隨著使用量的增加,WAL存儲的數(shù)據(jù)會暴增,為了防止磁盤很快就爆滿,etcd默認(rèn)每10000條記錄做一次snapshot,經(jīng)過snapshot以后的WAL文件就可以刪除。而通過API可以查詢的歷史etcd操作默認(rèn)為1000條。
客戶端優(yōu)化
etcd 的客戶端應(yīng)該避免一些頻繁操作或者大對象操作,如:
put 時避免大 value,精簡再精簡(例如 k8s 中 crd 使用)
避免創(chuàng)建頻繁變化的 kv(例如 k8s 中 node 信息匯報),如 node-lease
避免創(chuàng)建大量 lease,盡量選擇復(fù)用(例如 k8s 中 event 數(shù)據(jù)管理)
合理利用 apiserver 中的緩存,避免大量請求打到 etcd上,如集群異?;謴?fù)后大量 pod同步
其他
你可能還看到過lease revoke 、boltdb、內(nèi)存優(yōu)化等方式,這些已經(jīng)合入了最新的 etcd3.4版本,因此選擇最新的 release 版本也是提高穩(wěn)定性的一種方式。
壓縮機(jī)制
Etcd作為 KV 存儲,會為每個 key 都保留歷史版本,比如用于發(fā)布回滾、配置歷史等。
對 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 默認(rèn) --rev=0即最新值=103如果要拿到歷史值,需要制定 rev 版本 etcdctl get demo --rev=434841,得到 102觀察 key的變化:
etcdctl watch foo --rev=0歷史版本越多,存儲空間越大,性能越差,直到etcd到達(dá)空間配額限制的時候,etcd的寫入將會被禁止變?yōu)橹蛔x,影響線上服務(wù),因此這些歷史版本需要進(jìn)行壓縮。
數(shù)據(jù)壓縮并不是清理現(xiàn)有數(shù)據(jù),只是對給定版本之前的歷史版本進(jìn)行清理,清理后數(shù)據(jù)的歷史版本將不能訪問,但不會影響現(xiàn)有最新數(shù)據(jù)的訪問。
手動壓縮
etcdctl compact 5。 在 5 之前的所有版本都會被壓縮,不可訪問如果 etcdctl get --rev=4 demo,會報錯Error: rpc error: code = 11 desc = etcdserver: mvcc: required revision has been compacted手動操作畢竟繁瑣,Etcd提供了啟動參數(shù) “–auto-compaction-retention” 支持自動壓縮 key 的歷史版本,以小時為單位
etcd --auto-compaction-retention=1 代表 1 小時壓縮一次v3.3之上的版本有這樣一個規(guī)則:
如果配置的值小于1小時,那么就嚴(yán)格按照這個時間來執(zhí)行壓縮;如果配置的值大于1小時,會每小時執(zhí)行壓縮,但是采樣還是按照保留的版本窗口依然按照用戶指定的時間周期來定。
k8s api-server支持定期執(zhí)行壓縮操作,其參數(shù)里面有這樣的配置:
– etcd-compaction-interval 即默認(rèn) 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)碎片整理
進(jìn)行壓縮操作之后,舊的revision被清理,會產(chǎn)生內(nèi)部的碎片,內(nèi)部碎片是指空閑狀態(tài)的,能被etcd使用但是仍然消耗存儲空間的磁盤空間,去碎片化實際上是將存儲空間還給文件系統(tǒng)。
# defrag命令默認(rèn)只對本機(jī)有效 etcdctl defrag# 如果帶參數(shù)--endpoints,可以指定集群中的其他節(jié)點也做整理 etcdctl defrag --endpoints如果etcd沒有運行,可以直接整理目錄中db的碎片
etcdctl defrag --data-dir <path-to-etcd-data-dir>碎片整理會阻塞對etcd的讀寫操作,因此偶爾一次大量數(shù)據(jù)的defrag最好逐臺進(jìn)行,以免影響集群穩(wěn)定性。
etcdctl執(zhí)行后的返回?Finished defragmenting etcd member[https://127.0.0.1:2379]
存儲空間
Etcd 的存儲配額可保證集群操作的可靠性。如果沒有存儲配額,那么 Etcd 的性能就會因為存儲空間的持續(xù)增長而嚴(yán)重下降,甚至有耗完集群磁盤空間導(dǎo)致不可預(yù)測集群行為的風(fēng)險。一旦其中一個節(jié)點的后臺數(shù)據(jù)庫的存儲空間超出了存儲配額,Etcd 就會觸發(fā)集群范圍的告警,并將集群置于接受讀 key 和刪除 key 的維護(hù)模式。只有在釋放足夠的空間和消除后端數(shù)據(jù)庫的碎片之后,清除存儲配額告警,集群才能恢復(fù)正常操作。
啟動 etcd 時。–quota-backend-bytes 默認(rèn)為 2G,2G 一般情況下是不夠用的,
你可以通過 etcdctl endpoint status 命令來查看當(dāng)前的存儲使用量
在 3.4 版本中,etcd 的存儲容量得到了提高,你可以設(shè)置 100G 的存儲空間,當(dāng)然并不是越大越好,key 存儲過多性能也會變差,根據(jù)集群規(guī)模適當(dāng)調(diào)整。
另外,–max-request-bytes 限制了請求的大小,默認(rèn)值是1572864,即1.5M。在某些場景可能會出現(xiàn)請求過大導(dǎo)致無法寫入的情況,可以調(diào)大到10485760即10M。
如果遇到空間不足,可以這樣操作:
# 獲取當(dāng)前版本號 $ 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可以定期做備份、以保證數(shù)據(jù)更好的持久化。通過加載備份數(shù)據(jù),etcd可以將集群恢復(fù)到具有已知良好狀態(tài)的時間點。
使用命令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 投票選舉。通過這個新角色的引入,降低了加入新節(jié)點時給老集群的額外壓力,增強(qiáng)了集群的穩(wěn)定性。除此之外還可以使用它作為集群的熱備或服務(wù)一些讀請求。
舉例,如果 etcd集群需要加入一個新節(jié)點,新加入的 etcd 成員因為沒有任何數(shù)據(jù),因此需要從 leader 那里同步數(shù)據(jù),直到趕上領(lǐng)導(dǎo)者的日志為止。這樣就會導(dǎo)致 leader 的網(wǎng)絡(luò)過載,導(dǎo)致 leader 和 member 之間的心跳可能阻塞。然后就開始了新的leader選舉,也就是說,具有新成員的集群更容易受到領(lǐng)導(dǎo)人選舉的影響。領(lǐng)導(dǎo)者的選舉以及隨后向新成員的更新都容易導(dǎo)致一段時間的群集不可用,這種是不符合預(yù)期,風(fēng)險也是很大的。
因此為了解決這個問題,raft 4.2.1 論文中介紹了一種新的節(jié)點角色:Learner。加入集群的節(jié)點不參與投票選舉,只接收 leader 的 replication message,直到與 leader 保持同步為止。
learner 在網(wǎng)絡(luò)分區(qū)等場景下的處理,可以詳細(xì)參考:https://etcd.io/docs/v3.3.12/learning/learner/
具體操作:
# 增加一個節(jié)點作為learner member add --learner# 當(dāng)learner的日志趕上了leader的進(jìn)度時,將learner提升為有投票權(quán)的成員,然后該成員將計入法定人數(shù) member promoteetcd server 會驗證 promote 請求以確保真實在提升之前,learner僅充當(dāng)備用節(jié)點,leader無法轉(zhuǎn)移給learner。learner拒絕客戶端讀寫(客戶端平衡器不應(yīng)將請求路由到learner)
另外,etcd限制了集群可以擁有的learner總數(shù),并避免了日志復(fù)制導(dǎo)致領(lǐng)導(dǎo)者過載。learner永遠(yuǎn)不會自我提升。
etcd client v3
Etcd client v3是基于grpc實現(xiàn)的,而grpc又是基于http2.0實現(xiàn)的,借用了很多 http2的優(yōu)勢如二進(jìn)制通訊、多路復(fù)用等,因此整體上借用grpc的框架做地址管理、連接管理、負(fù)載均衡等,而底層對每個Etcd的server只需維持一個http2.0連接。
Etcd client v3實現(xiàn)了grpc中的Resolver接口,用于Etcd server地址管理。當(dāng)client初始化或者server集群地址發(fā)生變更(可以配置定時刷新地址)時,Resolver解析出新的連接地址,通知grpc ClientConn來響應(yīng)變更。
client v3的原理解析可以看這篇文章:https://www.jianshu.com/p/281b80ae619b
我們是用etcd client做應(yīng)用的選主操作,可以看下這篇
這里提一下,最早的時候以為 kubernetes 中的 scheduler、controller-manager是基于 etcd 做選主的,client拿來直接用很方便。后來發(fā)現(xiàn)不是,kubernetes 是用搶占 endpoint 資源的方式實現(xiàn)選主邏輯,不依賴外部 etcd,這么想來也合理,嚴(yán)格來講,etcd 不是kubernetes的東西,不應(yīng)該有太多依賴。
k8s 中 scheduler 的選主邏輯可以看這篇文章
問題排查
列幾個常遇到的 etcd 問題,后面監(jiān)控部分會提到如何監(jiān)測、預(yù)防這類問題
一個節(jié)點宕機(jī)
一個節(jié)點宕機(jī),并不會影響整個集群的正常工作,慢慢修復(fù)。
移出該節(jié)點:etcdctl member remove xx
修復(fù)機(jī)器問題,刪除舊的數(shù)據(jù)目錄,重新啟動 etcd 服務(wù)
因為 etcd 的證書需要簽入所有節(jié)點 ip,因此這里的節(jié)點不能更改 ip,否則要全部重簽證書,重啟服務(wù)
重啟啟動 etcd 時,需要將配置中的 cluster_state改為:existing,因為是加入已有集群,不能用 new
加入 memeber:etcdctl member add xxx –peer-urls=https://x.x.x.x:2380
驗證:etcdctl endpoint status
遷移數(shù)據(jù)
如果你的集群需要更換所有的機(jī)器,包括更換 IP,那就得通過快照恢復(fù)的方式了
使用 etcdctl snapshot save 來保存現(xiàn)有數(shù)據(jù),新集群更換后,使用 restore 命令恢復(fù)數(shù)據(jù),在執(zhí)行快照時會產(chǎn)生一個 hash 值,來標(biāo)記快照內(nèi)容后面恢復(fù)時用于校驗,如果你是直接復(fù)制的數(shù)據(jù)文件,可以–skip-hash-check 跳過這個檢查。
遷移集群會更換證書和端點,因此一定會影響上層服務(wù),在遷移之前一定要做好新舊切換,如 apiserver 分批升級(會有部分?jǐn)?shù)據(jù)不一致)、避免服務(wù)宕機(jī)時間過長等
failed to send out heartbeat on time
這個前面已經(jīng)提過,大概率是因為磁盤性能不足,導(dǎo)致心跳失敗,更換 SSD 或者排查機(jī)器上高 IO 的進(jìn)程
詳細(xì)可以查看這個: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
存儲空間不足,參考上面提到的清理和恢復(fù)步驟,或者提高存儲空間
endpoints問題
盡量不要使用lb 作為 etcd endpoints 配置,etcd client 是 grpc 訪問,請使用默認(rèn)的 全量list ,客戶端做負(fù)載均衡的方式。詳細(xì)內(nèi)容可以參考 grpc 負(fù)載均衡場景解析
監(jiān)控
etcd 默認(rèn)以/metrics的 path 暴露了監(jiān)控數(shù)據(jù),數(shù)據(jù)為 prometheus 標(biāo)準(zhǔn)格式。
通過 metric 數(shù)據(jù)可以配置出如下面板,一般我們關(guān)心的數(shù)據(jù),或者說需要配置報警的內(nèi)容:
是否有 leader:集群就不可用了
leader 更換次數(shù):一定時間內(nèi)頻率過高一般是有問題,且leader 更換會影響到上層服務(wù)
rpc 請求速率:即 qps,可以評估當(dāng)前負(fù)載
db 總大小:用于評估數(shù)據(jù)量、壓縮策略等
磁盤讀寫延遲:這個很關(guān)鍵,延遲過高會導(dǎo)致集群出現(xiàn)問題
后記
etcd 可以很簡單,畢竟只是 KV 存儲,也可以很復(fù)雜,代表了云原生時代分布式存儲的基石,本文中的內(nèi)容只是工作中的問題描述,淺嘗輒止,不足之處,歡迎指正。
參考
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
想知道更多?掃描下面的二維碼關(guān)注我
后臺回復(fù)"技術(shù)",加入技術(shù)群
后臺回復(fù)“k8s”,可領(lǐng)取k8s資料
【精彩推薦】
原創(chuàng)|OpenAPI標(biāo)準(zhǔn)規(guī)范
中臺不是萬能藥,關(guān)于中臺的思考和嘗試
ClickHouse到底是什么?為什么如此牛逼!
原來ElasticSearch還可以這么理解
面試官:InnoDB中一棵B+樹可以存放多少行數(shù)據(jù)?
微服務(wù)下如何解耦?對于已經(jīng)緊耦合下如何重構(gòu)?
如何構(gòu)建一套高性能、高可用、低成本的視頻處理系統(tǒng)?
架構(gòu)之道:分離業(yè)務(wù)邏輯和技術(shù)細(xì)節(jié)
星巴克不使用兩階段提交
點個贊+在看,少個 bug?????
總結(jié)
以上是生活随笔為你收集整理的ETCD 问题、调优、监控的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 科普 | 微服务和软件技术栈
- 下一篇: 聊一聊单机、集中式、分布式和云原生存储