mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-12-24 11:51:13 +08:00
feat: detect namespace kubevpn installed by helm (#498)
This commit is contained in:
@@ -4,3 +4,5 @@ description: A Helm chart for KubeVPN
|
||||
type: application
|
||||
version: 0.1.0
|
||||
appVersion: "1.16.0"
|
||||
annotations:
|
||||
app: kubevpn
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -14,9 +14,6 @@ const (
|
||||
// configmap name
|
||||
ConfigMapPodTrafficManager = "kubevpn-traffic-manager"
|
||||
|
||||
// const namespace
|
||||
KubevpnNamespace = "kubevpn-system"
|
||||
|
||||
// config map keys
|
||||
KeyDHCP = "DHCP"
|
||||
KeyDHCP6 = "DHCP6"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
37
pkg/util/helm.go
Normal file
37
pkg/util/helm.go
Normal file
@@ -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")
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user