Merge pull request #44965 from jpeeler/podpreset-exclusion-simple

Automatic merge from submit-queue

Allow pods to opt out of PodPreset mutation via an annotation on the pod

An annotation in the pod spec of the form:
podpreset.admission.kubernetes.io/PodPresetOptOut: "true"
Will cause the admission controller to skip manipulating the pod spec,
no matter the labelling.

This is an alternative implementation to pull #44163.

```release-note
Allow pods to opt out of PodPreset mutation via an annotation on the pod.
```
This commit is contained in:
Kubernetes Submit Queue 2017-06-08 22:57:34 -07:00 committed by GitHub
commit 9f23149a52
7 changed files with 96 additions and 3 deletions

View File

@ -23,6 +23,9 @@ const (
// webhook backend fails.
ImagePolicyFailedOpenKey string = "alpha.image-policy.k8s.io/failed-open"
// PodPresetOptOutAnnotationKey represents the annotation key for a pod to exempt itself from pod preset manipulation
PodPresetOptOutAnnotationKey string = "podpreset.admission.kubernetes.io/exclude"
// MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods
MirrorPodAnnotationKey string = "kubernetes.io/config.mirror"

View File

@ -23,6 +23,9 @@ const (
// webhook backend fails.
ImagePolicyFailedOpenKey string = "alpha.image-policy.k8s.io/failed-open"
// PodPresetOptOutAnnotationKey represents the annotation key for a pod to exempt itself from pod preset manipulation
PodPresetOptOutAnnotationKey string = "podpreset.admission.kubernetes.io/exclude"
// MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods
MirrorPodAnnotationKey string = "kubernetes.io/config.mirror"

View File

@ -104,6 +104,14 @@ func (c *podPresetPlugin) Admit(a admission.Attributes) error {
}
list, err := c.lister.PodPresets(pod.GetNamespace()).List(labels.Everything())
// Ignore if exclusion annotation is present
if podAnnotations := pod.GetAnnotations(); podAnnotations != nil {
glog.V(5).Infof("Looking at pod annotations, found: %v", podAnnotations)
if podAnnotations[api.PodPresetOptOutAnnotationKey] == "true" {
return nil
}
}
if err != nil {
return fmt.Errorf("listing pod presets failed: %v", err)
}
@ -182,7 +190,8 @@ func (c *podPresetPlugin) Admit(a admission.Attributes) error {
if pod.ObjectMeta.Annotations == nil {
pod.ObjectMeta.Annotations = map[string]string{}
}
pod.ObjectMeta.Annotations[fmt.Sprintf("%s/%s", annotationPrefix, pip.GetName())] = pip.GetResourceVersion()
pod.ObjectMeta.Annotations[fmt.Sprintf("%s/podpreset-%s", annotationPrefix, pip.GetName())] = pip.GetResourceVersion()
}
return nil

View File

@ -623,6 +623,78 @@ func TestAdmitMirrorPod(t *testing.T) {
}
}
func TestExclusionNoAdmit(t *testing.T) {
containerName := "container"
pod := &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "mypod",
Namespace: "namespace",
Labels: map[string]string{
"security": "S2",
},
Annotations: map[string]string{
api.PodPresetOptOutAnnotationKey: "true",
},
},
Spec: api.PodSpec{
Containers: []api.Container{
{
Name: containerName,
Env: []api.EnvVar{{Name: "abc", Value: "value2"}, {Name: "ABCD", Value: "value3"}},
},
},
},
}
pip := &settings.PodPreset{
ObjectMeta: v1.ObjectMeta{
Name: "hello",
Namespace: "namespace",
},
Spec: settings.PodPresetSpec{
Selector: v1.LabelSelector{
MatchExpressions: []v1.LabelSelectorRequirement{
{
Key: "security",
Operator: v1.LabelSelectorOpIn,
Values: []string{"S2"},
},
},
},
Volumes: []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},
Env: []api.EnvVar{{Name: "abcd", Value: "value"}, {Name: "ABC", Value: "value"}},
EnvFrom: []api.EnvFromSource{
{
ConfigMapRef: &api.ConfigMapEnvSource{
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
},
},
{
Prefix: "pre_",
ConfigMapRef: &api.ConfigMapEnvSource{
LocalObjectReference: api.LocalObjectReference{Name: "abc"},
},
},
},
},
}
originalPod, err := api.Scheme.Copy(pod)
if err != nil {
t.Fatal(err)
}
err = admitPod(pod, pip)
if err != nil {
t.Fatal(err)
}
// verify PodSpec has not been mutated
if !reflect.DeepEqual(pod, originalPod) {
t.Fatalf("Expected pod spec of '%v' to be unchanged", pod.Name)
}
}
func admitPod(pod *api.Pod, pip *settings.PodPreset) error {
informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc())
store := informerFactory.Settings().InternalVersion().PodPresets().Informer().GetStore()

View File

@ -23,6 +23,9 @@ const (
// webhook backend fails.
ImagePolicyFailedOpenKey string = "alpha.image-policy.k8s.io/failed-open"
// PodPresetOptOutAnnotationKey represents the annotation key for a pod to exempt itself from pod preset manipulation
PodPresetOptOutAnnotationKey string = "podpreset.admission.kubernetes.io/exclude"
// MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods
MirrorPodAnnotationKey string = "kubernetes.io/config.mirror"

View File

@ -23,6 +23,9 @@ const (
// webhook backend fails.
ImagePolicyFailedOpenKey string = "alpha.image-policy.k8s.io/failed-open"
// PodPresetOptOutAnnotationKey represents the annotation key for a pod to exempt itself from pod preset manipulation
PodPresetOptOutAnnotationKey string = "podpreset.admission.kubernetes.io/exclude"
// MirrorAnnotationKey represents the annotation key set by kubelets when creating mirror pods
MirrorPodAnnotationKey string = "kubernetes.io/config.mirror"

View File

@ -140,7 +140,7 @@ var _ = framework.KubeDescribe("PodPreset", func() {
Expect(err).NotTo(HaveOccurred(), "failed to GET scheduled pod")
// check the annotation is there
if _, ok := pod.Annotations["podpreset.admission.kubernetes.io/hello"]; !ok {
if _, ok := pod.Annotations["podpreset.admission.kubernetes.io/podpreset-hello"]; !ok {
framework.Failf("Annotation not found in pod annotations: \n%v\n", pod.Annotations)
}
@ -246,7 +246,7 @@ var _ = framework.KubeDescribe("PodPreset", func() {
Expect(err).NotTo(HaveOccurred(), "failed to GET scheduled pod")
// check the annotation is not there
if _, ok := pod.Annotations["podpreset.admission.kubernetes.io/hello"]; ok {
if _, ok := pod.Annotations["podpreset.admission.kubernetes.io/podpreset-hello"]; ok {
framework.Failf("Annotation found in pod annotations and should not be: \n%v\n", pod.Annotations)
}