feat: support restore from local config (#645)

* refactor: optimize dhcp

* feat: support recover from config

* feat: optimize code

* feat: fix bug

* feat: fix bug

* feat: rename
This commit is contained in:
naison
2025-06-14 13:01:24 +08:00
committed by GitHub
parent 33fba01904
commit 6ca22822f9
31 changed files with 2800 additions and 1157 deletions

View File

@@ -267,9 +267,9 @@ func GetClusterIDByConfig(cmd *cobra.Command, config Config) (string, error) {
if err != nil {
return "", err
}
err = c.InitDHCP(cmd.Context())
id, err := util.GetClusterID(cmd.Context(), c.GetClientset().CoreV1().Namespaces(), ns)
if err != nil {
return "", err
}
return c.GetClusterID(), nil
return string(id), nil
}

View File

@@ -24,6 +24,8 @@ const (
ConfigFile = "config.yaml"
TmpDir = "tmp"
DBFile = "db"
)
var (
@@ -107,3 +109,7 @@ func GetDaemonLogPath(isSudo bool) string {
func GetPProfPath() string {
return filepath.Join(daemonPath, PProfDir)
}
func GetDBPath() string {
return filepath.Join(daemonPath, DBFile)
}

View File

@@ -90,6 +90,7 @@ func (svr *Server) Clone(resp rpc.Daemon_CloneServer) (err error) {
TargetWorkloadNames: map[string]string{},
LocalDir: req.LocalDir,
RemoteDir: req.RemoteDir,
Request: req,
}
file, err := util.ConvertToTempKubeconfigFile([]byte(req.KubeconfigBytes))
if err != nil {

View File

@@ -5,6 +5,7 @@ import (
"io"
"os"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
@@ -18,6 +19,14 @@ import (
)
func (svr *Server) ConnectFork(resp rpc.Daemon_ConnectForkServer) (err error) {
if !svr.IsSudo {
defer func() {
if err == nil {
svr.OffloadToConfig()
}
}()
}
req, err := resp.Recv()
if err != nil {
return err
@@ -38,6 +47,7 @@ func (svr *Server) ConnectFork(resp rpc.Daemon_ConnectForkServer) (err error) {
Lock: &svr.Lock,
Image: req.Image,
ImagePullSecretName: req.ImagePullSecretName,
Request: proto.Clone(req).(*rpc.ConnectRequest),
}
file, err := util.ConvertToTempKubeconfigFile([]byte(req.KubeconfigBytes))
if err != nil {
@@ -100,6 +110,7 @@ func (svr *Server) redirectConnectForkToSudoDaemon(req *rpc.ConnectRequest, resp
ExtraRouteInfo: *handler.ParseExtraRouteFromRPC(req.ExtraRoute),
Engine: config.Engine(req.Engine),
OriginKubeconfigPath: req.OriginKubeconfigPath,
Request: proto.Clone(req).(*rpc.ConnectRequest),
}
connect.AddRolloutFunc(func() error {
sshCancel()
@@ -152,7 +163,10 @@ func (svr *Server) redirectConnectForkToSudoDaemon(req *rpc.ConnectRequest, resp
req.ManagerNamespace = req.Namespace
}
for _, options := range svr.secondaryConnect {
for _, options := range append(svr.secondaryConnect, svr.connect) {
if options == nil {
continue
}
isSameCluster, _ := util.IsSameCluster(
sshCtx,
options.GetClientset().CoreV1(), options.Namespace,
@@ -166,7 +180,8 @@ func (svr *Server) redirectConnectForkToSudoDaemon(req *rpc.ConnectRequest, resp
}
}
ctx, err := connect.RentIP(resp.Context())
var ipCtx context.Context
ipCtx, err = connect.RentIP(resp.Context(), req.IPv4, req.IPv6)
if err != nil {
return err
}
@@ -178,7 +193,7 @@ func (svr *Server) redirectConnectForkToSudoDaemon(req *rpc.ConnectRequest, resp
}
req.KubeconfigBytes = string(content)
req.SshJump = ssh.SshConfig{}.ToRPC()
connResp, err = cli.ConnectFork(ctx)
connResp, err = cli.ConnectFork(ipCtx)
if err != nil {
return err
}

View File

@@ -6,6 +6,7 @@ import (
"os"
"time"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
@@ -21,6 +22,14 @@ import (
)
func (svr *Server) Connect(resp rpc.Daemon_ConnectServer) (err error) {
if !svr.IsSudo {
defer func() {
if err == nil {
svr.OffloadToConfig()
}
}()
}
req, err := resp.Recv()
if err != nil {
return err
@@ -55,6 +64,7 @@ func (svr *Server) Connect(resp rpc.Daemon_ConnectServer) (err error) {
Lock: &svr.Lock,
Image: req.Image,
ImagePullSecretName: req.ImagePullSecretName,
Request: proto.Clone(req).(*rpc.ConnectRequest),
}
var file string
file, err = util.ConvertToTempKubeconfigFile([]byte(req.KubeconfigBytes))
@@ -114,6 +124,7 @@ func (svr *Server) redirectToSudoDaemon(req *rpc.ConnectRequest, resp rpc.Daemon
ExtraRouteInfo: *handler.ParseExtraRouteFromRPC(req.ExtraRoute),
Engine: config.Engine(req.Engine),
OriginKubeconfigPath: req.OriginKubeconfigPath,
Request: proto.Clone(req).(*rpc.ConnectRequest),
}
connect.AddRolloutFunc(func() error {
sshCancel()
@@ -184,7 +195,8 @@ func (svr *Server) redirectToSudoDaemon(req *rpc.ConnectRequest, resp rpc.Daemon
}
}
ctx, err := connect.RentIP(resp.Context())
var ipCtx context.Context
ipCtx, err = connect.RentIP(resp.Context(), req.IPv4, req.IPv6)
if err != nil {
return err
}
@@ -196,7 +208,7 @@ func (svr *Server) redirectToSudoDaemon(req *rpc.ConnectRequest, resp rpc.Daemon
}
req.KubeconfigBytes = string(content)
req.SshJump = ssh.SshConfig{}.ToRPC()
connResp, err = cli.Connect(ctx)
connResp, err = cli.Connect(ipCtx)
if err != nil {
return err
}

View File

@@ -18,7 +18,15 @@ import (
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func (svr *Server) Disconnect(resp rpc.Daemon_DisconnectServer) error {
func (svr *Server) Disconnect(resp rpc.Daemon_DisconnectServer) (err error) {
if !svr.IsSudo {
defer func() {
if err == nil {
svr.OffloadToConfig()
}
}()
}
req, err := resp.Recv()
if err != nil {
return err

View File

@@ -29,8 +29,9 @@ import (
// 2. if already connect to cluster
// 2.1 disconnect from cluster
// 2.2 same as step 1
func (svr *Server) Proxy(resp rpc.Daemon_ProxyServer) (e error) {
req, err := resp.Recv()
func (svr *Server) Proxy(resp rpc.Daemon_ProxyServer) (err error) {
var req *rpc.ProxyRequest
req, err = resp.Recv()
if err != nil {
return err
}
@@ -39,7 +40,8 @@ func (svr *Server) Proxy(resp rpc.Daemon_ProxyServer) (e error) {
ctx := plog.WithLogger(resp.Context(), logger)
var sshConf = ssh.ParseSshFromRPC(req.SshJump)
file, err := util.ConvertToTempKubeconfigFile([]byte(req.KubeconfigBytes))
var file string
file, err = util.ConvertToTempKubeconfigFile([]byte(req.KubeconfigBytes))
if err != nil {
return err
}
@@ -56,6 +58,7 @@ func (svr *Server) Proxy(resp rpc.Daemon_ProxyServer) (e error) {
OriginKubeconfigPath: req.OriginKubeconfigPath,
Image: req.Image,
ImagePullSecretName: req.ImagePullSecretName,
Request: convert(req),
}
err = connect.InitClient(util.InitFactoryByPath(file, req.Namespace))
if err != nil {
@@ -77,12 +80,13 @@ func (svr *Server) Proxy(resp rpc.Daemon_ProxyServer) (e error) {
}
defer func() {
if e != nil && svr.connect != nil {
if err != nil && svr.connect != nil {
_ = svr.connect.LeaveAllProxyResources(plog.WithLogger(context.Background(), logger))
}
}()
cli, err := svr.GetClient(false)
var cli rpc.DaemonClient
cli, err = svr.GetClient(false)
if err != nil {
return errors.Wrap(err, "daemon is not available")
}

View File

@@ -15,6 +15,8 @@ import (
)
func (svr *Server) Quit(resp rpc.Daemon_QuitServer) error {
defer svr.CleanupConfig()
logger := plog.GetLoggerForClient(int32(log.InfoLevel), io.MultiWriter(newQuitWarp(resp), svr.LogFile))
ctx := context.Background()
if resp != nil {

View File

@@ -38,6 +38,10 @@ func (svr *Server) Reset(resp rpc.Daemon_ResetServer) error {
if err != nil {
return err
}
connect.Namespace, err = util.DetectManagerNamespace(ctx, connect.GetFactory(), req.Namespace)
if err != nil {
return err
}
err = connect.Reset(ctx, req.Namespace, req.Workloads)
if err != nil {
return err

View File

@@ -1,15 +1,21 @@
package action
import (
"context"
"encoding/json"
"os"
"sync"
"time"
"gopkg.in/natefinch/lumberjack.v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/metadata/metadatainformer"
"sigs.k8s.io/yaml"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/v2/pkg/handler"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
type Server struct {
@@ -31,3 +37,86 @@ type Server struct {
ID string
}
type Config struct {
Connect *handler.ConnectOptions `json:"Connect"`
SecondaryConnect []*handler.ConnectOptions `json:"SecondaryConnect"`
}
func (svr *Server) LoadFromConfig() error {
file, err := os.ReadFile(config.GetDBPath())
if err != nil {
return err
}
jsonConf, err := yaml.YAMLToJSON(file)
if err != nil {
return err
}
var conf Config
err = json.Unmarshal(jsonConf, &conf)
if err != nil {
return err
}
if conf.Connect == nil && len(conf.SecondaryConnect) == 0 {
return nil
}
var client rpc.DaemonClient
for {
_, err = svr.GetClient(true)
if err != nil {
time.Sleep(time.Millisecond * 200)
continue
}
client, err = svr.GetClient(false)
if err != nil {
time.Sleep(time.Millisecond * 200)
continue
}
break
}
if conf.Connect != nil {
var resp rpc.Daemon_ConnectClient
resp, err = client.Connect(context.Background())
if err == nil {
conf.Connect.Request.IPv4 = conf.Connect.LocalTunIPv4.String()
conf.Connect.Request.IPv6 = conf.Connect.LocalTunIPv6.String()
err = resp.Send(conf.Connect.Request)
_ = util.PrintGRPCStream[rpc.ConnectResponse](nil, resp, svr.LogFile)
}
}
for _, conf := range append(conf.SecondaryConnect) {
if conf != nil {
var resp rpc.Daemon_ConnectClient
resp, err = client.ConnectFork(context.Background())
if err != nil {
continue
}
conf.Request.IPv4 = conf.LocalTunIPv4.String()
conf.Request.IPv6 = conf.LocalTunIPv6.String()
err = resp.Send(conf.Request)
_ = util.PrintGRPCStream[rpc.ConnectResponse](nil, resp, svr.LogFile)
}
}
return nil
}
func (svr *Server) OffloadToConfig() error {
conf := &Config{
Connect: svr.connect,
SecondaryConnect: svr.secondaryConnect,
}
jsonConf, err := json.Marshal(conf)
if err != nil {
return err
}
yamlConf, err := yaml.JSONToYAML(jsonConf)
if err != nil {
return err
}
err = os.WriteFile(config.GetDBPath(), yamlConf, 0644)
return err
}
func (svr *Server) CleanupConfig() error {
return os.Remove(config.GetDBPath())
}

View File

@@ -13,7 +13,9 @@ import (
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func (svr *Server) Uninstall(resp rpc.Daemon_UninstallServer) error {
func (svr *Server) Uninstall(resp rpc.Daemon_UninstallServer) (err error) {
defer svr.CleanupConfig()
req, err := resp.Recv()
if err != nil {
return err

View File

@@ -124,6 +124,9 @@ func (o *SvrOption) Start(ctx context.Context) error {
_ = l.Close()
}
o.svr = &action.Server{Cancel: cancel, IsSudo: o.IsSudo, GetClient: GetClient, LogFile: l, ID: o.ID}
if !o.IsSudo {
go o.svr.LoadFromConfig()
}
rpc.RegisterDaemonServer(svr, o.svr)
return downgradingServer.Serve(lis)
//return o.svr.Serve(lis)

File diff suppressed because it is too large Load Diff

View File

@@ -63,6 +63,11 @@ message ConnectRequest {
// 2. detect which namespace helm installed by (helm list -A), match app name==kubevpn and status is deployed
// 3. otherwise, use options '-n' or '--namespace'
string ManagerNamespace = 12;
// Inner ip v4 and v6, for recovery from local db,
// this filed only set when recover from local db, otherwise, always empty
string IPv4 = 13;
string IPv6 = 14;
}
message ConnectResponse {

File diff suppressed because it is too large Load Diff

View File

@@ -21,16 +21,16 @@ import (
)
type Manager struct {
client *kubernetes.Clientset
clientset *kubernetes.Clientset
cidr *net.IPNet
cidr6 *net.IPNet
namespace string
clusterID types.UID
}
func NewDHCPManager(client *kubernetes.Clientset, namespace string) *Manager {
func NewDHCPManager(clientset *kubernetes.Clientset, namespace string) *Manager {
return &Manager{
client: client,
clientset: clientset,
namespace: namespace,
cidr: &net.IPNet{IP: config.RouterIP, Mask: config.CIDR.Mask},
cidr6: &net.IPNet{IP: config.RouterIP6, Mask: config.CIDR6.Mask},
@@ -38,15 +38,15 @@ func NewDHCPManager(client *kubernetes.Clientset, namespace string) *Manager {
}
// InitDHCP
// TODO optimize dhcp, using mac address, ip and deadline as unit
// TODO optimize dhcp, using mac address, ipPair and deadline as unit
func (m *Manager) InitDHCP(ctx context.Context) error {
cm, err := m.client.CoreV1().ConfigMaps(m.namespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{})
cm, err := m.clientset.CoreV1().ConfigMaps(m.namespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{})
if err != nil && !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to get configmap %s, err: %v", config.ConfigMapPodTrafficManager, err)
}
if err == nil {
m.clusterID, err = util.GetClusterID(ctx, m.client.CoreV1().Namespaces(), m.namespace)
m.clusterID, err = util.GetClusterID(ctx, m.clientset.CoreV1().Namespaces(), m.namespace)
return err
}
@@ -63,11 +63,11 @@ func (m *Manager) InitDHCP(ctx context.Context) error {
config.KeyClusterIPv4POOLS: "",
},
}
cm, err = m.client.CoreV1().ConfigMaps(m.namespace).Create(ctx, cm, metav1.CreateOptions{})
cm, err = m.clientset.CoreV1().ConfigMaps(m.namespace).Create(ctx, cm, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("failed to create configmap: %v", err)
}
m.clusterID, err = util.GetClusterID(ctx, m.client.CoreV1().Namespaces(), m.namespace)
m.clusterID, err = util.GetClusterID(ctx, m.clientset.CoreV1().Namespaces(), m.namespace)
return err
}
@@ -86,6 +86,7 @@ func (m *Manager) RentIP(ctx context.Context) (*net.IPNet, *net.IPNet, error) {
}
return false
}
var uselessIPs []net.IP
var v4, v6 net.IP
err := m.updateDHCPConfigMap(ctx, func(ipv4 *ipallocator.Range, ipv6 *ipallocator.Range) (err error) {
for {
@@ -95,6 +96,7 @@ func (m *Manager) RentIP(ctx context.Context) (*net.IPNet, *net.IPNet, error) {
if !isAlreadyExistedFunc(v4) {
break
}
uselessIPs = append(uselessIPs, v4)
}
for {
if v6, err = ipv6.AllocateNext(); err != nil {
@@ -103,9 +105,15 @@ func (m *Manager) RentIP(ctx context.Context) (*net.IPNet, *net.IPNet, error) {
if !isAlreadyExistedFunc(v6) {
break
}
uselessIPs = append(uselessIPs, v6)
}
return
})
if len(uselessIPs) != 0 {
if er := m.releaseIP(ctx, uselessIPs...); er != nil {
plog.G(ctx).Errorf("Failed to release useless IPs: %v", er)
}
}
if err != nil {
plog.G(ctx).Errorf("Failed to rent IP from DHCP server: %v", err)
return nil, nil, err
@@ -113,28 +121,44 @@ func (m *Manager) RentIP(ctx context.Context) (*net.IPNet, *net.IPNet, error) {
return &net.IPNet{IP: v4, Mask: m.cidr.Mask}, &net.IPNet{IP: v6, Mask: m.cidr6.Mask}, nil
}
func (m *Manager) ReleaseIP(ctx context.Context, ips ...net.IP) error {
func (m *Manager) ReleaseIP(ctx context.Context, v4, v6 net.IP) error {
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
return m.updateDHCPConfigMap(ctx, func(ipv4 *ipallocator.Range, ipv6 *ipallocator.Range) error {
if err := ipv4.Release(v4); err != nil {
return err
}
if err := ipv6.Release(v6); err != nil {
return err
}
return nil
})
})
}
func (m *Manager) releaseIP(ctx context.Context, ips ...net.IP) error {
if len(ips) == 0 {
return nil
}
return m.updateDHCPConfigMap(ctx, func(ipv4 *ipallocator.Range, ipv6 *ipallocator.Range) error {
for _, ip := range ips {
var err error
if ip.To4() != nil {
err = ipv4.Release(ip)
} else {
err = ipv6.Release(ip)
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
return m.updateDHCPConfigMap(ctx, func(ipv4 *ipallocator.Range, ipv6 *ipallocator.Range) error {
for _, ip := range ips {
var err error
if ip.To4() != nil {
err = ipv4.Release(ip)
} else {
err = ipv6.Release(ip)
}
if err != nil {
return err
}
}
if err != nil {
return err
}
}
return nil
return nil
})
})
}
func (m *Manager) updateDHCPConfigMap(ctx context.Context, f func(ipv4 *ipallocator.Range, ipv6 *ipallocator.Range) error) error {
cm, err := m.client.CoreV1().ConfigMaps(m.namespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{})
cm, err := m.clientset.CoreV1().ConfigMaps(m.namespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("failed to get configmap DHCP server, err: %v", err)
}
@@ -189,38 +213,15 @@ func (m *Manager) updateDHCPConfigMap(ctx context.Context, f func(ipv4 *ipalloca
return err
}
cm.Data[config.KeyDHCP6] = base64.StdEncoding.EncodeToString(bytes)
_, err = m.client.CoreV1().ConfigMaps(m.namespace).Update(ctx, cm, metav1.UpdateOptions{})
_, err = m.clientset.CoreV1().ConfigMaps(m.namespace).Update(ctx, cm, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("failed to update DHCP: %v", err)
}
return nil
}
func (m *Manager) Set(ctx context.Context, key, value string) error {
err := retry.RetryOnConflict(
retry.DefaultRetry,
func() error {
p := []byte(fmt.Sprintf(`[{"op": "replace", "path": "/data/%s", "value": "%s"}]`, key, value))
_, err := m.client.CoreV1().ConfigMaps(m.namespace).Patch(ctx, config.ConfigMapPodTrafficManager, types.JSONPatchType, p, metav1.PatchOptions{})
return err
})
if err != nil {
plog.G(ctx).Errorf("Failed to update configmap: %v", err)
return err
}
return nil
}
func (m *Manager) Get(ctx context.Context, key string) (string, error) {
cm, err := m.client.CoreV1().ConfigMaps(m.namespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{})
if err != nil {
return "", err
}
return cm.Data[key], nil
}
func (m *Manager) ForEach(ctx context.Context, fnv4 func(net.IP), fnv6 func(net.IP)) error {
cm, err := m.client.CoreV1().ConfigMaps(m.namespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{})
cm, err := m.clientset.CoreV1().ConfigMaps(m.namespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{})
if err != nil {
return fmt.Errorf("failed to get cm DHCP server, err: %v", err)
}

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.6
// protoc-gen-go v1.33.0
// protoc v5.29.3
// source: dhcpserver.proto
@@ -11,7 +11,6 @@ import (
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -22,18 +21,21 @@ const (
)
type RentIPRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
}
func (x *RentIPRequest) Reset() {
*x = RentIPRequest{}
mi := &file_dhcpserver_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
if protoimpl.UnsafeEnabled {
mi := &file_dhcpserver_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RentIPRequest) String() string {
@@ -44,7 +46,7 @@ func (*RentIPRequest) ProtoMessage() {}
func (x *RentIPRequest) ProtoReflect() protoreflect.Message {
mi := &file_dhcpserver_proto_msgTypes[0]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -74,18 +76,21 @@ func (x *RentIPRequest) GetPodNamespace() string {
}
type RentIPResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
IPv4CIDR string `protobuf:"bytes,1,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
IPv6CIDR string `protobuf:"bytes,2,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
IPv4CIDR string `protobuf:"bytes,1,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
IPv6CIDR string `protobuf:"bytes,2,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
}
func (x *RentIPResponse) Reset() {
*x = RentIPResponse{}
mi := &file_dhcpserver_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
if protoimpl.UnsafeEnabled {
mi := &file_dhcpserver_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RentIPResponse) String() string {
@@ -96,7 +101,7 @@ func (*RentIPResponse) ProtoMessage() {}
func (x *RentIPResponse) ProtoReflect() protoreflect.Message {
mi := &file_dhcpserver_proto_msgTypes[1]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -126,20 +131,23 @@ func (x *RentIPResponse) GetIPv6CIDR() string {
}
type ReleaseIPRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
IPv4CIDR string `protobuf:"bytes,3,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
IPv6CIDR string `protobuf:"bytes,4,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PodName string `protobuf:"bytes,1,opt,name=PodName,proto3" json:"PodName,omitempty"`
PodNamespace string `protobuf:"bytes,2,opt,name=PodNamespace,proto3" json:"PodNamespace,omitempty"`
IPv4CIDR string `protobuf:"bytes,3,opt,name=IPv4CIDR,proto3" json:"IPv4CIDR,omitempty"`
IPv6CIDR string `protobuf:"bytes,4,opt,name=IPv6CIDR,proto3" json:"IPv6CIDR,omitempty"`
}
func (x *ReleaseIPRequest) Reset() {
*x = ReleaseIPRequest{}
mi := &file_dhcpserver_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
if protoimpl.UnsafeEnabled {
mi := &file_dhcpserver_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReleaseIPRequest) String() string {
@@ -150,7 +158,7 @@ func (*ReleaseIPRequest) ProtoMessage() {}
func (x *ReleaseIPRequest) ProtoReflect() protoreflect.Message {
mi := &file_dhcpserver_proto_msgTypes[2]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -194,17 +202,20 @@ func (x *ReleaseIPRequest) GetIPv6CIDR() string {
}
type ReleaseIPResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
unknownFields protoimpl.UnknownFields
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
}
func (x *ReleaseIPResponse) Reset() {
*x = ReleaseIPResponse{}
mi := &file_dhcpserver_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
if protoimpl.UnsafeEnabled {
mi := &file_dhcpserver_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReleaseIPResponse) String() string {
@@ -215,7 +226,7 @@ func (*ReleaseIPResponse) ProtoMessage() {}
func (x *ReleaseIPResponse) ProtoReflect() protoreflect.Message {
mi := &file_dhcpserver_proto_msgTypes[3]
if x != nil {
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
@@ -239,40 +250,55 @@ func (x *ReleaseIPResponse) GetMessage() string {
var File_dhcpserver_proto protoreflect.FileDescriptor
const file_dhcpserver_proto_rawDesc = "" +
"\n" +
"\x10dhcpserver.proto\x12\x03rpc\"M\n" +
"\rRentIPRequest\x12\x18\n" +
"\aPodName\x18\x01 \x01(\tR\aPodName\x12\"\n" +
"\fPodNamespace\x18\x02 \x01(\tR\fPodNamespace\"H\n" +
"\x0eRentIPResponse\x12\x1a\n" +
"\bIPv4CIDR\x18\x01 \x01(\tR\bIPv4CIDR\x12\x1a\n" +
"\bIPv6CIDR\x18\x02 \x01(\tR\bIPv6CIDR\"\x88\x01\n" +
"\x10ReleaseIPRequest\x12\x18\n" +
"\aPodName\x18\x01 \x01(\tR\aPodName\x12\"\n" +
"\fPodNamespace\x18\x02 \x01(\tR\fPodNamespace\x12\x1a\n" +
"\bIPv4CIDR\x18\x03 \x01(\tR\bIPv4CIDR\x12\x1a\n" +
"\bIPv6CIDR\x18\x04 \x01(\tR\bIPv6CIDR\"-\n" +
"\x11ReleaseIPResponse\x12\x18\n" +
"\amessage\x18\x01 \x01(\tR\amessage2y\n" +
"\x04DHCP\x123\n" +
"\x06RentIP\x12\x12.rpc.RentIPRequest\x1a\x13.rpc.RentIPResponse\"\x00\x12<\n" +
"\tReleaseIP\x12\x15.rpc.ReleaseIPRequest\x1a\x16.rpc.ReleaseIPResponse\"\x00B\aZ\x05.;rpcb\x06proto3"
var file_dhcpserver_proto_rawDesc = []byte{
0x0a, 0x10, 0x64, 0x68, 0x63, 0x70, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x03, 0x72, 0x70, 0x63, 0x22, 0x4d, 0x0a, 0x0d, 0x52, 0x65, 0x6e, 0x74, 0x49,
0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x6f, 0x64, 0x4e,
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x50, 0x6f, 0x64, 0x4e, 0x61,
0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d,
0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x48, 0x0a, 0x0e, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x34,
0x43, 0x49, 0x44, 0x52, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x34,
0x43, 0x49, 0x44, 0x52, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52,
0x22, 0x88, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12,
0x22, 0x0a, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18,
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x6f, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
0x61, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x34, 0x43, 0x49, 0x44, 0x52, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x34, 0x43, 0x49, 0x44, 0x52, 0x12,
0x1a, 0x0a, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52, 0x18, 0x04, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x49, 0x50, 0x76, 0x36, 0x43, 0x49, 0x44, 0x52, 0x22, 0x2d, 0x0a, 0x11, 0x52,
0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x79, 0x0a, 0x04, 0x44, 0x48,
0x43, 0x50, 0x12, 0x33, 0x0a, 0x06, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x12, 0x12, 0x2e, 0x72,
0x70, 0x63, 0x2e, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x13, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6e, 0x74, 0x49, 0x50, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x09, 0x52, 0x65, 0x6c, 0x65, 0x61,
0x73, 0x65, 0x49, 0x50, 0x12, 0x15, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61,
0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x49, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x07, 0x5a, 0x05, 0x2e, 0x3b, 0x72, 0x70, 0x63, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_dhcpserver_proto_rawDescOnce sync.Once
file_dhcpserver_proto_rawDescData []byte
file_dhcpserver_proto_rawDescData = file_dhcpserver_proto_rawDesc
)
func file_dhcpserver_proto_rawDescGZIP() []byte {
file_dhcpserver_proto_rawDescOnce.Do(func() {
file_dhcpserver_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_dhcpserver_proto_rawDesc), len(file_dhcpserver_proto_rawDesc)))
file_dhcpserver_proto_rawDescData = protoimpl.X.CompressGZIP(file_dhcpserver_proto_rawDescData)
})
return file_dhcpserver_proto_rawDescData
}
var file_dhcpserver_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_dhcpserver_proto_goTypes = []any{
var file_dhcpserver_proto_goTypes = []interface{}{
(*RentIPRequest)(nil), // 0: rpc.RentIPRequest
(*RentIPResponse)(nil), // 1: rpc.RentIPResponse
(*ReleaseIPRequest)(nil), // 2: rpc.ReleaseIPRequest
@@ -295,11 +321,61 @@ func file_dhcpserver_proto_init() {
if File_dhcpserver_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_dhcpserver_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RentIPRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_dhcpserver_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RentIPResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_dhcpserver_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReleaseIPRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_dhcpserver_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReleaseIPResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_dhcpserver_proto_rawDesc), len(file_dhcpserver_proto_rawDesc)),
RawDescriptor: file_dhcpserver_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
@@ -310,6 +386,7 @@ func file_dhcpserver_proto_init() {
MessageInfos: file_dhcpserver_proto_msgTypes,
}.Build()
File_dhcpserver_proto = out.File
file_dhcpserver_proto_rawDesc = nil
file_dhcpserver_proto_goTypes = nil
file_dhcpserver_proto_depIdxs = nil
}

View File

@@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc-gen-go-grpc v1.3.0
// - protoc v5.29.3
// source: dhcpserver.proto
@@ -15,8 +15,8 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const (
DHCP_RentIP_FullMethodName = "/rpc.DHCP/RentIP"
@@ -40,9 +40,8 @@ func NewDHCPClient(cc grpc.ClientConnInterface) DHCPClient {
}
func (c *dHCPClient) RentIP(ctx context.Context, in *RentIPRequest, opts ...grpc.CallOption) (*RentIPResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RentIPResponse)
err := c.cc.Invoke(ctx, DHCP_RentIP_FullMethodName, in, out, cOpts...)
err := c.cc.Invoke(ctx, DHCP_RentIP_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@@ -50,9 +49,8 @@ func (c *dHCPClient) RentIP(ctx context.Context, in *RentIPRequest, opts ...grpc
}
func (c *dHCPClient) ReleaseIP(ctx context.Context, in *ReleaseIPRequest, opts ...grpc.CallOption) (*ReleaseIPResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ReleaseIPResponse)
err := c.cc.Invoke(ctx, DHCP_ReleaseIP_FullMethodName, in, out, cOpts...)
err := c.cc.Invoke(ctx, DHCP_ReleaseIP_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
@@ -61,19 +59,16 @@ func (c *dHCPClient) ReleaseIP(ctx context.Context, in *ReleaseIPRequest, opts .
// DHCPServer is the server API for DHCP service.
// All implementations must embed UnimplementedDHCPServer
// for forward compatibility.
// for forward compatibility
type DHCPServer interface {
RentIP(context.Context, *RentIPRequest) (*RentIPResponse, error)
ReleaseIP(context.Context, *ReleaseIPRequest) (*ReleaseIPResponse, error)
mustEmbedUnimplementedDHCPServer()
}
// UnimplementedDHCPServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedDHCPServer struct{}
// UnimplementedDHCPServer must be embedded to have forward compatible implementations.
type UnimplementedDHCPServer struct {
}
func (UnimplementedDHCPServer) RentIP(context.Context, *RentIPRequest) (*RentIPResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RentIP not implemented")
@@ -82,7 +77,6 @@ func (UnimplementedDHCPServer) ReleaseIP(context.Context, *ReleaseIPRequest) (*R
return nil, status.Errorf(codes.Unimplemented, "method ReleaseIP not implemented")
}
func (UnimplementedDHCPServer) mustEmbedUnimplementedDHCPServer() {}
func (UnimplementedDHCPServer) testEmbeddedByValue() {}
// UnsafeDHCPServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to DHCPServer will
@@ -92,13 +86,6 @@ type UnsafeDHCPServer interface {
}
func RegisterDHCPServer(s grpc.ServiceRegistrar, srv DHCPServer) {
// If the following call pancis, it indicates UnimplementedDHCPServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&DHCP_ServiceDesc, srv)
}

View File

@@ -48,18 +48,19 @@ func (s *Server) ReleaseIP(ctx context.Context, req *rpc.ReleaseIPRequest) (*rpc
defer s.Unlock()
plog.G(ctx).Infof("Handling release IP request, pod name: %s, ns: %s, IPv4: %s, IPv6: %s", req.PodName, req.PodNamespace, req.IPv4CIDR, req.IPv6CIDR)
var ips []net.IP
for _, ipStr := range []string{req.IPv4CIDR, req.IPv6CIDR} {
ip, _, err := net.ParseCIDR(ipStr)
if err != nil {
plog.G(ctx).Errorf("IP %s is invailed: %v", ipStr, err)
continue
}
ips = append(ips, ip)
ipv4, _, err := net.ParseCIDR(req.IPv4CIDR)
if err != nil {
plog.G(ctx).Errorf("IP %s is invailed: %v", req.IPv4CIDR, err)
}
var ipv6 net.IP
ipv6, _, err = net.ParseCIDR(req.IPv6CIDR)
if err != nil {
plog.G(ctx).Errorf("IP %s is invailed: %v", req.IPv6CIDR, err)
}
manager := NewDHCPManager(s.clientset, req.PodNamespace)
if err := manager.ReleaseIP(ctx, ips...); err != nil {
if err = manager.ReleaseIP(ctx, ipv4, ipv6); err != nil {
plog.G(ctx).Errorf("Failed to release IP: %v", err)
return nil, err
}

View File

@@ -8,7 +8,7 @@ import (
"syscall"
"time"
"k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/pointer"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
@@ -25,62 +25,72 @@ func (c *ConnectOptions) setupSignalHandler() {
}
}
func (c *ConnectOptions) Cleanup(ctx context.Context) {
func (c *ConnectOptions) Cleanup(logCtx context.Context) {
if c == nil {
return
}
var inUserDaemon bool
// only root daemon really do connect
// root daemon: data plane
// user daemon: control plane
var userDaemon = true
if c.ctx != nil {
inUserDaemon = true
userDaemon = false
}
c.once.Do(func() {
if inUserDaemon {
plog.G(ctx).Info("Performing cleanup operations")
}
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*10)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
var ips []net.IP
if c.localTunIPv4 != nil && c.localTunIPv4.IP != nil {
ips = append(ips, c.localTunIPv4.IP)
}
if c.localTunIPv6 != nil && c.localTunIPv6.IP != nil {
ips = append(ips, c.localTunIPv6.IP)
}
if c.dhcp != nil {
err := c.dhcp.ReleaseIP(ctx2, ips...)
if err != nil {
plog.G(ctx).Errorf("Failed to release IP to DHCP server: %v", err)
} else {
plog.G(ctx).Infof("Releaseed IP %v to DHCP server", ips)
if userDaemon {
plog.G(logCtx).Info("Performing cleanup operations")
var ipv4, ipv6 net.IP
if c.LocalTunIPv4 != nil && c.LocalTunIPv4.IP != nil {
ipv4 = c.LocalTunIPv4.IP
}
}
if c.clientset != nil {
_ = c.clientset.CoreV1().Pods(c.Namespace).Delete(ctx2, config.CniNetName, v1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)})
_ = c.clientset.BatchV1().Jobs(c.Namespace).Delete(ctx2, config.ConfigMapPodTrafficManager, v1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)})
}
// leave proxy resources
err := c.LeaveAllProxyResources(ctx2)
if err != nil {
plog.G(ctx).Errorf("Leave proxy resources error: %v", err)
}
if c.cancel != nil {
c.cancel()
}
for _, function := range c.getRolloutFunc() {
if function != nil {
if err = function(); err != nil {
plog.G(ctx).Warnf("Rollout function error: %v", err)
if c.LocalTunIPv6 != nil && c.LocalTunIPv6.IP != nil {
ipv6 = c.LocalTunIPv6.IP
}
if c.dhcp != nil {
err := c.dhcp.ReleaseIP(ctx, ipv4, ipv6)
if err != nil {
plog.G(logCtx).Errorf("Failed to release IP to DHCP server: %v", err)
} else {
plog.G(logCtx).Infof("Releaseed IPv4 %v IPv6 %v to DHCP server", ipv4, ipv6)
}
}
}
if c.dnsConfig != nil {
if inUserDaemon {
plog.G(ctx2).Infof("Clearing DNS settings")
if c.clientset != nil {
_ = c.clientset.CoreV1().Pods(c.Namespace).Delete(ctx, config.CniNetName, v1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)})
_ = c.clientset.BatchV1().Jobs(c.Namespace).Delete(ctx, config.ConfigMapPodTrafficManager, v1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)})
}
// leave proxy resources
err := c.LeaveAllProxyResources(ctx)
if err != nil {
plog.G(logCtx).Errorf("Leave proxy resources error: %v", err)
}
for _, function := range c.getRolloutFunc() {
if function != nil {
if err = function(); err != nil {
plog.G(logCtx).Warnf("Rollout function error: %v", err)
}
}
}
} else {
if c.cancel != nil {
c.cancel()
}
for _, function := range c.getRolloutFunc() {
if function != nil {
if err := function(); err != nil {
plog.G(logCtx).Warnf("Rollout function error: %v", err)
}
}
}
if c.dnsConfig != nil {
plog.G(logCtx).Infof("Clearing DNS settings")
c.dnsConfig.CancelDNS()
}
c.dnsConfig.CancelDNS()
}
})
}

View File

@@ -32,6 +32,7 @@ import (
"k8s.io/utils/ptr"
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
plog "github.com/wencaiwulue/kubevpn/v2/pkg/log"
"github.com/wencaiwulue/kubevpn/v2/pkg/syncthing"
"github.com/wencaiwulue/kubevpn/v2/pkg/util"
@@ -51,6 +52,7 @@ type CloneOptions struct {
OriginKubeconfigPath string
LocalDir string
RemoteDir string
Request *rpc.CloneRequest `json:"Request,omitempty"`
clientset *kubernetes.Clientset
restclient *rest.RESTClient

View File

@@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"net"
"reflect"
"slices"
"sort"
"strconv"
@@ -30,6 +29,7 @@ import (
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
pkgruntime "k8s.io/apimachinery/pkg/runtime"
k8stypes "k8s.io/apimachinery/pkg/types"
pkgtypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets"
@@ -52,6 +52,7 @@ import (
"github.com/wencaiwulue/kubevpn/v2/pkg/config"
"github.com/wencaiwulue/kubevpn/v2/pkg/core"
"github.com/wencaiwulue/kubevpn/v2/pkg/daemon/rpc"
"github.com/wencaiwulue/kubevpn/v2/pkg/dhcp"
"github.com/wencaiwulue/kubevpn/v2/pkg/dns"
"github.com/wencaiwulue/kubevpn/v2/pkg/driver"
@@ -71,6 +72,7 @@ type ConnectOptions struct {
Lock *sync.Mutex
Image string
ImagePullSecretName string
Request *rpc.ConnectRequest `json:"Request,omitempty"`
ctx context.Context
cancel context.CancelFunc
@@ -82,8 +84,8 @@ type ConnectOptions struct {
cidrs []*net.IPNet
dhcp *dhcp.Manager
// needs to give it back to dhcp
localTunIPv4 *net.IPNet
localTunIPv6 *net.IPNet
LocalTunIPv4 *net.IPNet `json:"LocalTunIPv4,omitempty"`
LocalTunIPv6 *net.IPNet `json:"LocalTunIPv6,omitempty"`
rollbackFuncList []func() error
dnsConfig *dns.Config
@@ -106,21 +108,28 @@ func (c *ConnectOptions) InitDHCP(ctx context.Context) error {
return nil
}
func (c *ConnectOptions) RentIP(ctx context.Context) (context.Context, error) {
func (c *ConnectOptions) RentIP(ctx context.Context, ipv4, ipv6 string) (context.Context, error) {
if err := c.InitDHCP(ctx); err != nil {
return nil, err
}
var err error
c.localTunIPv4, c.localTunIPv6, err = c.dhcp.RentIP(ctx)
if err != nil {
return nil, err
if util.IsValidCIDR(ipv4) && util.IsValidCIDR(ipv6) {
ip, cidr, _ := net.ParseCIDR(ipv4)
c.LocalTunIPv4 = &net.IPNet{IP: ip, Mask: cidr.Mask}
ip, cidr, _ = net.ParseCIDR(ipv6)
c.LocalTunIPv6 = &net.IPNet{IP: ip, Mask: cidr.Mask}
} else {
var err error
c.LocalTunIPv4, c.LocalTunIPv6, err = c.dhcp.RentIP(ctx)
if err != nil {
return nil, err
}
}
ctx1 := metadata.AppendToOutgoingContext(
return metadata.AppendToOutgoingContext(
context.Background(),
config.HeaderIPv4, c.localTunIPv4.String(),
config.HeaderIPv6, c.localTunIPv6.String(),
)
return ctx1, nil
config.HeaderIPv4, c.LocalTunIPv4.String(),
config.HeaderIPv6, c.LocalTunIPv6.String(),
), nil
}
func (c *ConnectOptions) GetIPFromContext(ctx context.Context, logger *log.Logger) error {
@@ -137,8 +146,8 @@ func (c *ConnectOptions) GetIPFromContext(ctx context.Context, logger *log.Logge
if err != nil {
return fmt.Errorf("cat not convert IPv4 string: %s: %v", ipv4[0], err)
}
c.localTunIPv4 = &net.IPNet{IP: ip, Mask: ipNet.Mask}
logger.Debugf("Get IPv4 %s from context", c.localTunIPv4.String())
c.LocalTunIPv4 = &net.IPNet{IP: ip, Mask: ipNet.Mask}
logger.Debugf("Get IPv4 %s from context", c.LocalTunIPv4.String())
ipv6 := md.Get(config.HeaderIPv6)
if len(ipv6) == 0 {
@@ -148,13 +157,13 @@ func (c *ConnectOptions) GetIPFromContext(ctx context.Context, logger *log.Logge
if err != nil {
return fmt.Errorf("cat not convert IPv6 string: %s: %v", ipv6[0], err)
}
c.localTunIPv6 = &net.IPNet{IP: ip, Mask: ipNet.Mask}
logger.Debugf("Get IPv6 %s from context", c.localTunIPv6.String())
c.LocalTunIPv6 = &net.IPNet{IP: ip, Mask: ipNet.Mask}
logger.Debugf("Get IPv6 %s from context", c.LocalTunIPv6.String())
return nil
}
func (c *ConnectOptions) CreateRemoteInboundPod(ctx context.Context, namespace string, workloads []string, headers map[string]string, portMap []string, image string) (err error) {
if c.localTunIPv4 == nil || c.localTunIPv6 == nil {
if c.LocalTunIPv4 == nil || c.LocalTunIPv6 == nil {
return fmt.Errorf("local tun IP is invalid")
}
if c.proxyWorkloads == nil {
@@ -169,8 +178,8 @@ func (c *ConnectOptions) CreateRemoteInboundPod(ctx context.Context, namespace s
for _, workload := range workloads {
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(),
LocalTunIPv4: c.LocalTunIPv4.IP.String(),
LocalTunIPv6: c.LocalTunIPv6.IP.String(),
}
var object, controller *runtimeresource.Info
object, controller, err = util.GetTopOwnerObject(ctx, c.factory, namespace, workload)
@@ -211,13 +220,12 @@ func (c *ConnectOptions) CreateRemoteInboundPod(ctx context.Context, namespace s
func (c *ConnectOptions) DoConnect(ctx context.Context, isLite bool) (err error) {
c.ctx, c.cancel = context.WithCancel(ctx)
plog.G(ctx).Info("Starting connect to cluster")
m := dhcp.NewDHCPManager(c.clientset, c.Namespace)
if err = m.InitDHCP(c.ctx); err != nil {
if err = c.InitDHCP(c.ctx); err != nil {
plog.G(ctx).Errorf("Init DHCP server failed: %v", err)
return
}
go c.setupSignalHandler()
if err = c.getCIDR(c.ctx, m); err != nil {
if err = c.getCIDR(c.ctx); err != nil {
plog.G(ctx).Errorf("Failed to get network CIDR: %v", err)
return
}
@@ -324,7 +332,7 @@ func (c *ConnectOptions) portForward(ctx context.Context, portPair []string) err
// try to detect pod is delete event, if pod is deleted, needs to redo port-forward
go util.CheckPodStatus(childCtx, cancelFunc, podName, c.clientset.CoreV1().Pods(c.Namespace))
domain := fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, c.Namespace)
go healthCheckPortForward(childCtx, cancelFunc, readyChan, strings.Split(portPair[1], ":")[0], domain, c.localTunIPv4.IP)
go healthCheckPortForward(childCtx, cancelFunc, readyChan, strings.Split(portPair[1], ":")[0], domain, c.LocalTunIPv4.IP)
go healthCheckTCPConn(childCtx, cancelFunc, readyChan, domain, util.GetPodIP(pod)[0])
if *first {
go func() {
@@ -380,7 +388,7 @@ func (c *ConnectOptions) portForward(ctx context.Context, portPair []string) err
}
func (c *ConnectOptions) startLocalTunServer(ctx context.Context, forwardAddress string, lite bool) (err error) {
plog.G(ctx).Debugf("IPv4: %s, IPv6: %s", c.localTunIPv4.IP.String(), c.localTunIPv6.IP.String())
plog.G(ctx).Debugf("IPv4: %s, IPv6: %s", c.LocalTunIPv4.IP.String(), c.LocalTunIPv6.IP.String())
tlsSecret, err := c.clientset.CoreV1().Secrets(c.Namespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{})
if err != nil {
@@ -394,8 +402,8 @@ func (c *ConnectOptions) startLocalTunServer(ctx context.Context, forwardAddress
// windows needs to add tun IP self to route table, but linux and macOS not need
if util.IsWindows() {
cidrList = append(cidrList,
&net.IPNet{IP: c.localTunIPv4.IP, Mask: net.CIDRMask(32, 32)},
&net.IPNet{IP: c.localTunIPv6.IP, Mask: net.CIDRMask(128, 128)},
&net.IPNet{IP: c.LocalTunIPv4.IP, Mask: net.CIDRMask(32, 32)},
&net.IPNet{IP: c.LocalTunIPv6.IP, Mask: net.CIDRMask(128, 128)},
)
}
}
@@ -420,12 +428,12 @@ func (c *ConnectOptions) startLocalTunServer(ctx context.Context, forwardAddress
}
tunConfig := tun.Config{
Addr: (&net.IPNet{IP: c.localTunIPv4.IP, Mask: net.CIDRMask(32, 32)}).String(),
Addr: (&net.IPNet{IP: c.LocalTunIPv4.IP, Mask: net.CIDRMask(32, 32)}).String(),
Routes: routes,
MTU: config.DefaultMTU,
}
if enable, _ := util.IsIPv6Enabled(); enable {
tunConfig.Addr6 = (&net.IPNet{IP: c.localTunIPv6.IP, Mask: net.CIDRMask(128, 128)}).String()
tunConfig.Addr6 = (&net.IPNet{IP: c.LocalTunIPv6.IP, Mask: net.CIDRMask(128, 128)}).String()
}
localNode := fmt.Sprintf("tun:/127.0.0.1:8422")
@@ -814,7 +822,7 @@ func (c *ConnectOptions) GetRunningPodList(ctx context.Context) ([]v1.Pod, error
// https://stackoverflow.com/questions/45903123/kubernetes-set-service-cidr-and-pod-cidr-the-same
// https://stackoverflow.com/questions/44190607/how-do-you-find-the-cluster-service-cidr-of-a-kubernetes-cluster/54183373#54183373
// https://stackoverflow.com/questions/44190607/how-do-you-find-the-cluster-service-cidr-of-a-kubernetes-cluster
func (c *ConnectOptions) getCIDR(ctx context.Context, m *dhcp.Manager) error {
func (c *ConnectOptions) getCIDR(ctx context.Context) error {
var err error
c.apiServerIPs, err = util.GetAPIServerIP(c.config.Host)
if err != nil {
@@ -823,7 +831,7 @@ func (c *ConnectOptions) getCIDR(ctx context.Context, m *dhcp.Manager) error {
// (1) get CIDR from cache
var ipPoolStr string
ipPoolStr, err = m.Get(ctx, config.KeyClusterIPv4POOLS)
ipPoolStr, err = c.Get(ctx, config.KeyClusterIPv4POOLS)
if err != nil {
return err
}
@@ -845,7 +853,30 @@ func (c *ConnectOptions) getCIDR(ctx context.Context, m *dhcp.Manager) error {
for _, cidr := range c.cidrs {
s.Insert(cidr.String())
}
return m.Set(ctx, config.KeyClusterIPv4POOLS, strings.Join(s.UnsortedList(), " "))
return c.Set(ctx, config.KeyClusterIPv4POOLS, strings.Join(s.UnsortedList(), " "))
}
func (c *ConnectOptions) Set(ctx context.Context, key, value string) error {
err := retry.RetryOnConflict(
retry.DefaultRetry,
func() error {
p := []byte(fmt.Sprintf(`[{"op": "replace", "path": "/data/%s", "value": "%s"}]`, key, value))
_, err := c.clientset.CoreV1().ConfigMaps(c.Namespace).Patch(ctx, config.ConfigMapPodTrafficManager, k8stypes.JSONPatchType, p, metav1.PatchOptions{})
return err
})
if err != nil {
plog.G(ctx).Errorf("Failed to update configmap: %v", err)
return err
}
return nil
}
func (c *ConnectOptions) Get(ctx context.Context, key string) (string, error) {
cm, err := c.clientset.CoreV1().ConfigMaps(c.Namespace).Get(ctx, config.ConfigMapPodTrafficManager, metav1.GetOptions{})
if err != nil {
return "", err
}
return cm.Data[key], nil
}
func (c *ConnectOptions) addExtraRoute(ctx context.Context, name string) error {
@@ -959,11 +990,11 @@ func (c *ConnectOptions) GetFactory() cmdutil.Factory {
}
func (c *ConnectOptions) GetLocalTunIP() (v4 string, v6 string) {
if c.localTunIPv4 != nil {
v4 = c.localTunIPv4.IP.String()
if c.LocalTunIPv4 != nil {
v4 = c.LocalTunIPv4.IP.String()
}
if c.localTunIPv6 != nil {
v6 = c.localTunIPv6.IP.String()
if c.LocalTunIPv6 != nil {
v6 = c.LocalTunIPv6.IP.String()
}
return
}
@@ -1211,20 +1242,13 @@ func deletePodImmediately(ctx context.Context, clientset *kubernetes.Clientset,
return nil
}
func (c *ConnectOptions) Equal(a *ConnectOptions) bool {
return c.Engine == a.Engine &&
sets.New[string](c.ExtraRouteInfo.ExtraDomain...).HasAll(a.ExtraRouteInfo.ExtraDomain...) &&
sets.New[string](c.ExtraRouteInfo.ExtraCIDR...).HasAll(c.ExtraRouteInfo.ExtraCIDR...) &&
(reflect.DeepEqual(c.ExtraRouteInfo.ExtraNodeIP, a.ExtraRouteInfo.ExtraNodeIP) || c.ExtraRouteInfo.ExtraNodeIP == true)
}
func (c *ConnectOptions) GetTunDeviceName() (string, error) {
var ips []net.IP
if c.localTunIPv4 != nil {
ips = append(ips, c.localTunIPv4.IP)
if c.LocalTunIPv4 != nil {
ips = append(ips, c.LocalTunIPv4.IP)
}
if c.localTunIPv6 != nil {
ips = append(ips, c.localTunIPv6.IP)
if c.LocalTunIPv6 != nil {
ips = append(ips, c.LocalTunIPv6.IP)
}
device, err := util.GetTunDevice(ips...)
if err != nil {

View File

@@ -47,8 +47,8 @@ func (l *ProxyList) Remove(ns, workload string) {
}
}
func (l *ProxyList) Add(connectNamespace string, proxy *Proxy) {
go proxy.portMapper.Run(connectNamespace)
func (l *ProxyList) Add(managerNamespace string, proxy *Proxy) {
go proxy.portMapper.Run(managerNamespace)
*l = append(*l, proxy)
}
@@ -106,7 +106,7 @@ type Mapper struct {
clientset *kubernetes.Clientset
}
func (m *Mapper) Run(connectNamespace string) {
func (m *Mapper) Run(managerNamespace string) {
if m == nil {
return
}
@@ -121,7 +121,7 @@ func (m *Mapper) Run(connectNamespace string) {
var lastLocalPort2EnvoyRulePort map[int32]int32
for m.ctx.Err() == nil {
localPort2EnvoyRulePort, err := m.getLocalPort2EnvoyRulePort(connectNamespace)
localPort2EnvoyRulePort, err := m.getLocalPort2EnvoyRulePort(managerNamespace)
if err != nil {
if errors.Is(err, context.Canceled) {
continue
@@ -200,8 +200,8 @@ func (m *Mapper) Run(connectNamespace string) {
}
}
func (m *Mapper) getLocalPort2EnvoyRulePort(connectNamespace string) (map[int32]int32, error) {
configMap, err := m.clientset.CoreV1().ConfigMaps(connectNamespace).Get(m.ctx, config.ConfigMapPodTrafficManager, v1.GetOptions{})
func (m *Mapper) getLocalPort2EnvoyRulePort(managerNamespace string) (map[int32]int32, error) {
configMap, err := m.clientset.CoreV1().ConfigMaps(managerNamespace).Get(m.ctx, config.ConfigMapPodTrafficManager, v1.GetOptions{})
if err != nil {
return nil, err
}

View File

@@ -77,7 +77,7 @@ func resetConfigMap(ctx context.Context, mapInterface v1.ConfigMapInterface, nam
}
for i := 0; i < len(v); i++ {
if ws.Has(v[i].Uid) {
if ws.Has(v[i].Uid) && v[i].Namespace == namespace {
v = append(v[:i], v[i+1:]...)
i--
}

View File

@@ -38,7 +38,7 @@ func RemoveContainers(spec *v1.PodTemplateSpec) {
}
// AddMeshContainer todo envoy support ipv6
func AddMeshContainer(spec *v1.PodTemplateSpec, ns, nodeID string, ipv6 bool, connectNamespace string, secret *v1.Secret, image string) {
func AddMeshContainer(spec *v1.PodTemplateSpec, ns, nodeID string, ipv6 bool, managerNamespace string, secret *v1.Secret, image string) {
// remove envoy proxy containers if already exist
RemoveContainers(spec)
@@ -80,7 +80,7 @@ kubevpn server -l "tun:/localhost:8422?net=${TunIPv4}&net6=${TunIPv6}&route=${CI
},
{
Name: "TrafficManagerService",
Value: fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, connectNamespace),
Value: fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, managerNamespace),
},
{
Name: config.EnvPodNamespace,
@@ -152,9 +152,9 @@ kubevpn server -l "tun:/localhost:8422?net=${TunIPv4}&net6=${TunIPv6}&route=${CI
Args: []string{
func() string {
if ipv6 {
return GetEnvoyConfig(string(envoyConfig), fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, connectNamespace))
return GetEnvoyConfig(string(envoyConfig), fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, managerNamespace))
}
return GetEnvoyConfig(string(envoyConfigIPv4), fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, connectNamespace))
return GetEnvoyConfig(string(envoyConfigIPv4), fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, managerNamespace))
}(),
},
Resources: v1.ResourceRequirements{
@@ -171,7 +171,7 @@ kubevpn server -l "tun:/localhost:8422?net=${TunIPv4}&net6=${TunIPv6}&route=${CI
})
}
func AddEnvoyContainer(spec *v1.PodTemplateSpec, ns, nodeID string, ipv6 bool, connectNamespace string, image string) {
func AddEnvoyContainer(spec *v1.PodTemplateSpec, ns, nodeID string, ipv6 bool, managerNamespace string, image string) {
// remove envoy proxy containers if already exist
RemoveContainers(spec)
@@ -216,9 +216,9 @@ kubevpn server -l "ssh://:2222"`,
Args: []string{
func() string {
if ipv6 {
return GetEnvoyConfig(string(envoyConfigFargate), fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, connectNamespace))
return GetEnvoyConfig(string(envoyConfigFargate), fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, managerNamespace))
}
return GetEnvoyConfig(string(envoyConfigIPv4Fargate), fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, connectNamespace))
return GetEnvoyConfig(string(envoyConfigIPv4Fargate), fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, managerNamespace))
}(),
},
Resources: v1.ResourceRequirements{

View File

@@ -20,7 +20,7 @@ func RemoveContainer(spec *corev1.PodSpec) {
}
}
func AddContainer(spec *corev1.PodSpec, c util.PodRouteConfig, connectNamespace string, secret *corev1.Secret, image string) {
func AddContainer(spec *corev1.PodSpec, c util.PodRouteConfig, managerNamespace string, secret *corev1.Secret, image string) {
// remove vpn container if already exist
RemoveContainer(spec)
spec.Containers = append(spec.Containers, corev1.Container{
@@ -53,7 +53,7 @@ func AddContainer(spec *corev1.PodSpec, c util.PodRouteConfig, connectNamespace
},
{
Name: "TrafficManagerService",
Value: fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, connectNamespace),
Value: fmt.Sprintf("%s.%s", config.ConfigMapPodTrafficManager, managerNamespace),
},
{
Name: config.EnvPodNamespace,

View File

@@ -27,7 +27,7 @@ import (
// InjectEnvoySidecar patch a sidecar, using iptables to do port-forward let this pod decide should go to 233.254.254.100 or request to 127.0.0.1
// https://istio.io/latest/docs/ops/deployment/requirements/#ports-used-by-istio
func InjectEnvoySidecar(ctx context.Context, nodeID string, f cmdutil.Factory, connectNamespace string, current, object *runtimeresource.Info, headers map[string]string, portMap []string, image string) (err error) {
func InjectEnvoySidecar(ctx context.Context, nodeID string, f cmdutil.Factory, managerNamespace string, current, object *runtimeresource.Info, headers map[string]string, portMap []string, image string) (err error) {
var clientset *kubernetes.Clientset
clientset, err = f.KubernetesClientSet()
if err != nil {
@@ -50,7 +50,7 @@ func InjectEnvoySidecar(ctx context.Context, nodeID string, f cmdutil.Factory, c
port[i].EnvoyListenerPort = int32(randomPort)
containerPort2EnvoyListenerPort[port[i].ContainerPort] = int32(randomPort)
}
err = addEnvoyConfig(clientset.CoreV1().ConfigMaps(connectNamespace), object.Namespace, nodeID, c, headers, port, portmap)
err = addEnvoyConfig(clientset.CoreV1().ConfigMaps(managerNamespace), object.Namespace, nodeID, c, headers, port, portmap)
if err != nil {
plog.G(ctx).Errorf("Failed to add envoy config: %v", err)
return err
@@ -66,9 +66,9 @@ func InjectEnvoySidecar(ctx context.Context, nodeID string, f cmdutil.Factory, c
return
}
enableIPv6, _ := util.DetectPodSupportIPv6(ctx, f, connectNamespace)
enableIPv6, _ := util.DetectPodSupportIPv6(ctx, f, managerNamespace)
// (1) add mesh container
AddEnvoyContainer(templateSpec, object.Namespace, nodeID, enableIPv6, connectNamespace, image)
AddEnvoyContainer(templateSpec, object.Namespace, nodeID, enableIPv6, managerNamespace, image)
helper := pkgresource.NewHelper(object.Client, object.Mapping)
ps := []P{
{

View File

@@ -32,7 +32,7 @@ import (
// https://istio.io/latest/docs/ops/deployment/requirements/#ports-used-by-istio
// InjectVPNAndEnvoySidecar patch a sidecar, using iptables to do port-forward let this pod decide should go to 233.254.254.100 or request to 127.0.0.1
func InjectVPNAndEnvoySidecar(ctx context.Context, nodeID string, f cmdutil.Factory, connectNamespace string, object *runtimeresource.Info, c util.PodRouteConfig, headers map[string]string, portMaps []string, secret *v1.Secret, image string) (err error) {
func InjectVPNAndEnvoySidecar(ctx context.Context, nodeID string, f cmdutil.Factory, managerNamespace string, object *runtimeresource.Info, c util.PodRouteConfig, headers map[string]string, portMaps []string, secret *v1.Secret, image string) (err error) {
var clientset *kubernetes.Clientset
clientset, err = f.KubernetesClientSet()
if err != nil {
@@ -77,7 +77,7 @@ func InjectVPNAndEnvoySidecar(ctx context.Context, nodeID string, f cmdutil.Fact
}
}
err = addEnvoyConfig(clientset.CoreV1().ConfigMaps(connectNamespace), object.Namespace, nodeID, c, headers, ports, portmap)
err = addEnvoyConfig(clientset.CoreV1().ConfigMaps(managerNamespace), object.Namespace, nodeID, c, headers, ports, portmap)
if err != nil {
plog.G(ctx).Errorf("Failed to add envoy config: %v", err)
return err
@@ -89,13 +89,13 @@ func InjectVPNAndEnvoySidecar(ctx context.Context, nodeID string, f cmdutil.Fact
containerNames.Insert(container.Name)
}
if containerNames.HasAll(config.ContainerSidecarVPN, config.ContainerSidecarEnvoyProxy) {
plog.G(ctx).Infof("Workload %s/%s has already been injected with sidecar", connectNamespace, workload)
plog.G(ctx).Infof("Workload %s/%s has already been injected with sidecar", managerNamespace, workload)
return nil
}
enableIPv6, _ := util.DetectPodSupportIPv6(ctx, f, connectNamespace)
enableIPv6, _ := util.DetectPodSupportIPv6(ctx, f, managerNamespace)
// (1) add mesh container
AddMeshContainer(templateSpec, object.Namespace, nodeID, enableIPv6, connectNamespace, secret, image)
AddMeshContainer(templateSpec, object.Namespace, nodeID, enableIPv6, managerNamespace, secret, image)
helper := pkgresource.NewHelper(object.Client, object.Mapping)
ps := []P{
{

View File

@@ -24,7 +24,7 @@ import (
util2 "github.com/wencaiwulue/kubevpn/v2/pkg/util"
)
func InjectVPNSidecar(ctx context.Context, nodeID string, f util.Factory, connectNamespace string, object *resource.Info, c util2.PodRouteConfig, secret *v1.Secret, image string) error {
func InjectVPNSidecar(ctx context.Context, nodeID string, f util.Factory, managerNamespace string, object *resource.Info, c util2.PodRouteConfig, secret *v1.Secret, image string) error {
u := object.Object.(*unstructured.Unstructured)
podTempSpec, path, err := util2.GetPodTemplateSpecPath(u)
@@ -44,13 +44,13 @@ func InjectVPNSidecar(ctx context.Context, nodeID string, f util.Factory, connec
for _, port := range ports {
portmap[port.ContainerPort] = fmt.Sprintf("%d", port.ContainerPort)
}
err = addEnvoyConfig(clientset.CoreV1().ConfigMaps(connectNamespace), object.Namespace, nodeID, c, nil, controlplane.ConvertContainerPort(ports...), portmap)
err = addEnvoyConfig(clientset.CoreV1().ConfigMaps(managerNamespace), object.Namespace, nodeID, c, nil, controlplane.ConvertContainerPort(ports...), portmap)
if err != nil {
plog.G(ctx).Errorf("Failed to add envoy config: %v", err)
return err
}
AddContainer(&podTempSpec.Spec, c, connectNamespace, secret, image)
AddContainer(&podTempSpec.Spec, c, managerNamespace, secret, image)
workload := fmt.Sprintf("%s/%s", object.Mapping.Resource.Resource, object.Name)
helper := resource.NewHelper(object.Client, object.Mapping)

View File

@@ -254,3 +254,11 @@ func DetectSupportIPv6() (bool, error) {
}
return disableIPv6 == 0, nil
}
func IsValidCIDR(str string) bool {
_, _, err := net.ParseCIDR(str)
if err != nil {
return false
}
return true
}

View File

@@ -11,7 +11,6 @@ import (
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubectl/pkg/cmd/util/podcmd"
"k8s.io/utils/ptr"
@@ -84,16 +83,21 @@ func (h *admissionReviewHandler) handleCreate(ar v1.AdmissionReview) *v1.Admissi
// 2) release old ip
h.Lock()
defer h.Unlock()
var ips []net.IP
var ipv4, ipv6 net.IP
for k := 0; k < len(container.Env); k++ {
envVar := container.Env[k]
if sets.New[string](config.EnvInboundPodTunIPv4, config.EnvInboundPodTunIPv6).Has(envVar.Name) && envVar.Value != "" {
if config.EnvInboundPodTunIPv4 == envVar.Name && envVar.Value != "" {
if ip, _, _ := net.ParseCIDR(envVar.Value); ip != nil {
ips = append(ips, ip)
ipv4 = ip
}
}
if config.EnvInboundPodTunIPv6 == envVar.Name && envVar.Value != "" {
if ip, _, _ := net.ParseCIDR(envVar.Value); ip != nil {
ipv6 = ip
}
}
}
_ = h.dhcp.ReleaseIP(context.Background(), ips...)
_ = h.dhcp.ReleaseIP(context.Background(), ipv4, ipv6)
// 3) rent new ip
var v4, v6 *net.IPNet
@@ -171,22 +175,27 @@ func (h *admissionReviewHandler) handleDelete(ar v1.AdmissionReview) *v1.Admissi
}
// 2) release ip
var ips []net.IP
var ipv4, ipv6 net.IP
for _, envVar := range container.Env {
if envVar.Name == config.EnvInboundPodTunIPv4 || envVar.Name == config.EnvInboundPodTunIPv6 {
if envVar.Name == config.EnvInboundPodTunIPv4 {
if ip, _, err := net.ParseCIDR(envVar.Value); err == nil {
ips = append(ips, ip)
ipv4 = ip
}
}
if envVar.Name == config.EnvInboundPodTunIPv6 {
if ip, _, err := net.ParseCIDR(envVar.Value); err == nil {
ipv6 = ip
}
}
}
if len(ips) != 0 {
if ipv4 != nil || ipv6 != nil {
h.Lock()
defer h.Unlock()
err := h.dhcp.ReleaseIP(context.Background(), ips...)
err := h.dhcp.ReleaseIP(context.Background(), ipv4, ipv6)
if err != nil {
plog.G(context.Background()).Errorf("Failed to release IP %v to DHCP server: %v", ips, err)
plog.G(context.Background()).Errorf("Failed to release IPv4 %v IPv6 %s to DHCP server: %v", ipv4, ipv6, err)
} else {
plog.G(context.Background()).Debugf("Release IP %v to DHCP server", ips)
plog.G(context.Background()).Debugf("Release IPv4 %v IPv6 %v to DHCP server", ipv4, ipv6)
}
}
return &v1.AdmissionResponse{Allowed: true}