feat: webhook not use klog

This commit is contained in:
wencaiwulue
2023-02-21 23:02:36 +08:00
parent 9c73aabcce
commit faec23a854
6 changed files with 94 additions and 44 deletions

View File

@@ -1,4 +1,4 @@
FROM naison/kubevpn:test FROM naison/kubevpn:v1.1.19
WORKDIR /app WORKDIR /app

View File

@@ -4,6 +4,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
cmdutil "k8s.io/kubectl/pkg/cmd/util" cmdutil "k8s.io/kubectl/pkg/cmd/util"
"github.com/wencaiwulue/kubevpn/pkg/util"
"github.com/wencaiwulue/kubevpn/pkg/webhook" "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 After deploying it to Kubernetes cluster, the Administrator needs to create a MutatingWebhookConfiguration
in the Kubernetes cluster to register remote webhook admission controllers.`, in the Kubernetes cluster to register remote webhook admission controllers.`,
Args: cobra.MaximumNArgs(0), Args: cobra.MaximumNArgs(0),
PreRun: func(cmd *cobra.Command, args []string) {
util.InitLogger(true)
},
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
return webhook.Main(f) return webhook.Main(f)
}, },

View File

@@ -76,8 +76,12 @@ func InjectVPNAndEnvoySidecar(ctx1 context.Context, factory cmdutil.Factory, cli
} }
// (1) add mesh container // (1) add mesh container
removePatch, restorePatch := patch(*origin, path) removePatch, restorePatch := patch(*origin, path)
b, _ := json.Marshal(restorePatch) var b []byte
mesh.AddMeshContainer(templateSpec, namespace, nodeID, c) b, err = json.Marshal(restorePatch)
if err != nil {
return err
}
mesh.AddMeshContainer(templateSpec, nodeID, c)
helper := pkgresource.NewHelper(object.Client, object.Mapping) helper := pkgresource.NewHelper(object.Client, object.Mapping)
ps := []P{ ps := []P{
{ {

View File

@@ -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 // remove envoy proxy containers if already exist
RemoveContainers(spec) RemoveContainers(spec)
spec.Spec.ServiceAccountName = config.ConfigMapPodTrafficManager spec.Spec.ServiceAccountName = config.ConfigMapPodTrafficManager

View File

@@ -5,14 +5,14 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io"
"net/http" "net/http"
"os" "os"
log "github.com/sirupsen/logrus"
v1 "k8s.io/api/admission/v1" v1 "k8s.io/api/admission/v1"
"k8s.io/api/admission/v1beta1" "k8s.io/api/admission/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/klog/v2"
cmdutil "k8s.io/kubectl/pkg/cmd/util" 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) { func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) {
var body []byte var body []byte
if r.Body != nil { if r.Body != nil {
if data, err := ioutil.ReadAll(r.Body); err == nil { if data, err := io.ReadAll(r.Body); err == nil {
body = data body = data
} }
} }
@@ -61,17 +61,17 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) {
// verify the content type is accurate // verify the content type is accurate
contentType := r.Header.Get("Content-Type") contentType := r.Header.Get("Content-Type")
if contentType != "application/json" { if contentType != "application/json" {
klog.Errorf("contentType=%s, expect application/json", contentType) log.Errorf("contentType=%s, expect application/json", contentType)
return return
} }
klog.V(2).Info(fmt.Sprintf("handling request: %s", body)) log.Infof("handling request: %s", body)
deserializer := codecs.UniversalDeserializer() deserializer := codecs.UniversalDeserializer()
obj, gvk, err := deserializer.Decode(body, nil, nil) obj, gvk, err := deserializer.Decode(body, nil, nil)
if err != nil { if err != nil {
msg := fmt.Sprintf("Request could not be decoded: %v", err) msg := fmt.Sprintf("Request could not be decoded: %v", err)
klog.Error(msg) log.Error(msg)
http.Error(w, msg, http.StatusBadRequest) http.Error(w, msg, http.StatusBadRequest)
return return
} }
@@ -81,7 +81,7 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) {
case v1beta1.SchemeGroupVersion.WithKind("AdmissionReview"): case v1beta1.SchemeGroupVersion.WithKind("AdmissionReview"):
requestedAdmissionReview, ok := obj.(*v1beta1.AdmissionReview) requestedAdmissionReview, ok := obj.(*v1beta1.AdmissionReview)
if !ok { if !ok {
klog.Errorf("Expected v1beta1.AdmissionReview but got: %T", obj) log.Errorf("Expected v1beta1.AdmissionReview but got: %T", obj)
return return
} }
responseAdmissionReview := &v1beta1.AdmissionReview{} responseAdmissionReview := &v1beta1.AdmissionReview{}
@@ -92,7 +92,7 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) {
case v1.SchemeGroupVersion.WithKind("AdmissionReview"): case v1.SchemeGroupVersion.WithKind("AdmissionReview"):
requestedAdmissionReview, ok := obj.(*v1.AdmissionReview) requestedAdmissionReview, ok := obj.(*v1.AdmissionReview)
if !ok { if !ok {
klog.Errorf("Expected v1.AdmissionReview but got: %T", obj) log.Errorf("Expected v1.AdmissionReview but got: %T", obj)
return return
} }
responseAdmissionReview := &v1.AdmissionReview{} responseAdmissionReview := &v1.AdmissionReview{}
@@ -102,21 +102,21 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) {
responseObj = responseAdmissionReview responseObj = responseAdmissionReview
default: default:
msg := fmt.Sprintf("Unsupported group version kind: %v", gvk) msg := fmt.Sprintf("Unsupported group version kind: %v", gvk)
klog.Error(msg) log.Error(msg)
http.Error(w, msg, http.StatusBadRequest) http.Error(w, msg, http.StatusBadRequest)
return return
} }
klog.V(2).Info(fmt.Sprintf("sending response: %v", responseObj)) log.Infof("sending response: %v", responseObj)
respBytes, err := json.Marshal(responseObj) respBytes, err := json.Marshal(responseObj)
if err != nil { if err != nil {
klog.Error(err) log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return
} }
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
if _, err := w.Write(respBytes); err != nil { if _, err := w.Write(respBytes); err != nil {
klog.Error(err) log.Error(err)
} }
} }

