Introduction of a pod condition type indicating disruption. Its reason
field indicates the reason:
- PreemptionByKubeScheduler (Pod preempted by kube-scheduler) - DeletionByTaintManager (Pod deleted by taint manager due to NoExecute taint) - EvictionByEvictionAPI (Pod evicted by Eviction API) - DeletionByPodGC (an orphaned Pod deleted by PodGC)PreemptedByScheduler (Pod preempted by kube-scheduler)
This commit is contained in:
@@ -32,12 +32,14 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/apiserver/pkg/util/dryrun"
|
||||
"k8s.io/apiserver/pkg/util/feature"
|
||||
policyclient "k8s.io/client-go/kubernetes/typed/policy/v1"
|
||||
"k8s.io/client-go/util/retry"
|
||||
pdbhelper "k8s.io/component-helpers/apps/poddisruptionbudget"
|
||||
podutil "k8s.io/kubernetes/pkg/api/pod"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/policy"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -153,11 +155,10 @@ func (r *EvictionREST) Create(ctx context.Context, name string, obj runtime.Obje
|
||||
}
|
||||
|
||||
err = retry.OnError(EvictionsRetry, shouldRetry, func() error {
|
||||
obj, err = r.store.Get(ctx, eviction.Name, &metav1.GetOptions{})
|
||||
pod, err = getPod(r, ctx, eviction.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pod = obj.(*api.Pod)
|
||||
|
||||
// Evicting a terminal pod should result in direct deletion of pod as it already caused disruption by the time we are evicting.
|
||||
// There is no need to check for pdb.
|
||||
@@ -178,7 +179,7 @@ func (r *EvictionREST) Create(ctx context.Context, name string, obj runtime.Obje
|
||||
deleteOptions = deleteOptions.DeepCopy()
|
||||
setPreconditionsResourceVersion(deleteOptions, &pod.ResourceVersion)
|
||||
}
|
||||
_, _, err = r.store.Delete(ctx, eviction.Name, rest.ValidateAllObjectFunc, deleteOptions)
|
||||
err = addConditionAndDeletePod(r, ctx, eviction.Name, rest.ValidateAllObjectFunc, deleteOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -276,7 +277,7 @@ func (r *EvictionREST) Create(ctx context.Context, name string, obj runtime.Obje
|
||||
}
|
||||
|
||||
// Try the delete
|
||||
_, _, err = r.store.Delete(ctx, eviction.Name, rest.ValidateAllObjectFunc, deleteOptions)
|
||||
err = addConditionAndDeletePod(r, ctx, eviction.Name, rest.ValidateAllObjectFunc, deleteOptions)
|
||||
if err != nil {
|
||||
if errors.IsConflict(err) && updateDeletionOptions &&
|
||||
(originalDeleteOptions.Preconditions == nil || originalDeleteOptions.Preconditions.ResourceVersion == nil) {
|
||||
@@ -292,6 +293,41 @@ func (r *EvictionREST) Create(ctx context.Context, name string, obj runtime.Obje
|
||||
return &metav1.Status{Status: metav1.StatusSuccess}, nil
|
||||
}
|
||||
|
||||
func addConditionAndDeletePod(r *EvictionREST, ctx context.Context, name string, validation rest.ValidateObjectFunc, options *metav1.DeleteOptions) error {
|
||||
if feature.DefaultFeatureGate.Enabled(features.PodDisruptionConditions) {
|
||||
pod, err := getPod(r, ctx, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
conditionAppender := func(_ context.Context, newObj, _ runtime.Object) (runtime.Object, error) {
|
||||
podObj := newObj.(*api.Pod)
|
||||
podutil.UpdatePodCondition(&podObj.Status, &api.PodCondition{
|
||||
Type: api.AlphaNoCompatGuaranteeDisruptionTarget,
|
||||
Status: api.ConditionTrue,
|
||||
Reason: "EvictionByEvictionAPI",
|
||||
Message: "Eviction API: evicting",
|
||||
})
|
||||
return podObj, nil
|
||||
}
|
||||
|
||||
podCopyUpdated := rest.DefaultUpdatedObjectInfo(pod, conditionAppender)
|
||||
|
||||
if _, _, err = r.store.Update(ctx, name, podCopyUpdated, rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, _, err := r.store.Delete(ctx, name, rest.ValidateAllObjectFunc, options)
|
||||
return err
|
||||
}
|
||||
|
||||
func getPod(r *EvictionREST, ctx context.Context, name string) (*api.Pod, error) {
|
||||
obj, err := r.store.Get(ctx, name, &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*api.Pod), nil
|
||||
}
|
||||
|
||||
func setPreconditionsResourceVersion(deleteOptions *metav1.DeleteOptions, resourceVersion *string) {
|
||||
if deleteOptions.Preconditions == nil {
|
||||
deleteOptions.Preconditions = &metav1.Preconditions{}
|
||||
|
@@ -105,7 +105,7 @@ func NewStorage(optsGetter generic.RESTOptionsGetter, k client.ConnectionInfoGet
|
||||
Pod: &REST{store, proxyTransport},
|
||||
Binding: &BindingREST{store: store},
|
||||
LegacyBinding: &LegacyBindingREST{bindingREST},
|
||||
Eviction: newEvictionStorage(store, podDisruptionBudgetClient),
|
||||
Eviction: newEvictionStorage(&statusStore, podDisruptionBudgetClient),
|
||||
Status: &StatusREST{store: &statusStore},
|
||||
EphemeralContainers: &EphemeralContainersREST{store: &ephemeralContainersStore},
|
||||
Log: &podrest.LogREST{Store: store, KubeletConn: k},
|
||||
|
Reference in New Issue
Block a user