Etcd 概述及運維實踐
Etcd 概述
什麼是 Etcd ?
Etcd 是 CoreOS 團隊於 2013 年 6 月發起的開源項目,它的目標是構建一個高可用的分佈式鍵值 (key-value) 數據庫。etcd 內部採用raft
協議作爲一致性算法,Etcd 基於 Go 語言實現。
名字由來,它源於兩個方面,unix 的 “/etc” 文件夾和分佈式系統 (“D”istribute system) 的 D,組合在一起表示 etcd 是用於存儲分佈式配置的信息存儲服務。
Kubernetes 爲什麼用 Etcd ?
2014 年 6 月,Google 的 Kubernetes 項目誕生了,我們前面所討論到 Go 語言編寫、etcd 高可用、Watch 機制、CAS、TTL 等特性正是 Kubernetes 所需要的,它早期的 0.4 版本,使用的正是 etcd v0.2 版本。
Kubernetes 是如何使用 etcd v2 這些特性的呢?舉幾個簡單小例子。
當你使用 Kubernetes 聲明式 API 部署服務的時候,Kubernetes 的控制器通過 etcd Watch 機制,會實時監聽資源變化事件,對比實際狀態與期望狀態是否一致,並採取協調動作使其一致。Kubernetes 更新數據的時候,通過 CAS 機制保證併發場景下的原子更新,並通過對 key 設置 TTL 來存儲 Event 事件,提升 Kubernetes 集羣的可觀測性,基於 TTL 特性,Event 事件 key 到期後可自動刪除。
Kubernetes 項目使用 etcd,除了技術因素也與當時的商業競爭有關。CoreOS 是 Kubernetes 容器生態圈的核心成員之一。
Etcd 版本變化
時間軸圖,總結一下 etcd v1/v2 關鍵特性
然而隨着 Kubernetes 項目不斷髮展,v2 版本的瓶頸和缺陷逐漸暴露,遇到了若干性能和穩定性問題,Kubernetes 社區呼籲支持新的存儲、批評 etcd 不可靠的聲音開始不斷出現。
問題如下
2016 年 6 月,etcd 3.0 誕生,隨後 Kubernetes 1.6 發佈,默認啓用 etcd v3,助力 Kubernetes 支撐 5000 節點集羣規模。
時間軸及重要特性
發展到今天,在 GitHub 上 star 數超過 46K。在 Kubernetes 的業務場景磨鍊下它不斷成長,走向穩定和成熟,成爲技術圈衆所周知的開源產品,而 v3 方案的發佈,也標誌着 etcd 進入了技術成熟期,成爲雲原生時代的首選元數據存儲產品。
基礎架構
你可以看到,按照分層模型,etcd 可分爲 Client 層、API 網絡層、Raft 算法層、邏輯層和存儲層。這些層的功能如下:
-
Client 層:Client 層包括 client v2 和 v3 兩個大版本 API 客戶端庫,提供了簡潔易用的 API,同時支持負載均衡、節點間故障自動轉移,可極大降低業務使用 etcd 複雜度,提升開發效率、服務可用性。
-
API 網絡層:API 網絡層主要包括 client 訪問 server 和 server 節點之間的通信協議。一方面,client 訪問 etcd server 的 API 分爲 v2 和 v3 兩個大版本。v2 API 使用 HTTP/1.x 協議,v3 API 使用 gRPC 協議。同時 v3 通過 etcd grpc-gateway 組件也支持 HTTP/1.x 協議,便於各種語言的服務調用。另一方面,server 之間通信協議,是指節點間通過 Raft 算法實現數據複製和 Leader 選舉等功能時使用的 HTTP 協議。
-
Raft 算法層:Raft 算法層實現了 Leader 選舉、日誌複製、ReadIndex 等核心算法特性,用於保障 etcd 多個節點間的數據一致性、提升服務可用性等,是 etcd 的基石和亮點。
-
功能邏輯層:etcd 核心特性實現層,如典型的 KVServer 模塊、MVCC 模塊、Auth 鑑權模塊、Lease 租約模塊、Compactor 壓縮模塊等,其中 MVCC 模塊主要由 treeIndex 模塊和 boltdb 模塊組成。
-
存儲層:存儲層包含預寫日誌 (WAL) 模塊、快照 (Snapshot) 模塊、boltdb 模塊。其中 WAL 可保障 etcd crash 後數據不丟失,boltdb 則保存了集羣元數據和用戶寫入的數據。
概念術語
-
Raft:etcd 所採用的保證分佈式系統強一致性的算法。
-
Node:一個 Raft 狀態機實例。
-
Member:一個 etcd 實例。它管理着一個 Node,並且可以爲客戶端請求提供服務。
-
Cluster:由多個 Member 構成可以協同工作的 etcd 集羣。
-
Peer:對同一個 etcd 集羣中另外一個 Member 的稱呼。
-
Client:向 etcd 集羣發送 HTTP 請求的客戶端。
-
WAL:預寫式日誌,etcd 用於持久化存儲的日誌格式。
-
snapshot:etcd 防止 WAL 文件過多而設置的快照,存儲 etcd 數據狀態。
-
Proxy:etcd 的一種模式,爲 etcd 集羣提供反向代理服務。
-
Leader:Raft 算法中通過競選而產生的處理所有數據提交的節點。
-
Follower:競選失敗的節點作爲 Raft 中的從屬節點,爲算法提供強一致性保證。
-
Candidate:當 Follower 超過一定時間接收不到 Leader 的心跳時轉變爲 Candidate 開始競選。
-
Term:某個節點成爲 Leader 到下一次競選時間,稱爲一個 Term。
-
Index:數據項編號。Raft 中通過 Term 和 Index 來定位數據。
運維實踐
etcdctl 常用命令
全局參數
ETCD_CA_CERT="/etc/kubernetes/pki/etcd/ca.crt"
ETCD_CERT="/etc/kubernetes/pki/etcd/server.crt"
ETCD_KEY="/etc/kubernetes/pki/etcd/server.key"
HOST_1=https://xxx.xxx.xxx.xxx:2379
使用示例
ETCDCTL_API=3 etcdctl --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" \
--endpoints="${HOST_1}" endpoint status --write-out=table
常用命令
- 鍵值命令
# 增 & 改
put foo bar
# 查
get foo
# 根據前綴查詢
get --prefix "/demo"
# 查詢所有 keys
get --prefix "" --keys-only
# 刪
del foo
# 事務,多個操作合併爲一個事務
txn <<<'mod("key1") > "0"
put key1 "overwrote-key1"
put key1 "created-key1"
put key2 "some extra key"
'
# 壓縮
compaction 1234
# 監聽
watch foo
- 集羣維護命令
# 列出成員
member list
# 端點健康情況
endpoint health
# 端點狀態
endpoint status
# 告警列表
alarm list
# 解除所有告警
alarm disarm
# 碎片整理
defrag
# 創建快照進行備份
snapshot save snapshot.db
# 快照恢復
snapshot restore
# 快照狀態
snapshot status
Etcd 監控
重點監控指標
指標分類
-
健康狀態
-
USE 方法(系統)
-
使用率
-
飽和度
-
錯誤
-
-
RED 方法(應用)
-
請求速率
-
錯誤率
-
延遲
-
使用 kube-prometheus 收集 etcd 指標
http 模式(推薦)
修改--listen-metrics-urls
#- --listen-metrics-urls=http://127.0.0.1:2381
- --listen-metrics-urls=http://127.0.0.1:2381,http://ip:2381
部署
helm install monitoring -n cattle-prometheus --set kubeEtcd.service.port=2381 --set kubeEtcd.service.targetPort=2381 --set prometheusOperator.admissionWebhooks.patch.image.sha=null ./
https 模式
新增 etcd secret
kubectl create secret generic etcd-certs -n cattle-prometheus --from-file=/etc/kubernetes/pki/etcd/ca.crt --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.crt --from-file=/etc/kubernetes/pki/etcd/healthcheck-client.key
部署
helm install monitoring -n cattle-prometheus --set kubeEtcd.serviceMonitor.scheme=https --set kubeEtcd.serviceMonitor.caFile=/etc/prometheus/secrets/etcd-certs/ca.crt --set kubeEtcd.serviceMonitor.certFile=/etc/prometheus/secrets/etcd-certs/healthcheck-client.crt --set kubeEtcd.serviceMonitor.keyFile=/etc/prometheus/secrets/etcd-certs/healthcheck-client.key --set prometheus.prometheusSpec.secrets={etcd-certs} --set prometheusOperator.admissionWebhooks.patch.image.sha=null ./
大盤展示
Grafana 大盤:https://github.com/clay-wangzhi/grafana-dashboard/blob/master/etcd/etcd-dash.json
導入即可
監控指標補充
- 數據一致性、寫請求、資源對象數等
收集過程詳見:https://github.com/clay-wangzhi/etcd-metrics
參考 https://github.com/kstone-io/kstone 進行裁剪
Etcd 基準測試
SLI & SLO
SLI(Service Level Indicator):服務等級指標,其實就是我們選擇哪些指標來衡量我們的穩定性。
SLO(Service Level Objective):服務等級目標,指的就是我們設定的穩定性目標,比如 “幾個 9” 這樣的目標。
SLO 是 SLI 要達成的目標,我們需要選擇合適的 SLI,設定對應的 SLO。
目前已有 SLI 指標的收集、監控、展示及告警
使用 benchmark 測試延遲和吞吐量
環境準備
在 Linux 主機安裝 Go 環境
下載解壓
wget https://golang.google.cn/dl/go1.19.10.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.19.10.linux-amd64.tar.gz
配置到 PATH 環境變量
在 /etc/profile
文件追加如下內容
export PATH=$PATH:/usr/local/go/bin
export GOPROXY=https://goproxy.cn
最後 source 生效
source /etc/profile
安裝 benchmark 工具
clone 代碼,安裝 benchmark
git clone https://github.com/etcd-io/etcd.git --depth 1
cd etcd/
go install -v ./tools/benchmark
# 找到二進制文件位置
go list -f "{{.Target}}" ./tools/benchmark
基準測試
查看幫助
cd /root/go/bin/
./benchmark -h
配置變量
ETCD_CA_CERT="/etc/kubernetes/pki/etcd/ca.crt"
ETCD_CERT="/etc/kubernetes/pki/etcd/server.crt"
ETCD_KEY="/etc/kubernetes/pki/etcd/server.key"
HOST_1=https://xxx.xxx.xxx.xxx:2379
HOST_2=https://xxx.xxx.xxx.xxx:2379
HOST_3=https://xxx.xxx.xxx.xxx:2379
# 提前寫個測試 key
YOUR_KEY=foo
ETCDCTL_API=3 /usr/local/bin/etcdctl --endpoints=${HOST_1},${HOST_2},${HOST_3} --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" put $YOUR_KEY bar
寫測試
# write to leader
./benchmark --endpoints=${HOST_2} --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" --target-leader --conns=1 --clients=1 \
put --key-size=8 --sequential-keys --total=10000 --val-size=256
./benchmark --endpoints=${HOST_2} --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" --target-leader --conns=100 --clients=1000 \
put --key-size=8 --sequential-keys --total=100000 --val-size=256
# write to all members
./benchmark --endpoints=${HOST_1},${HOST_2},${HOST_3} --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" --conns=100 --clients=1000 \
put --key-size=8 --sequential-keys --total=100000 --val-size=256
讀測試
# Single connection read requests
./benchmark --endpoints=${HOST_1},${HOST_2},${HOST_3} --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" --conns=1 --clients=1 \
range $YOUR_KEY --consistency=l --total=10000
./benchmark --endpoints=${HOST_1},${HOST_2},${HOST_3} --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" --conns=1 --clients=1 \
range $YOUR_KEY --consistency=s --total=10000
# Many concurrent read requests
./benchmark --endpoints=${HOST_1},${HOST_2},${HOST_3} --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" --conns=100 --clients=1000 \
range $YOUR_KEY --consistency=l --total=100000
./benchmark --endpoints=${HOST_1},${HOST_2},${HOST_3} --cacert="${ETCD_CA_CERT}" --cert="${ETCD_CERT}" --key="${ETCD_KEY}" --conns=100 --clients=1000 \
range $YOUR_KEY --consistency=s --total=100000
使用 FIO 測試磁盤性能
Etcd 對內存和 CPU 消耗並不高,足夠就行。
一次 Etcd 請求的最小時間 = 成員節點之間的網絡往返時延 + 收到數據之後進行持久化的時延。因此,Etcd 的性能主要受兩方面的約束:
-
網絡
-
磁盤
多節點的 Etcd 集羣成員節點應該儘量部署在同一個數據中心,減少網絡時延。同一數據中心內,不同節點的網絡情況通常是非常好的,如果需要測試可以使用 ping
或 tcpdump
命令進行分析。
下面主要討論硬盤 IO 測試方法。
存儲性能能夠滿足 etcd 的性能要求,有兩種方法測試:
-
已運行的 etcd 集羣,通過指標
etcd_disk_wal_fysnc_duration_seconds
來評估存儲 I/O 性能, 該指標記錄了 WAL 文件系統調用 fsync 的延遲分佈,當 99% 樣本的同步時間小於 10 毫秒就可以認爲存儲性能能夠滿足 etcd 的性能要求。 -
是用 fio 命令,還原 etcd 使用場景,看 99 線
mkdir test-data fio --rw=write --ioengine=sync --fdatasync=1 --directory=test-data --size=22m --bs=2300 --name=mytest
調優
磁盤
換 SSD 盤 -------- 這個是必須的
給定較高的磁盤優先級
# best effort, highest priority
$ sudo ionice -c2 -n0 -p `pgrep etcd`
CPU
CPU 性能模式調整爲 performance , 如何調整不成功參考:https://clay-wangzhi.com/cloudnative/troubleshooting/vm-vs-container-performance.html#cpu
echo performance | tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
配置參數
開啓自動壓縮、修改 etcd raft 消息最大字節數、修改 etcd 最大容量等。
參考鏈接:
etcd 實戰課 | 極客時間 唐聰:https://time.geekbang.org/column/intro/100069901
github etcdctl doc:https://github.com/etcd-io/etcd/blob/main/etcdctl/README.md
datadog etcd 指標:https://docs.datadoghq.com/integrations/etcd/?tab=host
etcd 官方文檔 - tunning:https://etcd.io/docs/v3.5/tuning/
etcd 官方文檔 - 硬件要求:https://etcd.io/docs/v3.5/op-guide/hardware/
etcd 官方文檔 - benchmark:https://etcd.io/docs/v3.5/benchmarks/etcd-3-demo-benchmarks/
使用 fio 測試 etcd 是否滿足要求:https://www.ibm.com/cloud/blog/using-fio-to-tell-whether-your-storage-is-fast-enough-for-etcd
我是 Clay,下期見 👋
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/ytLTpNZ5_S3whIA4-f2lag