# ETCD IO 效能測試
## 安裝 benchmark
* 需先安裝 go 1.21 以上版本
```
$ SUSEConnect -p sle-module-desktop-applications/15.5/x86_64
$ SUSEConnect -p sle-module-development-tools/15.5/x86_64
$ zypper install go-1.23-150000.3.38.1
$ go version
go version go1.23.1 linux/amd64
```
* 安裝 benchmark
```
$ git clone https://github.com/etcd-io/etcd.git; cd etcd
$ go install -v ./tools/benchmark
$ mv $(go list -f "{{.Target}}" ./tools/benchmark) /usr/local/bin/benchmark
$ benchmark --help
```
## rke2 測試
* put 測試(寫入),這個測試會發送 10000 個 put 操作
```
$ benchmark --endpoints=127.0.0.1:2379 --cert /var/lib/rancher/rke2/server/tls/etcd/server-client.crt --key /var/lib/rancher/rke2/server/tls/etcd/server-client.key --cacert /var/lib/rancher/rke2/server/tls/etcd/server-ca.crt put --key-size=8 --val-size=256 --total=10000
```
* range 測試(讀取)
```
$ benchmark --endpoints=127.0.0.1:2379 --cert /var/lib/rancher/rke2/server/tls/etcd/server-client.crt --key /var/lib/rancher/rke2/server/tls/etcd/server-client.key --cacert /var/lib/rancher/rke2/server/tls/etcd/server-ca.crt range 10000 --consistency=l --total=10000
```
## rke 測試
* put 測試(寫入),這個測試會發送 10000 個 put 操作
```
$ benchmark --endpoints=127.0.0.1:2379 --cert /etc/kubernetes/ssl/kube-etcd-192-168-11-102.pem --key /etc/kubernetes/ssl/kube-etcd-192-168-11-102-key.pem --cacert /etc/kubernetes/ssl/kube-ca.pem put --key-size=8 --val-size=256 --total=10000
```
* range 測試(讀取)
```
$ benchmark --endpoints=127.0.0.1:2379 --cert /etc/kubernetes/ssl/kube-etcd-192-168-11-102.pem --key /etc/kubernetes/ssl/kube-etcd-192-168-11-102-key.pem --cacert /etc/kubernetes/ssl/kube-ca.pem range 10000 --consistency=l --total=10000
```
## fio 測試
* 安裝 fio
```
$ curl -LO https://github.com/rancherlabs/support-tools/raw/master/instant-fio-master/instant-fio-master.sh
$ bash instant-fio-master.sh
# 在 sles 可以直接 install
$ zypper in fio
```
* 測試
```
# rke1 進到以下目錄
$ cd /var/lib/etcd/
# rke2 進到以下目錄
$ cd /var/lib/rancher/rke2/server/db/etcd
$ mkdir test-data
$ fio --rw=write --ioengine=sync --fdatasync=1 --directory=test-data --size=100m --bs=2300 --name=mytest
mytest: (g=0): rw=write, bs=(R) 2300B-2300B, (W) 2300B-2300B, (T) 2300B-2300B, ioengine=sync, iodepth=1
fio-3.23
Starting 1 process
Jobs: 1 (f=1): [W(1)][100.0%][w=1265KiB/s][w=563 IOPS][eta 00m:00s]
mytest: (groupid=0, jobs=1): err= 0: pid=27216: Tue Jan 7 17:00:52 2025
write: IOPS=470, BW=1057KiB/s (1082kB/s)(99.0MiB/96919msec); 0 zone resets
clat (usec): min=8, max=320408, avg=832.45, stdev=3751.66
lat (usec): min=9, max=320408, avg=833.13, stdev=3751.67
clat percentiles (usec):
| 1.00th=[ 12], 5.00th=[ 15], 10.00th=[ 18], 20.00th=[ 23],
| 30.00th=[ 28], 40.00th=[ 41], 50.00th=[ 178], 60.00th=[ 229],
| 70.00th=[ 281], 80.00th=[ 363], 90.00th=[ 734], 95.00th=[ 4883],
| 99.00th=[ 14353], 99.50th=[ 19530], 99.90th=[ 43779], 99.95th=[ 56886],
| 99.99th=[119014]
bw ( KiB/s): min= 247, max= 1582, per=100.00%, avg=1057.02, stdev=227.47, samples=193
iops : min= 110, max= 704, avg=470.74, stdev=101.27, samples=193
lat (usec) : 10=0.32%, 20=15.28%, 50=25.76%, 100=1.35%, 250=21.52%
lat (usec) : 500=22.97%, 750=2.95%, 1000=1.59%
lat (msec) : 2=1.75%, 4=0.95%, 10=3.62%, 20=1.48%, 50=0.38%
lat (msec) : 100=0.05%, 250=0.01%, 500=0.01%
fsync/fdatasync/sync_file_range:
sync (usec): min=544, max=136068, avg=1284.51, stdev=2380.34
sync percentiles (usec):
| 1.00th=[ 652], 5.00th=[ 750], 10.00th=[ 816], 20.00th=[ 914],
| 30.00th=[ 1004], 40.00th=[ 1074], 50.00th=[ 1156], 60.00th=[ 1221],
| 70.00th=[ 1303], 80.00th=[ 1369], 90.00th=[ 1483], 95.00th=[ 1631],
| 99.00th=[ 2540], 99.50th=[ 9765], 99.90th=[ 27132], 99.95th=[ 51643],
| 99.99th=[111674]
cpu : usr=0.83%, sys=15.67%, ctx=212612, majf=0, minf=15
IO depths : 1=200.0%, 2=0.0%, 4=0.0%, 8=0.0%, 16=0.0%, 32=0.0%, >=64=0.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
issued rwts: total=0,45590,0,0 short=45590,0,0,0 dropped=0,0,0,0
latency : target=0, window=0, percentile=100.00%, depth=1
Run status group 0 (all jobs):
WRITE: bw=1057KiB/s (1082kB/s), 1057KiB/s-1057KiB/s (1082kB/s-1082kB/s), io=99.0MiB (105MB), run=96919-96919msec
```
* fdatasync 的 99.00th 是 2540usec 等於 2.540 毫秒 (ms),寫入 WAL 檔案時 fdatasync 呼叫的第 99 個百分位必須小於 10 毫秒,就是好的 etcd IO 效能。
環境清除
```
$ rm -r test-data/
```
## 優化方式
* 設定 etcd 容器的優先權,使其高於其他 process,但又不能太高導致壓垮伺服器。
```
$ ionice -c2 -n0 -p `pgrep -x etcd`
```
## rke1
* rke1 可以直接跑以下 container 來測試
```
$ docker run --volume /var/lib/etcd/:/var/lib/etcd:Z quay.io/cloud-bulldozer/etcd-perf
......
},
"latency_depth" : 1,
"latency_target" : 0,
"latency_percentile" : 100.000000,
"latency_window" : 0
}
]
}
--------------------------------------------------------------------------------------------------------------------------------------------------------
INFO: 99th percentile of fsync is 3981312 ns
INFO: 99th percentile of the fsync is within the recommended threshold: - 10 ms, the disk can be used to host etcd
```
## rke2
```
$ echo 'apiVersion: v1
kind: Pod
metadata:
name: etcd-perf
spec:
restartPolicy: Never
initContainers:
- name: etcd-perf
image: quay.io/cloud-bulldozer/etcd-perf
volumeMounts:
- name: etcd-data
mountPath: /var/lib/etcd
containers:
- name: wait
image: busybox
command: ["sh", "-c", "sleep infinity"]
lifecycle:
postStart:
exec:
command:
- /bin/sh
- -c
- |
rm -rf /var/lib/etcd/etcd_perf.0.0
volumeMounts:
- name: etcd-data
mountPath: /var/lib/etcd
volumes:
- name: etcd-data
hostPath:
path: /var/lib/rancher/rke2/server/db/etcd
type: Directory
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"
nodeSelector:
node-role.kubernetes.io/etcd: "true"' | kubectl apply -f -
```
* 檢查 log,以 10 ms 為基準,如果超過這個數值就會被判定為 etcd IO 效能太差。
```
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
etcd-perf 1/1 Running 0 108s
$ kubectl logs etcd-perf -c etcd-perf
......
INFO: 99th percentile of fsync is 7176192 ns
INFO: 99th percentile of the fsync is within the recommended threshold: - 10 ms, the disk can be used to host etcd
$ kubectl delete pod etcd-perf
```
## 參考
https://doczhcn.gitbook.io/etcd/index/index-1/performance
https://www.suse.com/support/kb/doc/?id=000020100
https://access.redhat.com/solutions/4885641