From 2edc42e71cdf87818c48f689a6e466936e940daf Mon Sep 17 00:00:00 2001 From: Jeff Peeler Date: Tue, 31 Jul 2018 13:41:50 -0400 Subject: [PATCH] fix a number of issues with the webhook ensure that pod creation events are monitored for refactor away unnecessary k8s clientset ensure mutatePods never returns nil, which fixed kube API server crashes --- webhook/apod-deployment.yaml | 2 ++ webhook/config.go | 29 +++++++---------------------- webhook/deployment.yaml | 1 + webhook/main.go | 27 ++++++++++++++++++--------- 4 files changed, 28 insertions(+), 31 deletions(-) diff --git a/webhook/apod-deployment.yaml b/webhook/apod-deployment.yaml index e053245f..02c221fe 100644 --- a/webhook/apod-deployment.yaml +++ b/webhook/apod-deployment.yaml @@ -4,6 +4,7 @@ metadata: name: apod-deployment labels: app: apod-deployment + mutateAll: "true" spec: replicas: 1 selector: @@ -26,3 +27,4 @@ spec: args: - sleep - "86400" + terminationGracePeriodSeconds: 1 diff --git a/webhook/config.go b/webhook/config.go index ff92c506..5b00e744 100644 --- a/webhook/config.go +++ b/webhook/config.go @@ -19,41 +19,26 @@ package main import ( "crypto/tls" - crdversioned "github.com/jpeeler/podpreset-crd/pkg/client/clientset/versioned" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" "github.com/golang/glog" + "sigs.k8s.io/controller-runtime/pkg/client/config" ) -// Get a clientset with in-cluster config. -func getClient() *kubernetes.Clientset { - config, err := rest.InClusterConfig() +func getCrdClient() client.Client { + config, err := config.GetConfig() if err != nil { glog.Fatal(err) } - clientset, err := kubernetes.NewForConfig(config) + crdclient, err := client.New(config, client.Options{Scheme: scheme}) if err != nil { glog.Fatal(err) } - return clientset + return crdclient } -func getCrdClient() *crdversioned.Clientset { - config, err := rest.InClusterConfig() - if err != nil { - glog.Fatal(err) - } - clientset, err := crdversioned.NewForConfig(config) - if err != nil { - glog.Fatal(err) - } - - return clientset -} - -func configTLS(config Config, clientset *kubernetes.Clientset) *tls.Config { +func configTLS(config Config) *tls.Config { sCert, err := tls.LoadX509KeyPair(config.CertFile, config.KeyFile) if err != nil { glog.Fatalf("config=%#v Error: %v", config, err) diff --git a/webhook/deployment.yaml b/webhook/deployment.yaml index 9a753b93..9119a4df 100644 --- a/webhook/deployment.yaml +++ b/webhook/deployment.yaml @@ -60,6 +60,7 @@ webhooks: - v1 operations: - CREATE + - UPDATE resources: - pods failurePolicy: Ignore diff --git a/webhook/main.go b/webhook/main.go index 7118c361..a0ca435f 100644 --- a/webhook/main.go +++ b/webhook/main.go @@ -17,6 +17,7 @@ limitations under the License. package main import ( + "context" "encoding/json" "flag" "fmt" @@ -30,10 +31,11 @@ import ( "github.com/mattbaird/jsonpatch" "k8s.io/api/admission/v1beta1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" utilerrors "k8s.io/apimachinery/pkg/util/errors" + "sigs.k8s.io/controller-runtime/pkg/client" "k8s.io/apimachinery/pkg/runtime" ) @@ -349,21 +351,29 @@ func mutatePods(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { if podAnnotations := pod.GetAnnotations(); podAnnotations != nil { glog.V(5).Infof("Looking at pod annotations, found: %v", podAnnotations) if podAnnotations[fmt.Sprintf("%s/exclude", annotationPrefix)] == "true" { - return nil + return &reviewResponse } if _, isMirrorPod := podAnnotations[corev1.MirrorPodAnnotationKey]; isMirrorPod { - return nil + return &reviewResponse } } crdclient := getCrdClient() - list, err := crdclient.SettingsV1alpha1().PodPresets(pod.Namespace).List(v1.ListOptions{}) - if err != nil { - glog.Errorf("error fetching podpresets : %v", err) + list := &settingsapi.PodPresetList{} + err := crdclient.List(context.TODO(), &client.ListOptions{Namespace: pod.Namespace}, list) + if meta.IsNoMatchError(err) { + glog.Errorf("%v (has the CRD been loaded?)", err) + return toAdmissionResponse(err) + } else if err != nil { + glog.Errorf("error fetching podpresets: %v", err) return toAdmissionResponse(err) } glog.Infof("fetched %d podpreset(s) in namespace %s", len(list.Items), pod.Namespace) + if len(list.Items) == 0 { + glog.V(5).Infof("No pod presets created, so skipping pod %v", pod.Name) + return &reviewResponse + } matchingPPs, err := filterPodPresets(list.Items, &pod) if err != nil { @@ -373,7 +383,7 @@ func mutatePods(ar v1beta1.AdmissionReview) *v1beta1.AdmissionResponse { if len(matchingPPs) == 0 { glog.V(5).Infof("No matching pod presets, so skipping pod %v", pod.Name) - return nil + return &reviewResponse } presetNames := make([]string, len(matchingPPs)) @@ -479,10 +489,9 @@ func main() { flag.Parse() http.HandleFunc("/mutating-pods", serveMutatePods) - clientset := getClient() server := &http.Server{ Addr: ":443", - TLSConfig: configTLS(config, clientset), + TLSConfig: configTLS(config), } glog.Infof("About to start serving webhooks: %#v", server) server.ListenAndServeTLS("", "")