ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

【Kubernetes从入门到精通】第70篇:K8s垃圾回收机制——“打扫卫生“的艺术,级联删除不留孤儿

【Kubernetes从入门到精通】第70篇:K8s垃圾回收机制——“打扫卫生“的艺术,级联删除不留孤儿 上一篇【第69篇】K8s Event机制——集群的“黑匣子“排障全靠它吼一嗓子下一篇【第71篇】Admission Webhook——API Server的安检通道摘要你有没有想过删一个Deployment它底下的ReplicaSet、Pod为什么也跟着灰飞烟灭如果只删PodDeployment为什么又默默给你建一个新的这就是K8s的**垃圾回收Garbage Collection, GC和OwnerReference属主引用**在干活。K8s会维护资源之间的父子关系当父被删子要么跟着删级联要么变成孤儿独立存活。这篇文章讲清GC的三种策略Foreground/Background/Orphan、OwnerReference怎么建立关系、kubelet怎么清理死容器和旧镜像以及etcd的compaction/defrag防止数据库无限膨胀。一、OwnerReference父子关系1.1 谁是谁的孩子【资源的家谱】 Deployment web │ owns (ownerReferences) ▼ ReplicaSet web-7d8f9 │ owns ▼ Pod web-7d8f9-abc12 Pod web-7d8f9-def34 Pod web-7d8f9-ghi56 看Pod的ownerReferences: metadata: ownerReferences: - apiVersion: apps/v1 kind: ReplicaSet name: web-7d8f9 uid: a1b2c3... controller: true要点OwnerReference是GC的基础——它记录了我是谁的孩子。controller: true表示这是主要属主负责管我生死。一个资源可以有多个owner比如一个Pod被一个ReplicaSet和一个Job同时引用但只能有一个controller: true的owner。GC看到父没了就按策略处理子。二、三种GC策略2.1 Foreground / Background / Orphan【删除一个资源时的三种策略】 ┌──────────────────────────────────────────────┐ │ Orphan (孤儿模式) —— 爹死了孩子自己过 │ │ kubectl delete deploy web --cascadeorphan │ │ → Deployment删了 │ │ → ReplicaSet和Pod保留(变成孤儿独立存活) │ │ → 常用于只想删控制器保留现有Pod │ └──────────────────────────────────────────────┘ ┌──────────────────────────────────────────────┐ │ Background (后台, 默认) —— 先删爹娃后删 │ │ → 立刻删Deployment(返回成功) │ │ → GC控制器后台异步删RS和Pod │ │ → 用户感觉秒删实际子资源稍后消失 │ └──────────────────────────────────────────────┘ ┌──────────────────────────────────────────────┐ │ Foreground (前台) —— 先删娃再删爹 │ │ → 先标记Deployment为正在删除 │ │ → 等所有子资源(RS/Pod)都删干净 │ │ → 最后才删Deployment本身 │ │ → 保证爹死的时候娃一定已经没了 │ └──────────────────────────────────────────────┘策略删除顺序返回时机用途Background父先删立刻返回默认最快Foreground子先删子全删完才返回需保证级联完成Orphan父删子留立刻返回保留子资源# 默认(后台级联)kubectl delete deployment web# 保留Pod不删(孤儿)kubectl delete deployment web--cascadeorphan# 前台级联(等子资源全删)kubectl delete deployment web--cascadeforeground要点Background是默认且最快的——父资源立刻消失子资源GC后台慢慢清。Foreground保证父删除时子一定已删适合对一致性要求高的场景。Orphan用于我只想撤掉控制器但Pod先留着观察的运维操作。理解这三种你就不会疑惑为什么Pod删了又活或为什么删Deployment后Pod还在。三、kubelet的GC3.1 清理死容器和旧镜像【kubelet 的两类垃圾回收】 1. 容器GC (Container GC) • 清理已退出的容器(Exited) • 参数: --max-per-node-count100 (每节点最多保留的容器数) --min-per-node-count2 (最少保留) --max-age0 (容器最大存活时长,0不限制) • 原则: 超出上限 → 删最老的已退出容器 2. 镜像GC (Image GC) • 清理不用的镜像(腾磁盘) • 参数: --image-gc-high-threshold85 (磁盘用到85%开始清) --image-gc-low-threshold80 (清到80%停止) • 原则: 磁盘快满 → 删最久没用的镜像# 看kubelet的GC参数psaux|grepkubelet|grep-Emax-per-node|image-gc四、etcd的compaction和defrag4.1 别让数据库无限膨胀【etcd 为什么要compaction】 etcd是追加日志(MVCC, 多版本): • 每次写都生成新版本(为了支持Watch) • 一个key被改100次 → 历史有100个版本 • 不清理 → 数据库无限膨胀 compaction (压缩): • 丢弃旧版本, 只留指定revision之后(或最近N个) • kube-apiserver默认定时compact(hourly) • 也可手动: etcdctl compact revision defrag (碎片整理): • compaction后空间标记可回收但未真正释放 • defrag 真正回收磁盘空间(期间etcd短暂不可用!) • 定期(如每月)做一次# 看etcd数据库大小(膨胀了就该compactdefrag)ETCDCTL_API3etcdctl endpoint status --write-outtable# DB SIZE 持续增长超配额 → 危险!# 压缩历史ETCDCTL_API3etcdctl compact12345# 碎片整理(谨慎!会短暂阻塞)ETCDCTL_API3etcdctl defrag要点etcd用MVCC多版本存储为了支持Watch每次修改都留历史版本。不压缩数据库会无限涨。kube-apiserver默认每小时自动compact但defrag真正释放磁盘需要手动/定期做。如果etcd db size超过配额默认2GB见第061篇它直接拒绝写入——整个集群罢工。所以etcd的GCcompactdefrag是保命操作。五、GC相关的坑【常见GC坑】 1. 孤儿PV/PVC → 删Pod但PVC是独立资源不级联删(除非设了回收策略) → 注意PV的reclaimPolicy(Retain/Delete) 2. Finalizer卡住删除 → 资源带finalizer(清理钩子)控制器没清完 → 资源一直 Terminating → 强制删: kubectl delete pod xxx --force --grace-period0 (谨慎) 3. Nodes notReady时Pod不删 → kube-controller-manager的node-monitor-grace-period → 节点失联超过阈值才删上面的Pod本篇小结K8s的GC靠OwnerReference建立父子关系——父资源被删子资源按策略处理Background默认父先删子后台清、Foreground子先删父才删、Orphan父删子留。这解释了删Deployment后Pod为何跟着没和只删Pod为何又重建。kubelet清理死容器超数删最老和旧镜像磁盘超阈值删最久未用。etcd用MVCC多版本存储靠compactiondefrag防止数据库膨胀——超配额会拒绝写入是集群级风险。下篇讲Admission Webhook——API Server的安检通道。上一篇【第69篇】K8s Event机制——集群的“黑匣子“排障全靠它吼一嗓子下一篇【第71篇】Admission Webhook——API Server的安检通道
返回列表