Merge pull request #29356 from smarterclayton/init_containers

Automatic merge from submit-queue

LimitRanger and PodSecurityPolicy need to check more on init containers

Container limits not applied to init containers. HostPorts not checked on podsecuritypolicy

@pweil- @derekwaynecarr
This commit is contained in:
k8s-merge-robot 2016-07-27 16:09:34 -07:00 committed by GitHub
commit 3301f6d14f
5 changed files with 92 additions and 52 deletions

View File

@ -250,6 +250,12 @@ func (s *simpleProvider) ValidateContainerSecurityContext(pod *api.Pod, containe
allErrs = append(allErrs, s.hasInvalidHostPort(&c, idxPath)...) allErrs = append(allErrs, s.hasInvalidHostPort(&c, idxPath)...)
} }
containersPath = fldPath.Child("initContainers")
for idx, c := range pod.Spec.InitContainers {
idxPath := containersPath.Index(idx)
allErrs = append(allErrs, s.hasInvalidHostPort(&c, idxPath)...)
}
if !s.psp.Spec.HostPID && pod.Spec.SecurityContext.HostPID { if !s.psp.Spec.HostPID && pod.Spec.SecurityContext.HostPID {
allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPID"), pod.Spec.SecurityContext.HostPID, "Host PID is not allowed to be used")) allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPID"), pod.Spec.SecurityContext.HostPID, "Host PID is not allowed to be used"))
} }

View File

