LimitRanger plugin annotates the pods it modifies

This commit is contained in:
derekwaynecarr 2015-09-15 17:13:05 -04:00
parent 0662141f67
commit 8c3bea7e79
3 changed files with 65 additions and 0 deletions

View File

@ -19,6 +19,7 @@ package initialresources
import (
"flag"
"io"
"sort"
"strings"
"time"
@ -123,6 +124,7 @@ func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
req[api.ResourceMemory] = *mem
}
if len(setRes) > 0 {
sort.Strings(setRes)
a := strings.Join(setRes, ", ") + " request for container " + c.Name
annotations = append(annotations, a)
}

View File

@ -19,6 +19,8 @@ package limitranger
import (
"fmt"
"io"
"sort"
"strings"
"k8s.io/kubernetes/pkg/admission"
"k8s.io/kubernetes/pkg/api"
@ -33,6 +35,10 @@ import (
"k8s.io/kubernetes/pkg/watch"
)
const (
limitRangerAnnotation = "kubernetes.io/limit-ranger"
)
func init() {
admission.RegisterPlugin("LimitRanger", func(client client.Interface, config io.Reader) (admission.Interface, error) {
return NewLimitRanger(client, Limit), nil
@ -162,9 +168,14 @@ func defaultContainerResourceRequirements(limitRange *api.LimitRange) api.Resour
}
// mergePodResourceRequirements merges enumerated requirements with default requirements
// it annotates the pod with information about what requirements were modified
func mergePodResourceRequirements(pod *api.Pod, defaultRequirements *api.ResourceRequirements) {
annotations := []string{}
for i := range pod.Spec.Containers {
container := &pod.Spec.Containers[i]
setRequests := []string{}
setLimits := []string{}
if container.Resources.Limits == nil {
container.Resources.Limits = api.ResourceList{}
}
@ -175,14 +186,34 @@ func mergePodResourceRequirements(pod *api.Pod, defaultRequirements *api.Resourc
_, found := container.Resources.Limits[k]
if !found {
container.Resources.Limits[k] = *v.Copy()
setLimits = append(setLimits, string(k))
}
}
for k, v := range defaultRequirements.Requests {
_, found := container.Resources.Requests[k]
if !found {
container.Resources.Requests[k] = *v.Copy()
setRequests = append(setRequests, string(k))
}
}
if len(setRequests) > 0 {
sort.Strings(setRequests)
a := strings.Join(setRequests, ", ") + " request for container " + container.Name
annotations = append(annotations, a)
}
if len(setLimits) > 0 {
sort.Strings(setLimits)
a := strings.Join(setLimits, ", ") + " limit for container " + container.Name
annotations = append(annotations, a)
}
}
if len(annotations) > 0 {
if pod.ObjectMeta.Annotations == nil {
pod.ObjectMeta.Annotations = make(map[string]string)
}
val := "LimitRanger plugin set: " + strings.Join(annotations, "; ")
pod.ObjectMeta.Annotations[limitRangerAnnotation] = val
}
}

View File

@ -125,6 +125,7 @@ func validPod(name string, numContainers int, resources api.ResourceRequirements
pod.Spec.Containers = append(pod.Spec.Containers, api.Container{
Image: "foo:V" + strconv.Itoa(i),
Resources: resources,
Name: "foo-" + strconv.Itoa(i),
})
}
return pod
@ -145,6 +146,22 @@ func TestDefaultContainerResourceRequirements(t *testing.T) {
}
}
func verifyAnnotation(t *testing.T, pod *api.Pod, expected string) {
a, ok := pod.ObjectMeta.Annotations[limitRangerAnnotation]
if !ok {
t.Errorf("No annotation but expected %v", expected)
}
if a != expected {
t.Errorf("Wrong annotation set by Limit Ranger: got %v, expected %v", a, expected)
}
}
func expectNoAnnotation(t *testing.T, pod *api.Pod) {
if a, ok := pod.ObjectMeta.Annotations[limitRangerAnnotation]; ok {
t.Errorf("Expected no annotation but got %v", a)
}
}
func TestMergePodResourceRequirements(t *testing.T) {
limitRange := validLimitRange()
@ -159,6 +176,7 @@ func TestMergePodResourceRequirements(t *testing.T) {
t.Errorf("pod %v, expected != actual; %v != %v", pod.Name, expected, actual)
}
}
verifyAnnotation(t, &pod, "LimitRanger plugin set: cpu, memory request for container foo-0; cpu, memory limit for container foo-0")
// pod with some resources enumerated should only merge empty
input := getResourceRequirements(getResourceList("", "512Mi"), getResourceList("", ""))
@ -177,6 +195,20 @@ func TestMergePodResourceRequirements(t *testing.T) {
t.Errorf("pod %v, expected != actual; %v != %v", pod.Name, expected, actual)
}
}
verifyAnnotation(t, &pod, "LimitRanger plugin set: cpu request for container foo-0; cpu, memory limit for container foo-0")
// pod with all resources enumerated should not merge anything
input = getResourceRequirements(getResourceList("100m", "512Mi"), getResourceList("200m", "1G"))
pod = validPod("limit-memory", 1, input)
expected = input
mergePodResourceRequirements(&pod, &defaultRequirements)
for i := range pod.Spec.Containers {
actual := pod.Spec.Containers[i].Resources
if !api.Semantic.DeepEqual(expected, actual) {
t.Errorf("pod %v, expected != actual; %v != %v", pod.Name, expected, actual)
}
}
expectNoAnnotation(t, &pod)
}
func TestPodLimitFunc(t *testing.T) {