Merge pull request #13985 from piosz/annotations

Auto commit by PR queue bot
This commit is contained in:
k8s-merge-robot 2015-09-21 00:43:34 -07:00
commit 832370ed4f
2 changed files with 68 additions and 28 deletions

View File

@ -36,9 +36,10 @@ var (
)
const (
samplesThreshold = 60
week = 7 * 24 * time.Hour
month = 30 * 24 * time.Hour
initialResourcesAnnotation = "kubernetes.io/initial-resources"
samplesThreshold = 60
week = 7 * 24 * time.Hour
month = 30 * 24 * time.Hour
)
// 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
// if there is estimation available the method fills Request field.
func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
annotations := []string{}
for i := range pod.Spec.Containers {
c := &pod.Spec.Containers[i]
req := c.Resources.Requests
@ -109,16 +111,29 @@ func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
c.Resources.Requests = api.ResourceList{}
req = c.Resources.Requests
}
setRes := []string{}
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())
setRes = append(setRes, string(api.ResourceCPU))
req[api.ResourceCPU] = *cpu
}
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())
setRes = append(setRes, string(api.ResourceMemory))
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) {

View File

@ -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 {
pod := api.Pod{
func createPod(name string, image string, request api.ResourceList) *api.Pod {
pod := &api.Pod{
ObjectMeta: api.ObjectMeta{Name: name, Namespace: "test"},
Spec: api.PodSpec{},
}
pod.Spec.Containers = []api.Container{}
addContainer(&pod, "c0", image, request)
addContainer(pod, "c0", image, request)
return pod
}
func getPods() []api.Pod {
return []api.Pod{
func getPods() []*api.Pod {
return []*api.Pod{
createPod("p0", "image:v0", parseReq("", "")),
createPod("p1", "image:v1", parseReq("", "300")),
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)
}
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 {
p := &pods[i]
p := pods[i]
if err := ir.Admit(admission.NewAttributesRecord(p, "Pod", "test", p.ObjectMeta.Name, "pods", "", admission.Create, nil)); err != nil {
t.Error(err)
}
@ -109,10 +125,15 @@ func TestEstimationBasedOnTheSameImage7d(t *testing.T) {
pods := getPods()
admit(t, ir, pods)
verifyPod(t, &pods[0], 100, 100)
verifyPod(t, &pods[1], 100, 300)
verifyPod(t, &pods[2], 300, 100)
verifyPod(t, &pods[3], 300, 300)
verifyPod(t, pods[0], 100, 100)
verifyPod(t, pods[1], 100, 300)
verifyPod(t, pods[2], 300, 100)
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) {
@ -130,10 +151,10 @@ func TestEstimationBasedOnTheSameImage30d(t *testing.T) {
pods := getPods()
admit(t, ir, pods)
verifyPod(t, &pods[0], 100, 100)
verifyPod(t, &pods[1], 100, 300)
verifyPod(t, &pods[2], 300, 100)
verifyPod(t, &pods[3], 300, 300)
verifyPod(t, pods[0], 100, 100)
verifyPod(t, pods[1], 100, 300)
verifyPod(t, pods[2], 300, 100)
verifyPod(t, pods[3], 300, 300)
}
func TestEstimationBasedOnOtherImages(t *testing.T) {
@ -148,10 +169,10 @@ func TestEstimationBasedOnOtherImages(t *testing.T) {
pods := getPods()
admit(t, ir, pods)
verifyPod(t, &pods[0], 100, 100)
verifyPod(t, &pods[1], 100, 300)
verifyPod(t, &pods[2], 300, 100)
verifyPod(t, &pods[3], 300, 300)
verifyPod(t, pods[0], 100, 100)
verifyPod(t, pods[1], 100, 300)
verifyPod(t, pods[2], 300, 100)
verifyPod(t, pods[3], 300, 300)
}
func TestNoData(t *testing.T) {
@ -160,7 +181,7 @@ func TestNoData(t *testing.T) {
}
ir := newInitialResources(&fakeSource{f: f})
pods := []api.Pod{
pods := []*api.Pod{
createPod("p0", "image:v0", parseReq("", "")),
}
admit(t, ir, pods)
@ -168,6 +189,8 @@ func TestNoData(t *testing.T) {
if pods[0].Spec.Containers[0].Resources.Requests != nil {
t.Errorf("Unexpected resource estimation")
}
expectNoAnnotation(t, pods[0])
}
func TestManyContainers(t *testing.T) {
@ -180,13 +203,15 @@ func TestManyContainers(t *testing.T) {
ir := newInitialResources(&fakeSource{f: f})
pod := createPod("p", "image:v0", parseReq("", ""))
addContainer(&pod, "c1", "image:v1", parseReq("", "300"))
addContainer(&pod, "c2", "image:v2", parseReq("300m", ""))
addContainer(&pod, "c3", "image:v3", parseReq("300m", "300"))
admit(t, ir, []api.Pod{pod})
addContainer(pod, "c1", "image:v1", parseReq("", "300"))
addContainer(pod, "c2", "image:v2", parseReq("300m", ""))
addContainer(pod, "c3", "image:v3", parseReq("300m", "300"))
admit(t, ir, []*api.Pod{pod})
verifyContainer(t, &pod.Spec.Containers[0], 100, 100)
verifyContainer(t, &pod.Spec.Containers[1], 100, 300)
verifyContainer(t, &pod.Spec.Containers[2], 300, 100)
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")
}