From faec23a85400a08bdc58d12870efa8564f69dcf4 Mon Sep 17 00:00:00 2001 From: wencaiwulue <895703375@qq.com> Date: Tue, 21 Feb 2023 23:02:36 +0800 Subject: [PATCH] feat: webhook not use klog --- build/test.Dockerfile | 2 +- cmd/kubevpn/cmds/webhook.go | 4 ++ pkg/handler/envoy.go | 8 ++- pkg/mesh/controller.go | 2 +- pkg/webhook/mutateadmissionwebhook.go | 24 +++---- pkg/webhook/pods.go | 98 +++++++++++++++++++-------- 6 files changed, 94 insertions(+), 44 deletions(-) diff --git a/build/test.Dockerfile b/build/test.Dockerfile index 4b2526ae..2253bf4e 100644 --- a/build/test.Dockerfile +++ b/build/test.Dockerfile @@ -1,4 +1,4 @@ -FROM naison/kubevpn:test +FROM naison/kubevpn:v1.1.19 WORKDIR /app diff --git a/cmd/kubevpn/cmds/webhook.go b/cmd/kubevpn/cmds/webhook.go index 4f9154cd..e6b9040d 100644 --- a/cmd/kubevpn/cmds/webhook.go +++ b/cmd/kubevpn/cmds/webhook.go @@ -4,6 +4,7 @@ import ( "github.com/spf13/cobra" cmdutil "k8s.io/kubectl/pkg/cmd/util" + "github.com/wencaiwulue/kubevpn/pkg/util" "github.com/wencaiwulue/kubevpn/pkg/webhook" ) @@ -15,6 +16,9 @@ func CmdWebhook(f cmdutil.Factory) *cobra.Command { After deploying it to Kubernetes cluster, the Administrator needs to create a MutatingWebhookConfiguration in the Kubernetes cluster to register remote webhook admission controllers.`, Args: cobra.MaximumNArgs(0), + PreRun: func(cmd *cobra.Command, args []string) { + util.InitLogger(true) + }, RunE: func(cmd *cobra.Command, args []string) error { return webhook.Main(f) }, diff --git a/pkg/handler/envoy.go b/pkg/handler/envoy.go index bc2b70d6..642a8f3b 100644 --- a/pkg/handler/envoy.go +++ b/pkg/handler/envoy.go @@ -76,8 +76,12 @@ func InjectVPNAndEnvoySidecar(ctx1 context.Context, factory cmdutil.Factory, cli } // (1) add mesh container removePatch, restorePatch := patch(*origin, path) - b, _ := json.Marshal(restorePatch) - mesh.AddMeshContainer(templateSpec, namespace, nodeID, c) + var b []byte + b, err = json.Marshal(restorePatch) + if err != nil { + return err + } + mesh.AddMeshContainer(templateSpec, nodeID, c) helper := pkgresource.NewHelper(object.Client, object.Mapping) ps := []P{ { diff --git a/pkg/mesh/controller.go b/pkg/mesh/controller.go index 71292f9c..31a502f6 100644 --- a/pkg/mesh/controller.go +++ b/pkg/mesh/controller.go @@ -21,7 +21,7 @@ func RemoveContainers(spec *v1.PodTemplateSpec) { } } -func AddMeshContainer(spec *v1.PodTemplateSpec, ns, nodeId string, c util.PodRouteConfig) { +func AddMeshContainer(spec *v1.PodTemplateSpec, nodeId string, c util.PodRouteConfig) { // remove envoy proxy containers if already exist RemoveContainers(spec) spec.Spec.ServiceAccountName = config.ConfigMapPodTrafficManager diff --git a/pkg/webhook/mutateadmissionwebhook.go b/pkg/webhook/mutateadmissionwebhook.go index d20c17be..7b95b1f5 100644 --- a/pkg/webhook/mutateadmissionwebhook.go +++ b/pkg/webhook/mutateadmissionwebhook.go @@ -5,14 +5,14 @@ import ( "encoding/base64" "encoding/json" "fmt" - "io/ioutil" + "io" "net/http" "os" + log "github.com/sirupsen/logrus" v1 "k8s.io/api/admission/v1" "k8s.io/api/admission/v1beta1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/klog/v2" cmdutil "k8s.io/kubectl/pkg/cmd/util" ) @@ -53,7 +53,7 @@ func delegateV1beta1AdmitToV1(f admitv1Func) admitv1beta1Func { func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) { var body []byte if r.Body != nil { - if data, err := ioutil.ReadAll(r.Body); err == nil { + if data, err := io.ReadAll(r.Body); err == nil { body = data } } @@ -61,17 +61,17 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) { // verify the content type is accurate contentType := r.Header.Get("Content-Type") if contentType != "application/json" { - klog.Errorf("contentType=%s, expect application/json", contentType) + log.Errorf("contentType=%s, expect application/json", contentType) return } - klog.V(2).Info(fmt.Sprintf("handling request: %s", body)) + log.Infof("handling request: %s", body) deserializer := codecs.UniversalDeserializer() obj, gvk, err := deserializer.Decode(body, nil, nil) if err != nil { msg := fmt.Sprintf("Request could not be decoded: %v", err) - klog.Error(msg) + log.Error(msg) http.Error(w, msg, http.StatusBadRequest) return } @@ -81,7 +81,7 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) { case v1beta1.SchemeGroupVersion.WithKind("AdmissionReview"): requestedAdmissionReview, ok := obj.(*v1beta1.AdmissionReview) if !ok { - klog.Errorf("Expected v1beta1.AdmissionReview but got: %T", obj) + log.Errorf("Expected v1beta1.AdmissionReview but got: %T", obj) return } responseAdmissionReview := &v1beta1.AdmissionReview{} @@ -92,7 +92,7 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) { case v1.SchemeGroupVersion.WithKind("AdmissionReview"): requestedAdmissionReview, ok := obj.(*v1.AdmissionReview) if !ok { - klog.Errorf("Expected v1.AdmissionReview but got: %T", obj) + log.Errorf("Expected v1.AdmissionReview but got: %T", obj) return } responseAdmissionReview := &v1.AdmissionReview{} @@ -102,21 +102,21 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) { responseObj = responseAdmissionReview default: msg := fmt.Sprintf("Unsupported group version kind: %v", gvk) - klog.Error(msg) + log.Error(msg) http.Error(w, msg, http.StatusBadRequest) return } - klog.V(2).Info(fmt.Sprintf("sending response: %v", responseObj)) + log.Infof("sending response: %v", responseObj) respBytes, err := json.Marshal(responseObj) if err != nil { - klog.Error(err) + log.Error(err) http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json") if _, err := w.Write(respBytes); err != nil { - klog.Error(err) + log.Error(err) } } diff --git a/pkg/webhook/pods.go b/pkg/webhook/pods.go index b979d9e6..7b2d99d2 100644 --- a/pkg/webhook/pods.go +++ b/pkg/webhook/pods.go @@ -6,10 +6,12 @@ import ( "net" "github.com/mattbaird/jsonpatch" + log "github.com/sirupsen/logrus" "k8s.io/api/admission/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/klog/v2" + "k8s.io/client-go/kubernetes" "k8s.io/kubectl/pkg/cmd/util/podcmd" "github.com/wencaiwulue/kubevpn/pkg/config" @@ -18,26 +20,30 @@ import ( // only allow pods to pull images from specific registry. func (h *admissionReviewHandler) admitPods(ar v1.AdmissionReview) *v1.AdmissionResponse { - klog.V(2).Info("admitting pods") + r, _ := json.Marshal(ar) + log.Infof("admitting pods called, req: %v", string(r)) podResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"} if ar.Request.Resource != podResource { - err := fmt.Errorf("expect resource to be %s", podResource) - klog.Error(err) - return toV1AdmissionResponse(err) - } - - raw := ar.Request.Object.Raw - pod := corev1.Pod{} - - deserializer := codecs.UniversalDeserializer() - if _, _, err := deserializer.Decode(raw, nil, &pod); err != nil { - klog.Error(err) + err := fmt.Errorf("expect resource to be %s but real %s", podResource, ar.Request.Resource) + log.Error(err) return toV1AdmissionResponse(err) } switch ar.Request.Operation { case v1.Create: - from, _ := json.Marshal(pod) + raw := ar.Request.Object.Raw + pod := corev1.Pod{} + deserializer := codecs.UniversalDeserializer() + if _, _, err := deserializer.Decode(raw, nil, &pod); err != nil { + log.Errorf("can not decode into pod, err: %v, raw: %s", err, string(raw)) + return toV1AdmissionResponse(err) + } + + from, err := json.Marshal(pod) + if err != nil { + log.Errorf("can not marshal into pod, err: %v", err) + return toV1AdmissionResponse(err) + } var found bool for i := 0; i < len(pod.Spec.Containers); i++ { if pod.Spec.Containers[i].Name == config.ContainerSidecarVPN { @@ -45,27 +51,50 @@ func (h *admissionReviewHandler) admitPods(ar v1.AdmissionReview) *v1.AdmissionR pair := pod.Spec.Containers[i].Env[j] if pair.Name == config.EnvInboundPodTunIP && pair.Value == "" { found = true - clientset, err := h.f.KubernetesClientSet() + var clientset *kubernetes.Clientset + clientset, err = h.f.KubernetesClientSet() if err != nil { - klog.Error(err) + log.Errorf("can not get clientset, err: %v", err) return toV1AdmissionResponse(err) } cmi := clientset.CoreV1().ConfigMaps(ar.Request.Namespace) dhcp := handler.NewDHCPManager(cmi, ar.Request.Namespace, &net.IPNet{IP: config.RouterIP, Mask: config.CIDR.Mask}) - random, err := dhcp.RentIPRandom() + var random *net.IPNet + random, err = dhcp.RentIPRandom() if err != nil { - klog.Error(err) + log.Errorf("rent ip random failed, err: %v", err) return toV1AdmissionResponse(err) } + var name string + if accessor, errT := meta.Accessor(ar.Request.Object); errT == nil { + name = accessor.GetName() + } + + log.Infof("rent ip %s for pod %s in namespace: %s", random.String(), name, ar.Request.Namespace) pod.Spec.Containers[i].Env[j].Value = random.String() } } } } if found { - to, _ := json.Marshal(pod) - patch, _ := jsonpatch.CreatePatch(from, to) - marshal, _ := json.Marshal(patch) + var to []byte + to, err = json.Marshal(pod) + if err != nil { + log.Errorf("can not marshal pod, err: %v", err) + return toV1AdmissionResponse(err) + } + var patch []jsonpatch.JsonPatchOperation + patch, err = jsonpatch.CreatePatch(from, to) + if err != nil { + log.Errorf("can not create patch json, err: %v", err) + return toV1AdmissionResponse(err) + } + var marshal []byte + marshal, err = json.Marshal(patch) + if err != nil { + log.Errorf("can not marshal json patch %v, err: %v", patch, err) + return toV1AdmissionResponse(err) + } return applyPodPatch( ar, func(pod *corev1.Pod) bool { @@ -76,18 +105,28 @@ func (h *admissionReviewHandler) admitPods(ar v1.AdmissionReview) *v1.AdmissionR ) } return &v1.AdmissionResponse{ + UID: ar.Request.UID, Allowed: true, } case v1.Delete: + raw := ar.Request.OldObject.Raw + pod := corev1.Pod{} + deserializer := codecs.UniversalDeserializer() + if _, _, err := deserializer.Decode(raw, nil, &pod); err != nil { + log.Errorf("can not decode into pod, err: %v, raw: %s", err, string(raw)) + return toV1AdmissionResponse(err) + } + name, _ := podcmd.FindContainerByName(&pod, config.ContainerSidecarVPN) if name != nil { for _, envVar := range name.Env { if envVar.Name == config.EnvInboundPodTunIP && envVar.Value != "" { ip, cidr, err := net.ParseCIDR(envVar.Value) if err == nil { - clientset, err := h.f.KubernetesClientSet() + var clientset *kubernetes.Clientset + clientset, err = h.f.KubernetesClientSet() if err != nil { - klog.Error(err) + log.Errorf("can not get clientset, err: %v", err) return toV1AdmissionResponse(err) } cmi := clientset.CoreV1().ConfigMaps(ar.Request.Namespace) @@ -97,7 +136,9 @@ func (h *admissionReviewHandler) admitPods(ar v1.AdmissionReview) *v1.AdmissionR } err = handler.NewDHCPManager(cmi, ar.Request.Namespace, &net.IPNet{IP: config.RouterIP, Mask: config.CIDR.Mask}).ReleaseIpToDHCP(ipnet) if err != nil { - klog.V(1).Infof("release ip to dhcp err: %v", err) + log.Errorf("release ip to dhcp err: %v, ip: %s", err, envVar.Value) + } else { + log.Errorf("release ip to dhcp ok, ip: %s", envVar.Value) } } } @@ -109,16 +150,17 @@ func (h *admissionReviewHandler) admitPods(ar v1.AdmissionReview) *v1.AdmissionR } default: err := fmt.Errorf("expect operation is %s or %s, not %s", v1.Create, v1.Delete, ar.Request.Operation) - klog.Error(err) + log.Error(err) return toV1AdmissionResponse(err) } } func applyPodPatch(ar v1.AdmissionReview, shouldPatchPod func(*corev1.Pod) bool, patch string) *v1.AdmissionResponse { - klog.V(2).Info("mutating pods") + r, _ := json.Marshal(ar) + log.Infof("mutating pods called, req: %s", string(r)) podResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"} if ar.Request.Resource != podResource { - klog.Errorf("expect resource to be %s", podResource) + log.Errorf("expect resource to be %s but real is %s", podResource, ar.Request.Resource) return nil } @@ -126,7 +168,7 @@ func applyPodPatch(ar v1.AdmissionReview, shouldPatchPod func(*corev1.Pod) bool, pod := corev1.Pod{} deserializer := codecs.UniversalDeserializer() if _, _, err := deserializer.Decode(raw, nil, &pod); err != nil { - klog.Error(err) + log.Errorf("can not decode request into pod, err: %v, req: %s", err, string(raw)) return toV1AdmissionResponse(err) } reviewResponse := v1.AdmissionResponse{}