Kubernetes存儲大腦之etcd
本文轉載自微信公眾號「武培軒」,作者武培軒。轉載本文請聯系武培軒公眾號。
etcd 簡介
etcd 是兼具一致性和高可用性的鍵值數據庫,可用于服務發現以及配置中心。ETCD 采用 raft 一致性算法,基于 Go 語言實現??梢宰鳛楸4? Kubernetes 所有集群數據的后臺數據庫,在整個云原生中發揮極其重要的作用。
ectd 版本: v3.4 etcd 文檔地址: https://etcd.io/docs/v3.4/
etcd 在 kubernetes 的架構
etcd存儲著k8s所有的元數據
etcd 中存儲著 k8s 的所有的元數據,至關重要,再次,我們就揭開 etcd 的最佳實踐。
etcd 特點
- 扁平化二進制鍵值空間
- 保留事件歷史記錄,直到壓縮為止
- 訪問舊版本 keys
- 用戶自定義 key 版本歷史壓縮
- 支持范圍查詢
- 帶 limit 參數的分頁支持
- 支持多個范圍查詢的一致性保證
- 通過租約替換 TTL 鍵
- 更高效以及低成本的 keepalive
- 為不同的 TTL key 配置配置相同邏輯的租約
- 通過多對象 Txn 替換 CAS/CAD
- 更加強大和靈活
- 支持多范圍高效 watch
- RPC API 支持完整的 API 集
- 比 JSON/HTTP 更有效
- 額外的 TXN/租約支持
- HTTP API 支持 API 子集。
- 用戶更容易嘗試 etcd
- 用戶更易于編寫簡單的 etcd 應用程序
etcd 運行建議
- 運行的 etcd 集群個數成員為奇數。
- etcd 是一個 leader-based 分布式系統。確保主節點定期向所有從節點發送心跳,以保持集群穩定。
- 確保資源充足。
- 集群的性能和穩定性對網絡和磁盤 IO 非常敏感。任何資源匱乏都會導致心跳超時,從而導致集群的不穩定。不穩定的情況表明沒有選出任何主節點。在這種情況下,集群不能對其當前狀態進行任何更改,這意味著不能調度新的 pod。
- 保持穩定的 etcd 集群對 Kubernetes 集群的穩定性至關重要。因此,請在專用機器或隔離環境上運行 etcd 集群,以滿足所需資源需求。
- 在生產中運行的 etcd 的最低推薦版本是 3.2.10+
- 硬件建議:https://etcd.io/docs/v3.4/op-guide/hardware/
etcd 架構實踐
為了性能和高可用性,在生產中將以多節點集群的方式運行 etcd,并且定期備份。建議在生產中使用五個成員的集群。有關該內容的更多信息,請參閱https://etcd.io/docs/v3.4/faq/#what-is-failure-tolerance。
可以通過靜態成員信息或動態發現的方式配置 etcd 集群。有關集群的詳細信息,請參閱https://etcd.io/docs/v3.4/op-guide/clustering/。
集群規模 | 半數節點 | 容錯節點 |
---|---|---|
1 | 1 | 0 |
2 | 2 | 0 |
3 | 2 | 1 |
4 | 3 | 1 |
5 | 3 | 2 |
6 | 4 | 2 |
7 | 4 | 3 |
8 | 5 | 3 |
9 | 5 | 4 |
etcd 調優指南
本次調優針對于 etcd 本身的參數調優:
1.時間相關參數
在大型 etcd 集群中,由于網絡的復雜性,etcd 本身的分布式共識協議將受到影響,其主要依賴于兩個時間參數:
第一個參數稱為 Heartbeat Interval。領導者將以此頻率通知關注者它仍然是領導者。為了獲得最佳實踐,應圍繞成員之間的往返時間設置參數。默認情況下,etcd 使用 100ms 心跳間隔。
第二個參數是 Election Timeout。此超時時間是指跟隨者節點在嘗試成為領導者之前要等待多長時間而不會聽到心跳信號。默認情況下,etcd 使用 1000ms 選舉超時。
調整這些值是一個權衡。建議心跳間隔的值應介于成員之間的平均往返時間(RTT)的最大值附近,通常約為往返時間的 0.5-1.5 倍。如果心跳間隔太短,etcd 將發送不必要的消息,從而增加 CPU 和網絡資源的使用。另一方面,過高的心跳間隔會導致較高的選舉超時時間。較高的選舉超時時間需要更長的時間才能檢測到領導者失敗。測量往返時間(RTT)的最簡單方法是使用 PING 實用程序。
應該根據心跳間隔和成員之間的平均往返時間來設置選舉超時。選舉超時時間必須至少是往返時間的 10 倍,這樣才能解決網絡中的差異。例如,如果成員之間的往返時間為 10 毫秒,則選舉超時應至少為 100 毫秒。
選舉超時上限為 50000ms(50s),僅在部署全球分布的 etcd 集群時才應使用。
一個集群中所有成員的心跳間隔和選舉超時值應相同。為 etcd 成員設置不同的值可能會破壞集群的穩定性。
以上參數可以通過命令進行調整:
- # Command line arguments:
- $ etcd --heartbeat-interval=100 --election-timeout=500
- # Environment variables:
- $ ETCD_HEARTBEAT_INTERVAL=100 ETCD_ELECTION_TIMEOUT=500 etcd
2.快照
etcd 將所有關鍵更改附加到日志文件。此日志將永遠增長,并且是對鍵所做的每次更改的完整線性歷史記錄。完整的歷史記錄適用于輕度使用的集群,但是頻繁使用的集群將攜帶大量日志。
為了避免有大量日志,etcd 會進行定期快照。這些快照為 etcd 提供了一種通過保存系統當前狀態并刪除舊日志來壓縮日志的方法。
使用 V2 后端創建快照可能會很昂貴,因此僅在對 etcd 進行給定數量的更改后才能創建快照。默認情況下,每 10,000 次更改后將創建快照。如果 etcd 的內存使用量和磁盤使用量過高,請嘗試通過在命令行上設置以下內容來降低快照閾值:
- # Command line arguments:
- $ etcd --snapshot-count=5000
- # Environment variables:
- $ ETCD_SNAPSHOT_COUNT=5000 etcd
3.磁盤
etcd 集群對磁盤延遲非常敏感。由于 etcd 必須將建議持久保存到其日志中,因此其他進程的磁盤活動可能會導致較長的 fsync 延遲。etcd 可能會錯過心跳,從而導致請求超時和臨時領導者丟失。當給予較高的磁盤優先級時,etcd 服務器有時可以與這些進程一起穩定運行。
在 Linux 上,可以使用以下命令配置 etcd 的磁盤優先級 ionice:
- # best effort, highest priority
- $ sudo ionice -c2 -n0 -p `pgrep etcd`
4.網絡 如果 etcd 領導者處理大量并發的客戶端請求,由于網絡擁塞,可能會延遲處理跟隨者對等體請求。這表現為在跟隨者節點上的發送緩沖區錯誤消息:
- dropped MsgProp to 247ae21ff9436b2d since streamMsg's sending buffer is full
- dropped MsgAppResp to 247ae21ff9436b2d since streamMsg's sending buffer is full
通過將 etcd 的對等流量優先于其客戶端流量,可以解決這些錯誤。在 Linux 上,可以使用流量控制機制來確定對等流量的優先級:
- tc qdisc add dev eth0 root handle 1: prio bands 3
- tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip sport 2380 0xffff flowid 1:1
- tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip dport 2380 0xffff flowid 1:1
- tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip sport 2379 0xffff flowid 1:1
- tc filter add dev eth0 parent 1: protocol ip prio 2 u32 match ip dport 2379 0xffff flowid 1:1
5.內存
etcd 默認的存儲大小限制為 2GB,可使用--quota-backend-bytes 標志進行配置。建議在正常環境下使用 8GB 的最大大小,如果配置的值超過該值,etcd 會在啟動時發出警告。
6.請求體
etcd 被設計用于元數據的小鍵值對的處理。較大的請求將工作的同時,可能會增加其他請求的延遲。默認情況下,任何請求的最大大小為 1.5 MiB。這個限制可以通過--max-request-bytesetcd 服務器的標志來配置。
7.key 的歷史記錄壓縮 ETCD 會存儲多版本數據,隨著寫入的主鍵增加,歷史版本將會越來越多,并且 ETCD 默認不會自動清理歷史數據。數據達到 --quota-backend-bytes 設置的配額值時就無法寫入數據,必須要壓縮并清理歷史數據才能繼續寫入。
- --auto-compaction-mode
- --auto-compaction-retention
所以,為了避免配額空間耗盡的問題,在創建集群時候建議默認開啟歷史版本清理 功能。
3.3.0 之前的版本,只能按周期 periodic 來壓縮。比如設置 --auto-compaction-retention=72h,那么就會每 72 小時進行一次數據壓縮。
3.3.0 之后的版本,可以通過 --auto-compaction-mode 設置壓縮模式,可以選擇 revision 或者 periodic 來壓縮數據,默認為 periodic。
etcd 備份
所有 Kubernetes 對象都存儲在 etcd 上。定期備份 etcd 集群數據對于在災難場景(例如丟失所有主節點)下恢復 Kubernetes 集群非常重要。快照文件包含所有 Kubernetes 狀態和關鍵信息。為了保證敏感的 Kubernetes 數據的安全,可以對快照文件進行加密。備份 etcd 集群可以通過兩種方式完成: etcd 內置快照和卷快照。
1.內置快照
etcd 支持內置快照,因此備份 etcd 集群很容易。快照可以從使用 etcdctl snapshot save 命令的活動成員中獲取,也可以通過從 etcd 數據目錄復制 member/snap/db 文件,該 etcd 數據目錄目前沒有被 etcd 進程使用。獲取快照通常不會影響成員的性能。
下面是一個示例,用于獲取 $ENDPOINT 所提供的鍵空間的快照到文件 snapshotdb:
- ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshotdb
- # exit 0
- # verify the snapshot
- ETCDCTL_API=3 etcdctl --write-out=table snapshot status snapshotdb
- +----------+----------+------------+------------+
- | HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
- +----------+----------+------------+------------+
- | fe01cf57 | 10 | 7 | 2.1 MB |
- +----------+----------+------------+------------+
2.卷快照
如果 etcd 運行在支持備份的存儲卷(如 Amazon Elastic Block 存儲)上,則可以通過獲取存儲卷的快照來備份 etcd 數據。
etcd 恢復
etcd 支持從 major.minor 或其他不同 patch 版本的 etcd 進程中獲取的快照進行恢復。還原操作用于恢復失敗的集群的數據。
在啟動還原操作之前,必須有一個快照文件。它可以是來自以前備份操作的快照文件,也可以是來自剩余數據目錄的快照文件。有關從快照文件還原集群的詳細信息和示例,請參閱 etcd 災難恢復文檔。
如果還原的集群的訪問 URL 與前一個集群不同,則必須相應地重新配置 Kubernetes API 服務器。在本例中,使用參數 --etcd-servers=$NEW_ETCD_CLUSTER 而不是參數--etcd-servers=$OLD_ETCD_CLUSTER 重新啟動 Kubernetes API 服務器。用相應的 IP 地址替換 $NEW_ETCD_CLUSTER 和 $OLD_ETCD_CLUSTER。如果在 etcd 集群前面使用負載平衡,則可能需要更新負載均衡器。
如果大多數 etcd 成員永久失敗,則認為 etcd 集群失敗。在這種情況下,Kubernetes 不能對其當前狀態進行任何更改。雖然已調度的 pod 可能繼續運行,但新的 pod 無法調度。在這種情況下,恢復 etcd 集群并可能需要重新配置 Kubernetes API 服務器以修復問題。
注意:
如果集群中正在運行任何 API 服務器,則不應嘗試還原 etcd 的實例。相反,請按照以下步驟還原 etcd:
- 停止 所有 kube-apiserver 實例
- 在所有 etcd 實例中恢復狀態
- 重啟所有 kube-apiserver 實例
我們還建議重啟所有組件(例如 kube-scheduler、kube-controller-manager、kubelet),以確保它們不會 依賴一些過時的數據。請注意,實際中還原會花費一些時間。在還原過程中,關鍵組件將丟失領導鎖并自行重啟。
總結
etcd 為 kubernetes 的存儲基石,想用好 k8s,必須熟悉 etcd,我們才更有信心,以及更好的服務業務,提供更穩定的技術服務。
參考文檔
https://etcd.io/docs/
https://kubernetes.io/zh/docs/tasks/administer-cluster/configure-upgrade-etcd/