diff --git a/charts/kubevpn/Chart.yaml b/charts/kubevpn/Chart.yaml index b5edafe8..9f59ed99 100644 --- a/charts/kubevpn/Chart.yaml +++ b/charts/kubevpn/Chart.yaml @@ -4,3 +4,5 @@ description: A Helm chart for KubeVPN type: application version: 0.1.0 appVersion: "1.16.0" +annotations: + app: kubevpn \ No newline at end of file diff --git a/charts/kubevpn/templates/deployment.yaml b/charts/kubevpn/templates/deployment.yaml index 5637730d..3e711ea4 100644 --- a/charts/kubevpn/templates/deployment.yaml +++ b/charts/kubevpn/templates/deployment.yaml @@ -106,6 +106,11 @@ spec: envFrom: - secretRef: name: {{ include "kubevpn.fullname" . }} + env: + - name: "POD_NAMESPACE" + valueFrom: + fieldRef: + fieldPath: metadata.namespace image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} name: webhook diff --git a/charts/kubevpn/templates/mutatingwebhookconfiguration.yaml b/charts/kubevpn/templates/mutatingwebhookconfiguration.yaml index 8eeef5b0..f1dbd732 100644 --- a/charts/kubevpn/templates/mutatingwebhookconfiguration.yaml +++ b/charts/kubevpn/templates/mutatingwebhookconfiguration.yaml @@ -16,9 +16,7 @@ webhooks: failurePolicy: Ignore matchPolicy: Equivalent name: {{ include "kubevpn.fullname" . }}.naison.io - namespaceSelector: - matchLabels: - ns: {{ .Release.Namespace }} + namespaceSelector: { } objectSelector: { } reinvocationPolicy: Never rules: diff --git a/cmd/kubevpn/cmds/connect.go b/cmd/kubevpn/cmds/connect.go index d85d197b..1187e93d 100644 --- a/cmd/kubevpn/cmds/connect.go +++ b/cmd/kubevpn/cmds/connect.go @@ -81,6 +81,10 @@ func CmdConnect(f cmdutil.Factory) *cobra.Command { if err != nil { return err } + helmNs, _ := util.GetHelmInstalledNamespace(cmd.Context(), f) + if helmNs != "" { + ns = helmNs + } if !sshConf.IsEmpty() { if ip := util.GetAPIServerFromKubeConfigBytes(bytes); ip != nil { extraRoute.ExtraCIDR = append(extraRoute.ExtraCIDR, ip.String()) diff --git a/pkg/config/config.go b/pkg/config/config.go index 8b7286f2..ea724dbf 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -14,9 +14,6 @@ const ( // configmap name ConfigMapPodTrafficManager = "kubevpn-traffic-manager" - // const namespace - KubevpnNamespace = "kubevpn-system" - // config map keys KeyDHCP = "DHCP" KeyDHCP6 = "DHCP6" diff --git a/pkg/daemon/action/proxy.go b/pkg/daemon/action/proxy.go index 5463adbb..5cc86e9b 100644 --- a/pkg/daemon/action/proxy.go +++ b/pkg/daemon/action/proxy.go @@ -71,6 +71,11 @@ func (svr *Server) Proxy(req *rpc.ProxyRequest, resp rpc.Daemon_ProxyServer) (e if daemonClient == nil { return fmt.Errorf("daemon is not avaliable") } + helmNs, _ := util.GetHelmInstalledNamespace(ctx, connect.GetFactory()) + if helmNs != "" { + connect.Namespace = helmNs + } + if svr.connect != nil { isSameCluster, _ := util.IsSameCluster( ctx, @@ -107,7 +112,7 @@ func (svr *Server) Proxy(req *rpc.ProxyRequest, resp rpc.Daemon_ProxyServer) (e if svr.connect == nil { plog.G(ctx).Debugf("Connectting to cluster") var connResp rpc.Daemon_ConnectClient - connResp, err = daemonClient.Connect(ctx, convert(req)) + connResp, err = daemonClient.Connect(ctx, convert(req, helmNs)) if err != nil { return err } @@ -140,10 +145,10 @@ func newProxyWarp(server rpc.Daemon_ProxyServer) io.Writer { return &proxyWarp{server: server} } -func convert(req *rpc.ProxyRequest) *rpc.ConnectRequest { +func convert(req *rpc.ProxyRequest, ns string) *rpc.ConnectRequest { return &rpc.ConnectRequest{ KubeconfigBytes: req.KubeconfigBytes, - Namespace: req.Namespace, + Namespace: util.If(ns != "", ns, req.Namespace), Engine: req.Engine, ExtraRoute: req.ExtraRoute, SshJump: req.SshJump, diff --git a/pkg/handler/connect.go b/pkg/handler/connect.go index d77269e3..a84d015e 100644 --- a/pkg/handler/connect.go +++ b/pkg/handler/connect.go @@ -156,7 +156,7 @@ func (c *ConnectOptions) CreateRemoteInboundPod(ctx context.Context, namespace s } for _, workload := range workloads { - plog.G(ctx).Infof("Injecting inbound sidecar for %s", workload) + plog.G(ctx).Infof("Injecting inbound sidecar for %s in namespace %s", workload, namespace) configInfo := util.PodRouteConfig{ LocalTunIPv4: c.localTunIPv4.IP.String(), LocalTunIPv6: c.localTunIPv6.IP.String(), @@ -182,7 +182,7 @@ func (c *ConnectOptions) CreateRemoteInboundPod(ctx context.Context, namespace s err = inject.InjectVPNSidecar(ctx, c.factory, c.Namespace, object, configInfo) } if err != nil { - plog.G(ctx).Errorf("Injecting inbound sidecar for %s failed: %s", workload, err.Error()) + plog.G(ctx).Errorf("Injecting inbound sidecar for %s in namespace %s failed: %s", workload, namespace, err.Error()) return err } c.proxyWorkloads.Add(c.Namespace, &Proxy{ @@ -286,7 +286,7 @@ func (c *ConnectOptions) portForward(ctx context.Context, portPair []string) err defer firstCancelFunc() var errChan = make(chan error, 1) go func() { - runtime.ErrorHandlers = []func(error){} + runtime.ErrorHandlers = runtime.ErrorHandlers[0:0] var first = pointer.Bool(true) for ctx.Err() == nil { func() { diff --git a/pkg/handler/remote.go b/pkg/handler/remote.go index e51e5e0d..97ac822e 100644 --- a/pkg/handler/remote.go +++ b/pkg/handler/remote.go @@ -476,7 +476,14 @@ kubevpn serve -L "tcp://:10800" -L "tun://:8422?net=${TunIPv4}" -L "gtcp://:1080 }, }, }}, - Env: []v1.EnvVar{}, + Env: []v1.EnvVar{{ + Name: config.EnvPodNamespace, + ValueFrom: &v1.EnvVarSource{ + FieldRef: &v1.ObjectFieldSelector{ + FieldPath: "metadata.namespace", + }, + }, + }}, ImagePullPolicy: v1.PullIfNotPresent, Resources: resourcesSmall, }, diff --git a/pkg/inject/controller.go b/pkg/inject/controller.go index 7edfb709..92fddfac 100644 --- a/pkg/inject/controller.go +++ b/pkg/inject/controller.go @@ -60,13 +60,6 @@ iptables -t nat -A POSTROUTING ! -p icmp ! -s 127.0.0.1 ! -d ${CIDR4} -j MASQUER ip6tables -t nat -A POSTROUTING ! -p icmp ! -s 0:0:0:0:0:0:0:1 ! -d ${CIDR6} -j MASQUERADE kubevpn serve -L "tun:/localhost:8422?net=${TunIPv4}&route=${CIDR4}" -F "tcp://${TrafficManagerService}:10800"`, }, - EnvFrom: []v1.EnvFromSource{{ - SecretRef: &v1.SecretEnvSource{ - LocalObjectReference: v1.LocalObjectReference{ - Name: config.ConfigMapPodTrafficManager, - }, - }, - }}, Env: []v1.EnvVar{ { Name: "CIDR4", diff --git a/pkg/inject/exchange.go b/pkg/inject/exchange.go index 23cbbcfb..6a16d462 100644 --- a/pkg/inject/exchange.go +++ b/pkg/inject/exchange.go @@ -24,13 +24,6 @@ func AddContainer(spec *corev1.PodSpec, c util.PodRouteConfig) { spec.Containers = append(spec.Containers, corev1.Container{ Name: config.ContainerSidecarVPN, Image: config.Image, - EnvFrom: []corev1.EnvFromSource{{ - SecretRef: &corev1.SecretEnvSource{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: config.ConfigMapPodTrafficManager, - }, - }, - }}, Env: []corev1.EnvVar{ { Name: "LocalTunIPv4", diff --git a/pkg/util/helm.go b/pkg/util/helm.go new file mode 100644 index 00000000..95161fbe --- /dev/null +++ b/pkg/util/helm.go @@ -0,0 +1,37 @@ +package util + +import ( + "context" + "os" + + "github.com/pkg/errors" + "helm.sh/helm/v4/pkg/action" + "helm.sh/helm/v4/pkg/release/v1" + cmdutil "k8s.io/kubectl/pkg/cmd/util" +) + +// GetHelmInstalledNamespace +// 1. use helm to install kubevpn server, means cluster mode, +// all kubevpn client should connect to this namespace. +// 2. if any error occurs, just ignore and will use options `-n` or `--namespace` +func GetHelmInstalledNamespace(ctx context.Context, f cmdutil.Factory) (string, error) { + cfg := new(action.Configuration) + client := action.NewList(cfg) + var nothing = func(format string, v ...interface{}) {} + err := cfg.Init(f, "", os.Getenv("HELM_DRIVER"), nothing) + if err != nil { + return "", err + } + client.SetStateMask() + releases, err := client.Run() + if err != nil { + return "", err + } + for _, app := range releases { + if app.Name == "kubevpn" && + app.Info != nil && app.Info.Status == v1.StatusDeployed { + return app.Namespace, nil + } + } + return "", errors.New("app kubevpn not found") +} diff --git a/pkg/util/ns.go b/pkg/util/ns.go index a75b6ab7..64f705ed 100644 --- a/pkg/util/ns.go +++ b/pkg/util/ns.go @@ -39,11 +39,6 @@ func GetClusterIDByCM(cm *v1.ConfigMap) types.UID { } func IsSameCluster(ctx context.Context, client v12.CoreV1Interface, namespace string, clientB v12.CoreV1Interface, namespaceB string) (bool, error) { - if UseDefaultNs(ctx, client) { - namespace = config.KubevpnNamespace - namespaceB = config.KubevpnNamespace - } - if namespace != namespaceB { return false, nil } @@ -59,11 +54,6 @@ func IsSameCluster(ctx context.Context, client v12.CoreV1Interface, namespace st return clusterIDA == clusterIDB, nil } -func UseDefaultNs(ctx context.Context, client v12.CoreV1Interface) bool { - _, err := client.Services(config.KubevpnNamespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{}) - return err == nil -} - func ConvertToKubeConfigBytes(factory cmdutil.Factory) ([]byte, string, error) { loader := factory.ToRawKubeConfigLoader() namespace, _, err := loader.Namespace() diff --git a/pkg/webhook/main.go b/pkg/webhook/main.go index 660b19a9..8d11e6aa 100644 --- a/pkg/webhook/main.go +++ b/pkg/webhook/main.go @@ -4,7 +4,6 @@ import ( "context" "crypto/tls" "fmt" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "net/http" "os" @@ -29,12 +28,8 @@ func Main(f util.Factory) error { if err != nil { return err } - var ns string - _, err = clientset.CoreV1().Services(config.KubevpnNamespace).Get(context.Background(), config.ConfigMapPodTrafficManager, metav1.GetOptions{}) - if err == nil { - ns = config.KubevpnNamespace - } + ns := os.Getenv(config.EnvPodNamespace) h := &admissionReviewHandler{f: f, clientset: clientset, ns: ns} http.HandleFunc("/pods", func(w http.ResponseWriter, r *http.Request) { serve(w, r, newDelegateToV1AdmitHandler(h.admitPods)) diff --git a/pkg/webhook/mutateadmissionwebhook.go b/pkg/webhook/mutateadmissionwebhook.go index 425041ce..2537279a 100644 --- a/pkg/webhook/mutateadmissionwebhook.go +++ b/pkg/webhook/mutateadmissionwebhook.go @@ -71,12 +71,10 @@ func serve(w http.ResponseWriter, r *http.Request, admit admitHandler) { return } - plog.G(context.Background()).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) + msg := fmt.Sprintf("Request: %s could not be decoded: %v", string(body), err) plog.G(context.Background()).Error(msg) http.Error(w, msg, http.StatusBadRequest) return diff --git a/pkg/webhook/pods.go b/pkg/webhook/pods.go index e37a47d2..c01c81e2 100644 --- a/pkg/webhook/pods.go +++ b/pkg/webhook/pods.go @@ -23,8 +23,13 @@ import ( // create pod will rent ip and delete pod will release ip func (h *admissionReviewHandler) admitPods(ar v1.AdmissionReview) *v1.AdmissionResponse { - r, _ := json.Marshal(ar) - plog.G(context.Background()).Infof("Admitting pods called, req: %v", string(r)) + var name, ns string + accessor, _ := meta.Accessor(ar.Request.Object.Object) + if accessor != nil { + name = accessor.GetName() + ns = accessor.GetNamespace() + } + plog.G(context.Background()).Infof("Admitting %s pods called, name: %s, namespace: %s", ar.Request.Operation, name, ns) podResource := metav1.GroupVersionResource{Group: "", Version: "v1", Resource: "pods"} if ar.Request.Resource != podResource { err := fmt.Errorf("expect resource to be %s but real %s", podResource, ar.Request.Resource)