Do not delete pods in a non-graceful manner
This moves from forcefully deleting pods to deleting pods in a graceful manner from the API Server. It waits for the pod to get to a terminal status prior to deleting the pod from api server.
This commit is contained in:
97
node/pod.go
97
node/pod.go
@@ -19,7 +19,6 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
pkgerrors "github.com/pkg/errors"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/errdefs"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/log"
|
||||
"github.com/virtual-kubelet/virtual-kubelet/trace"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -133,61 +132,19 @@ func (pc *PodController) handleProviderError(ctx context.Context, span trace.Spa
|
||||
span.SetStatus(origErr)
|
||||
}
|
||||
|
||||
func (pc *PodController) deletePod(ctx context.Context, namespace, name string) error {
|
||||
func (pc *PodController) deletePod(ctx context.Context, pod *corev1.Pod) error {
|
||||
ctx, span := trace.StartSpan(ctx, "deletePod")
|
||||
defer span.End()
|
||||
|
||||
pod, err := pc.provider.GetPod(ctx, namespace, name)
|
||||
if err != nil {
|
||||
if errdefs.IsNotFound(err) {
|
||||
// The provider is not aware of the pod, but we must still delete the Kubernetes API resource.
|
||||
return pc.forceDeletePodResource(ctx, namespace, name)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// NOTE: Some providers return a non-nil error in their GetPod implementation when the pod is not found while some other don't.
|
||||
if pod == nil {
|
||||
// The provider is not aware of the pod, but we must still delete the Kubernetes API resource.
|
||||
return pc.forceDeletePodResource(ctx, namespace, name)
|
||||
}
|
||||
|
||||
ctx = addPodAttributes(ctx, span, pod)
|
||||
|
||||
var delErr error
|
||||
if delErr = pc.provider.DeletePod(ctx, pod.DeepCopy()); delErr != nil && !errdefs.IsNotFound(delErr) {
|
||||
span.SetStatus(delErr)
|
||||
return delErr
|
||||
err := pc.provider.DeletePod(ctx, pod.DeepCopy())
|
||||
if err != nil {
|
||||
span.SetStatus(err)
|
||||
return err
|
||||
}
|
||||
|
||||
log.G(ctx).Debug("Deleted pod from provider")
|
||||
|
||||
if err := pc.forceDeletePodResource(ctx, namespace, name); err != nil {
|
||||
span.SetStatus(err)
|
||||
return err
|
||||
}
|
||||
log.G(ctx).Info("Deleted pod from Kubernetes")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pc *PodController) forceDeletePodResource(ctx context.Context, namespace, name string) error {
|
||||
ctx, span := trace.StartSpan(ctx, "forceDeletePodResource")
|
||||
defer span.End()
|
||||
ctx = span.WithFields(ctx, log.Fields{
|
||||
"namespace": namespace,
|
||||
"name": name,
|
||||
})
|
||||
|
||||
var grace int64
|
||||
if err := pc.client.Pods(namespace).Delete(name, &metav1.DeleteOptions{GracePeriodSeconds: &grace}); err != nil {
|
||||
if errors.IsNotFound(err) {
|
||||
log.G(ctx).Debug("Pod does not exist in Kubernetes, nothing to delete")
|
||||
return nil
|
||||
}
|
||||
span.SetStatus(err)
|
||||
return pkgerrors.Wrap(err, "Failed to delete Kubernetes pod")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -280,3 +237,47 @@ func (pc *PodController) podStatusHandler(ctx context.Context, key string) (retE
|
||||
|
||||
return pc.updatePodStatus(ctx, pod, key)
|
||||
}
|
||||
|
||||
func (pc *PodController) deletePodHandler(ctx context.Context, key string) error {
|
||||
ctx, span := trace.StartSpan(ctx, "processDeletionReconcilationWorkItem")
|
||||
defer span.End()
|
||||
|
||||
namespace, name, err := cache.SplitMetaNamespaceKey(key)
|
||||
ctx = span.WithFields(ctx, log.Fields{
|
||||
"namespace": namespace,
|
||||
"name": name,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
// Log the error as a warning, but do not requeue the key as it is invalid.
|
||||
log.G(ctx).Warn(pkgerrors.Wrapf(err, "invalid resource key: %q", key))
|
||||
span.SetStatus(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the pod has been deleted from API server, we don't need to do anything.
|
||||
k8sPod, err := pc.podsLister.Pods(namespace).Get(name)
|
||||
if errors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
span.SetStatus(err)
|
||||
return err
|
||||
}
|
||||
|
||||
if running(&k8sPod.Status) {
|
||||
log.G(ctx).Error("Force deleting pod in running state")
|
||||
}
|
||||
|
||||
// We don't check with the provider before doing this delete. At this point, even if an outstanding pod status update
|
||||
// was in progress,
|
||||
err = pc.client.Pods(namespace).Delete(name, metav1.NewDeleteOptions(0))
|
||||
if errors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
span.SetStatus(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user