mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 15:25:57 +00:00
Merge pull request #13985 from piosz/annotations
Auto commit by PR queue bot
This commit is contained in:
commit
832370ed4f
@ -36,9 +36,10 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
samplesThreshold = 60
|
initialResourcesAnnotation = "kubernetes.io/initial-resources"
|
||||||
week = 7 * 24 * time.Hour
|
samplesThreshold = 60
|
||||||
month = 30 * 24 * time.Hour
|
week = 7 * 24 * time.Hour
|
||||||
|
month = 30 * 24 * time.Hour
|
||||||
)
|
)
|
||||||
|
|
||||||
// WARNING: this feature is experimental and will definitely change.
|
// WARNING: this feature is experimental and will definitely change.
|
||||||
@ -81,6 +82,7 @@ func (ir initialResources) Admit(a admission.Attributes) (err error) {
|
|||||||
// The method veryfies whether resources should be set for the given pod and
|
// The method veryfies whether resources should be set for the given pod and
|
||||||
// if there is estimation available the method fills Request field.
|
// if there is estimation available the method fills Request field.
|
||||||
func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
|
func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
|
||||||
|
annotations := []string{}
|
||||||
for i := range pod.Spec.Containers {
|
for i := range pod.Spec.Containers {
|
||||||
c := &pod.Spec.Containers[i]
|
c := &pod.Spec.Containers[i]
|
||||||
req := c.Resources.Requests
|
req := c.Resources.Requests
|
||||||
@ -109,16 +111,29 @@ func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
|
|||||||
c.Resources.Requests = api.ResourceList{}
|
c.Resources.Requests = api.ResourceList{}
|
||||||
req = c.Resources.Requests
|
req = c.Resources.Requests
|
||||||
}
|
}
|
||||||
|
setRes := []string{}
|
||||||
if cpu != nil {
|
if cpu != nil {
|
||||||
glog.Infof("CPU estimation for container %v in pod %v/%v is %v", c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, cpu.String())
|
glog.Infof("CPU estimation for container %v in pod %v/%v is %v", c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, cpu.String())
|
||||||
|
setRes = append(setRes, string(api.ResourceCPU))
|
||||||
req[api.ResourceCPU] = *cpu
|
req[api.ResourceCPU] = *cpu
|
||||||
}
|
}
|
||||||
if mem != nil {
|
if mem != nil {
|
||||||
glog.Infof("Memory estimation for container %v in pod %v/%v is %v", c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, mem.String())
|
glog.Infof("Memory estimation for container %v in pod %v/%v is %v", c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, mem.String())
|
||||||
|
setRes = append(setRes, string(api.ResourceMemory))
|
||||||
req[api.ResourceMemory] = *mem
|
req[api.ResourceMemory] = *mem
|
||||||
}
|
}
|
||||||
|
if len(setRes) > 0 {
|
||||||
|
a := strings.Join(setRes, ", ") + " request for container " + c.Name
|
||||||
|
annotations = append(annotations, a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(annotations) > 0 {
|
||||||
|
if pod.ObjectMeta.Annotations == nil {
|
||||||
|
pod.ObjectMeta.Annotations = make(map[string]string)
|
||||||
|
}
|
||||||
|
val := "Initial Resources plugin set: " + strings.Join(annotations, "; ")
|
||||||
|
pod.ObjectMeta.Annotations[initialResourcesAnnotation] = val
|
||||||
}
|
}
|
||||||
// TODO(piosz): verify the estimates fits in LimitRanger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ir initialResources) getEstimation(kind api.ResourceName, c *api.Container) (*resource.Quantity, error) {
|
func (ir initialResources) getEstimation(kind api.ResourceName, c *api.Container) (*resource.Quantity, error) {
|
||||||
|
@ -55,18 +55,18 @@ func addContainer(pod *api.Pod, name, image string, request api.ResourceList) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func createPod(name string, image string, request api.ResourceList) api.Pod {
|
func createPod(name string, image string, request api.ResourceList) *api.Pod {
|
||||||
pod := api.Pod{
|
pod := &api.Pod{
|
||||||
ObjectMeta: api.ObjectMeta{Name: name, Namespace: "test"},
|
ObjectMeta: api.ObjectMeta{Name: name, Namespace: "test"},
|
||||||
Spec: api.PodSpec{},
|
Spec: api.PodSpec{},
|
||||||
}
|
}
|
||||||
pod.Spec.Containers = []api.Container{}
|
pod.Spec.Containers = []api.Container{}
|
||||||
addContainer(&pod, "c0", image, request)
|
addContainer(pod, "c0", image, request)
|
||||||
return pod
|
return pod
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPods() []api.Pod {
|
func getPods() []*api.Pod {
|
||||||
return []api.Pod{
|
return []*api.Pod{
|
||||||
createPod("p0", "image:v0", parseReq("", "")),
|
createPod("p0", "image:v0", parseReq("", "")),
|
||||||
createPod("p1", "image:v1", parseReq("", "300")),
|
createPod("p1", "image:v1", parseReq("", "300")),
|
||||||
createPod("p2", "image:v2", parseReq("300m", "")),
|
createPod("p2", "image:v2", parseReq("300m", "")),
|
||||||
@ -88,9 +88,25 @@ func verifyPod(t *testing.T, pod *api.Pod, cpu, mem int64) {
|
|||||||
verifyContainer(t, &pod.Spec.Containers[0], cpu, mem)
|
verifyContainer(t, &pod.Spec.Containers[0], cpu, mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func admit(t *testing.T, ir admission.Interface, pods []api.Pod) {
|
func verifyAnnotation(t *testing.T, pod *api.Pod, expected string) {
|
||||||
|
a, ok := pod.ObjectMeta.Annotations[initialResourcesAnnotation]
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("No annotation but expected %v", expected)
|
||||||
|
}
|
||||||
|
if a != expected {
|
||||||
|
t.Errorf("Wrong annatation set by Initial Resources: got %v, expected %v", a, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectNoAnnotation(t *testing.T, pod *api.Pod) {
|
||||||
|
if a, ok := pod.ObjectMeta.Annotations[initialResourcesAnnotation]; ok {
|
||||||
|
t.Errorf("Expected no annatation but got %v", a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func admit(t *testing.T, ir admission.Interface, pods []*api.Pod) {
|
||||||
for i := range pods {
|
for i := range pods {
|
||||||
p := &pods[i]
|
p := pods[i]
|
||||||
if err := ir.Admit(admission.NewAttributesRecord(p, "Pod", "test", p.ObjectMeta.Name, "pods", "", admission.Create, nil)); err != nil {
|
if err := ir.Admit(admission.NewAttributesRecord(p, "Pod", "test", p.ObjectMeta.Name, "pods", "", admission.Create, nil)); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -109,10 +125,15 @@ func TestEstimationBasedOnTheSameImage7d(t *testing.T) {
|
|||||||
pods := getPods()
|
pods := getPods()
|
||||||
admit(t, ir, pods)
|
admit(t, ir, pods)
|
||||||
|
|
||||||
verifyPod(t, &pods[0], 100, 100)
|
verifyPod(t, pods[0], 100, 100)
|
||||||
verifyPod(t, &pods[1], 100, 300)
|
verifyPod(t, pods[1], 100, 300)
|
||||||
verifyPod(t, &pods[2], 300, 100)
|
verifyPod(t, pods[2], 300, 100)
|
||||||
verifyPod(t, &pods[3], 300, 300)
|
verifyPod(t, pods[3], 300, 300)
|
||||||
|
|
||||||
|
verifyAnnotation(t, pods[0], "Initial Resources plugin set: cpu, memory request for container c0")
|
||||||
|
verifyAnnotation(t, pods[1], "Initial Resources plugin set: cpu request for container c0")
|
||||||
|
verifyAnnotation(t, pods[2], "Initial Resources plugin set: memory request for container c0")
|
||||||
|
expectNoAnnotation(t, pods[3])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEstimationBasedOnTheSameImage30d(t *testing.T) {
|
func TestEstimationBasedOnTheSameImage30d(t *testing.T) {
|
||||||
@ -130,10 +151,10 @@ func TestEstimationBasedOnTheSameImage30d(t *testing.T) {
|
|||||||
pods := getPods()
|
pods := getPods()
|
||||||
admit(t, ir, pods)
|
admit(t, ir, pods)
|
||||||
|
|
||||||
verifyPod(t, &pods[0], 100, 100)
|
verifyPod(t, pods[0], 100, 100)
|
||||||
verifyPod(t, &pods[1], 100, 300)
|
verifyPod(t, pods[1], 100, 300)
|
||||||
verifyPod(t, &pods[2], 300, 100)
|
verifyPod(t, pods[2], 300, 100)
|
||||||
verifyPod(t, &pods[3], 300, 300)
|
verifyPod(t, pods[3], 300, 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEstimationBasedOnOtherImages(t *testing.T) {
|
func TestEstimationBasedOnOtherImages(t *testing.T) {
|
||||||
@ -148,10 +169,10 @@ func TestEstimationBasedOnOtherImages(t *testing.T) {
|
|||||||
pods := getPods()
|
pods := getPods()
|
||||||
admit(t, ir, pods)
|
admit(t, ir, pods)
|
||||||
|
|
||||||
verifyPod(t, &pods[0], 100, 100)
|
verifyPod(t, pods[0], 100, 100)
|
||||||
verifyPod(t, &pods[1], 100, 300)
|
verifyPod(t, pods[1], 100, 300)
|
||||||
verifyPod(t, &pods[2], 300, 100)
|
verifyPod(t, pods[2], 300, 100)
|
||||||
verifyPod(t, &pods[3], 300, 300)
|
verifyPod(t, pods[3], 300, 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoData(t *testing.T) {
|
func TestNoData(t *testing.T) {
|
||||||
@ -160,7 +181,7 @@ func TestNoData(t *testing.T) {
|
|||||||
}
|
}
|
||||||
ir := newInitialResources(&fakeSource{f: f})
|
ir := newInitialResources(&fakeSource{f: f})
|
||||||
|
|
||||||
pods := []api.Pod{
|
pods := []*api.Pod{
|
||||||
createPod("p0", "image:v0", parseReq("", "")),
|
createPod("p0", "image:v0", parseReq("", "")),
|
||||||
}
|
}
|
||||||
admit(t, ir, pods)
|
admit(t, ir, pods)
|
||||||
@ -168,6 +189,8 @@ func TestNoData(t *testing.T) {
|
|||||||
if pods[0].Spec.Containers[0].Resources.Requests != nil {
|
if pods[0].Spec.Containers[0].Resources.Requests != nil {
|
||||||
t.Errorf("Unexpected resource estimation")
|
t.Errorf("Unexpected resource estimation")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expectNoAnnotation(t, pods[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestManyContainers(t *testing.T) {
|
func TestManyContainers(t *testing.T) {
|
||||||
@ -180,13 +203,15 @@ func TestManyContainers(t *testing.T) {
|
|||||||
ir := newInitialResources(&fakeSource{f: f})
|
ir := newInitialResources(&fakeSource{f: f})
|
||||||
|
|
||||||
pod := createPod("p", "image:v0", parseReq("", ""))
|
pod := createPod("p", "image:v0", parseReq("", ""))
|
||||||
addContainer(&pod, "c1", "image:v1", parseReq("", "300"))
|
addContainer(pod, "c1", "image:v1", parseReq("", "300"))
|
||||||
addContainer(&pod, "c2", "image:v2", parseReq("300m", ""))
|
addContainer(pod, "c2", "image:v2", parseReq("300m", ""))
|
||||||
addContainer(&pod, "c3", "image:v3", parseReq("300m", "300"))
|
addContainer(pod, "c3", "image:v3", parseReq("300m", "300"))
|
||||||
admit(t, ir, []api.Pod{pod})
|
admit(t, ir, []*api.Pod{pod})
|
||||||
|
|
||||||
verifyContainer(t, &pod.Spec.Containers[0], 100, 100)
|
verifyContainer(t, &pod.Spec.Containers[0], 100, 100)
|
||||||
verifyContainer(t, &pod.Spec.Containers[1], 100, 300)
|
verifyContainer(t, &pod.Spec.Containers[1], 100, 300)
|
||||||
verifyContainer(t, &pod.Spec.Containers[2], 300, 100)
|
verifyContainer(t, &pod.Spec.Containers[2], 300, 100)
|
||||||
verifyContainer(t, &pod.Spec.Containers[3], 300, 300)
|
verifyContainer(t, &pod.Spec.Containers[3], 300, 300)
|
||||||
|
|
||||||
|
verifyAnnotation(t, pod, "Initial Resources plugin set: cpu, memory request for container c0; cpu request for container c1; memory request for container c2")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user