Skip to content

Commit

Permalink
Add e2e test for DaemonSet pod affinity
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Shvedunov committed Oct 13, 2016
1 parent f46ddc5 commit ba437c0
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 12 deletions.
110 changes: 110 additions & 0 deletions test/e2e/daemon_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ var _ = framework.KubeDescribe("Daemon set [Serial]", func() {

var ns string
var c *client.Client
ignoreLabels := framework.ImagePullerLabels

BeforeEach(func() {
ns = f.Namespace.Name
Expand Down Expand Up @@ -269,6 +270,115 @@ var _ = framework.KubeDescribe("Daemon set [Serial]", func() {
Expect(c.DaemonSets(ns).Delete(dsName)).NotTo(HaveOccurred())

})

It("should respect InterPodAffinity", func() {
nodeNames, cleanupPods := getTwoNodesByCreatingTwoPods(f)
cleanupPods()

By("Trying to create a DaemonSet that runs on one of the nodes but not another")
node0Affinity := map[string]string{
api.AffinityAnnotationKey: `{
"nodeAffinity": {
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [{
"matchExpressions": [{
"key": "kubernetes.io/hostname",
"operator": "In",
"values": ["` + nodeNames[0] + `"]
}]
}]
}
}
}`,
}
_, err := c.DaemonSets(ns).Create(&extensions.DaemonSet{
ObjectMeta: api.ObjectMeta{
Name: "ds1",
},
Spec: extensions.DaemonSetSpec{
Template: api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: map[string]string{"e2e-ds-antiaffinity-test": "true"},
Annotations: node0Affinity,
},
Spec: api.PodSpec{
Containers: []api.Container{
{
Name: "ds1",
Image: framework.GetPauseImageName(f.Client),
},
},
},
},
},
})
ExpectNoError(err)

err = framework.WaitForPodsRunningReady(c, ns, 1, framework.PodReadyBeforeTimeout, ignoreLabels)
Expect(err).NotTo(HaveOccurred())

By("Trying to create a DaemonSet that attempts to run on both nodes but can only run on one of them due to PodAntiAffinity")
node01AffinityAndPodAntiAffinity := map[string]string{
api.AffinityAnnotationKey: `{
"nodeAffinity": {
"requiredDuringSchedulingIgnoredDuringExecution": {
"nodeSelectorTerms": [{
"matchExpressions": [{
"key": "kubernetes.io/hostname",
"operator": "In",
"values": ["` + nodeNames[0] + `", "` + nodeNames[1] + `"]
}]
}]
}
},
"podAntiAffinity": {
"requiredDuringSchedulingIgnoredDuringExecution": [{
"labelSelector": {
"matchLabels": {
"e2e-ds-antiaffinity-test": "true"
}
},
"topologyKey": "kubernetes.io/hostname"
}]
}
}`,
}
_, err = c.DaemonSets(ns).Create(&extensions.DaemonSet{
ObjectMeta: api.ObjectMeta{
Name: "ds2",
},
Spec: extensions.DaemonSetSpec{
Template: api.PodTemplateSpec{
ObjectMeta: api.ObjectMeta{
Labels: map[string]string{"e2e-foo": "bar"},
Annotations: node01AffinityAndPodAntiAffinity,
},
Spec: api.PodSpec{
Containers: []api.Container{
{
Name: "ds2",
Image: framework.GetPauseImageName(f.Client),
},
},
},
},
},
})
ExpectNoError(err)

err = framework.WaitForPodsRunningReady(c, ns, 2, framework.PodReadyBeforeTimeout, ignoreLabels)
Expect(err).NotTo(HaveOccurred())

By("Waiting 10 seconds")
time.Sleep(time.Duration(10 * time.Second))

By("Verifying daemon pods")
ds, err := c.DaemonSets(ns).Get("ds2")
framework.ExpectNoError(err)

Expect(ds.Status.DesiredNumberScheduled).To(Equal(int32(1)))
Expect(ds.Status.CurrentNumberScheduled).To(Equal(int32(1)))
})
})

func separateDaemonSetNodeLabels(labels map[string]string) (map[string]string, map[string]string) {
Expand Down
31 changes: 19 additions & 12 deletions test/e2e/scheduler_predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -507,18 +507,8 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {

// test when the pod anti affinity rule is not satisfied, the pod would stay pending.
It("validates that InterPodAntiAffinity is respected if matching 2", func() {
// launch pods to find nodes which can launch a pod. We intentionally do
// not just take the node list and choose the first and the second of them.
// Depending on the cluster and the scheduler it might be that a "normal" pod
// cannot be scheduled onto it.
By("Launching two pods on two distinct nodes to get two node names")
CreateHostPortPods(f, "host-port", 2, true)
defer framework.DeleteRCAndPods(c, f.ClientSet, ns, "host-port")
podList, err := c.Pods(ns).List(api.ListOptions{})
ExpectNoError(err)
Expect(len(podList.Items)).To(Equal(2))
nodeNames := []string{podList.Items[0].Spec.NodeName, podList.Items[1].Spec.NodeName}
Expect(nodeNames[0]).ToNot(Equal(nodeNames[1]))
nodeNames, cleanupPods := getTwoNodesByCreatingTwoPods(f)
defer cleanupPods()

By("Applying a random label to both nodes.")
k := "e2e.inter-pod-affinity.kubernetes.io/zone"
Expand Down Expand Up @@ -955,3 +945,20 @@ func getNodeThatCanRunPodWithoutToleration(f *framework.Framework) string {
By("Trying to launch a pod without a toleration to get a node which can launch it.")
return runPodAndGetNodeName(f, pausePodConfig{Name: "without-toleration"})
}

func getTwoNodesByCreatingTwoPods(f *framework.Framework) ([]string, func()) {
// launch pods to find nodes which can launch a pod. We intentionally do
// not just take the node list and choose the first and the second of them.
// Depending on the cluster and the scheduler it might be that a "normal" pod
// cannot be scheduled onto it.
By("Launching two pods on two distinct nodes to get two node names")
CreateHostPortPods(f, "host-port", 2, true)
podList, err := f.Client.Pods(f.Namespace.Name).List(api.ListOptions{})
ExpectNoError(err)
Expect(len(podList.Items)).To(Equal(2))
nodeNames := []string{podList.Items[0].Spec.NodeName, podList.Items[1].Spec.NodeName}
Expect(nodeNames[0]).ToNot(Equal(nodeNames[1]))
return nodeNames, func() {
framework.DeleteRCAndPods(f.Client, f.ClientSet, f.Namespace.Name, "host-port")
}
}

0 comments on commit ba437c0

Please sign in to comment.