一、etcd存储空间为什么总是不够用
相信很多运维同学都遇到过这样的情况:明明集群规模不大,但etcd的存储空间却像吹气球一样快速膨胀。这就像家里的衣柜,明明衣服不多,但总是塞得满满当当。etcd作为Kubernetes的大脑,记录着集群的所有关键数据,但有些数据就像过季的衣服,早就该清理了却一直占着空间。
造成这种情况的主要原因有三个:
- 频繁的部署操作会产生大量历史版本数据
- 未清理的终止Pod记录会持续堆积
- 过大的ConfigMap和Secret像衣柜里的大棉被特别占地方
举个例子,我们有个Java应用每天部署10次,一个月就会产生300个ReplicaSet记录。虽然Kubernetes默认会保留10个旧ReplicaSet,但如果配置不当,这些"过季时装"就会一直堆积。
二、手动清理的常规操作
先教大家几个立竿见影的清理方法,就像给衣柜做次大扫除。我们可以通过etcdctl工具直接操作:
# 查看当前etcd存储使用情况(技术栈:etcdctl + Kubernetes)
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
endpoint status
这个命令会返回类似这样的信息:
https://127.0.0.1:2379, 2.5GB, 3.1GB
第二个数字是当前使用量,第三个是配额限制。
对于已经删除的资源残留数据,我们可以手动压缩:
# 获取当前修订版本
rev=$(ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 endpoint status | grep -oE 'revision:[0-9]+' | awk -F: '{print $2}')
# 执行压缩(保留最近10000个版本)
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 compact $((rev - 10000))
# 整理磁盘碎片
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 defrag
注意压缩操作需要在所有etcd节点上执行,就像整理衣柜要把所有抽屉都清理一遍。
三、自动维护的进阶方案
手动清理毕竟不是长久之计,我们需要建立自动化机制。这里介绍两种方案:
方案1:调整Kubernetes垃圾回收策略
修改kube-apiserver启动参数,就像设置衣柜的自动整理规则:
# /etc/kubernetes/manifests/kube-apiserver.yaml 片段
spec:
containers:
- command:
- kube-apiserver
- --etcd-compaction-retention=8h # 每8小时压缩一次
- --storage-backend=etcd3
- --delete-collection-workers=2
- --api-audiences=https://kubernetes.default.svc
方案2:使用CronJob定期清理
创建一个定时清理Job,就像设置每周一次的衣柜整理闹钟:
# etcd-housekeeper-cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: etcd-housekeeper
spec:
schedule: "0 3 * * 6" # 每周六凌晨3点
jobTemplate:
spec:
template:
spec:
containers:
- name: cleaner
image: bitnami/etcd:3.4.15
command:
- /bin/sh
- -c
- |
rev=$(ETCDCTL_API=3 etcdctl endpoint status | grep -oE 'revision:[0-9]+' | awk -F: '{print $2}')
etcdctl compact $((rev - 10000))
etcdctl defrag
restartPolicy: OnFailure
四、预防胜于治疗的配置优化
除了事后清理,更重要的是从源头控制存储增长:
- 调整Deployment的修订历史限制:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
revisionHistoryLimit: 5 # 只保留5个旧版本
- 为etcd设置合理的存储配额:
# 启动etcd时设置2GB存储配额
etcd --quota-backend-bytes=2147483648
- 监控etcd存储使用情况,配置Prometheus告警规则:
# prometheus-etcd-rules.yaml
groups:
- name: etcd
rules:
- alert: EtcdExcessiveStorageUsage
expr: etcd_mvcc_db_total_size_in_bytes / etcd_server_quota_backend_bytes > 0.8
for: 10m
labels:
severity: warning
annotations:
summary: "Etcd storage usage over 80%"
五、特殊情况处理技巧
有时候我们会遇到一些棘手的情况,比如:
场景1:误删了重要资源,但etcd已经压缩过
这时候可以尝试从etcd备份恢复:
# 从快照恢复(技术栈:etcdctl)
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
snapshot restore snapshot.db \
--data-dir=/var/lib/etcd-restore
场景2:ConfigMap过大导致性能问题
建议将大配置拆分成多个小ConfigMap,或者改用其他存储方案:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-part1
data:
config-part1.json: |
{"section1": {"item1": "value1"}}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config-part2
data:
config-part2.json: |
{"section2": {"item2": "value2"}}
六、经验总结与最佳实践
经过多次实战,我总结了以下黄金法则:
- 监控先行:部署Prometheus监控etcd存储增长趋势
- 定期维护:设置每周自动压缩和碎片整理
- 合理配额:根据集群规模设置etcd存储配额
- 精简历史:所有Deployment都设置revisionHistoryLimit
- 分离存储:大文件考虑使用PV或对象存储
记住,etcd就像集群的记忆中枢,既不能让它负担过重,也不能让它失忆。通过合理的配置和维护,完全可以让etcd保持轻盈健康的状态。
最后分享一个真实案例:某电商平台在618大促前发现etcd存储使用率已达95%,通过压缩历史版本和调整Deployment配置,在一小时内将使用率降至65%,确保了活动期间集群的稳定运行。
评论