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 算法層、邏輯層和存儲層。這些層的功能如下:

概念術語

運維實踐

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 監控

重點監控指標

指標分類

t8Hexi

使用 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。

4kzIi3

目前已有 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=\
     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

3b21Jg

讀測試

# 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=\
    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=\
    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

36hoGS

使用 FIO 測試磁盤性能

Etcd 對內存和 CPU 消耗並不高,足夠就行。

一次 Etcd 請求的最小時間 = 成員節點之間的網絡往返時延 + 收到數據之後進行持久化的時延。因此,Etcd 的性能主要受兩方面的約束:

多節點的 Etcd 集羣成員節點應該儘量部署在同一個數據中心,減少網絡時延。同一數據中心內,不同節點的網絡情況通常是非常好的,如果需要測試可以使用 pingtcpdump 命令進行分析。

下面主要討論硬盤 IO 測試方法。

存儲性能能夠滿足 etcd 的性能要求,有兩種方法測試:

  1. 已運行的 etcd 集羣,通過指標etcd_disk_wal_fysnc_duration_seconds來評估存儲 I/O 性能, 該指標記錄了 WAL 文件系統調用 fsync 的延遲分佈,當 99% 樣本的同步時間小於 10 毫秒就可以認爲存儲性能能夠滿足 etcd 的性能要求。

  2. 是用 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