@ -18,6 +18,7 @@ package initialresources
import ( import (
"flag" "flag"
"fmt"
"io" "io"
"sort" "sort"
"strings" "strings"
@ -89,9 +90,24 @@ 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{} var annotations []string
for i := range pod.Spec.InitContainers {
annotations = append(annotations, ir.estimateContainer(pod, &pod.Spec.InitContainers[i], "init container")...)
}
for i := range pod.Spec.Containers { for i := range pod.Spec.Containers {
c := &pod.Spec.Containers[i] annotations = append(annotations, ir.estimateContainer(pod, &pod.Spec.Containers[i], "container")...)
}
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
}
}
func (ir initialResources) estimateContainer(pod *api.Pod, c *api.Container, message string) []string {
var annotations []string
req := c.Resources.Requests req := c.Resources.Requests
lim := c.Resources.Limits lim := c.Resources.Limits
var cpu, mem *resource.Quantity var cpu, mem *resource.Quantity
@ -120,28 +136,21 @@ func (ir initialResources) estimateAndFillResourcesIfNotSet(pod *api.Pod) {
} }
setRes := []string{} 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 %s %v in pod %v/%v is %v", message, c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, cpu.String())
setRes = append(setRes, string(api.ResourceCPU)) 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 %s %v in pod %v/%v is %v", message, c.Name, pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, mem.String())
setRes = append(setRes, string(api.ResourceMemory)) setRes = append(setRes, string(api.ResourceMemory))
req[api.ResourceMemory] = *mem req[api.ResourceMemory] = *mem
} }
if len(setRes) > 0 { if len(setRes) > 0 {
sort.Strings(setRes) sort.Strings(setRes)
a := strings.Join(setRes, ", ") + " request for container " + c.Name a := strings.Join(setRes, ", ") + fmt.Sprintf(" request for %s %s", message, c.Name)
annotations = append(annotations, a) annotations = append(annotations, a)
} }
} return annotations
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
}
} }
func (ir initialResources) getEstimation(kind api.ResourceName, c *api.Container, ns string) (*resource.Quantity, error) { func (ir initialResources) getEstimation(kind api.ResourceName, c *api.Container, ns string) (*resource.Quantity, error) {

View File

@ -61,6 +61,9 @@ func createPod(name string, image string, request api.ResourceList) *api.Pod {
Spec: api.PodSpec{}, Spec: api.PodSpec{},
} }
pod.Spec.Containers = []api.Container{} pod.Spec.Containers = []api.Container{}
addContainer(pod, "i0", image, request)
pod.Spec.InitContainers = pod.Spec.Containers
pod.Spec.Containers = []api.Container{}
addContainer(pod, "c0", image, request) addContainer(pod, "c0", image, request)
return pod return pod
} }
@ -86,6 +89,7 @@ func verifyContainer(t *testing.T, c *api.Container, cpu, mem int64) {
func verifyPod(t *testing.T, pod *api.Pod, cpu, mem int64) { 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)
verifyContainer(t, &pod.Spec.InitContainers[0], cpu, mem)
} }
func verifyAnnotation(t *testing.T, pod *api.Pod, expected string) { func verifyAnnotation(t *testing.T, pod *api.Pod, expected string) {
@ -94,13 +98,13 @@ func verifyAnnotation(t *testing.T, pod *api.Pod, expected string) {
t.Errorf("No annotation but expected %v", expected) t.Errorf("No annotation but expected %v", expected)
} }
if a != expected { if a != expected {
t.Errorf("Wrong annatation set by Initial Resources: got %v, expected %v", a, expected) t.Errorf("Wrong annotation set by Initial Resources: got %v, expected %v", a, expected)
} }
} }
func expectNoAnnotation(t *testing.T, pod *api.Pod) { func expectNoAnnotation(t *testing.T, pod *api.Pod) {
if a, ok := pod.ObjectMeta.Annotations[initialResourcesAnnotation]; ok { if a, ok := pod.ObjectMeta.Annotations[initialResourcesAnnotation]; ok {
t.Errorf("Expected no annatation but got %v", a) t.Errorf("Expected no annotation but got %v", a)
} }
} }
@ -122,9 +126,9 @@ func performTest(t *testing.T, ir admission.Interface) {
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[0], "Initial Resources plugin set: cpu, memory request for init container i0; cpu, memory request for container c0")
verifyAnnotation(t, pods[1], "Initial Resources plugin set: cpu request for container c0") verifyAnnotation(t, pods[1], "Initial Resources plugin set: cpu request for init container i0")
verifyAnnotation(t, pods[2], "Initial Resources plugin set: memory request for container c0") verifyAnnotation(t, pods[2], "Initial Resources plugin set: memory request for init container i0")
expectNoAnnotation(t, pods[3]) expectNoAnnotation(t, pods[3])
} }
@ -229,7 +233,7 @@ func TestManyContainers(t *testing.T) {
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") verifyAnnotation(t, pod, "Initial Resources plugin set: cpu, memory request for init container i0; cpu, memory request for container c0; cpu request for container c1; memory request for container c2")
} }
func TestNamespaceAware(t *testing.T) { func TestNamespaceAware(t *testing.T) {

View File

@ -448,6 +448,24 @@ func PodLimitFunc(limitRange *api.LimitRange, pod *api.Pod) error {
} }
} }
} }
for j := range pod.Spec.InitContainers {
container := &pod.Spec.InitContainers[j]
for k, v := range limit.Min {
if err := minConstraint(limitType, k, v, container.Resources.Requests, container.Resources.Limits); err != nil {
errs = append(errs, err)
}
}
for k, v := range limit.Max {
if err := maxConstraint(limitType, k, v, container.Resources.Requests, container.Resources.Limits); err != nil {
errs = append(errs, err)
}
}
for k, v := range limit.MaxLimitRequestRatio {
if err := limitRequestRatioConstraint(limitType, k, v, container.Resources.Requests, container.Resources.Limits); err != nil {
errs = append(errs, err)
}
}
}
} }
// enforce pod limits on init containers // enforce pod limits on init containers

View File

@ -394,9 +394,12 @@ func TestAdmitHostPorts(t *testing.T) {
}, },
} }
for i := 0; i < 2; i++ {
for k, v := range tests { for k, v := range tests {
v.pod.Spec.Containers, v.pod.Spec.InitContainers = v.pod.Spec.InitContainers, v.pod.Spec.Containers
testPSPAdmit(k, v.psps, v.pod, v.shouldPass, v.expectedPSP, t) testPSPAdmit(k, v.psps, v.pod, v.shouldPass, v.expectedPSP, t)
} }
}
} }
func TestAdmitHostPID(t *testing.T) { func TestAdmitHostPID(t *testing.T) {