View File

@@ -6,10 +6,12 @@ import (
"net" "net"
"github.com/mattbaird/jsonpatch" "github.com/mattbaird/jsonpatch"
log "github.com/sirupsen/logrus"
"k8s.io/api/admission/v1" "k8s.io/api/admission/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/klog/v2" "k8s.io/client-go/kubernetes"
"k8s.io/kubectl/pkg/cmd/util/podcmd" "k8s.io/kubectl/pkg/cmd/util/podcmd"
"github.com/wencaiwulue/kubevpn/pkg/config" "github.com/wencaiwulue/kubevpn/pkg/config"
@@ -18,26 +20,30 @@ import (
// only allow pods to pull images from specific registry. // only allow pods to pull images from specific registry.
func (h *admissionReviewHandler) admitPods(ar v1.AdmissionReview) *v1.AdmissionResponse { 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"} podResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
if ar.Request.Resource != podResource { if ar.Request.Resource != podResource {
err := fmt.Errorf("expect resource to be %s", podResource) err := fmt.Errorf("expect resource to be %s but real %s", podResource, ar.Request.Resource)
klog.Error(err) log.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)
return toV1AdmissionResponse(err) return toV1AdmissionResponse(err)
} }
switch ar.Request.Operation { switch ar.Request.Operation {
case v1.Create: 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 var found bool
for i := 0; i < len(pod.Spec.Containers); i++ { for i := 0; i < len(pod.Spec.Containers); i++ {
if pod.Spec.Containers[i].Name == config.ContainerSidecarVPN { 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] pair := pod.Spec.Containers[i].Env[j]
if pair.Name == config.EnvInboundPodTunIP && pair.Value == "" { if pair.Name == config.EnvInboundPodTunIP && pair.Value == "" {
found = true found = true
clientset, err := h.f.KubernetesClientSet() var clientset *kubernetes.Clientset
clientset, err = h.f.KubernetesClientSet()
if err != nil { if err != nil {
klog.Error(err) log.Errorf("can not get clientset, err: %v", err)
return toV1AdmissionResponse(err) return toV1AdmissionResponse(err)
} }
cmi := clientset.CoreV1().ConfigMaps(ar.Request.Namespace) cmi := clientset.CoreV1().ConfigMaps(ar.Request.Namespace)
dhcp := handler.NewDHCPManager(cmi, ar.Request.Namespace, &net.IPNet{IP: config.RouterIP, Mask: config.CIDR.Mask}) 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 { if err != nil {
klog.Error(err) log.Errorf("rent ip random failed, err: %v", err)
return toV1AdmissionResponse(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() pod.Spec.Containers[i].Env[j].Value = random.String()
} }
} }
} }
} }
if found { if found {
to, _ := json.Marshal(pod) var to []byte
patch, _ := jsonpatch.CreatePatch(from, to) to, err = json.Marshal(pod)
marshal, _ := json.Marshal(patch) 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( return applyPodPatch(
ar, ar,
func(pod *corev1.Pod) bool { func(pod *corev1.Pod) bool {
@@ -76,18 +105,28 @@ func (h *admissionReviewHandler) admitPods(ar v1.AdmissionReview) *v1.AdmissionR
) )
} }
return &v1.AdmissionResponse{ return &v1.AdmissionResponse{
UID: ar.Request.UID,
Allowed: true, Allowed: true,
} }
case v1.Delete: 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) name, _ := podcmd.FindContainerByName(&pod, config.ContainerSidecarVPN)
if name != nil { if name != nil {
for _, envVar := range name.Env { for _, envVar := range name.Env {
if envVar.Name == config.EnvInboundPodTunIP && envVar.Value != "" { if envVar.Name == config.EnvInboundPodTunIP && envVar.Value != "" {
ip, cidr, err := net.ParseCIDR(envVar.Value) ip, cidr, err := net.ParseCIDR(envVar.Value)
if err == nil { if err == nil {
clientset, err := h.f.KubernetesClientSet() var clientset *kubernetes.Clientset
clientset, err = h.f.KubernetesClientSet()
if err != nil { if err != nil {
klog.Error(err) log.Errorf("can not get clientset, err: %v", err)
return toV1AdmissionResponse(err) return toV1AdmissionResponse(err)
} }
cmi := clientset.CoreV1().ConfigMaps(ar.Request.Namespace) 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) err = handler.NewDHCPManager(cmi, ar.Request.Namespace, &net.IPNet{IP: config.RouterIP, Mask: config.CIDR.Mask}).ReleaseIpToDHCP(ipnet)
if err != nil { 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: default:
err := fmt.Errorf("expect operation is %s or %s, not %s", v1.Create, v1.Delete, ar.Request.Operation) 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) return toV1AdmissionResponse(err)
} }
} }
func applyPodPatch(ar v1.AdmissionReview, shouldPatchPod func(*corev1.Pod) bool, patch string) *v1.AdmissionResponse { 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"} podResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"}
if ar.Request.Resource != podResource { 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 return nil
} }
@@ -126,7 +168,7 @@ func applyPodPatch(ar v1.AdmissionReview, shouldPatchPod func(*corev1.Pod) bool,
pod := corev1.Pod{} pod := corev1.Pod{}
deserializer := codecs.UniversalDeserializer() deserializer := codecs.UniversalDeserializer()
if _, _, err := deserializer.Decode(raw, nil, &pod); err != nil { 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) return toV1AdmissionResponse(err)
} }
reviewResponse := v1.AdmissionResponse{} reviewResponse := v1.AdmissionResponse{}