mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 00:07:50 +00:00
Merge pull request #85571 from mgugino-upstream-stage/drain-ignore-pdbs
kubectl/drain: add disable-eviction option
This commit is contained in:
commit
b42f21982c
@ -192,6 +192,7 @@ func NewCmdDrain(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobr
|
|||||||
cmd.Flags().DurationVar(&o.drainer.Timeout, "timeout", o.drainer.Timeout, "The length of time to wait before giving up, zero means infinite")
|
cmd.Flags().DurationVar(&o.drainer.Timeout, "timeout", o.drainer.Timeout, "The length of time to wait before giving up, zero means infinite")
|
||||||
cmd.Flags().StringVarP(&o.drainer.Selector, "selector", "l", o.drainer.Selector, "Selector (label query) to filter on")
|
cmd.Flags().StringVarP(&o.drainer.Selector, "selector", "l", o.drainer.Selector, "Selector (label query) to filter on")
|
||||||
cmd.Flags().StringVarP(&o.drainer.PodSelector, "pod-selector", "", o.drainer.PodSelector, "Label selector to filter pods on the node")
|
cmd.Flags().StringVarP(&o.drainer.PodSelector, "pod-selector", "", o.drainer.PodSelector, "Label selector to filter pods on the node")
|
||||||
|
cmd.Flags().BoolVar(&o.drainer.DisableEviction, "disable-eviction", o.drainer.DisableEviction, "Force drain to use delete, even if eviction is supported. This will bypass checking PodDisruptionBudgets, use with caution.")
|
||||||
|
|
||||||
cmdutil.AddDryRunFlag(cmd)
|
cmdutil.AddDryRunFlag(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
|
@ -52,8 +52,12 @@ type Helper struct {
|
|||||||
DeleteLocalData bool
|
DeleteLocalData bool
|
||||||
Selector string
|
Selector string
|
||||||
PodSelector string
|
PodSelector string
|
||||||
Out io.Writer
|
|
||||||
ErrOut io.Writer
|
// DisableEviction forces drain to use delete rather than evict
|
||||||
|
DisableEviction bool
|
||||||
|
|
||||||
|
Out io.Writer
|
||||||
|
ErrOut io.Writer
|
||||||
|
|
||||||
// TODO(justinsb): unnecessary?
|
// TODO(justinsb): unnecessary?
|
||||||
DryRun bool
|
DryRun bool
|
||||||
@ -179,17 +183,20 @@ func (d *Helper) DeleteOrEvictPods(pods []corev1.Pod) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
policyGroupVersion, err := CheckEvictionSupport(d.Client)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(justinsb): unnecessary?
|
// TODO(justinsb): unnecessary?
|
||||||
getPodFn := func(namespace, name string) (*corev1.Pod, error) {
|
getPodFn := func(namespace, name string) (*corev1.Pod, error) {
|
||||||
return d.Client.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
|
return d.Client.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
|
||||||
}
|
}
|
||||||
if len(policyGroupVersion) > 0 {
|
|
||||||
return d.evictPods(pods, policyGroupVersion, getPodFn)
|
if !d.DisableEviction {
|
||||||
|
policyGroupVersion, err := CheckEvictionSupport(d.Client)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(policyGroupVersion) > 0 {
|
||||||
|
return d.evictPods(pods, policyGroupVersion, getPodFn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.deletePods(pods, getPodFn)
|
return d.deletePods(pods, getPodFn)
|
||||||
|
@ -245,90 +245,114 @@ func TestCheckEvictionSupport(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteOrEvict(t *testing.T) {
|
func TestDeleteOrEvict(t *testing.T) {
|
||||||
for _, evictionSupported := range []bool{true, false} {
|
tests := []struct {
|
||||||
evictionSupported := evictionSupported
|
description string
|
||||||
t.Run(fmt.Sprintf("evictionSupported=%v", evictionSupported),
|
evictionSupported bool
|
||||||
func(t *testing.T) {
|
disableEviction bool
|
||||||
h := &Helper{
|
}{
|
||||||
Out: os.Stdout,
|
{
|
||||||
GracePeriodSeconds: 10,
|
description: "eviction supported/enabled",
|
||||||
}
|
evictionSupported: true,
|
||||||
|
disableEviction: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "eviction unsupported/disabled",
|
||||||
|
evictionSupported: false,
|
||||||
|
disableEviction: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "eviction supported/disabled",
|
||||||
|
evictionSupported: true,
|
||||||
|
disableEviction: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "eviction unsupported/disabled",
|
||||||
|
evictionSupported: false,
|
||||||
|
disableEviction: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.description, func(t *testing.T) {
|
||||||
|
h := &Helper{
|
||||||
|
Out: os.Stdout,
|
||||||
|
GracePeriodSeconds: 10,
|
||||||
|
}
|
||||||
|
|
||||||
// Create 4 pods, and try to remove the first 2
|
// Create 4 pods, and try to remove the first 2
|
||||||
var expectedEvictions []policyv1beta1.Eviction
|
var expectedEvictions []policyv1beta1.Eviction
|
||||||
var create []runtime.Object
|
var create []runtime.Object
|
||||||
deletePods := []corev1.Pod{}
|
deletePods := []corev1.Pod{}
|
||||||
for i := 1; i <= 4; i++ {
|
for i := 1; i <= 4; i++ {
|
||||||
pod := &corev1.Pod{}
|
pod := &corev1.Pod{}
|
||||||
pod.Name = fmt.Sprintf("mypod-%d", i)
|
pod.Name = fmt.Sprintf("mypod-%d", i)
|
||||||
pod.Namespace = "default"
|
pod.Namespace = "default"
|
||||||
|
|
||||||
create = append(create, pod)
|
create = append(create, pod)
|
||||||
if i <= 2 {
|
if i <= 2 {
|
||||||
deletePods = append(deletePods, *pod)
|
deletePods = append(deletePods, *pod)
|
||||||
|
|
||||||
if evictionSupported {
|
if tc.evictionSupported && !tc.disableEviction {
|
||||||
eviction := policyv1beta1.Eviction{}
|
eviction := policyv1beta1.Eviction{}
|
||||||
eviction.Kind = "Eviction"
|
eviction.Kind = "Eviction"
|
||||||
eviction.APIVersion = "policy/v1"
|
eviction.APIVersion = "policy/v1"
|
||||||
eviction.Namespace = pod.Namespace
|
eviction.Namespace = pod.Namespace
|
||||||
eviction.Name = pod.Name
|
eviction.Name = pod.Name
|
||||||
|
|
||||||
gracePeriodSeconds := int64(h.GracePeriodSeconds)
|
gracePeriodSeconds := int64(h.GracePeriodSeconds)
|
||||||
eviction.DeleteOptions = &metav1.DeleteOptions{
|
eviction.DeleteOptions = &metav1.DeleteOptions{
|
||||||
GracePeriodSeconds: &gracePeriodSeconds,
|
GracePeriodSeconds: &gracePeriodSeconds,
|
||||||
}
|
|
||||||
|
|
||||||
expectedEvictions = append(expectedEvictions, eviction)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectedEvictions = append(expectedEvictions, eviction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Build the fake client
|
// Build the fake client
|
||||||
k := fake.NewSimpleClientset(create...)
|
k := fake.NewSimpleClientset(create...)
|
||||||
if evictionSupported {
|
if tc.evictionSupported {
|
||||||
addEvictionSupport(t, k)
|
addEvictionSupport(t, k)
|
||||||
}
|
}
|
||||||
h.Client = k
|
h.Client = k
|
||||||
|
h.DisableEviction = tc.disableEviction
|
||||||
|
// Do the eviction
|
||||||
|
if err := h.DeleteOrEvictPods(deletePods); err != nil {
|
||||||
|
t.Fatalf("error from DeleteOrEvictPods: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Do the eviction
|
// Test that other pods are still there
|
||||||
if err := h.DeleteOrEvictPods(deletePods); err != nil {
|
var remainingPods []string
|
||||||
t.Fatalf("error from DeleteOrEvictPods: %v", err)
|
{
|
||||||
|
podList, err := k.CoreV1().Pods("").List(metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("error listing pods: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that other pods are still there
|
for _, pod := range podList.Items {
|
||||||
var remainingPods []string
|
remainingPods = append(remainingPods, pod.Namespace+"/"+pod.Name)
|
||||||
{
|
}
|
||||||
podList, err := k.CoreV1().Pods("").List(metav1.ListOptions{})
|
sort.Strings(remainingPods)
|
||||||
if err != nil {
|
}
|
||||||
t.Fatalf("error listing pods: %v", err)
|
expected := []string{"default/mypod-3", "default/mypod-4"}
|
||||||
}
|
if !reflect.DeepEqual(remainingPods, expected) {
|
||||||
|
t.Errorf("%s: unexpected remaining pods after DeleteOrEvictPods; actual %v; expected %v", tc.description, remainingPods, expected)
|
||||||
|
}
|
||||||
|
|
||||||
for _, pod := range podList.Items {
|
// Test that pods were evicted as expected
|
||||||
remainingPods = append(remainingPods, pod.Namespace+"/"+pod.Name)
|
var actualEvictions []policyv1beta1.Eviction
|
||||||
}
|
for _, action := range k.Actions() {
|
||||||
sort.Strings(remainingPods)
|
if action.GetVerb() != "create" || action.GetResource().Resource != "pods" || action.GetSubresource() != "eviction" {
|
||||||
}
|
continue
|
||||||
expected := []string{"default/mypod-3", "default/mypod-4"}
|
|
||||||
if !reflect.DeepEqual(remainingPods, expected) {
|
|
||||||
t.Errorf("unexpected remaining pods after DeleteOrEvictPods; actual %v; expected %v", remainingPods, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that pods were evicted as expected
|
|
||||||
var actualEvictions []policyv1beta1.Eviction
|
|
||||||
for _, action := range k.Actions() {
|
|
||||||
if action.GetVerb() != "create" || action.GetResource().Resource != "pods" || action.GetSubresource() != "eviction" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
eviction := *action.(ktest.CreateAction).GetObject().(*policyv1beta1.Eviction)
|
|
||||||
actualEvictions = append(actualEvictions, eviction)
|
|
||||||
}
|
|
||||||
sort.Slice(actualEvictions, func(i, j int) bool {
|
|
||||||
return actualEvictions[i].Name < actualEvictions[j].Name
|
|
||||||
})
|
|
||||||
if !reflect.DeepEqual(actualEvictions, expectedEvictions) {
|
|
||||||
t.Errorf("unexpected evictions; actual %v; expected %v", actualEvictions, expectedEvictions)
|
|
||||||
}
|
}
|
||||||
|
eviction := *action.(ktest.CreateAction).GetObject().(*policyv1beta1.Eviction)
|
||||||
|
actualEvictions = append(actualEvictions, eviction)
|
||||||
|
}
|
||||||
|
sort.Slice(actualEvictions, func(i, j int) bool {
|
||||||
|
return actualEvictions[i].Name < actualEvictions[j].Name
|
||||||
})
|
})
|
||||||
|
if !reflect.DeepEqual(actualEvictions, expectedEvictions) {
|
||||||
|
t.Errorf("%s: unexpected evictions; actual %v; expected %v", tc.description, actualEvictions, expectedEvictions)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user