@@ -402,6 +402,8 @@ func (e *Etcd) Delete(ctx api.Context, name string, options *api.DeleteOptions)
402402 if pendingGraceful {
403403 return e .finalizeDelete (obj , false )
404404 }
405+ var ignoreNotFound bool = false
406+ var lastExisting runtime.Object = nil
405407 if graceful {
406408 out := e .NewFunc ()
407409 lastGraceful := int64 (0 )
@@ -419,6 +421,7 @@ func (e *Etcd) Delete(ctx api.Context, name string, options *api.DeleteOptions)
419421 return nil , errDeleteNow
420422 }
421423 lastGraceful = * options .GracePeriodSeconds
424+ lastExisting = existing
422425 return existing , nil
423426 }),
424427 )
@@ -427,7 +430,15 @@ func (e *Etcd) Delete(ctx api.Context, name string, options *api.DeleteOptions)
427430 if lastGraceful > 0 {
428431 return out , nil
429432 }
430- // fall through and delete immediately
433+ // If we are here, the registry supports grace period mechanism and
434+ // we are intentionally delete gracelessly. In this case, we may
435+ // enter a race with other k8s components. If other component wins
436+ // the race, the object will not be found, and we should tolerate
437+ // the NotFound error. See
438+ // https://github.com/kubernetes/kubernetes/issues/19403 for
439+ // details.
440+ ignoreNotFound = true
441+ // exit the switch and delete immediately
431442 case errDeleteNow :
432443 // we've updated the object to have a zero grace period, or it's already at 0, so
433444 // we should fall through and truly delete the object.
@@ -441,6 +452,13 @@ func (e *Etcd) Delete(ctx api.Context, name string, options *api.DeleteOptions)
441452 // delete immediately, or no graceful deletion supported
442453 out := e .NewFunc ()
443454 if err := e .Storage .Delete (ctx , key , out ); err != nil {
455+ // Please refer to the place where we set ignoreNotFound for the reason
456+ // why we ignore the NotFound error .
457+ if storage .IsNotFound (err ) && ignoreNotFound && lastExisting != nil {
458+ // The lastExisting object may not be the last state of the object
459+ // before its deletion, but it's the best approximation.
460+ return e .finalizeDelete (lastExisting , true )
461+ }
444462 return nil , etcderr .InterpretDeleteError (err , e .QualifiedResource , name )
445463 }
446464 return e .finalizeDelete (out , true )
0 commit comments