mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 03:41:45 +00:00
Merge pull request #32160 from mml/evict.test.extra
Automatic merge from submit-queue Refactor disruption e2e test and add some eviction test cases.
This commit is contained in:
commit
a26da7a1c4
@ -23,14 +23,24 @@ import (
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
release_1_4 "k8s.io/client-go/1.4/kubernetes"
|
||||
apiapi "k8s.io/client-go/1.4/pkg/api"
|
||||
"k8s.io/client-go/1.4/pkg/api/unversioned"
|
||||
api "k8s.io/client-go/1.4/pkg/api/v1"
|
||||
extensions "k8s.io/client-go/1.4/pkg/apis/extensions/v1beta1"
|
||||
policy "k8s.io/client-go/1.4/pkg/apis/policy/v1alpha1"
|
||||
"k8s.io/client-go/1.4/pkg/util/intstr"
|
||||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
"k8s.io/kubernetes/test/e2e/framework"
|
||||
)
|
||||
|
||||
// timeout is used for most polling/waiting activities
|
||||
const timeout = 60 * time.Second
|
||||
|
||||
// schedulingTimeout is longer specifically because sometimes we need to wait
|
||||
// awhile to guarantee that we've been patient waiting for something ordinary
|
||||
// to happen: a pod to get scheduled and move into Ready
|
||||
const schedulingTimeout = 5 * time.Minute
|
||||
|
||||
var _ = framework.KubeDescribe("DisruptionController", func() {
|
||||
f := framework.NewDefaultFramework("disruption")
|
||||
var ns string
|
||||
@ -55,7 +65,7 @@ var _ = framework.KubeDescribe("DisruptionController", func() {
|
||||
|
||||
// Since disruptionAllowed starts out false, if we see it ever become true,
|
||||
// that means the controller is working.
|
||||
err := wait.PollImmediate(framework.Poll, 60*time.Second, func() (bool, error) {
|
||||
err := wait.PollImmediate(framework.Poll, timeout, func() (bool, error) {
|
||||
pdb, err := cs.Policy().PodDisruptionBudgets(ns).Get("foo")
|
||||
if err != nil {
|
||||
return false, err
|
||||
@ -66,73 +76,107 @@ var _ = framework.KubeDescribe("DisruptionController", func() {
|
||||
|
||||
})
|
||||
|
||||
It("should allow an eviction when there is no PDB", func() {
|
||||
createPodsOrDie(cs, ns, 1)
|
||||
|
||||
pod, err := cs.Pods(ns).Get("pod-0")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
e := &policy.Eviction{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: pod.Name,
|
||||
Namespace: ns,
|
||||
},
|
||||
evictionCases := []struct {
|
||||
description string
|
||||
minAvailable intstr.IntOrString
|
||||
podCount int
|
||||
replicaSetSize int32
|
||||
shouldDeny bool
|
||||
exclusive bool
|
||||
}{
|
||||
{
|
||||
description: "no PDB",
|
||||
minAvailable: intstr.FromString(""),
|
||||
podCount: 1,
|
||||
shouldDeny: false,
|
||||
}, {
|
||||
description: "too few pods, absolute",
|
||||
minAvailable: intstr.FromInt(2),
|
||||
podCount: 1,
|
||||
shouldDeny: true,
|
||||
}, {
|
||||
description: "enough pods, absolute",
|
||||
minAvailable: intstr.FromInt(2),
|
||||
podCount: 2,
|
||||
shouldDeny: false,
|
||||
}, {
|
||||
description: "enough pods, replicaSet, percentage",
|
||||
minAvailable: intstr.FromString("100%"),
|
||||
replicaSetSize: 10,
|
||||
exclusive: false,
|
||||
shouldDeny: false,
|
||||
}, {
|
||||
description: "too few pods, replicaSet, percentage",
|
||||
minAvailable: intstr.FromString("100%"),
|
||||
replicaSetSize: 10,
|
||||
exclusive: true,
|
||||
shouldDeny: true,
|
||||
},
|
||||
}
|
||||
for _, c := range evictionCases {
|
||||
expectation := "should allow an eviction"
|
||||
if c.shouldDeny {
|
||||
expectation = "should not allow an eviction"
|
||||
}
|
||||
It(fmt.Sprintf("evictions: %s => %s", c.description, expectation), func() {
|
||||
createPodsOrDie(cs, ns, c.podCount)
|
||||
if c.replicaSetSize > 0 {
|
||||
createReplicaSetOrDie(cs, ns, c.replicaSetSize, c.exclusive)
|
||||
}
|
||||
|
||||
err = cs.Pods(ns).Evict(e)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
if c.minAvailable.String() != "" {
|
||||
createPodDisruptionBudgetOrDie(cs, ns, c.minAvailable)
|
||||
}
|
||||
|
||||
It("should not allow an eviction when too few pods", func() {
|
||||
createPodDisruptionBudgetOrDie(cs, ns, intstr.FromInt(2))
|
||||
// Locate a running pod.
|
||||
var pod api.Pod
|
||||
err := wait.PollImmediate(framework.Poll, schedulingTimeout, func() (bool, error) {
|
||||
podList, err := cs.Pods(ns).List(apiapi.ListOptions{})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
createPodsOrDie(cs, ns, 1)
|
||||
for i := range podList.Items {
|
||||
if podList.Items[i].Status.Phase == api.PodRunning {
|
||||
pod = podList.Items[i]
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
pod, err := cs.Pods(ns).Get("pod-0")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
e := &policy.Eviction{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: pod.Name,
|
||||
Namespace: ns,
|
||||
},
|
||||
}
|
||||
|
||||
// Since disruptionAllowed starts out false, wait at least 60s hoping that
|
||||
// this gives the controller enough time to have truly set the status.
|
||||
time.Sleep(60 * time.Second)
|
||||
|
||||
err = cs.Pods(ns).Evict(e)
|
||||
Expect(err).Should(MatchError("Cannot evict pod as it would violate the pod's disruption budget."))
|
||||
})
|
||||
|
||||
It("should allow an eviction when enough pods", func() {
|
||||
createPodDisruptionBudgetOrDie(cs, ns, intstr.FromInt(2))
|
||||
|
||||
createPodsOrDie(cs, ns, 2)
|
||||
|
||||
pod, err := cs.Pods(ns).Get("pod-0")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
e := &policy.Eviction{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: pod.Name,
|
||||
Namespace: ns,
|
||||
},
|
||||
}
|
||||
|
||||
// Since disruptionAllowed starts out false, if an eviction is ever allowed,
|
||||
// that means the controller is working.
|
||||
err = wait.PollImmediate(framework.Poll, 60*time.Second, func() (bool, error) {
|
||||
err = cs.Pods(ns).Evict(e)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
e := &policy.Eviction{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: pod.Name,
|
||||
Namespace: ns,
|
||||
},
|
||||
}
|
||||
|
||||
if c.shouldDeny {
|
||||
// Since disruptionAllowed starts out false, wait at least 60s hoping that
|
||||
// this gives the controller enough time to have truly set the status.
|
||||
time.Sleep(timeout)
|
||||
|
||||
err = cs.Pods(ns).Evict(e)
|
||||
Expect(err).Should(MatchError("Cannot evict pod as it would violate the pod's disruption budget."))
|
||||
} else {
|
||||
return true, nil
|
||||
// Since disruptionAllowed starts out false, if an eviction is ever allowed,
|
||||
// that means the controller is working.
|
||||
err = wait.PollImmediate(framework.Poll, timeout, func() (bool, error) {
|
||||
err = cs.Pods(ns).Evict(e)
|
||||
if err != nil {
|
||||
return false, nil
|
||||
} else {
|
||||
return true, nil
|
||||
}
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
})
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
})
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
func createPodDisruptionBudgetOrDie(cs *release_1_4.Clientset, ns string, minAvailable intstr.IntOrString) {
|
||||
@ -173,3 +217,39 @@ func createPodsOrDie(cs *release_1_4.Clientset, ns string, n int) {
|
||||
framework.ExpectNoError(err, "Creating pod %q in namespace %q", pod.Name, ns)
|
||||
}
|
||||
}
|
||||
|
||||
func createReplicaSetOrDie(cs *release_1_4.Clientset, ns string, size int32, exclusive bool) {
|
||||
container := api.Container{
|
||||
Name: "busybox",
|
||||
Image: "gcr.io/google_containers/echoserver:1.4",
|
||||
}
|
||||
if exclusive {
|
||||
container.Ports = []api.ContainerPort{
|
||||
{HostPort: 5555, ContainerPort: 5555},
|
||||
}
|
||||
}
|
||||
|
||||
rs := &extensions.ReplicaSet{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "rs",
|
||||
Namespace: ns,
|
||||
},
|
||||
Spec: extensions.ReplicaSetSpec{
|
||||
Replicas: &size,
|
||||
Selector: &extensions.LabelSelector{
|
||||
MatchLabels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
Template: api.PodTemplateSpec{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{container},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := cs.Extensions().ReplicaSets(ns).Create(rs)
|
||||
framework.ExpectNoError(err, "Creating replica set %q in namespace %q", rs.Name, ns)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user