Kubernetes:etcd容量管理(配额、压缩、碎片整理等)
在Kubernetes中,所有的API对象都通过kube-apiserver保存在etcd中。etcd有数据大小限制(配额),但还需注意一些其他事项,如历史数据和片段化大小在compaction之前的情况。本文总结了一些关于etcd容量管理的信息,所使用的etcd版本为3.2.24。
etcd的容量限制(配额)
etcd 默认设置了2GB的配额。一旦超过这个配额,etcd会进入警报状态,并且除非解除警报(解除武装),否则将无法向etcd写入数据。如果超过容量限制,将显示错误消息“mvcc: database space exceeded”。配额大小可以通过 –quota-backend-bytes选项指定最大为8GB。
包含在配额大小中的内容
配额大小将根据 etcd 使用的 BoltDB(etcd-io/bbolt)后端的物理大小来计算。由于该大小包括历史数据和由于碎片化引起的间隙,因此需要注意。
現在のデータ(キーと値)
Kubernetes の場合、API オブジェクトごとにキーができ、protocol buffer でエンコードされている
履歴データ
etcd の compaction のタイミングで指定した revision 以下の履歴は消える
断片化による隙間
etcd の defrag のタイミングで解消する
物理尺寸和逻辑尺寸
在etcd的数据大小中,有物理大小和逻辑大小两种。这些大小可以通过以下Prometheus的指标进行查看。
etcd_mvcc_db_total_size_in_bytes 断片化による隙間を含む、物理的な DB のサイズ
クォータの対象となるサイズ
defrag を行ったときのみサイズが減る
etcd_mvcc_db_total_size_in_use_in_bytes 断片化による隙間を含まない、論理的な DB のサイズ
compaction で履歴データを消したときにサイズが減る
看看实际操作
这个图表显示了通过kube-apiserver每秒修改一次1MB的ConfigMap并写入历史数据的时候的指标。由于是对同一个ConfigMap进行更新,所以从kube-apiserver的角度来看,应该只增加了大约1MB。但是可以看出etcd的数据量正在增加。
从上面的图表中可以看出,红色代表物理尺寸,绿色代表逻辑尺寸。上述图表显示以下操作。
-
- ConfigMap の更新を開始すると etcd の論理サイズ(緑)、物理サイズ(赤)ともに増えていく
履歴データによってサイズが増えていく
論理サイズ(緑) は定期的にサイズが小さくなる
5分ごとに kube-apiserver によって compaction が走って履歴データが消えるため
一定以上データが消えていないのは、compaction の revision 指定の仕様 (後述)
一方物理サイズ(赤) は一度上がったサイズはそのまま
最後に手動で defrag を実行したタイミングで初めてサイズが下がる
以下是实际执行的操作。为了对etcd施加负载,请在尝试时小心注意。
# 1MB のダミーファイルを作成
$ dd if=/dev/urandom of=random.bin bs=1024 count=1024
# ダミーファイルを入れた ConfigMap を作成
$ kubectl create cm dummy-config --from-file random.bin
# 1秒ごとにパッチを当てて、履歴データを etcd に書いていく
$ while true; do
kubectl patch configmap dummy-config \
-p "{\"metadata\":{\"annotations\":{\"dummy-for-update\":\"`date +%s`\"}}}"
sleep 1
done
# 適当なタイミングで止める
# defrag だけ手動実行
$ sudo ETCDCTL_API=3 etcdctl --endpoints=... defrag
历史数据和压缩
当发生更改操作时,etcd会保留旧数据并创建新数据。在内部,它会给每个数据分配一个称为revision的连续编号。当进行压缩操作时,会删除指定的revision之前的数据。
etcd拥有自动执行压缩的功能,但在Kubernetes中,默认操作是通过kube-apiserver的功能定期进行压缩。压缩间隔可以使用kube-apiserver的–etcd-compaction-interval参数进行指定,默认为5分钟。(kubernetes v1.14.0)
在 kube-apiserver 的压缩处理中,将上次执行压缩的修订版本记录在一个特殊的键“compactRevKey”中,在下次处理中执行该修订版本之前的压缩操作,然后重复这个过程。换句话说,默认情况下,会保留两个区间,即10分钟的历史数据。
数据间隙和碎片整理
根据 etcd 使用的 BoltDB (etcd-io/bbolt) 的规范,删除数据不会减小数据库的大小(参考: Question: Shrink BoltDB File? #423)。此外,数据库可能会发生碎片化,有时需要进行 defrag 操作。然而,在 defrag 过程中,写入或读取数据可能会失败,因此最好避免不必要的操作。
etcd 的碎片整理实现方式似乎是简单地创建一个新的 BoltDB 文件,并将所有数据写入其中,然后通过重命名进行切换。
- 参考: https://github.com/etcd-io/etcd/blob/v3.3.12/mvcc/backend/backend.go#L293-L415
提示:了解API对象数量。
可以通过Prometheus的度量标准“kube-apiserver的etcd_object_counts”查看当前的Kubernetes API对象数。由于资源标签的存在,可以立即了解哪种资源的数量最多。虽然没有历史信息,但可以轻松地确认etcd中哪个对象最多。
使用以下命令按照资源数量从多到少进行排序。
$ kubectl get --raw /metrics | grep etcd_object_counts | sort -k2 -n
...
etcd_object_counts{resource="clusterroles.rbac.authorization.k8s.io"} 76
etcd_object_counts{resource="secrets"} 118
etcd_object_counts{resource="pods"} 162
etcd_object_counts{resource="events"} 647
Kubernetes中etcd配额的注意事项
需要注意的是Compaction之间的历史数据。
-
- デフォルトだと約10分の履歴が保持される
-
- 特にレプリカ数の大きな Deployment のローリングアップデートには注意
Pod ごとにオブジェクトが作られ、ローリングアップデートの最中に複数回アップデートされる
大きなファイルサイズのオブジェクト (ConfigMap, Secret) の更新にも注意
请注意Event对象。
-
- Event オブジェクトには TTL (デフォルト 1時間) はあるものの、障害などで大量のイベントが発生する可能性がある
- Deployment のローリングアップデート時には Event が増えることも留意
总结
etcd有配额限制,其中Bolt DB的物理大小受到限制。物理大小包括了压缩前的历史记录和片段化。在Kubernetes中,kube-apiserver会定期(默认为5分钟)执行压缩操作,但由于保留了10分钟的历史记录,因此在进行大规模滚动更新等操作时需要注意。