implement taints and tolerations
This commit is contained in:
@@ -19,6 +19,7 @@ package e2e
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
@@ -1280,4 +1281,250 @@ var _ = framework.KubeDescribe("SchedulerPredicates [Serial]", func() {
|
||||
framework.ExpectNoError(err)
|
||||
Expect(labelPod.Spec.NodeName).To(Equal(nodeName))
|
||||
})
|
||||
|
||||
// 1. Run a pod to get an available node, then delete the pod
|
||||
// 2. Taint the node with a random taint
|
||||
// 3. Try to relaunch the pod with tolerations tolerate the taints on node,
|
||||
// and the pod's nodeName specified to the name of node found in step 1
|
||||
It("validates that taints-tolerations is respected if matching", func() {
|
||||
// launch a pod to find a node which can launch a pod. We intentionally do
|
||||
// not just take the node list and choose the first of them. Depending on the
|
||||
// cluster and the scheduler it might be that a "normal" pod cannot be
|
||||
// scheduled onto it.
|
||||
By("Trying to launch a pod without a toleration to get a node which can launch it.")
|
||||
podName := "without-toleration"
|
||||
_, err := c.Pods(ns).Create(&api.Pod{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "Pod",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: podName,
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: podName,
|
||||
Image: "gcr.io/google_containers/pause-amd64:3.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
framework.ExpectNoError(err)
|
||||
framework.ExpectNoError(framework.WaitForPodRunningInNamespace(c, podName, ns))
|
||||
pod, err := c.Pods(ns).Get(podName)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
nodeName := pod.Spec.NodeName
|
||||
err = c.Pods(ns).Delete(podName, api.NewDeleteOptions(0))
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
By("Trying to apply a random taint on the found node.")
|
||||
taintName := fmt.Sprintf("kubernetes.io/e2e-taint-key-%s", string(util.NewUUID()))
|
||||
taintValue := "testing-taint-value"
|
||||
taintEffect := string(api.TaintEffectNoSchedule)
|
||||
framework.RunKubectlOrDie("taint", "nodes", nodeName, taintName+"="+taintValue+":"+taintEffect)
|
||||
By("verifying the node has the taint " + taintName + " with the value " + taintValue)
|
||||
output := framework.RunKubectlOrDie("describe", "node", nodeName)
|
||||
requiredStrings := [][]string{
|
||||
{"Name:", nodeName},
|
||||
{"Taints:"},
|
||||
{taintName, taintValue, taintEffect},
|
||||
}
|
||||
checkOutput(output, requiredStrings)
|
||||
|
||||
By("Trying to apply a random label on the found node.")
|
||||
labelKey := fmt.Sprintf("kubernetes.io/e2e-label-key-%s", string(util.NewUUID()))
|
||||
labelValue := "testing-label-value"
|
||||
framework.RunKubectlOrDie("label", "nodes", nodeName, labelKey+"="+labelValue)
|
||||
By("verifying the node has the label " + labelKey + " with the value " + labelValue)
|
||||
labelOutput := framework.RunKubectlOrDie("describe", "node", nodeName)
|
||||
labelOutputRequiredStrings := [][]string{
|
||||
{"Name:", nodeName},
|
||||
{"Labels:"},
|
||||
{labelKey + "=" + labelValue},
|
||||
}
|
||||
checkOutput(labelOutput, labelOutputRequiredStrings)
|
||||
|
||||
By("Trying to relaunch the pod, now with tolerations.")
|
||||
tolerationPodName := "with-tolerations"
|
||||
_, err = c.Pods(ns).Create(&api.Pod{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "Pod",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: tolerationPodName,
|
||||
Annotations: map[string]string{
|
||||
"scheduler.alpha.kubernetes.io/tolerations": `
|
||||
[
|
||||
{
|
||||
"key": "` + taintName + `",
|
||||
"value": "` + taintValue + `",
|
||||
"effect": "` + taintEffect + `"
|
||||
}
|
||||
]`,
|
||||
},
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
NodeSelector: map[string]string{labelKey: labelValue},
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: tolerationPodName,
|
||||
Image: "gcr.io/google_containers/pause-amd64:3.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
framework.ExpectNoError(err)
|
||||
defer c.Pods(ns).Delete(tolerationPodName, api.NewDeleteOptions(0))
|
||||
|
||||
// check that pod got scheduled. We intentionally DO NOT check that the
|
||||
// pod is running because this will create a race condition with the
|
||||
// kubelet and the scheduler: the scheduler might have scheduled a pod
|
||||
// already when the kubelet does not know about its new taint yet. The
|
||||
// kubelet will then refuse to launch the pod.
|
||||
framework.ExpectNoError(framework.WaitForPodNotPending(c, ns, tolerationPodName))
|
||||
deployedPod, err := c.Pods(ns).Get(tolerationPodName)
|
||||
framework.ExpectNoError(err)
|
||||
Expect(deployedPod.Spec.NodeName).To(Equal(nodeName))
|
||||
|
||||
By("removing the taint " + taintName + " off the node " + nodeName)
|
||||
framework.RunKubectlOrDie("taint", "nodes", nodeName, taintName+"-")
|
||||
By("verifying the node doesn't have the taint " + taintName)
|
||||
output = framework.RunKubectlOrDie("describe", "node", nodeName)
|
||||
if strings.Contains(output, taintName) {
|
||||
framework.Failf("Failed removing taint " + taintName + " of the node " + nodeName)
|
||||
}
|
||||
|
||||
By("removing the label " + labelKey + " off the node " + nodeName)
|
||||
framework.RunKubectlOrDie("label", "nodes", nodeName, labelKey+"-")
|
||||
By("verifying the node doesn't have the label " + labelKey)
|
||||
output = framework.RunKubectlOrDie("describe", "node", nodeName)
|
||||
if strings.Contains(output, labelKey) {
|
||||
framework.Failf("Failed removing label " + labelKey + " of the node " + nodeName)
|
||||
}
|
||||
})
|
||||
|
||||
// 1. Run a pod to get an available node, then delete the pod
|
||||
// 2. Taint the node with a random taint
|
||||
// 3. Try to relaunch the pod still no tolerations,
|
||||
// and the pod's nodeName specified to the name of node found in step 1
|
||||
It("validates that taints-tolerations is respected if not matching", func() {
|
||||
// launch a pod to find a node which can launch a pod. We intentionally do
|
||||
// not just take the node list and choose the first of them. Depending on the
|
||||
// cluster and the scheduler it might be that a "normal" pod cannot be
|
||||
// scheduled onto it.
|
||||
By("Trying to launch a pod without a toleration to get a node which can launch it.")
|
||||
podName := "without-toleration"
|
||||
_, err := c.Pods(ns).Create(&api.Pod{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "Pod",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: podName,
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: podName,
|
||||
Image: "gcr.io/google_containers/pause-amd64:3.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
framework.ExpectNoError(err)
|
||||
framework.ExpectNoError(framework.WaitForPodRunningInNamespace(c, podName, ns))
|
||||
pod, err := c.Pods(ns).Get(podName)
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
nodeName := pod.Spec.NodeName
|
||||
err = c.Pods(ns).Delete(podName, api.NewDeleteOptions(0))
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
By("Trying to apply a random taint on the found node.")
|
||||
taintName := fmt.Sprintf("kubernetes.io/e2e-taint-key-%s", string(util.NewUUID()))
|
||||
taintValue := "testing-taint-value"
|
||||
taintEffect := string(api.TaintEffectNoSchedule)
|
||||
framework.RunKubectlOrDie("taint", "nodes", nodeName, taintName+"="+taintValue+":"+taintEffect)
|
||||
By("verifying the node has the taint " + taintName + " with the value " + taintValue)
|
||||
output := framework.RunKubectlOrDie("describe", "node", nodeName)
|
||||
requiredStrings := [][]string{
|
||||
{"Name:", nodeName},
|
||||
{"Taints:"},
|
||||
{taintName, taintValue, taintEffect},
|
||||
}
|
||||
checkOutput(output, requiredStrings)
|
||||
|
||||
By("Trying to apply a random label on the found node.")
|
||||
labelKey := fmt.Sprintf("kubernetes.io/e2e-label-key-%s", string(util.NewUUID()))
|
||||
labelValue := "testing-label-value"
|
||||
framework.RunKubectlOrDie("label", "nodes", nodeName, labelKey+"="+labelValue)
|
||||
By("verifying the node has the label " + labelKey + " with the value " + labelValue)
|
||||
labelOutput := framework.RunKubectlOrDie("describe", "node", nodeName)
|
||||
labelOutputRequiredStrings := [][]string{
|
||||
{"Name:", nodeName},
|
||||
{"Labels:"},
|
||||
{labelKey + "=" + labelValue},
|
||||
}
|
||||
checkOutput(labelOutput, labelOutputRequiredStrings)
|
||||
|
||||
By("Trying to relaunch the pod, still no tolerations.")
|
||||
podNameNoTolerations := "still-no-tolerations"
|
||||
podNoTolerations := api.Pod{
|
||||
TypeMeta: unversioned.TypeMeta{
|
||||
Kind: "Pod",
|
||||
},
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: podNameNoTolerations,
|
||||
},
|
||||
Spec: api.PodSpec{
|
||||
NodeSelector: map[string]string{labelKey: labelValue},
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: podNameNoTolerations,
|
||||
Image: "gcr.io/google_containers/pause-amd64:3.0",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err = c.Pods(ns).Create(&podNoTolerations)
|
||||
framework.ExpectNoError(err)
|
||||
// Wait a bit to allow scheduler to do its thing
|
||||
// TODO: this is brittle; there's no guarantee the scheduler will have run in 10 seconds.
|
||||
framework.Logf("Sleeping 10 seconds and crossing our fingers that scheduler will run in that time.")
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
verifyResult(c, podNameNoTolerations, ns)
|
||||
cleanupPods(c, ns)
|
||||
|
||||
By("removing the taint " + taintName + " off the node " + nodeName)
|
||||
framework.RunKubectlOrDie("taint", "nodes", nodeName, taintName+"-")
|
||||
By("verifying the node doesn't have the taint " + taintName)
|
||||
output = framework.RunKubectlOrDie("describe", "node", nodeName)
|
||||
if strings.Contains(output, taintName) {
|
||||
framework.Failf("Failed removing taint " + taintName + " of the node " + nodeName)
|
||||
}
|
||||
|
||||
By("Trying to relaunch the same.")
|
||||
_, err = c.Pods(ns).Create(&podNoTolerations)
|
||||
framework.ExpectNoError(err)
|
||||
defer c.Pods(ns).Delete(podNameNoTolerations, api.NewDeleteOptions(0))
|
||||
|
||||
// check that pod got scheduled. We intentionally DO NOT check that the
|
||||
// pod is running because this will create a race condition with the
|
||||
// kubelet and the scheduler: the scheduler might have scheduled a pod
|
||||
// already when the kubelet does not know about its new taint yet. The
|
||||
// kubelet will then refuse to launch the pod.
|
||||
framework.ExpectNoError(framework.WaitForPodNotPending(c, ns, podNameNoTolerations))
|
||||
deployedPod, err := c.Pods(ns).Get(podNameNoTolerations)
|
||||
framework.ExpectNoError(err)
|
||||
Expect(deployedPod.Spec.NodeName).To(Equal(nodeName))
|
||||
|
||||
By("removing the label " + labelKey + " off the node " + nodeName)
|
||||
framework.RunKubectlOrDie("label", "nodes", nodeName, labelKey+"-")
|
||||
By("verifying the node doesn't have the label " + labelKey)
|
||||
output = framework.RunKubectlOrDie("describe", "node", nodeName)
|
||||
if strings.Contains(output, labelKey) {
|
||||
framework.Failf("Failed removing label " + labelKey + " of the node " + nodeName)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user