cache.DeletedFinalStateUnknown是什么?

1,147 阅读1分钟

概要

在k8s的源码或者开源项目中,onDelete事件是经常出现,处理方法也具有一定的规律,其中用到了cache.DeletedFinalStateUnknown,它是什么?有什么作用?

onDelete 常规流程

func onDelete(obj interface{}) {
    apiObject, ok := obj.(*APIObject)
    if !ok {
        tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
        if !ok {
            return
        }
        apiObject, ok := tombstone.Obj.(*APIObject)
        if !ok {
            return
        }
    }
}

看起来,这段流程有点怪异,为什么额外进行了2次Type断言?这种时候,直接看k8s源码,会发现非常简单。 首先找到cache.DeletedFinalStateUnknown的定义:

// DeletedFinalStateUnknown is placed into a DeltaFIFO in the case where an object
// was deleted but the watch deletion event was missed while disconnected from
// apiserver. In this case we don't know the final "resting" state of the object, so
// there's a chance the included `Obj` is stale.
type DeletedFinalStateUnknown struct {
	Key string
	Obj interface{}
}

原来,它就是把一个Object放入了Obj变量中,保存了那些已经被删除的对象,作为一种cache,避免获取不到这个对象了。 而它的用法,在cache包中也只出现了2次,在同一个函数中:

func (f *DeltaFIFO) Replace(list []interface{}, _ string) error {
    if f.knownObjects == nil {
        // Do deletion detection against our own list.
        queuedDeletions := 0
        for k, oldItem := range f.items {
                if keys.Has(k) {
                        continue
                }
                // Delete pre-existing items not in the new list.
                // This could happen if watch deletion event was missed while
                // disconnected from apiserver.
                var deletedObj interface{}
                if n := oldItem.Newest(); n != nil {
                        deletedObj = n.Object
                }
                queuedDeletions++
                if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil {
                        return err
                }
        }
    }
    
    // Detect deletions not already in the queue.
    knownKeys := f.knownObjects.ListKeys()
    queuedDeletions := 0
    for _, k := range knownKeys {
            if keys.Has(k) {
                    continue
            }

            deletedObj, exists, err := f.knownObjects.GetByKey(k)
            if err != nil {
                    deletedObj = nil
                    klog.Errorf("Unexpected error %v during lookup of key %v, placing DeleteFinalStateUnknown marker without object", err, k)
            } else if !exists {
                    deletedObj = nil
                    klog.Infof("Key %v does not exist in known objects store, placing DeleteFinalStateUnknown marker without object", k)
            }
            queuedDeletions++
            if err := f.queueActionLocked(Deleted, DeletedFinalStateUnknown{k, deletedObj}); err != nil {
                    return err
            }
    }
}

这只是cache包的一角,但也能看出,DeletedFinalStateUnknown是一个缓存已被删除对象的一种机制,如果需要,记得使用它。