mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-07 03:03:59 +00:00
LimitRanger plugin annotates the pods it modifies
This commit is contained in:
parent
0662141f67
commit
8c3bea7e79
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user