gccontroller
# 1.简介
# 1.1.原理
gc controller会监听所有资源的事件,基于ownerReference生成Graph拓扑图,obj变化会触发owner或子资源入队,实现级联删除效果。
补充
finalizer作为资源对象的属性绑定,GC会略过标记OrphanFinalizer的子资源,其它子资源GC会触发级联清理
# 1.2.机制
删除划分为
前台级联、后台级联和孤儿删除,前台级联由子资源开始清理,后台级联(默认)由owner开始清理,孤儿删除仅清理当前对象。
注意
gc controller默认采用后台级联删除策略,owner删除后异步清晰子资源
# 2.入口
# 2.1.start
startGarbageCollectorController()会监听集群中所有资源,实例化garbageCollector对象,激活Run和Sync处理模块。// NewGarbageCollector creates a new GarbageCollector. func NewGarbageCollector(...) (*GarbageCollector, error) { ... gc := &GarbageCollector{ metadataClient: metadataClient, restMapper: mapper, attemptToDelete: attemptToDelete, // 尝试删除的资源队列 attemptToOrphan: attemptToOrphan, // 尝试删除的资源对应子资源队列 absentOwnerCache: absentOwnerCache, // 未找到的node缓存(500) kubeClient: kubeClient, ... } // 有向无环图 gc.dependencyGraphBuilder = &GraphBuilder{ ... metadataClient: metadataClient, informersStarted: informersStarted, restMapper: mapper, graphChanges: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "..."), uidToNode: &concurrentUIDToNode{ uidToNode: make(map[types.UID]*node) }, attemptToDelete: attemptToDelete, attemptToOrphan: attemptToOrphan, absentOwnerCache: absentOwnerCache, sharedInformers: sharedInformers, ignoredResources: ignoredResources, } ... return gc, nil } func startGarbageCollectorController(ctx context.Context, controllerContext ControllerContext) (...) { ... // 配置忽略的GC资源 for _, r := range controllerContext.ComponentConfig.GarbageCollectorController.GCIgnoredResources { ignoredResources[schema.GroupResource{Group: r.Group, Resource: r.Resource}] = struct{}{} } // 初始化GC对象 garbageCollector, err := garbagecollector.NewGarbageCollector( gcClientset, metadataClient, // finalizer变动普通的informer无法感知,这里采用metadata informer controllerContext.RESTMapper, ignoredResources, controllerContext.ObjectOrMetadataInformerFactory, controllerContext.InformersStarted, ) ... // 激活30个run worker go garbageCollector.Run(ctx, workers) // 间隔30s执行一次sync go garbageCollector.Sync(ctx, discoveryClient, 30*time.Second) return garbageCollector, true, nil }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60补充
GC最核心的模块是DAG结构,DAG存储了集群中不同资源从属关系拓扑,DAG资源发生变化会由GC加入attemptToXX队列
# 2.2.run
gc.Run()会激活DAG模块执行资源从属拓扑构造,启动一定数量的worker处理attemptToDelete和attemptToOrphan队列的任务。// Run starts garbage collector workers. func (gc *GarbageCollector) Run(ctx context.Context, workers int) { ... // 激活DAG模块 go gc.dependencyGraphBuilder.Run(ctx) // 阻塞至DAG构造完成 if !cache.WaitForNamedCacheSync("garbage collector", ctx.Done(), gc.dependencyGraphBuilder.IsSynced(logger){ return } // 激活30个worker for i := 0; i < workers; i++ { // 执行资源清理 go wait.UntilWithContext(ctx, gc.runAttemptToDeleteWorker, 1*time.Second) // 执行依赖对象清理 go wait.Until(func() { gc.runAttemptToOrphanWorker(logger) }, 1*time.Second, ctx.Done()) } <-ctx.Done() }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22补充
DAG模块会检测资源变化,将相关的owner及所属资源推入attemptToDelete和attemptToOrphan
# 2.3.sync
gc.sync()会周期性的查询集群所有资源,过滤出deletableResources,区别于已监控的deletableResources会注册到DAG monitor监听。// Sync periodically resyncs the garbage collector when new resources are observed from discovery. func (gc *GarbageCollector) Sync(...) { oldResources := make(map[schema.GroupVersionResource]struct{}) // 间隔30s触发一次同步 wait.UntilWithContext(ctx, func(ctx context.Context) { // 获取集群所有的deletableResources(支持delete/list/watch方法的资源) newResources := GetDeletableResources(discoveryClient) // This can occur if there is an internal error in GetDeletableResources. if len(newResources) == 0 { return } // deletableResources无变化 if reflect.DeepEqual(oldResources, newResources) { return } // 加锁,暂停gc worker gc.workerLock.Lock() defer gc.workerLock.Unlock() ... // 间隔100ms触发,最大30s wait.PollImmediateUntilWithContext(ctx, 100*time.Millisecond, func(ctx context.Context) (bool, error) { attempt++ // 重试失败的同步 if attempt > 1 { newResources = GetDeletableResources(discoveryClient) if len(newResources) == 0 { return false, nil } } // 重置缓存 gc.restMapper.Reset() // 基于newResources注册monitor if err := gc.resyncMonitors(logger, newResources); err != nil { return false, nil } // 最大等待30s至同步完成 if !cache.WaitForNamedCacheSync("gc", waitForStopOrTimeout(ctx.Done(), period), func() bool { // 标记同步完成 return gc.dependencyGraphBuilder.IsSynced(logger) }) { return false, nil } // success, break out of the loop return true, nil }) oldResources = newResources }, period) } // starts or stops resource monitors as needed to ensure all those resources present in the map are monitored. func (gc *GarbageCollector) resyncMonitors(...) error { // 基于deletableResources注册或清理monitor gc.dependencyGraphBuilder.syncMonitors(logger, deletableResources) ... // 激活monitor informer同步 gc.dependencyGraphBuilder.startMonitors(logger) return nil }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
注意
sync()周期同步deletableResources,基于最新资源注册或清理monitor及激活事件监听,触发graphChanges队列推送
# 3.graph
# 3.1.run
gb.dependencyGraphBuilder.Run()会激活informer,基于监听回调向graphChanges推送事件,通过processGraphChanges消费事件。// Run sets the stop channel and starts monitor execution until stopCh is closed. func (gb *GraphBuilder) Run(ctx context.Context) { ... // 激活informer监听及graphChanges推送 gb.startMonitors(logger) // 间隔1s触发一次graphChanges消费 wait.Until(func() { gb.runProcessGraphChanges(logger) }, 1*time.Second, ctx.Done()) ... } // started monitors will also cause shared informers to be started. func (gb *GraphBuilder) startMonitors(logger klog.Logger) { ... // monitor未标记启动 if !gb.running { return } // kcm中所有controller启动完成 <-gb.informersStarted ... // 遍历monitor for _, monitor := range gb.monitors { if monitor.stopCh == nil { monitor.stopCh = make(chan struct{}) gb.sharedInformers.Start(gb.stopCh) // 启动informer go monitor.Run() started++ } } } // Run is intended to be called in a goroutine. Multiple calls of this is an error. func (m *monitor) Run() { // 这里其实是dummyController informer,动态监听resource及执行回调 m.controller.Run(m.stopCh) }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
注意
startMonitors主要启动resource删除事件监听及更新graphChanges,供runProcessGraphChanges消费
# 3.2.monitor
gc.Sync()间隔30s检测一次deletableResources,基于deletableResources注册monitor,本质是注册resource Informer。func (gc *GarbageCollector) resyncMonitors(...) error { // 基于deletableResources注册monitor gc.dependencyGraphBuilder.syncMonitors(logger, deletableResources) ... gc.dependencyGraphBuilder.startMonitors(logger) return nil } // syncMonitors rebuilds the monitor set according to the supplied resources. func (gb *GraphBuilder) syncMonitors(...) error { ... // 待删除的monitor toRemove := gb.monitors ... // 基于resource初始化monitor for resource := range resources { // 配置忽略的资源 if _, ok := gb.ignoredResources[resource.GroupResource()]; ok { continue } // 已注册过的资源 if m, ok := toRemove[resource]; ok { current[resource] = m delete(toRemove, resource) kept++ continue } // 获取resource GVK kind, err := gb.restMapper.KindFor(resource) ... // 获取resource Informer c, s, err := gb.controllerFor(logger, resource, kind) ... current[resource] = &monitor{store: s, controller: c} added++ } // 更新monitor gb.monitors = current // 停止过期的monitor for _, monitor := range toRemove { if monitor.stopCh != nil { close(monitor.stopCh) } } return utilerrors.NewAggregate(errs) } func (gb *GraphBuilder) controllerFor(...) (cache.Controller, cache.Store, error) { handlers := cache.ResourceEventHandlerFuncs{ // add the event to the dependencyGraphBuilder's graphChanges. AddFunc: func(obj interface{}) { event := &event{ eventType: addEvent, obj: obj, gvk: kind } gb.graphChanges.Add(event) }, UpdateFunc: func(oldObj, newObj interface{}) { event := &event{ eventType: updateEvent, obj: newObj, oldObj: oldObj, gvk: kind } gb.graphChanges.Add(event) }, DeleteFunc: func(obj interface{}) { ... event := &event{ eventType: deleteEvent, obj: obj, gvk: kind } gb.graphChanges.Add(event) }, } // 基于GVR初始化shared Informer shared, err := gb.sharedInformers.ForResource(resource) ... // 注册eventHandler shared.Informer().AddEventHandlerWithResyncPeriod(handlers, ResourceResyncTime) // controller负责驱动reflector+deltaFIFO进行list/watch,store负责缓存 return shared.Informer().GetController(), shared.Informer().GetStore(), nil }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
补充
monitor本质就是deletableResource Informer,注册及启动就是激活eventHandler,推送event至graphChanges
# 3.3.process
processGraphChanges消费graphChanges队列,将event node更新至uidToNode及分发至attemptToDelete和attemptToOrphan。func (gb *GraphBuilder) runProcessGraphChanges(logger klog.Logger) { for gb.processGraphChanges(logger) { } } // Dequeueing an event from graphChanges, updating graph, populating dirty_queue. func (gb *GraphBuilder) processGraphChanges(logger klog.Logger) bool { item, quit := gb.graphChanges.Get() ... defer gb.graphChanges.Done(item) event, ok := item.(*event) ... obj := event.obj accessor, err := meta.Accessor(obj) ... existingNode, found := gb.uidToNode.Read(accessor.GetUID()) // informer的事件+virtual node if found && !event.virtual && !existingNode.isObserved() { // 生成event node身份信息 observedIdentity := identityFromEvent(event, accessor) // event node和virtual node身份不匹配 if observedIdentity != existingNode.identity { // event node未匹配的依赖 potentiallyInvalidDependents := partitionDependents(existingNode.getDependents(), observedIdentity) // 不匹配真实node的依赖会放到attemptToDelete for _, dep := range potentiallyInvalidDependents { ... gb.attemptToDelete.Add(dep) } // 更新node身份 existingNode = existingNode.clone() existingNode.identity = observedIdentity gb.uidToNode.Write(existingNode) } // 标记node是观测到的真实节点,virtual=false existingNode.markObserved() } switch { // node不存在+ADD/UPDATE事件 case (event.eventType == addEvent || event.eventType == updateEvent) && !found: newNode := &node{ identity: identityFromEvent(event, accessor), // node身份 dependents: make(map[*node]struct{}), owners: accessor.GetOwnerReferences(), // node ownerRef deletingDependents: beingDeleted(accessor) && hasDeleteDependentsFinalizer(accessor), // 前台删除 beingDeleted: beingDeleted(accessor), // 正在删除 } // 注册node及相关的owner至uidToNode,补充相关依赖,owner无效或owner node是virtual,将node推到attemptToDelete gb.insertNode(logger, newNode) // foregroundDeletion: node和dependents放到attemptToDelete队列 // orphanDeletion: node推到attemptToOrphan队列 gb.processTransitions(logger, event.oldObj, accessor, newNode) // node存在+ADD/UPDATE事件 case (event.eventType == addEvent || event.eventType == updateEvent) && found: // ownerRef差异 added, removed, changed := referencesDiffs(existingNode.owners, accessor.GetOwnerReferences()) if len(added) != 0 || len(removed) != 0 || len(changed) != 0 { // blockOnwer状态变化将owner node推到attemptToDelete gb.addUnblockedOwnersToDeleteQueue(logger, removed, changed) // 更新node的ownerRef existingNode.owners = accessor.GetOwnerReferences() // 补充新增owner的dependent,owner无效或owner node是virtual,将node推到attemptToDelete gb.addDependentToOwners(logger, existingNode, added) // 移除过期owner的dependent gb.removeDependentFromOwners(existingNode, removed) } // 对象正在删除,标记node状态 if beingDeleted(accessor) { existingNode.markBeingDeleted() } // foregroundDeletion: node和dependents放到attemptToDelete队列 // orphanDeletion: node推到attemptToOrphan队列 gb.processTransitions(logger, event.oldObj, accessor, existingNode) // DEL事件 case event.eventType == deleteEvent: if !found { return true } removeExistingNode := true // virtual event if event.virtual { // 生成event node身份 identity := identityFromEvent(event, accessor) // virtual node if existingNode.virtual { // event node身份存疑,有未匹配的依赖 if matching, nonmatching := partitionDependents(existingNode.getDependents(), identity); len(nonmatching) > 0 { // event node身份存疑,node不清理 removeExistingNode = false // event node匹配的依赖推入attemptToDelete if len(matching) > 0 { // 标记event node不存在 gb.absentOwnerCache.Add(identity) // 匹配身份的node依赖推到attemptToDelete for _, dep := range matchingDependents { gb.attemptToDelete.Add(dep) } } // node身份确认异常 if existingNode.identity == identity { // 由不匹配的子对象owner找个备用身份 replacementIdentity := getAlternateOwnerIdentity(nonmatchingDependents, deletedIdentity) if replacementIdentity != nil { // 基于新身份生成virtual node replacementNode := existingNode.clone() replacementNode.identity = *replacementIdentity gb.uidToNode.Write(replacementNode) // 将virtual node放入attemptToDelete重新观察 gb.attemptToDelete.AddRateLimited(replacementNode) } } } // 非虚拟node+身份不匹配 } else if existingNode.identity != deletedIdentity { // 来自informer的node不该被虚事件清理 removeExistingNode = false // 获取身份匹配的node依赖 matchingDependents, _ := partitionDependents(existingNode.getDependents(), deletedIdentity) if len(matchingDependents) > 0 { // 标记event node不存在 gb.absentOwnerCache.Add(deletedIdentity) // event node的依赖推到attemptToDelete for _, dep := range matchingDependents { gb.attemptToDelete.Add(dep) } } } } if removeExistingNode { // 移除node及owner依赖 gb.removeNode(existingNode) ... // 标记node已不存在 if len(existingNode.dependents) > 0 { gb.absentOwnerCache.Add(identityFromEvent(event, accessor)) } // node依赖推到attemptToDelete for dep := range existingNode.dependents { gb.attemptToDelete.Add(dep) } // node owner推到attemptToDelete for _, owner := range existingNode.owners { ownerNode, found := gb.uidToNode.Read(owner.UID) if !found || !ownerNode.isDeletingDependents() { continue } gb.attemptToDelete.Add(ownerNode) } } } return true }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
注意
processGraphChanges主要基于event及existing node检查finalizer及ownerRef,将相关的node推到attemptToDelete
# 3.4.transition
gb.processTransitions()负责检测node状态,删除的node及其依赖根据回收策略会推到attemptToOrphan或attemptToDelete。// this function takes newAccessor directly because the caller already instantiates an accessor for the newObj. func startsWaitingForDependentsOrphaned(oldObj interface{}, newAccessor metav1.Object) bool { return deletionStartsWithFinalizer(oldObj, newAccessor, "orphan") } // this function takes newAccessor directly because the caller already instantiates an accessor for the newObj. func startsWaitingForDependentsDeleted(oldObj interface{}, newAccessor metav1.Object) bool { return deletionStartsWithFinalizer(oldObj, newAccessor, "foregroundDeletion") } func deletionStartsWithFinalizer(oldObj interface{}, newAccessor metav1.Object, matchingFinalizer string) bool { // newObj未删除或未注入orphan finalizer if !beingDeleted(newAccessor) || !hasFinalizer(newAccessor, matchingFinalizer) { return false } // 走到这里说明newObj正在删除或注入orphan finalizer if oldObj == nil { return true } // oldObj未删除或未注入orphan finalizer oldAccessor, err := meta.Accessor(oldObj) ... return !beingDeleted(oldAccessor) || !hasFinalizer(oldAccessor, matchingFinalizer) } func (gb *GraphBuilder) processTransitions(...) { // 孤儿删除 if startsWaitingForDependentsOrphaned(oldObj, newAccessor) { gb.attemptToOrphan.Add(n) return } // 前台删除 if startsWaitingForDependentsDeleted(oldObj, newAccessor) { // 标记正在清理node 依赖 n.markDeletingDependents() for dep := range n.dependents { gb.attemptToDelete.Add(dep) } gb.attemptToDelete.Add(n) } }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
注意
processTransitions负责将未处理过的正在删除且有相关finalizer的node和相关依赖推到对应队列
# 5.worker
# 5.1.attemptworker
gc.runAttemptToDeleteWorker()负责回收队列中待删除的对象,内部是一个无限循环,通过调用processAttemptToDeleteWorker完成回收。func (gc *GarbageCollector) runAttemptToDeleteWorker(ctx context.Context) { for gc.processAttemptToDeleteWorker(ctx) { } } func (gc *GarbageCollector) processAttemptToDeleteWorker(ctx context.Context) bool { // 从队列中取出一个资源对象 item, quit := gc.attemptToDelete.Get() ... defer gc.attemptToDelete.Done(item) ... // 执行清理 action := gc.attemptToDeleteWorker(ctx, item) switch action { case forgetItem: // item重试状态重置 gc.attemptToDelete.Forget(item) case requeueItem: // item重入队 gc.attemptToDelete.AddRateLimited(item) } return true } func (gc *GarbageCollector) attemptToDeleteWorker(ctx context.Context, item interface{}) workQueueItemAction { n, ok := item.(*node) ... // virtual node if !n.isObserved() { // 获取Grapth节点 nodeFromGraph, existsInGraph := gc.dependencyGraphBuilder.uidToNode.Read(n.identity.UID) // Grapth未记录 if !existsInGraph { return forgetItem } // virtual Node不能清理grapth中的真实节点 if nodeFromGraph.isObserved() { return forgetItem } } // 执行清理 err := gc.attemptToDeleteItem(ctx, n) // 已经生成虚拟事件 if err == enqueuedVirtualDeleteEventErr { return forgetItem // 命名空间所有者引用集群范围对象 } else if err == namespacedOwnerOfClusterScopedObjectErr { return forgetItem // 执行出错,需要重入队 } else if err != nil { return requeueItem // node virtual,重入队 } else if !n.isObserved() { return requeueItem } return forgetItem }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
注意
runAttemptToDeleteWorker推出attemptToDelete Item执行相关处理,根据处理情况决定item完成还是入队
# 5.2.deleteworker
gc.attemptToDeleteItem()会检查item node状态,根据删除状态及finalizer执行相关的清理,直到item无依赖则摘掉finalizer。// looks up the live API object associated with the node, and issues a delete IFF the uid matches, the item is not blocked on deleting dependents, and all owner references are dangling. func (gc *GarbageCollector) attemptToDeleteItem(ctx context.Context, item *node) error { // orphan/backgroud方式删除 if item.isBeingDeleted() && !item.isDeletingDependents() { return nil } // 获取APIServer对象 latest, err := gc.getObject(item.identity) switch { // 未找到 case errors.IsNotFound(err): // item是virtual node,入队一个虚拟删除事件 gc.dependencyGraphBuilder.enqueueVirtualDeleteEvent(item.identity) return enqueuedVirtualDeleteEventErr case err != nil: return err } // uid不匹配 if latest.GetUID() != item.identity.UID { // item未找到,属于virtual node,入队一个虚拟删除事件 gc.dependencyGraphBuilder.enqueueVirtualDeleteEvent(item.identity) return enqueuedVirtualDeleteEventErr } // item正在前台删除 if item.isDeletingDependents() { // 清理finalizer或将blockOwnerRef=true的依赖推到attemptToDelete return gc.processDeletingDependentsItem(logger, item) } // 走到这里说明item还没删,基于owner状态决定删不删 // 获取item对象的ownerRef ownerReferences := latest.GetOwnerReferences() // 无owner,不能贸然删item if len(ownerReferences) == 0 { return nil } // owner分类 solid, dangling, waitingForDependentsDeletion, err := gc.classifyReferences(ctx, item, ownerReferences) ... switch { // 存在未删除的有效owner,item还不能删 case len(solid) != 0: if len(dangling) == 0 && len(waitingForDependentsDeletion) == 0 { return nil } // 清理不存在的和正在前台删除的ownerRef ownerUIDs := append(ownerRefsToUIDs(dangling), ownerRefsToUIDs(waitingForDependentsDeletion)...) p, err := c.GenerateDeleteOwnerRefStrategicMergeBytes(item.identity.UID, ownerUIDs) ... // 先执行delete merge,不支持则基于回调获取该保留的owner进行merge _, err = gc.patch(item, p, func(n *node) ([]byte, error) { // ownerUIDs以外的保留 return gc.deleteOwnerRefJSONMergePatch(n, ownerUIDs...) }) return err // item的owner正在等待item删除且item依赖未全部清理 case len(waitingForDependentsDeletion) != 0 && item.dependentsLength() != 0: deps := item.getDependents() // 遍历item dependents for _, dep := range deps { // dep正在前台删除 if dep.isDeletingDependents() { // 修正blockOwnerRef=false,避免循环依赖 patch, err := item.unblockOwnerReferencesStrategicMergePatch() gc.patch(item, patch, gc.unblockOwnerReferencesJSONMergePatch) ... break } } // 无前台删除的dep,以forword模式递归删除item policy := metav1.DeletePropagationForeground return gc.deleteObject(item.identity, &policy) // item没有owner default: ... switch { // 孤儿删除 case hasOrphanFinalizer(latest): // if an existing orphan finalizer is already on the object, honor it. policy = metav1.DeletePropagationOrphan // foreground删除 case hasDeleteDependentsFinalizer(latest): // if an existing foreground finalizer is already on the object, honor it. policy = metav1.DeletePropagationForeground // backgroud删除(默认) default: // otherwise, default to background. policy = metav1.DeletePropagationBackground } // 清理item对象 return gc.deleteObject(item.identity, &policy) } } // process item that's waiting for its dependents to be deleted func (gc *GarbageCollector) processDeletingDependentsItem(logger klog.Logger, item *node) error { // item没有blockOnwerRef=true的依赖 blockingDependents := item.blockingDependents() if len(blockingDependents) == 0 { // 移除item的foreground finalizer return gc.removeFinalizer(logger, item, metav1.FinalizerDeleteDependents) } // 有阻塞依赖 for _, dep := range blockingDependents { // dep未处于前台删除状态 if !dep.isDeletingDependents() { // dep推到attemptToDelete队列 gc.attemptToDelete.Add(dep) } } return nil }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
补充
item未处于删除或正在前台删除会进行处理,正在前台删除的item会执行依赖清理及finalizer调整,未删除的则检查owner状态进行删除
# 5.2.orphanworker
gc.attemptToOrphanWorker()负责清理orphan资源,更新关联资源的ownerRef以解除关联关系,清理item finalizer实现对象清理。func (gc *GarbageCollector) runAttemptToOrphanWorker(logger klog.Logger) { for gc.processAttemptToOrphanWorker(logger) { } } // dequeues a node from the attemptToOrphan, removes OwnerReferences of its dependents, and updates the owner to remove the "Orphan" finalizer. The node is added back into the attemptToOrphan if any of these steps fail. func (gc *GarbageCollector) processAttemptToOrphanWorker(logger klog.Logger) bool { item, quit := gc.attemptToOrphan.Get() ... defer gc.attemptToOrphan.Done(item) // orphan删除 action := gc.attemptToOrphanWorker(logger, item) switch action { // 重置状态 case forgetItem: gc.attemptToOrphan.Forget(item) // 重入队 case requeueItem: gc.attemptToOrphan.AddRateLimited(item) } return true } func (gc *GarbageCollector) attemptToOrphanWorker(logger klog.Logger, item interface{}) workQueueItemAction { // item node owner, ok := item.(*node) ... // 收集owner dependent for dependent := range owner.dependents { dependents = append(dependents, dependent) } ... // 解除dep ownerRef关联 gc.orphanDependents(logger, owner.identity, dependents) ... // 清理item对象的orphan finalizer gc.removeFinalizer(logger, owner, metav1.FinalizerOrphanDependents) ... return forgetItem }1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
注意
orphan清理仅清理item finalizer及解除dependent ownerRef依赖,不会递归删除dependent