mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-11 21:12:07 +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 (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"io"
|
"io"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -123,6 +124,7 @@ func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
|
|||||||
req[api.ResourceMemory] = *mem
|
req[api.ResourceMemory] = *mem
|
||||||
}
|
}
|
||||||
if len(setRes) > 0 {
|
if len(setRes) > 0 {
|
||||||
|
sort.Strings(setRes)
|
||||||
a := strings.Join(setRes, ", ") + " request for container " + c.Name
|
a := strings.Join(setRes, ", ") + " request for container " + c.Name
|
||||||
annotations = append(annotations, a)
|
annotations = append(annotations, a)
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,8 @@ package limitranger
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/admission"
|
"k8s.io/kubernetes/pkg/admission"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
@ -33,6 +35,10 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/watch"
|
"k8s.io/kubernetes/pkg/watch"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
limitRangerAnnotation = "kubernetes.io/limit-ranger"
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
admission.RegisterPlugin("LimitRanger", func(client client.Interface, config io.Reader) (admission.Interface, error) {
|
admission.RegisterPlugin("LimitRanger", func(client client.Interface, config io.Reader) (admission.Interface, error) {
|
||||||
return NewLimitRanger(client, Limit), nil
|
return NewLimitRanger(client, Limit), nil
|
||||||
@ -162,9 +168,14 @@ func defaultContainerResourceRequirements(limitRange *api.LimitRange) api.Resour
|
|||||||
}
|
}
|
||||||
|
|
||||||
// mergePodResourceRequirements merges enumerated requirements with default requirements
|
// 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) {
|
func mergePodResourceRequirements(pod *api.Pod, defaultRequirements *api.ResourceRequirements) {
|
||||||
|
annotations := []string{}
|
||||||
|
|
||||||
for i := range pod.Spec.Containers {
|
for i := range pod.Spec.Containers {
|
||||||
container := &pod.Spec.Containers[i]
|
container := &pod.Spec.Containers[i]
|
||||||
|
setRequests := []string{}
|
||||||
|
setLimits := []string{}
|
||||||
if container.Resources.Limits == nil {
|
if container.Resources.Limits == nil {
|
||||||
container.Resources.Limits = api.ResourceList{}
|
container.Resources.Limits = api.ResourceList{}
|
||||||
}
|
}
|
||||||
@ -175,14 +186,34 @@ func mergePodResourceRequirements(pod *api.Pod, defaultRequirements *api.Resourc
|
|||||||
_, found := container.Resources.Limits[k]
|
_, found := container.Resources.Limits[k]
|
||||||
if !found {
|
if !found {
|
||||||
container.Resources.Limits[k] = *v.Copy()
|
container.Resources.Limits[k] = *v.Copy()
|
||||||
|
setLimits = append(setLimits, string(k))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for k, v := range defaultRequirements.Requests {
|
for k, v := range defaultRequirements.Requests {
|
||||||
_, found := container.Resources.Requests[k]
|
_, found := container.Resources.Requests[k]
|
||||||
if !found {
|
if !found {
|
||||||
container.Resources.Requests[k] = *v.Copy()
|
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{
|
pod.Spec.Containers = append(pod.Spec.Containers, api.Container{
|
||||||
Image: "foo:V" + strconv.Itoa(i),
|
Image: "foo:V" + strconv.Itoa(i),
|
||||||
Resources: resources,
|
Resources: resources,
|
||||||
|
Name: "foo-" + strconv.Itoa(i),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return pod
|
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) {
|
func TestMergePodResourceRequirements(t *testing.T) {
|
||||||
limitRange := validLimitRange()
|
limitRange := validLimitRange()
|
||||||
|
|
||||||
@ -159,6 +176,7 @@ func TestMergePodResourceRequirements(t *testing.T) {
|
|||||||
t.Errorf("pod %v, expected != actual; %v != %v", pod.Name, expected, actual)
|
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
|
// pod with some resources enumerated should only merge empty
|
||||||
input := getResourceRequirements(getResourceList("", "512Mi"), getResourceList("", ""))
|
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)
|
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) {
|
func TestPodLimitFunc(t *testing.T) {
|
||||||
|
Loading…
Reference in New Issue
Block a user