mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/kube-vip/kube-vip.git
synced 2026-09-20 08:03:47 +08:00
Big refactor to log/slog
This commit is contained in:
@@ -4,8 +4,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/kubevip"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -34,30 +35,34 @@ var kubeKubeadmInit = &cobra.Command{
|
||||
Long: "The \"init\" subcommand will generate the Kubernetes manifest that will be started by kubeadm through the kubeadm init process",
|
||||
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
|
||||
// Set the logging level for all subsequent functions
|
||||
log.SetLevel(log.Level(logLevel))
|
||||
log.SetLogLoggerLevel(log.Level(logLevel))
|
||||
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
|
||||
// TODO - A load of text detailing what's actually happening
|
||||
err := kubevip.ParseEnvironment(&initConfig)
|
||||
if err != nil {
|
||||
log.Fatalf("Error parsing environment from config: %v", err)
|
||||
log.Error("parsing environment", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO - check for certain things VIP/interfaces
|
||||
if initConfig.Interface == "" {
|
||||
_ = cmd.Help()
|
||||
log.Fatalln("No interface is specified for kube-vip to bind to")
|
||||
log.Error("No interface is specified for kube-vip to bind to")
|
||||
return
|
||||
}
|
||||
|
||||
if initConfig.VIP == "" && initConfig.Address == "" {
|
||||
_ = cmd.Help()
|
||||
log.Fatalln("No address is specified for kube-vip to expose services on")
|
||||
log.Error("No address is specified for kube-vip to expose services on")
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure there is an address to generate the CIDR from
|
||||
if initConfig.VIPCIDR == "" && initConfig.Address != "" {
|
||||
initConfig.VIPCIDR, err = GenerateCidrRange(initConfig.Address)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("generating CIDR", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,35 +76,40 @@ var kubeKubeadmJoin = &cobra.Command{
|
||||
Short: "kube-vip join",
|
||||
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
|
||||
// Set the logging level for all subsequent functions
|
||||
log.SetLevel(log.Level(logLevel))
|
||||
log.SetLogLoggerLevel(log.Level(logLevel))
|
||||
|
||||
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
|
||||
// TODO - A load of text detailing what's actually happening
|
||||
err := kubevip.ParseEnvironment(&initConfig)
|
||||
if err != nil {
|
||||
log.Fatalf("Error parsing environment from config: %v", err)
|
||||
log.Error("parsing environment", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO - check for certain things VIP/interfaces
|
||||
if initConfig.Interface == "" {
|
||||
_ = cmd.Help()
|
||||
log.Fatalln("No interface is specified for kube-vip to bind to")
|
||||
log.Error("No interface is specified for kube-vip to bind to")
|
||||
return
|
||||
}
|
||||
|
||||
if initConfig.VIP == "" && initConfig.Address == "" {
|
||||
_ = cmd.Help()
|
||||
log.Fatalln("No address is specified for kube-vip to expose services on")
|
||||
log.Error("No address is specified for kube-vip to expose services on")
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := os.Stat(kubeConfigPath); os.IsNotExist(err) {
|
||||
log.Fatalf("Unable to find file [%s]", kubeConfigPath)
|
||||
log.Error("kubeConfig not found", "Path", kubeConfigPath)
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure there is an address to generate the CIDR from
|
||||
if initConfig.VIPCIDR == "" && initConfig.Address != "" {
|
||||
initConfig.VIPCIDR, err = GenerateCidrRange(initConfig.Address)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("generating CIDR", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@ package cmd
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/kubevip"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
@@ -41,25 +42,29 @@ var kubeManifestPod = &cobra.Command{
|
||||
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
|
||||
var err error
|
||||
|
||||
// Set the logging level for all subsequent functions
|
||||
log.SetLevel(log.Level(logLevel))
|
||||
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
|
||||
// TODO - A load of text detailing what's actually happening
|
||||
if err := kubevip.ParseEnvironment(&initConfig); err != nil {
|
||||
log.Fatalf("Error parsing environment from config: %v", err)
|
||||
log.Error("parsing environment", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Set the logging level for all subsequent functions
|
||||
log.SetLogLoggerLevel(log.Level(initConfig.Logging))
|
||||
|
||||
// The control plane has a requirement for a VIP being specified
|
||||
if initConfig.EnableControlPlane && (initConfig.VIP == "" && initConfig.Address == "" && !initConfig.DDNS) {
|
||||
_ = cmd.Help()
|
||||
log.Fatalln("No address is specified for kube-vip to expose services on")
|
||||
log.Error("No address is specified for kube-vip to expose services on")
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure there is an address to generate the CIDR from
|
||||
if initConfig.VIPCIDR == "" && initConfig.Address != "" {
|
||||
initConfig.VIPCIDR, err = GenerateCidrRange(initConfig.Address)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("No interface is specified for kube-vip to bind to")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,27 +79,29 @@ var kubeManifestDaemon = &cobra.Command{
|
||||
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
|
||||
var err error
|
||||
|
||||
// Set the logging level for all subsequent functions
|
||||
log.SetLevel(log.Level(logLevel))
|
||||
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
|
||||
// TODO - A load of text detailing what's actually happening
|
||||
if err := kubevip.ParseEnvironment(&initConfig); err != nil {
|
||||
log.Fatalf("error parsing environment config: %v", err)
|
||||
log.Error("parsing environment", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO - check for certain things VIP/interfaces
|
||||
// Set the logging level for all subsequent functions
|
||||
log.SetLogLoggerLevel(log.Level(initConfig.Logging))
|
||||
|
||||
// The control plane has a requirement for a VIP being specified
|
||||
if initConfig.EnableControlPlane && (initConfig.VIP == "" && initConfig.Address == "" && !initConfig.DDNS) {
|
||||
_ = cmd.Help()
|
||||
log.Fatalln("No address is specified for kube-vip to expose services on")
|
||||
log.Error("No address is specified for kube-vip to expose services on")
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure there is an address to generate the CIDR from
|
||||
if initConfig.VIPCIDR == "" && initConfig.Address != "" {
|
||||
initConfig.VIPCIDR, err = GenerateCidrRange(initConfig.Address)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("No interface is specified for kube-vip to bind to")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,24 +117,27 @@ var kubeManifestRbac = &cobra.Command{
|
||||
var err error
|
||||
|
||||
// Set the logging level for all subsequent functions
|
||||
log.SetLevel(log.Level(logLevel))
|
||||
log.SetLogLoggerLevel(log.Level(logLevel))
|
||||
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
|
||||
// TODO - A load of text detailing what's actually happening
|
||||
if err := kubevip.ParseEnvironment(&initConfig); err != nil {
|
||||
log.Fatalf("Error parsing environment from config: %v", err)
|
||||
log.Error("parsing environment", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// The control plane has a requirement for a VIP being specified
|
||||
if initConfig.EnableControlPlane && (initConfig.VIP == "" && initConfig.Address == "" && !initConfig.DDNS) {
|
||||
_ = cmd.Help()
|
||||
log.Fatalln("No address is specified for kube-vip to expose services on")
|
||||
log.Error("No address is specified for kube-vip to expose services on")
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure there is an address to generate the CIDR from
|
||||
if initConfig.VIPCIDR == "" && initConfig.Address != "" {
|
||||
initConfig.VIPCIDR, err = GenerateCidrRange(initConfig.Address)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("generating CIDR", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/vishvananda/netlink"
|
||||
|
||||
@@ -191,16 +192,18 @@ var kubeVipService = &cobra.Command{
|
||||
Short: "Start the Virtual IP / Load balancer as a service within a Kubernetes cluster",
|
||||
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
|
||||
// Set the logging level for all subsequent functions
|
||||
log.SetLevel(log.Level(logLevel))
|
||||
log.SetLogLoggerLevel(log.Level(logLevel))
|
||||
|
||||
// parse environment variables, these will overwrite anything loaded or flags
|
||||
err := kubevip.ParseEnvironment(&initConfig)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("parsing env", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := initConfig.CheckInterface(); err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("checking interface", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// User Environment variables as an option to make manifest clearer
|
||||
@@ -213,20 +216,23 @@ var kubeVipService = &cobra.Command{
|
||||
if initConfig.VIPCIDR == "" && initConfig.Address != "" {
|
||||
initConfig.VIPCIDR, err = GenerateCidrRange(initConfig.Address)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("generating CIDR", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Define the new service manager
|
||||
mgr, err := manager.New(configMap, &initConfig)
|
||||
if err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
log.Error("new manager", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Start the service manager, this will watch the config Map and construct kube-vip services for it
|
||||
err = mgr.Start()
|
||||
if err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
log.Error("manager start", "err", err)
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -238,23 +244,24 @@ var kubeVipManager = &cobra.Command{
|
||||
// parse environment variables, these will overwrite anything loaded or flags
|
||||
err := kubevip.ParseEnvironment(&initConfig)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("parsing environment", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure there is an address to generate the CIDR from
|
||||
if initConfig.VIPCIDR == "" && initConfig.Address != "" {
|
||||
initConfig.VIPCIDR, err = GenerateCidrRange(initConfig.Address)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("No interface is specified for kube-vip to bind to")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Set the logging level for all subsequent functions
|
||||
log.SetLevel(log.Level(initConfig.Logging))
|
||||
log.SetLogLoggerLevel(log.Level(initConfig.Logging))
|
||||
|
||||
// Welome messages
|
||||
log.Infof("Starting kube-vip.io [%s]", Release.Version)
|
||||
log.Infof("Build kube-vip.io [%s]", Release.Build)
|
||||
log.Info("kube-vip.io", "verison", Release.Version, "build", Release.Build)
|
||||
|
||||
// start prometheus server
|
||||
if initConfig.PrometheusHTTPServer != "" {
|
||||
@@ -282,19 +289,22 @@ var kubeVipManager = &cobra.Command{
|
||||
}
|
||||
|
||||
// Provide configuration to output/logging
|
||||
log.Infof("namespace [%s], Mode: [%s], Features(s): Control Plane:[%t], Services:[%t]", initConfig.Namespace, mode, initConfig.EnableControlPlane, initConfig.EnableServices)
|
||||
log.Info("starting", "namespace", initConfig.Namespace, "Mode", mode, "Control Plane", initConfig.EnableControlPlane, "Services", initConfig.EnableServices)
|
||||
|
||||
// End if nothing is enabled
|
||||
if !initConfig.EnableServices && !initConfig.EnableControlPlane {
|
||||
log.Fatalln("no features are enabled")
|
||||
log.Error("no features are enabled")
|
||||
return
|
||||
}
|
||||
|
||||
if !initConfig.EnableARP && strings.Contains(initConfig.VIPCIDR, kubevip.Auto) {
|
||||
log.Fatalln("auto subnet discovery cannot be used outside ARP mode")
|
||||
log.Error("auto subnet discovery cannot be used outside ARP mode")
|
||||
return
|
||||
}
|
||||
|
||||
if strings.Contains(initConfig.VIPCIDR, kubevip.Auto) && initConfig.Address != "" {
|
||||
log.Fatalln("auto subnet discovery cannot be used if VIP address was provided")
|
||||
log.Error("auto subnet discovery cannot be used if VIP address was provided")
|
||||
return
|
||||
}
|
||||
|
||||
// If we're using wireguard then all traffic goes through the wg0 interface
|
||||
@@ -304,48 +314,55 @@ var kubeVipManager = &cobra.Command{
|
||||
initConfig.Interface = "wg0"
|
||||
}
|
||||
|
||||
log.Infof("configuring Wireguard networking")
|
||||
log.Info("configuring Wireguard networking")
|
||||
l, err := netlink.LinkByName(initConfig.Interface)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "Link not found") {
|
||||
log.Warnf("interface \"%s\" doesn't exist, attempting to create wireguard interface", initConfig.Interface)
|
||||
log.Warn("attempting to create wireguard interface", "interface not found", initConfig.Interface)
|
||||
err = netlink.LinkAdd(&netlink.Wireguard{LinkAttrs: netlink.LinkAttrs{Name: initConfig.Interface}})
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("adding link", "err", err)
|
||||
return
|
||||
}
|
||||
l, err = netlink.LinkByName(initConfig.Interface)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("finding link", "err", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
err = netlink.LinkSetUp(l)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("setting link UP", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
} else { // if we're not using Wireguard then we'll need to use an actual interface
|
||||
// Check if the interface needs auto-detecting
|
||||
if initConfig.Interface == "" {
|
||||
log.Infof("No interface is specified for VIP in config, auto-detecting default Interface")
|
||||
log.Info("No interface is specified for VIP in config, auto-detecting default Interface")
|
||||
defaultIF, err := vip.GetDefaultGatewayInterface()
|
||||
if err != nil {
|
||||
_ = cmd.Help()
|
||||
log.Fatalf("unable to detect default interface -> [%v]", err)
|
||||
log.Error("detecting interface", "err", err)
|
||||
return
|
||||
}
|
||||
initConfig.Interface = defaultIF.Name
|
||||
log.Infof("kube-vip will bind to interface [%s]", initConfig.Interface)
|
||||
log.Info("kube-vip bind", "interface", initConfig.Interface)
|
||||
|
||||
go func() {
|
||||
if err := vip.MonitorDefaultInterface(context.TODO(), defaultIF); err != nil {
|
||||
log.Fatalf("crash: %s", err.Error())
|
||||
|
||||
log.Error("interface monitor", "err", err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
// Perform a check on th state of the interface
|
||||
// Perform a check on the state of the interface
|
||||
if err := initConfig.CheckInterface(); err != nil {
|
||||
log.Fatalln(err)
|
||||
log.Error("checking interface", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
// User Environment variables as an option to make manifest clearer
|
||||
@@ -359,7 +376,8 @@ var kubeVipManager = &cobra.Command{
|
||||
if providerConfig != "" {
|
||||
providerAPI, providerProject, err := equinixmetal.GetPacketConfig(providerConfig)
|
||||
if err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
log.Error("retrieving equinix metal config", "err", err)
|
||||
return
|
||||
}
|
||||
initConfig.MetalAPIKey = providerAPI
|
||||
initConfig.MetalProject = providerProject
|
||||
@@ -369,7 +387,8 @@ var kubeVipManager = &cobra.Command{
|
||||
// Define the new service manager
|
||||
mgr, err := manager.New(configMap, &initConfig)
|
||||
if err != nil {
|
||||
log.Fatalf("configuring new Manager error -> %v", err)
|
||||
log.Error("new manager", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
prometheus.MustRegister(mgr.PrometheusCollector()...)
|
||||
@@ -377,7 +396,8 @@ var kubeVipManager = &cobra.Command{
|
||||
// Start the service manager, this will watch the config Map and construct kube-vip services for it
|
||||
err = mgr.Start()
|
||||
if err != nil {
|
||||
log.Fatalf("starting new Manager error -> %v", err)
|
||||
log.Error("start manager", "err", err)
|
||||
return
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -410,15 +430,16 @@ func servePrometheusHTTPServer(ctx context.Context, config PrometheusHTTPServerC
|
||||
|
||||
go func() {
|
||||
if err = srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("listen:%+s\n", err)
|
||||
log.Error("prometheus HTTP server", "err", err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
log.Printf("prometheus HTTP server started")
|
||||
log.Info("prometheus HTTP server started")
|
||||
|
||||
<-ctx.Done()
|
||||
|
||||
log.Printf("prometheus HTTP server stopped")
|
||||
log.Info("prometheus HTTP server stopped")
|
||||
|
||||
ctxShutDown, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer func() {
|
||||
@@ -426,7 +447,8 @@ func servePrometheusHTTPServer(ctx context.Context, config PrometheusHTTPServerC
|
||||
}()
|
||||
|
||||
if err = srv.Shutdown(ctxShutDown); err != nil {
|
||||
log.Fatalf("server Shutdown Failed:%+s", err)
|
||||
log.Error("shutting down prometheus HTTP server", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err == http.ErrServerClosed {
|
||||
|
||||
@@ -4,10 +4,11 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/k8s"
|
||||
"github.com/kube-vip/kube-vip/pkg/utils"
|
||||
"github.com/kube-vip/kube-vip/pkg/vip"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
@@ -40,26 +41,26 @@ func (e *Entry) Check() bool {
|
||||
config, err = k8s.NewRestConfig(adminConfigPath, false, k8sAddr)
|
||||
// client, err = k8s.NewClientset(adminConfigPath, false, k8sAddr)
|
||||
if err != nil {
|
||||
log.Errorf("could not create k8s REST config for external file: %q: %v", adminConfigPath, err)
|
||||
log.Error("create k8s REST config", "path", adminConfigPath, "err", err)
|
||||
return false
|
||||
}
|
||||
default:
|
||||
config, err = k8s.NewRestConfig("", true, k8sAddr)
|
||||
if err != nil {
|
||||
log.Errorf("could not create k8s REST config %v", err)
|
||||
log.Error("create k8s REST config", "err", err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
client, err = k8s.NewClientset(config)
|
||||
if err != nil {
|
||||
log.Errorf("failed to create k8s client: %v", err)
|
||||
log.Error("create k8s client", "err", err)
|
||||
return false
|
||||
}
|
||||
|
||||
_, err = client.DiscoveryClient.ServerVersion()
|
||||
if err != nil {
|
||||
log.Errorf("failed check k8s server version: %s", err)
|
||||
log.Error("discover k8s version", "err", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@@ -5,9 +5,10 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
api "github.com/osrg/gobgp/v3/api"
|
||||
gobgp "github.com/osrg/gobgp/v3/pkg/server"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NewBGPServer takes a configuration and returns a running BGP server instance
|
||||
@@ -42,7 +43,7 @@ func NewBGPServer(c *Config, peerStateChangeCallback func(*api.WatchEventRespons
|
||||
|
||||
if err = b.s.WatchEvent(context.Background(), &api.WatchEventRequest{Peer: &api.WatchEventRequest_Peer{}}, func(r *api.WatchEventResponse) {
|
||||
if p := r.GetPeer(); p != nil && p.Type == api.WatchEventResponse_PeerEvent_STATE {
|
||||
log.Infof("[BGP] %s", p.String())
|
||||
log.Info("[BGP]", "peer", p.String())
|
||||
if peerStateChangeCallback != nil {
|
||||
peerStateChangeCallback(p)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package cluster
|
||||
import (
|
||||
"sync"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/kubevip"
|
||||
"github.com/kube-vip/kube-vip/pkg/vip"
|
||||
@@ -34,7 +34,7 @@ func InitCluster(c *kubevip.Config, disableVIP bool) (*Cluster, error) {
|
||||
Network: networks,
|
||||
}
|
||||
|
||||
log.Debugf("init enable service security: %t", c.EnableServiceSecurity)
|
||||
log.Debug("service security", "enabled", c.EnableServiceSecurity)
|
||||
|
||||
return newCluster, nil
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ import (
|
||||
|
||||
"github.com/packethost/packngo"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -96,7 +97,7 @@ func NewManager(path string, inCluster bool, port int) (*Manager, error) {
|
||||
func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *bgp.Server) error {
|
||||
var err error
|
||||
|
||||
log.Infof("Beginning cluster membership, namespace [%s], lock name [%s], id [%s]", c.Namespace, c.LeaseName, c.NodeName)
|
||||
log.Info("cluster membership", "namespace", c.Namespace, "lock", c.LeaseName, "id", c.NodeName)
|
||||
|
||||
// use a Go context so we can tell the leaderelection code when we
|
||||
// want to step down
|
||||
@@ -136,7 +137,7 @@ func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *
|
||||
for i := range cluster.Network {
|
||||
err = cluster.Network[i].DeleteIP()
|
||||
if err != nil {
|
||||
log.Errorf("could not delete virtualIP: %v", err)
|
||||
log.Error("could not delete virtualIP", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +154,7 @@ func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *
|
||||
if c.ProviderConfig != "" {
|
||||
key, project, err := equinixmetal.GetPacketConfig(c.ProviderConfig)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error("retrieve Equinix metal config", "err", err)
|
||||
} else {
|
||||
// Set the environment variable with the key for the project
|
||||
os.Setenv("PACKET_AUTH_TOKEN", key)
|
||||
@@ -163,15 +164,15 @@ func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *
|
||||
}
|
||||
packetClient, err = packngo.NewClient()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error("create Equinix metal client", "err", err)
|
||||
}
|
||||
|
||||
// We're using Equinix Metal with BGP, populate the Peer information from the API
|
||||
if c.EnableBGP {
|
||||
log.Infoln("Looking up the BGP configuration from Equinix Metal")
|
||||
log.Info("Looking up the BGP configuration from Equinix Metal")
|
||||
err = equinixmetal.BGPLookup(packetClient, c)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error("retrieve Equinix metal BPG config", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,7 +182,7 @@ func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *
|
||||
log.Info("Starting the BGP server to advertise VIP routes to VGP peers")
|
||||
bgpServer, err = bgp.NewBGPServer(&c.BGPConfig, nil)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error("new BGP server", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +194,7 @@ func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *
|
||||
// As we're leading lets start the vip service
|
||||
err := cluster.vipService(ctxArp, ctxDNS, c, sm, bgpServer, packetClient)
|
||||
if err != nil {
|
||||
log.Errorf("Error starting the VIP service on the leader [%s]", err)
|
||||
log.Error("starting VIP service on leader", "err", err)
|
||||
}
|
||||
},
|
||||
onStoppedLeading: func() {
|
||||
@@ -209,22 +210,23 @@ func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *
|
||||
if bgpServer != nil {
|
||||
err := bgpServer.Close()
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn("close BGP server", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := range cluster.Network {
|
||||
err := cluster.Network[i].DeleteIP()
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn("delete VIP", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Fatal("lost leadership, restarting kube-vip")
|
||||
log.Error("lost leadership, restarting kube-vip")
|
||||
panic("") // TODO - we could also return here
|
||||
},
|
||||
onNewLeader: func(identity string) {
|
||||
// we're notified when new leader elected
|
||||
log.Infof("Node [%s] is assuming leadership of the cluster", identity)
|
||||
log.Info("New leader", "leader", identity)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -307,7 +309,7 @@ func (cluster *Cluster) runEtcdLeaderElectionOrDie(ctx context.Context, run *run
|
||||
|
||||
func (sm *Manager) NodeWatcher(lb *loadbalancer.IPVSLoadBalancer, port uint16) error {
|
||||
// Use a restartable watcher, as this should help in the event of etcd or timeout issues
|
||||
log.Infof("Kube-Vip is watching nodes for control-plane labels")
|
||||
log.Info("Kube-Vip is watching nodes for control-plane labels")
|
||||
|
||||
listOptions := metav1.ListOptions{
|
||||
LabelSelector: "node-role.kubernetes.io/control-plane",
|
||||
@@ -345,7 +347,7 @@ func (sm *Manager) NodeWatcher(lb *loadbalancer.IPVSLoadBalancer, port uint16) e
|
||||
if node.Status.Addresses[x].Type == v1.NodeInternalIP {
|
||||
err = lb.AddBackend(node.Status.Addresses[x].Address, port)
|
||||
if err != nil {
|
||||
log.Errorf("add IPVS backend [%v]", err)
|
||||
log.Error("add IPVS backend", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -360,12 +362,12 @@ func (sm *Manager) NodeWatcher(lb *loadbalancer.IPVSLoadBalancer, port uint16) e
|
||||
if node.Status.Addresses[x].Type == v1.NodeInternalIP {
|
||||
err = lb.RemoveBackend(node.Status.Addresses[x].Address, port)
|
||||
if err != nil {
|
||||
log.Errorf("Del IPVS backend [%v]", err)
|
||||
log.Error("Del IPVS backend", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("Node [%s] has been deleted", node.Name)
|
||||
log.Info("Node deleted", "name", node.Name)
|
||||
|
||||
case watch.Bookmark:
|
||||
// Un-used
|
||||
@@ -380,11 +382,11 @@ func (sm *Manager) NodeWatcher(lb *loadbalancer.IPVSLoadBalancer, port uint16) e
|
||||
}
|
||||
|
||||
status := statusErr.ErrStatus
|
||||
log.Errorf("%v", status)
|
||||
log.Error("watcher", "status", status)
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
log.Infoln("Exiting Node watcher")
|
||||
log.Info("Exiting Node watcher")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/backend"
|
||||
"github.com/kube-vip/kube-vip/pkg/bgp"
|
||||
"github.com/kube-vip/kube-vip/pkg/equinixmetal"
|
||||
@@ -18,7 +20,6 @@ import (
|
||||
"github.com/kube-vip/kube-vip/pkg/loadbalancer"
|
||||
"github.com/kube-vip/kube-vip/pkg/vip"
|
||||
"github.com/packethost/packngo"
|
||||
log "github.com/sirupsen/logrus"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -41,13 +42,13 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
for i := range cluster.Network {
|
||||
if cluster.Network[i].IsDDNS() {
|
||||
if err := cluster.StartDDNS(ctxDNS); err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// start the dns updater if address is dns
|
||||
if cluster.Network[i].IsDNS() {
|
||||
log.Infof("starting the DNS updater for the address %s", cluster.Network[i].DNSName())
|
||||
log.Info("starting the DNS updater", "address", cluster.Network[i].DNSName())
|
||||
ipUpdater := vip.NewIPUpdater(cluster.Network[i])
|
||||
ipUpdater.Run(ctxDNS)
|
||||
}
|
||||
@@ -63,14 +64,16 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
subnet = subnets[1]
|
||||
}
|
||||
if subnet == "" {
|
||||
log.Fatalf("no subnet provided for IP %s", cluster.Network[i].IP())
|
||||
log.Error("no subnet provided", "IP", cluster.Network[i].IP())
|
||||
panic("")
|
||||
}
|
||||
if err = cluster.Network[i].SetMask(subnet); err != nil {
|
||||
log.Fatalf("failed to set mask %s: %s", subnet, err.Error())
|
||||
log.Error("failed to set mask", "subnet", subnet, "err", err)
|
||||
panic("")
|
||||
}
|
||||
}
|
||||
if err = cluster.Network[i].AddIP(false); err != nil {
|
||||
log.Fatalf("%v", err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,10 +81,10 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
// We're not using Equinix Metal with BGP
|
||||
if !c.EnableBGP {
|
||||
// Attempt to attach the EIP in the standard manner
|
||||
log.Debugf("Attaching the Equinix Metal EIP through the API to this host")
|
||||
log.Debug("Attaching the Equinix Metal EIP through the API to this host")
|
||||
err = equinixmetal.AttachEIP(packetClient, c, c.NodeName)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,26 +92,26 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
if c.EnableBGP {
|
||||
// Lets advertise the VIP over BGP, the host needs to be passed using CIDR notation
|
||||
cidrVip := fmt.Sprintf("%s/%s", cluster.Network[i].IP(), c.VIPCIDR)
|
||||
log.Debugf("Attempting to advertise the address [%s] over BGP", cidrVip)
|
||||
log.Debug("Attempting to advertise over BGP", "address", cidrVip)
|
||||
|
||||
err = bgpServer.AddHost(cidrVip)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if c.EnableLoadBalancer {
|
||||
log.Infof("Starting IPVS LoadBalancer")
|
||||
log.Info("Starting IPVS LoadBalancer")
|
||||
|
||||
lb, err := loadbalancer.NewIPVSLB(cluster.Network[i].IP(), c.LoadBalancerPort, c.LoadBalancerForwardingMethod, c.BackendHealthCheckInterval)
|
||||
if err != nil {
|
||||
log.Errorf("Error creating IPVS LoadBalancer [%s]", err)
|
||||
log.Error("Error creating IPVS LoadBalancer", "err", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
err = sm.NodeWatcher(lb, c.Port)
|
||||
if err != nil {
|
||||
log.Errorf("Error watching node labels [%s]", err)
|
||||
log.Error("Error watching node labels", "err", err)
|
||||
}
|
||||
}()
|
||||
// Shutdown function that will wait on this signal, unless we call it ourselves
|
||||
@@ -116,7 +119,7 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
<-signalChan
|
||||
err = lb.RemoveIPVSLB()
|
||||
if err != nil {
|
||||
log.Errorf("Error stopping IPVS LoadBalancer [%s]", err)
|
||||
log.Error("Error stopping IPVS LoadBalancer", "err", err)
|
||||
}
|
||||
log.Info("Stopping IPVS LoadBalancer")
|
||||
}()
|
||||
@@ -131,14 +134,15 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
if isIPv6 {
|
||||
ndp, err = vip.NewNDPResponder(cluster.Network[i].Interface())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create new NDP Responder")
|
||||
log.Error("failed to create new NDP Responder")
|
||||
panic("")
|
||||
}
|
||||
}
|
||||
|
||||
if ndp != nil {
|
||||
defer ndp.Close()
|
||||
}
|
||||
log.Infof("Gratuitous Arp broadcast will repeat every 3 seconds for [%s/%s]", ipString, cluster.Network[i].Interface())
|
||||
log.Info("Gratuitous Arp broadcast repeats every 3 seconds", "ip", ipString, "interface", cluster.Network[i].Interface())
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done(): // if cancel() execute
|
||||
@@ -167,7 +171,7 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
ips := []string{}
|
||||
if nodename != "" {
|
||||
if ips, err = getNodeIPs(ctxArp, nodename, sm.KubernetesClient); err != nil && !apierrors.IsNotFound(err) {
|
||||
log.Error("failed to get IP of control-plane node: %w", err)
|
||||
log.Error("failed to get IP of control-plane nod", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +186,7 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
ips = append(ips, "::1")
|
||||
}
|
||||
|
||||
log.Infof("no IP address found for node - will fallback to use localhost address: %v", ips)
|
||||
log.Info("no IP address found for node - will fallback to use localhost address", "addresses", ips)
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
@@ -224,17 +228,17 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
if entry.Check() {
|
||||
err = cluster.Network[i].AddIP(true)
|
||||
if err != nil {
|
||||
log.Fatalf("error adding IP: %v", err)
|
||||
log.Error("error adding address", "err", err)
|
||||
}
|
||||
if !(*backendMap)[entry] {
|
||||
log.Infof("added IP: %s", cluster.Network[i].IP())
|
||||
log.Info("added backend", "ip", cluster.Network[i].IP())
|
||||
}
|
||||
|
||||
err = cluster.Network[i].AddRoute(true)
|
||||
if err != nil && !errors.Is(err, fs.ErrExist) && !errors.Is(err, syscall.ESRCH) {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
} else if err == nil && !(*backendMap)[entry] {
|
||||
log.Infof("added route: %s", cluster.Network[i].PrepareRoute().String())
|
||||
log.Info("added route", "route", cluster.Network[i].PrepareRoute().String())
|
||||
}
|
||||
|
||||
(*backendMap)[entry] = true
|
||||
@@ -254,9 +258,9 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
if deleteAddress {
|
||||
err = cluster.Network[i].DeleteRoute()
|
||||
if err != nil && !errors.Is(err, fs.ErrNotExist) && !errors.Is(err, syscall.ESRCH) {
|
||||
log.Warnf("error while deleting route: %v", err)
|
||||
log.Warn("deleting route", "err", err)
|
||||
} else if err == nil {
|
||||
log.Infof("deleted route: %s", cluster.Network[i].PrepareRoute().String())
|
||||
log.Info("deleted route", "route", cluster.Network[i].PrepareRoute().String())
|
||||
}
|
||||
|
||||
isSet, err := cluster.Network[i].IsSet()
|
||||
@@ -266,9 +270,10 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
|
||||
if isSet {
|
||||
err = cluster.Network[i].DeleteIP()
|
||||
if err != nil {
|
||||
log.Fatalf("error deleting IP: %v", err)
|
||||
log.Error("error deleting IP", "err", err)
|
||||
panic("")
|
||||
}
|
||||
log.Infof("deleted IP: %s", cluster.Network[i].IP())
|
||||
log.Info("deleted address", "ip", cluster.Network[i].IP())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -315,12 +320,12 @@ func (cluster *Cluster) StartLoadBalancerService(c *kubevip.Config, bgp *bgp.Ser
|
||||
|
||||
err := network.DeleteIP()
|
||||
if err != nil {
|
||||
log.Warnf("Attempted to clean existing VIP => %v", err)
|
||||
log.Warn("Attempted to clean existing VIP", "err", err)
|
||||
}
|
||||
if c.EnableRoutingTable && (c.EnableLeaderElection || c.EnableServicesElection) {
|
||||
err = network.AddRoute(false)
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
} else if !c.EnableRoutingTable {
|
||||
if c.EnableARP {
|
||||
@@ -333,14 +338,16 @@ func (cluster *Cluster) StartLoadBalancerService(c *kubevip.Config, bgp *bgp.Ser
|
||||
subnet = subnets[1]
|
||||
}
|
||||
if subnet == "" {
|
||||
log.Fatalf("no subnet provided for IP %s", cluster.Network[i].IP())
|
||||
log.Error("no subnet provided for address", "ip", cluster.Network[i].IP())
|
||||
panic("")
|
||||
}
|
||||
if err = network.SetMask(subnet); err != nil {
|
||||
log.Fatalf("failed to set mask %s: %s", subnet, err.Error())
|
||||
log.Error("failed to set mask", "subnet", subnet, "err", err)
|
||||
panic("")
|
||||
}
|
||||
}
|
||||
if err = network.AddIP(false); err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,25 +357,26 @@ func (cluster *Cluster) StartLoadBalancerService(c *kubevip.Config, bgp *bgp.Ser
|
||||
if vip.IsIPv6(ipString) {
|
||||
ndp, err = vip.NewNDPResponder(network.Interface())
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create new NDP Responder")
|
||||
log.Error("failed to create new NDP Responder")
|
||||
panic("")
|
||||
}
|
||||
}
|
||||
go func(ctx context.Context) {
|
||||
if ndp != nil {
|
||||
defer ndp.Close()
|
||||
}
|
||||
log.Debugf("(svcs) broadcasting ARP update for %s via %s, every %dms", ipString, network.Interface(), c.ArpBroadcastRate)
|
||||
log.Debug("(svcs) broadcasting ARP update", "ip", ipString, "interface", network.Interface(), "rate", c.ArpBroadcastRate)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done(): // if cancel() execute
|
||||
log.Debugf("(svcs) ending ARP update for %s via %s, every %dms", ipString, network.Interface(), c.ArpBroadcastRate)
|
||||
log.Debug("(svcs) ending ARP update", "ip", ipString, "interface", network.Interface(), "rate", c.ArpBroadcastRate)
|
||||
return
|
||||
default:
|
||||
cluster.ensureIPAndSendGratuitous(i, ndp)
|
||||
}
|
||||
if c.ArpBroadcastRate < 500 {
|
||||
log.Errorf("arp broadcast rate is [%d], this shouldn't be lower that 300ms (defaulting to 3000)", c.ArpBroadcastRate)
|
||||
log.Error("arp broadcast rate shouldn't be lower that 300ms (defaulting to 3000)", "currentRate", c.ArpBroadcastRate)
|
||||
c.ArpBroadcastRate = 3000
|
||||
}
|
||||
time.Sleep(time.Duration(c.ArpBroadcastRate) * time.Millisecond)
|
||||
@@ -379,10 +387,10 @@ func (cluster *Cluster) StartLoadBalancerService(c *kubevip.Config, bgp *bgp.Ser
|
||||
if c.EnableBGP && (c.EnableLeaderElection || c.EnableServicesElection) {
|
||||
// Lets advertise the VIP over BGP, the host needs to be passed using CIDR notation
|
||||
cidrVip := fmt.Sprintf("%s/%s", network.IP(), c.VIPCIDR)
|
||||
log.Debugf("(svcs) attempting to advertise the address [%s] over BGP", cidrVip)
|
||||
log.Debug("(svcs) attempting to advertise over BGP", "address", cidrVip)
|
||||
err = bgp.AddHost(cidrVip)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -396,9 +404,9 @@ func (cluster *Cluster) StartLoadBalancerService(c *kubevip.Config, bgp *bgp.Ser
|
||||
|
||||
if c.EnableRoutingTable {
|
||||
for i := range cluster.Network {
|
||||
log.Infof("[VIP] Deleting Route for Virtual IP [%s]", cluster.Network[i].IP())
|
||||
log.Info("[VIP] Deleting Route for VIP [%s]", "ip", cluster.Network[i].IP())
|
||||
if err := cluster.Network[i].DeleteRoute(); err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,9 +414,9 @@ func (cluster *Cluster) StartLoadBalancerService(c *kubevip.Config, bgp *bgp.Ser
|
||||
return
|
||||
}
|
||||
for i := range cluster.Network {
|
||||
log.Infof("[VIP] Releasing the Virtual IP [%s]", cluster.Network[i].IP())
|
||||
log.Info("[VIP] Deleting VIP", "ip", cluster.Network[i].IP())
|
||||
if err := cluster.Network[i].DeleteIP(); err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,23 +433,23 @@ func (cluster *Cluster) ensureIPAndSendGratuitous(index int, ndp *vip.NdpRespond
|
||||
|
||||
// Check if IP is dadfailed
|
||||
if cluster.Network[index].IsDADFAIL() {
|
||||
log.Warnf("IP address is in dadfailed state, removing [%s] from interface [%s]", ipString, iface)
|
||||
log.Warn("IP address is in dadfailed state, removing config", "ip", ipString, "interface", iface)
|
||||
err := cluster.Network[index].DeleteIP()
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the address exists on the interface before attempting to ARP
|
||||
set, err := cluster.Network[index].IsSet()
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
if !set {
|
||||
log.Warnf("Re-applying the VIP configuration [%s] to the interface [%s]", ipString, iface)
|
||||
log.Warn("Re-applying the VIP configuration", "ip", ipString, "interface", iface)
|
||||
err = cluster.Network[index].AddIP(false)
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,7 +460,7 @@ func (cluster *Cluster) ensureIPAndSendGratuitous(index int, ndp *vip.NdpRespond
|
||||
} else {
|
||||
err := ndp.SendGratuitous(ipString)
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +468,7 @@ func (cluster *Cluster) ensureIPAndSendGratuitous(index int, ndp *vip.NdpRespond
|
||||
// Gratuitous ARP, will broadcast to new MAC <-> IPv4 address
|
||||
err := vip.ARPSendGratuitous(ipString, iface)
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@ package cluster
|
||||
import (
|
||||
"context"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/packethost/packngo"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/bgp"
|
||||
"github.com/kube-vip/kube-vip/pkg/kubevip"
|
||||
@@ -16,7 +17,7 @@ func (cluster *Cluster) StartSingleNode(c *kubevip.Config, disableVIP bool) erro
|
||||
// Start kube-vip as a single node server
|
||||
|
||||
// TODO - Split all this code out as a separate function
|
||||
log.Infoln("Starting kube-vip as a single node cluster")
|
||||
log.Info("Starting kube-vip as a single node cluster")
|
||||
|
||||
log.Info("This node is assuming leadership of the cluster")
|
||||
|
||||
@@ -27,12 +28,12 @@ func (cluster *Cluster) StartSingleNode(c *kubevip.Config, disableVIP bool) erro
|
||||
if !disableVIP {
|
||||
err := cluster.Network[i].DeleteIP()
|
||||
if err != nil {
|
||||
log.Warnf("Attempted to clean existing VIP => %v", err)
|
||||
log.Warn("Attempted to clean existing VIP", "err", err)
|
||||
}
|
||||
|
||||
err = cluster.Network[i].AddIP(false)
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,7 +42,7 @@ func (cluster *Cluster) StartSingleNode(c *kubevip.Config, disableVIP bool) erro
|
||||
// Gratuitous ARP, will broadcast to new MAC <-> IP
|
||||
err := vip.ARPSendGratuitous(cluster.Network[i].IP(), c.Interface)
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,16 +52,16 @@ func (cluster *Cluster) StartSingleNode(c *kubevip.Config, disableVIP bool) erro
|
||||
|
||||
if !disableVIP {
|
||||
for i := range cluster.Network {
|
||||
log.Infof("[VIP] Releasing the Virtual IP [%s]", cluster.Network[i].IP())
|
||||
log.Info("[VIP] Releasing the VIP", "address", cluster.Network[i].IP())
|
||||
err := cluster.Network[i].DeleteIP()
|
||||
if err != nil {
|
||||
log.Warnf("%v", err)
|
||||
log.Warn(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
close(cluster.completed)
|
||||
}()
|
||||
log.Infoln("Started Load Balancer and Virtual IP")
|
||||
log.Info("Started Load Balancer and Virtual IP")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,11 @@ package equinixmetal
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/bgp"
|
||||
"github.com/kube-vip/kube-vip/pkg/kubevip"
|
||||
"github.com/packethost/packngo"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// BGPLookup will use the Equinix Metal API functions to populate the BGP information
|
||||
@@ -25,7 +26,7 @@ func BGPLookup(c *packngo.Client, k *kubevip.Config) error {
|
||||
return fmt.Errorf("Unable to find local/this device in Equinix Metal API")
|
||||
}
|
||||
|
||||
log.Infof("Querying BGP settings for [%s]", thisDevice.Hostname)
|
||||
log.Info("Querying BGP settings", "hostname", thisDevice.Hostname)
|
||||
neighbours, _, err := c.Devices.ListBGPNeighbors(thisDevice.ID, &packngo.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -37,7 +38,7 @@ func BGPLookup(c *packngo.Client, k *kubevip.Config) error {
|
||||
|
||||
// Add a warning (TODO)
|
||||
if len(neighbours) > 1 {
|
||||
log.Warnf("There are [%d] neighbours, only designed to manage one", len(neighbours))
|
||||
log.Warn(fmt.Sprintf("There are [%d] neighbours, only designed to manage one", len(neighbours)))
|
||||
}
|
||||
|
||||
// Ensure a peer exists
|
||||
|
||||
@@ -4,9 +4,10 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/kubevip"
|
||||
"github.com/packethost/packngo"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// AttachEIP will use the Equinix Metal APIs to move an EIP and attach to a host
|
||||
@@ -34,7 +35,7 @@ func AttachEIP(c *packngo.Client, k *kubevip.Config, _ string) error {
|
||||
for _, ip := range ips {
|
||||
// Find the device id for our EIP
|
||||
if ip.Address == vip {
|
||||
log.Infof("Found EIP ->%s ID -> %s\n", ip.Address, ip.ID)
|
||||
log.Info("Found EIP", "address", ip.Address, "id", ip.ID)
|
||||
// If attachments already exist then remove them
|
||||
if len(ip.Assignments) != 0 {
|
||||
hrefID := path.Base(ip.Assignments[0].Href)
|
||||
@@ -53,7 +54,7 @@ func AttachEIP(c *packngo.Client, k *kubevip.Config, _ string) error {
|
||||
}
|
||||
|
||||
// Assign the EIP to this device
|
||||
log.Infof("Assigning EIP to -> %s\n", thisDevice.Hostname)
|
||||
log.Info("Assigning EIP", "hostname", thisDevice.Hostname)
|
||||
_, _, err := c.DeviceIPs.Assign(thisDevice.ID, &packngo.AddressStruct{
|
||||
Address: vip,
|
||||
})
|
||||
|
||||
@@ -5,15 +5,16 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/packethost/packngo"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func findProject(project string, c *packngo.Client) *packngo.Project {
|
||||
l := &packngo.ListOptions{Includes: []string{project}}
|
||||
ps, _, err := c.Projects.List(l)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
for _, p := range ps {
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@ import (
|
||||
"hash/fnv"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
|
||||
clientv3 "go.etcd.io/etcd/client/v3"
|
||||
"go.etcd.io/etcd/client/v3/concurrency"
|
||||
@@ -147,9 +148,9 @@ watcher:
|
||||
|
||||
m.isLeader = true
|
||||
m.key = m.election.Key() // by this time, this should already be set, since Campaign has already returned
|
||||
log.Debugf("[%s] Marking self as leader with key %s\n", m.memberID, m.key)
|
||||
log.Debug("Marking self as leader with key", "id", m.memberID, "key", m.key)
|
||||
case response := <-changes:
|
||||
log.Debugf("[%s] Leader Changes: %+v\n", m.memberID, response)
|
||||
log.Debug("Leader Changes", "id", m.memberID, "response", response)
|
||||
if len(response.Kvs) == 0 {
|
||||
// There is a race condition where just after we stop being the leader
|
||||
// if there are no more leaders, we might get a response with no key-values
|
||||
@@ -181,15 +182,15 @@ watcher:
|
||||
m.callbacks.OnStoppedLeading()
|
||||
}
|
||||
|
||||
log.Debugf("[%s] Exiting watcher\n", m.memberID)
|
||||
log.Debug("Exiting watcher", "id", m.memberID)
|
||||
}
|
||||
|
||||
func (m *member) tryToBeLeader(ctx context.Context) {
|
||||
if err := m.election.Campaign(ctx, m.memberID); err != nil {
|
||||
log.Errorf("Failed trying to become the leader: %s", err)
|
||||
log.Error("Failed trying to become the leader", "err", err)
|
||||
// Resign just in case we acquired leadership just before failing
|
||||
if err := m.election.Resign(m.client.Ctx()); err != nil {
|
||||
log.Warnf("Failed to resign after we failed becoming the leader, this might not be a problem if we were never the leader: %s", err)
|
||||
log.Warn("Failed to resign after we failed becoming the leader, this might not be a problem if we were never the leader", "err", err)
|
||||
}
|
||||
return
|
||||
// TODO: what to do here?
|
||||
@@ -209,7 +210,7 @@ func (m *member) tryToBeLeader(ctx context.Context) {
|
||||
// the previous leader to detect the new leadership (if there was one) and
|
||||
// stop its processes
|
||||
// TODO: is this too cautious?
|
||||
log.Debugf("[%s] Waiting %d seconds before running OnStartedLeading", m.memberID, m.leaseTTL)
|
||||
log.Debug("timeout before OnStartedLeading", "id", m.memberID, "timeout", m.leaseTTL)
|
||||
time.Sleep(time.Second * time.Duration(m.leaseTTL))
|
||||
|
||||
// We are the leader, execute our code
|
||||
@@ -221,6 +222,6 @@ func (m *member) tryToBeLeader(ctx context.Context) {
|
||||
func (m *member) resignOnCancel(ctx context.Context) {
|
||||
<-ctx.Done()
|
||||
if err := m.election.Resign(m.client.Ctx()); err != nil {
|
||||
log.Errorf("Failed to resign after the context was canceled: %s", err)
|
||||
log.Error("Failed to resign after the context was canceled", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
@@ -99,21 +100,21 @@ func FindWorkingKubernetesAddress(configPath string, inCluster bool) (*rest.Conf
|
||||
return nil, err
|
||||
}
|
||||
for x := range ips {
|
||||
log.Debugf("[k8s client] checking with IP address [%s]", ips[x].String())
|
||||
log.Debug("[k8s client] testing", "address", ips[x].String())
|
||||
c, err := NewRestConfig(configPath, inCluster, net.JoinHostPort(ips[x].String(), "6443"))
|
||||
if err != nil {
|
||||
log.Errorf("failed to create k8s REST config: %v", err)
|
||||
log.Error("failed to create k8s REST config", "err", err)
|
||||
}
|
||||
|
||||
c.Timeout = 2 * time.Second
|
||||
k, err := NewClientset(c)
|
||||
if err != nil {
|
||||
log.Errorf("failed to create k8s clientset: %v", err)
|
||||
log.Error("failed to create k8s clientset", "err", err)
|
||||
}
|
||||
|
||||
_, err = k.DiscoveryClient.ServerVersion()
|
||||
if err == nil {
|
||||
log.Infof("[k8s client] working with IP address [%s]", ips[x].String())
|
||||
log.Info("[k8s client] working", "address", ips[x].String())
|
||||
c.Timeout = defaultTimeout
|
||||
return c, nil
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ package kubevip
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
@@ -44,8 +45,8 @@ func isValidInterface(iface string) error {
|
||||
// userspace has set operational state. Interface must be considered for user
|
||||
// data as setting operational state has not been implemented in every driver."
|
||||
if attrs.OperState == netlink.OperUnknown {
|
||||
log.Warningf(
|
||||
"the status of the interface %s is unknown. Ensure your interface is ready to accept traffic, if so you can safely ignore this message",
|
||||
log.Warn(
|
||||
"the status of the interface is unknown. Ensure your interface is ready to accept traffic, if so you can safely ignore this message", "interface",
|
||||
iface,
|
||||
)
|
||||
} else if attrs.OperState != netlink.OperUp {
|
||||
|
||||
@@ -7,11 +7,12 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/cloudflare/ipvs"
|
||||
"github.com/cloudflare/ipvs/netmask"
|
||||
"github.com/kube-vip/kube-vip/pkg/backend"
|
||||
"github.com/kube-vip/kube-vip/pkg/sysctl"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
/*
|
||||
@@ -51,28 +52,32 @@ func NewIPVSLB(address string, port uint16, forwardingMethod string, backendHeal
|
||||
// Create IPVS client
|
||||
c, err := ipvs.New()
|
||||
if err != nil {
|
||||
log.Errorf("ensure IPVS kernel modules are loaded")
|
||||
log.Fatalf("Error starting IPVS [%v]", err)
|
||||
log.Error("ensure IPVS kernel modules are loaded")
|
||||
log.Error("Error starting IPVS", "err", err)
|
||||
panic("")
|
||||
}
|
||||
i, err := c.Info()
|
||||
if err != nil {
|
||||
log.Errorf("ensure IPVS kernel modules are loaded")
|
||||
log.Fatalf("Error getting IPVS version [%v]", err)
|
||||
log.Error("ensure IPVS kernel modules are loaded")
|
||||
log.Error("Error retrieving IPVS info", "err", err)
|
||||
panic("")
|
||||
}
|
||||
log.Infof("IPVS Loadbalancer enabled for %d.%d.%d", i.Version[0], i.Version[1], i.Version[2])
|
||||
log.Info("IPVS Loadbalancer enabled", "version", fmt.Sprintf(" %d.%d.%d", i.Version[0], i.Version[1], i.Version[2]))
|
||||
|
||||
if strings.ToLower(forwardingMethod) == "masquerade" {
|
||||
err = sysctl.WriteProcSys("/proc/sys/net/ipv4/vs/conntrack", "1")
|
||||
if err != nil {
|
||||
log.Fatalf("Error ensuring net.ipv4.vs.conntrack enabled [%v]", err)
|
||||
log.Error("ensuring net.ipv4.vs.conntrack enabled", "err", err)
|
||||
panic("")
|
||||
}
|
||||
log.Infof("sysctl set net.ipv4.vs.conntrack to 1")
|
||||
log.Info("sysctl set net.ipv4.vs.conntrack to 1")
|
||||
|
||||
err = sysctl.WriteProcSys("/proc/sys/net/ipv4/ip_forward", "1")
|
||||
if err != nil {
|
||||
log.Fatalf("Error ensuring net.ipv4.ip_forward enabled [%v]", err)
|
||||
log.Error("ensuring net.ipv4.ip_forward enabled", "err", err)
|
||||
panic("")
|
||||
}
|
||||
log.Infof("sysctl set net.ipv4.ip_forward to 1")
|
||||
log.Info("sysctl set net.ipv4.ip_forward to 1")
|
||||
}
|
||||
|
||||
ip, family := ipAndFamily(address)
|
||||
@@ -106,7 +111,7 @@ func NewIPVSLB(address string, port uint16, forwardingMethod string, backendHeal
|
||||
m = ipvs.Bypass
|
||||
default:
|
||||
m = ipvs.Local
|
||||
log.Warnf("unknown forwarding method. Defaulting to Local")
|
||||
log.Warn("unknown forwarding method. Defaulting to Local")
|
||||
}
|
||||
|
||||
if backendHealthCheckInterval <= 0 {
|
||||
@@ -161,14 +166,14 @@ func (lb *IPVSLoadBalancer) addBackend(backend backend.Entry) error {
|
||||
// Check if this is the first backend
|
||||
backends, err := lb.client.Destinations(lb.loadBalancerService)
|
||||
if err != nil && strings.Contains(err.Error(), "file does not exist") {
|
||||
log.Errorf("Error querying backends %s", err)
|
||||
log.Error("querying backends", "err", err)
|
||||
}
|
||||
// If this is our first backend, then we can create the load-balancer service and add a backend
|
||||
if len(backends) == 0 {
|
||||
err = lb.client.CreateService(lb.loadBalancerService)
|
||||
// If we've an error it could be that the IPVS lb instance has been left from a previous leadership
|
||||
if err != nil && strings.Contains(err.Error(), "file exists") {
|
||||
log.Warnf("load balancer for API server already exists, attempting to remove and re-create")
|
||||
log.Warn("load balancer for API server already exists, attempting to remove and re-create")
|
||||
err = lb.client.RemoveService(lb.loadBalancerService)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error re-creating IPVS service: %v", err)
|
||||
@@ -179,10 +184,12 @@ func (lb *IPVSLoadBalancer) addBackend(backend backend.Entry) error {
|
||||
}
|
||||
} else if err != nil {
|
||||
// Fatal error at this point as IPVS is probably not working
|
||||
log.Errorf("Unable to create an IPVS service, ensure IPVS kernel modules are loaded")
|
||||
log.Fatalf("IPVS service error: %v", err)
|
||||
log.Error("Unable to create an IPVS service, ensure IPVS kernel modules are loaded")
|
||||
log.Error("IPVS service", "err", err)
|
||||
panic("")
|
||||
|
||||
}
|
||||
log.Infof("Created Load-Balancer services on [%s:%d]", lb.addrString(), lb.Port)
|
||||
log.Info("load-Balancer services created", "address", lb.addrString(), "port", lb.Port)
|
||||
}
|
||||
|
||||
ip, family := ipAndFamily(backend.Addr)
|
||||
@@ -211,7 +218,7 @@ func (lb *IPVSLoadBalancer) addBackend(backend backend.Entry) error {
|
||||
// file exists is fine, we will just return at this point
|
||||
return nil
|
||||
}
|
||||
log.Infof("Added backend for [%s:%d] on [%s:%d]", lb.addrString(), lb.Port, backend.Addr, backend.Port)
|
||||
log.Info("backend added", "src addr", lb.addrString(), "src port", lb.Port, "dst addr", backend.Addr, "dst port", backend.Port)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -274,17 +281,17 @@ func (lb *IPVSLoadBalancer) healthCheck() {
|
||||
if !oldStatus {
|
||||
err := lb.AddBackend(backend.Addr, backend.Port)
|
||||
if err != nil {
|
||||
log.Errorf("failed to add backend: %s", err)
|
||||
log.Error("add backend", "err", err)
|
||||
}
|
||||
lb.backendMap[backend] = newStatus
|
||||
}
|
||||
} else {
|
||||
// old status -> not health
|
||||
if oldStatus {
|
||||
log.Infof("healthCheck failed for backend %s:%d, attempting to remove from load balancer", backend.Addr, backend.Port)
|
||||
log.Info("healthCheck failed removing backend", "address", backend.Addr, "port", backend.Port)
|
||||
err := lb.removeBackend(backend.Addr, backend.Port)
|
||||
if err != nil {
|
||||
log.Errorf("failed to remove backend %s:%d: %s", backend.Addr, backend.Port, err)
|
||||
log.Error("failed to remove backend", "address", backend.Addr, "port", backend.Port, "err", err)
|
||||
}
|
||||
lb.backendMap[backend] = newStatus
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
||||
@@ -57,10 +58,10 @@ func NewInstance(svc *v1.Service, config *kubevip.Config) (*Instance, error) {
|
||||
if svcInterface == kubevip.Auto {
|
||||
link, err = autoFindInterface(address)
|
||||
if err != nil {
|
||||
log.Errorf("failed to automatically discover network interface for annotated IP address [%s] with error: %s", address, err.Error())
|
||||
log.Error("automatically discover network interface for annotated IP", "address", address, "err", err)
|
||||
} else {
|
||||
if link == nil {
|
||||
log.Errorf("failed to automatically discover network interface for annotated IP address [%s]", address)
|
||||
log.Error("automatically discover network interface for annotated IP address", "address", address)
|
||||
}
|
||||
}
|
||||
if link == nil {
|
||||
@@ -75,9 +76,9 @@ func NewInstance(svc *v1.Service, config *kubevip.Config) (*Instance, error) {
|
||||
case kubevip.Auto:
|
||||
link, err = autoFindInterface(address)
|
||||
if err != nil {
|
||||
log.Errorf("failed to automatically discover network interface for IP address [%s] with error: %s - defaulting to: %s", address, err.Error(), config.Interface)
|
||||
log.Error("failed to automatically discover network interface for address", "ip", address, "err", err, "interface", config.Interface)
|
||||
} else if link == nil {
|
||||
log.Errorf("failed to automatically discover network interface for IP address [%s] - defaulting to: %s", address, config.Interface)
|
||||
log.Error("failed to automatically discover network interface for address", "ip", address, "defaulting to", config.Interface)
|
||||
}
|
||||
svcInterface = getAutoInterfaceName(link, config.Interface)
|
||||
case "":
|
||||
@@ -229,7 +230,7 @@ func NewInstance(svc *v1.Service, config *kubevip.Config) (*Instance, error) {
|
||||
for _, vipConfig := range instance.vipConfigs {
|
||||
c, err := cluster.InitCluster(vipConfig, false)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to add Service %s/%s", svc.Namespace, svc.Name)
|
||||
log.Error("Failed to add Service %s/%s", svc.Namespace, svc.Name)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -238,7 +239,7 @@ func NewInstance(svc *v1.Service, config *kubevip.Config) (*Instance, error) {
|
||||
}
|
||||
|
||||
instance.clusters = append(instance.clusters, c)
|
||||
log.Infof("(svcs) adding VIP [%s] via %s for [%s/%s]", vipConfig.VIP, vipConfig.Interface, svc.Namespace, svc.Name)
|
||||
log.Info("(svcs) adding VIP", "ip", vipConfig.VIP, "interface", vipConfig.Interface, "namespace", svc.Namespace, "name", svc.Name)
|
||||
|
||||
}
|
||||
|
||||
@@ -317,7 +318,7 @@ func (i *Instance) startDHCP() error {
|
||||
// Check if the interface doesn't exist first
|
||||
iface, err := net.InterfaceByName(interfaceName)
|
||||
if err != nil {
|
||||
log.Infof("Creating new macvlan interface for DHCP [%s]", interfaceName)
|
||||
log.Info("creating new macvlan interface for DHCP", "interface", interfaceName)
|
||||
|
||||
hwaddr, err := net.ParseMAC(i.dhcpInterfaceHwaddr)
|
||||
if i.dhcpInterfaceHwaddr != "" && err != nil {
|
||||
@@ -329,7 +330,7 @@ func (i *Instance) startDHCP() error {
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("New interface [%s] mac is %s", interfaceName, hwaddr)
|
||||
log.Info("new macvlan interface", "interface", interfaceName, "hardware address", hwaddr)
|
||||
mac := &netlink.Macvlan{
|
||||
LinkAttrs: netlink.LinkAttrs{
|
||||
Name: interfaceName,
|
||||
@@ -354,7 +355,7 @@ func (i *Instance) startDHCP() error {
|
||||
return fmt.Errorf("error finding new DHCP interface by name [%v]", err)
|
||||
}
|
||||
} else {
|
||||
log.Infof("Using existing macvlan interface for DHCP [%s]", interfaceName)
|
||||
log.Info("Using existing macvlan interface for DHCP", "interface", interfaceName)
|
||||
}
|
||||
|
||||
var initRebootFlag bool
|
||||
@@ -366,7 +367,7 @@ func (i *Instance) startDHCP() error {
|
||||
|
||||
// Add hostname to dhcp client if annotated
|
||||
if i.dhcpHostname != "" {
|
||||
log.Infof("Hostname specified for dhcp lease: [%s] - [%s]", interfaceName, i.dhcpHostname)
|
||||
log.Info("Hostname specified for dhcp lease", "interface", interfaceName, "hostname", i.dhcpHostname)
|
||||
client.WithHostName(i.dhcpHostname)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/bgp"
|
||||
"github.com/kube-vip/kube-vip/pkg/k8s"
|
||||
"github.com/kube-vip/kube-vip/pkg/kubevip"
|
||||
@@ -19,7 +21,6 @@ import (
|
||||
"github.com/kube-vip/kube-vip/pkg/upnp"
|
||||
"github.com/kube-vip/kube-vip/pkg/utils"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
@@ -72,14 +73,14 @@ func New(configMap string, config *kubevip.Config) (*Manager, error) {
|
||||
// we set it to hostname as a fallback.
|
||||
// This mimics legacy behavior and should work on old kube-vip installations.
|
||||
if config.NodeName == "" {
|
||||
log.Warning("Node name is missing from the config, fall back to hostname")
|
||||
log.Warn("Node name is missing from the config, fall back to hostname")
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get hostname: %v", err)
|
||||
}
|
||||
config.NodeName = hostname
|
||||
}
|
||||
log.Infof("Using node name [%v]", config.NodeName)
|
||||
log.Info("using node name", "name", config.NodeName)
|
||||
|
||||
adminConfigPath := "/etc/kubernetes/admin.conf"
|
||||
homeConfigPath := filepath.Join(os.Getenv("HOME"), ".kube", "config")
|
||||
@@ -93,7 +94,7 @@ func New(configMap string, config *kubevip.Config) (*Manager, error) {
|
||||
// Do nothing, we don't construct a k8s client for etcd leader election
|
||||
case utils.FileExists(adminConfigPath):
|
||||
if config.KubernetesAddr != "" {
|
||||
log.Infof("k8s address [%s]", config.KubernetesAddr)
|
||||
log.Info("k8s address", "address", config.KubernetesAddr)
|
||||
clientConfig, err = k8s.NewRestConfig(adminConfigPath, false, config.KubernetesAddr)
|
||||
} else if config.EnableControlPlane {
|
||||
// If this is a control plane host it will likely have started as a static pod or won't have the
|
||||
@@ -114,7 +115,7 @@ func New(configMap string, config *kubevip.Config) (*Manager, error) {
|
||||
if clientset, err = k8s.NewClientset(clientConfig); err != nil {
|
||||
return nil, fmt.Errorf("could not create k8s clientset: %w", err)
|
||||
}
|
||||
log.Debugf("Using external Kubernetes configuration from file: %q", adminConfigPath)
|
||||
log.Debug("Using external Kubernetes configuration from file", "path", adminConfigPath)
|
||||
case utils.FileExists(homeConfigPath):
|
||||
clientConfig, err = k8s.NewRestConfig(homeConfigPath, false, "")
|
||||
if err != nil {
|
||||
@@ -124,7 +125,7 @@ func New(configMap string, config *kubevip.Config) (*Manager, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not create k8s clientset from external file: %q: %w", homeConfigPath, err)
|
||||
}
|
||||
log.Debugf("Using external Kubernetes configuration from file [%s]", homeConfigPath)
|
||||
log.Debug("Using external Kubernetes configuration from file", "path", adminConfigPath)
|
||||
default:
|
||||
clientConfig, err = k8s.NewRestConfig("", true, "")
|
||||
if err != nil {
|
||||
@@ -210,7 +211,7 @@ func (sm *Manager) Start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infoln("Starting Kube-vip Manager with the BGP engine")
|
||||
log.Info("Starting Kube-vip Manager with the BGP engine")
|
||||
return sm.startBGP()
|
||||
}
|
||||
|
||||
@@ -222,13 +223,17 @@ func (sm *Manager) Start() error {
|
||||
sm.upnp = true
|
||||
clients := upnp.GetConnectionClients(context.TODO())
|
||||
if len(clients) == 0 {
|
||||
log.Errorf("Error Enabling UPNP. No Clients found")
|
||||
log.Error("Error Enabling UPNP. No Clients found")
|
||||
// Set the struct to false so nothing should use it in future
|
||||
sm.upnp = false
|
||||
} else {
|
||||
for _, c := range clients {
|
||||
ip, err := c.GetExternalIPAddress()
|
||||
log.Infof("Found UPNP IGD2 Gateway address[%s] error: [%s]", ip, err)
|
||||
if err != nil {
|
||||
log.Error("unable to find IGD2 Gateway address", "err", err)
|
||||
}
|
||||
log.Info("Found UPNP IGD2 Gateway address", "ip", ip)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -238,21 +243,21 @@ func (sm *Manager) Start() error {
|
||||
|
||||
// If ARP is enabled then we start a LeaderElection that will use ARP to advertise VIPs
|
||||
if sm.config.EnableARP {
|
||||
log.Infoln("Starting Kube-vip Manager with the ARP engine")
|
||||
log.Info("Starting Kube-vip Manager with the ARP engine")
|
||||
return sm.startARP(sm.config.NodeName)
|
||||
}
|
||||
|
||||
if sm.config.EnableWireguard {
|
||||
log.Infoln("Starting Kube-vip Manager with the Wireguard engine")
|
||||
log.Info("Starting Kube-vip Manager with the Wireguard engine")
|
||||
return sm.startWireguard(sm.config.NodeName)
|
||||
}
|
||||
|
||||
if sm.config.EnableRoutingTable {
|
||||
log.Infoln("Starting Kube-vip Manager with the Routing Table engine")
|
||||
log.Info("Starting Kube-vip Manager with the Routing Table engine")
|
||||
return sm.startTableMode(sm.config.NodeName)
|
||||
}
|
||||
|
||||
log.Errorln("prematurely exiting Load-balancer as no modes [ARP/BGP/Wireguard] are enabled")
|
||||
log.Error("prematurely exiting Load-balancer as no modes [ARP/BGP/Wireguard] are enabled")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -268,7 +273,7 @@ func returnNameSpace() (string, error) {
|
||||
|
||||
func (sm *Manager) parseAnnotations() error {
|
||||
if sm.config.Annotations == "" {
|
||||
log.Debugf("No Node annotations to parse")
|
||||
log.Debug("No Node annotations to parse")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -290,7 +295,7 @@ func (sm *Manager) serviceInterface() string {
|
||||
func (sm *Manager) startTrafficMirroringIfEnabled() error {
|
||||
if sm.config.MirrorDestInterface != "" {
|
||||
svcIf := sm.serviceInterface()
|
||||
log.Infof("mirroring traffic from interface %s to interface %s", svcIf, sm.config.MirrorDestInterface)
|
||||
log.Info("mirroring traffic", "src", svcIf, "dest", sm.config.MirrorDestInterface)
|
||||
if err := trafficmirror.MirrorTrafficFromNIC(svcIf, sm.config.MirrorDestInterface); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -303,7 +308,7 @@ func (sm *Manager) startTrafficMirroringIfEnabled() error {
|
||||
func (sm *Manager) stopTrafficMirroringIfEnabled() error {
|
||||
if sm.config.MirrorDestInterface != "" {
|
||||
svcIf := sm.serviceInterface()
|
||||
log.Infof("clean up qdisc config on interface %s", svcIf)
|
||||
log.Info("clean up qdisc config", "interface", svcIf)
|
||||
if err := trafficmirror.CleanupQDSICFromNIC(svcIf); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -314,9 +319,9 @@ func (sm *Manager) stopTrafficMirroringIfEnabled() error {
|
||||
}
|
||||
|
||||
func (sm *Manager) findServiceInstance(svc *v1.Service) *Instance {
|
||||
log.Debugf("service UID: %s", svc.UID)
|
||||
log.Debug("finding service", "UID", svc.UID)
|
||||
for i := range sm.serviceInstances {
|
||||
log.Debugf("saved service instance %d UID: %s", i, sm.serviceInstances[i].serviceSnapshot.UID)
|
||||
log.Debug("saved service", "instance", i, "UID", sm.serviceInstances[i].serviceSnapshot.UID)
|
||||
if sm.serviceInstances[i].serviceSnapshot.UID == svc.UID {
|
||||
return sm.serviceInstances[i]
|
||||
}
|
||||
@@ -330,11 +335,11 @@ func (sm *Manager) refreshUPNPForwards() {
|
||||
for {
|
||||
time.Sleep(300 * time.Second)
|
||||
|
||||
log.Infof("[UPNP] Refreshing %d Instances", len(sm.serviceInstances))
|
||||
log.Info("[UPNP] Refreshing Instances", "number of instances", len(sm.serviceInstances))
|
||||
for i := range sm.serviceInstances {
|
||||
sm.upnpMap(context.TODO(), sm.serviceInstances[i])
|
||||
if err := sm.updateStatus(sm.serviceInstances[i]); err != nil {
|
||||
log.Warnf("[UPNP] Error updating service IPs %s [%s]", sm.serviceInstances[i].serviceSnapshot.Name, err.Error())
|
||||
log.Warn("[UPNP] Error updating service", "ip", sm.serviceInstances[i].serviceSnapshot.Name, "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/tools/leaderelection"
|
||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||
@@ -54,7 +55,7 @@ func (sm *Manager) startARP(id string) error {
|
||||
go func() {
|
||||
err := cpCluster.StartCluster(sm.config, clusterManager, nil)
|
||||
if err != nil {
|
||||
log.Errorf("Control Plane Error [%v]", err)
|
||||
log.Error("starting control plane", "err", err)
|
||||
// Trigger the shutdown of this manager instance
|
||||
sm.signalChan <- syscall.SIGINT
|
||||
|
||||
@@ -64,7 +65,7 @@ func (sm *Manager) startARP(id string) error {
|
||||
// Check if we're also starting the services, if not we can sit and wait on the closing channel and return here
|
||||
if !sm.config.EnableServices {
|
||||
<-sm.signalChan
|
||||
log.Infof("Shutting down Kube-Vip")
|
||||
log.Info("Shutting down Kube-Vip")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -74,7 +75,7 @@ func (sm *Manager) startARP(id string) error {
|
||||
|
||||
ns, err = returnNameSpace()
|
||||
if err != nil {
|
||||
log.Warnf("unable to auto-detect namespace, dropping to [%s]", sm.config.Namespace)
|
||||
log.Warn("unable to auto-detect namespace, dropping to config", "namespace", sm.config.Namespace)
|
||||
ns = sm.config.Namespace
|
||||
}
|
||||
}
|
||||
@@ -87,14 +88,14 @@ func (sm *Manager) startARP(id string) error {
|
||||
// Start a services watcher (all kube-vip pods will watch services), upon a new service
|
||||
// a lock based upon that service is created that they will all leaderElection on
|
||||
if sm.config.EnableServicesElection {
|
||||
log.Infof("beginning watching services, leaderelection will happen for every service")
|
||||
log.Info("beginning watching services, leaderelection will happen for every service")
|
||||
err = sm.startServicesWatchForLeaderElection(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
||||
log.Infof("beginning services leadership, namespace [%s], lock name [%s], id [%s]", ns, sm.config.ServicesLeaseName, id)
|
||||
log.Info("beginning services leadership", "namespace", ns, "lock name", sm.config.ServicesLeaseName, "id", id)
|
||||
// we use the Lease lock type since edits to Leases are less common
|
||||
// and fewer objects in the cluster watch "all Leases".
|
||||
lock := &resourcelock.LeaseLock{
|
||||
@@ -125,19 +126,21 @@ func (sm *Manager) startARP(id string) error {
|
||||
OnStartedLeading: func(ctx context.Context) {
|
||||
err = sm.servicesWatcher(ctx, sm.syncServices)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Error("service watcher", "err", err)
|
||||
panic("") // TODO: - emulating log.fatal here
|
||||
}
|
||||
},
|
||||
OnStoppedLeading: func() {
|
||||
// we can do cleanup here
|
||||
log.Infof("leader lost: %s", id)
|
||||
log.Info("leader lost", "new leader", id)
|
||||
for _, instance := range sm.serviceInstances {
|
||||
for _, cluster := range instance.clusters {
|
||||
cluster.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
log.Fatal("lost leadership, restarting kube-vip")
|
||||
log.Error("lost leadership, restarting kube-vip")
|
||||
panic("") // TODO: - emulating log.fatal here
|
||||
},
|
||||
OnNewLeader: func(identity string) {
|
||||
// we're notified when new leader elected
|
||||
@@ -148,7 +151,7 @@ func (sm *Manager) startARP(id string) error {
|
||||
// I just got the lock
|
||||
return
|
||||
}
|
||||
log.Infof("new leader elected: %s", identity)
|
||||
log.Info("new leader elected", "new leader", identity)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -6,13 +6,14 @@ import (
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/bgp"
|
||||
"github.com/kube-vip/kube-vip/pkg/cluster"
|
||||
"github.com/kube-vip/kube-vip/pkg/equinixmetal"
|
||||
api "github.com/osrg/gobgp/v3/api"
|
||||
"github.com/packethost/packngo"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Start will begin the Manager, which will start services and watch the configmap
|
||||
@@ -42,7 +43,7 @@ func (sm *Manager) startBGP() error {
|
||||
|
||||
// We're using Equinix Metal with BGP, populate the Peer information from the API
|
||||
if sm.config.EnableBGP {
|
||||
log.Infoln("Looking up the BGP configuration from Equinix Metal")
|
||||
log.Info("Looking up the BGP configuration from Equinix Metal")
|
||||
err = equinixmetal.BGPLookup(packetClient, sm.config)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -115,7 +116,7 @@ func (sm *Manager) startBGP() error {
|
||||
err = cpCluster.StartVipService(sm.config, clusterManager, sm.bgpServer, packetClient)
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("Control Plane Error [%v]", err)
|
||||
log.Error("Control Plane", "err", err)
|
||||
// Trigger the shutdown of this manager instance
|
||||
sm.signalChan <- syscall.SIGINT
|
||||
}
|
||||
@@ -124,7 +125,7 @@ func (sm *Manager) startBGP() error {
|
||||
// Check if we're also starting the services, if not we can sit and wait on the closing channel and return here
|
||||
if !sm.config.EnableServices {
|
||||
<-sm.signalChan
|
||||
log.Infof("Shutting down Kube-Vip")
|
||||
log.Info("Shutting down Kube-Vip")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -135,7 +136,7 @@ func (sm *Manager) startBGP() error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("Shutting down Kube-Vip")
|
||||
log.Info("Shutting down Kube-Vip")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/cluster"
|
||||
"github.com/kube-vip/kube-vip/pkg/iptables"
|
||||
"github.com/kube-vip/kube-vip/pkg/vip"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/tools/leaderelection"
|
||||
@@ -27,14 +28,14 @@ func (sm *Manager) startTableMode(id string) error {
|
||||
// want to step down
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
log.Infof("all routing table entries will exist in table [%d] with protocol [%d]", sm.config.RoutingTableID, sm.config.RoutingProtocol)
|
||||
log.Info("destination for routes", "table", sm.config.RoutingTableID, "protocol", sm.config.RoutingProtocol)
|
||||
|
||||
if sm.config.CleanRoutingTable {
|
||||
go func() {
|
||||
// we assume that after 10s all services should be configured so we can delete redundant routes
|
||||
time.Sleep(time.Second * 10)
|
||||
if err := sm.cleanRoutes(); err != nil {
|
||||
log.Errorf("error checking for old routes: %v", err)
|
||||
log.Error("error checking for old routes", "err", err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -43,12 +44,12 @@ func (sm *Manager) startTableMode(id string) error {
|
||||
if egressCleanEnv != "" {
|
||||
egressClean, err := strconv.ParseBool(egressCleanEnv)
|
||||
if err != nil {
|
||||
log.Warnf("failed to parse EGRESS_CLEAN env value [%s]. Egress cleaning will not be performed: %s", egressCleanEnv, err.Error())
|
||||
log.Warn("failed to parse EGRESS_CLEAN env value [%s]. Egress cleaning will not be performed: %s", egressCleanEnv, err.Error())
|
||||
}
|
||||
if egressClean {
|
||||
vip.ClearIPTables(sm.config.EgressWithNftables, sm.config.ServiceNamespace, iptables.ProtocolIPv4)
|
||||
vip.ClearIPTables(sm.config.EgressWithNftables, sm.config.ServiceNamespace, iptables.ProtocolIPv6)
|
||||
log.Debug("IPTables rules cleaned on startup")
|
||||
log.Debug("IPtables rules cleaned on startup")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,28 +77,28 @@ func (sm *Manager) startTableMode(id string) error {
|
||||
}
|
||||
|
||||
if err := cpCluster.StartVipService(sm.config, clusterManager, nil, nil); err != nil {
|
||||
log.Errorf("Control Plane Error [%v]", err)
|
||||
log.Error("Control Plane", "err", err)
|
||||
// Trigger the shutdown of this manager instance
|
||||
sm.signalChan <- syscall.SIGINT
|
||||
}
|
||||
} else {
|
||||
ns, err := returnNameSpace()
|
||||
if err != nil {
|
||||
log.Warnf("unable to auto-detect namespace, dropping to [%s]", sm.config.Namespace)
|
||||
log.Warn("unable to auto-detect namespace", "dropping to", sm.config.Namespace)
|
||||
ns = sm.config.Namespace
|
||||
}
|
||||
|
||||
// Start a services watcher (all kube-vip pods will watch services), upon a new service
|
||||
// a lock based upon that service is created that they will all leaderElection on
|
||||
if sm.config.EnableServicesElection {
|
||||
log.Infof("beginning watching services, leaderelection will happen for every service")
|
||||
log.Info("beginning watching services, leaderelection will happen for every service")
|
||||
err = sm.startServicesWatchForLeaderElection(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if sm.config.EnableLeaderElection {
|
||||
|
||||
log.Infof("beginning services leadership, namespace [%s], lock name [%s], id [%s]", ns, plunderLock, id)
|
||||
log.Info("beginning services leadership", "namespace", ns, "lock name", plunderLock, "id", id)
|
||||
// we use the Lease lock type since edits to Leases are less common
|
||||
// and fewer objects in the cluster watch "all Leases".
|
||||
lock := &resourcelock.LeaseLock{
|
||||
@@ -127,19 +128,21 @@ func (sm *Manager) startTableMode(id string) error {
|
||||
OnStartedLeading: func(ctx context.Context) {
|
||||
err = sm.servicesWatcher(ctx, sm.syncServices)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Error(err.Error())
|
||||
panic("")
|
||||
}
|
||||
},
|
||||
OnStoppedLeading: func() {
|
||||
// we can do cleanup here
|
||||
log.Infof("leader lost: %s", id)
|
||||
log.Info("leader lost", "id", id)
|
||||
for _, instance := range sm.serviceInstances {
|
||||
for _, cluster := range instance.clusters {
|
||||
cluster.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
log.Fatal("lost leadership, restarting kube-vip")
|
||||
log.Error("lost leadership, restarting kube-vip")
|
||||
panic("")
|
||||
},
|
||||
OnNewLeader: func(identity string) {
|
||||
// we're notified when new leader elected
|
||||
@@ -147,15 +150,15 @@ func (sm *Manager) startTableMode(id string) error {
|
||||
// I just got the lock
|
||||
return
|
||||
}
|
||||
log.Infof("new leader elected: %s", identity)
|
||||
log.Info("new leader elected", "id", identity)
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
log.Infof("beginning watching services without leader election")
|
||||
log.Info("beginning watching services without leader election")
|
||||
err = sm.servicesWatcher(ctx, sm.syncServices)
|
||||
if err != nil {
|
||||
log.Errorf("Cannot watch services, %v", err)
|
||||
log.Error("Cannot watch services", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,9 +192,9 @@ func (sm *Manager) cleanRoutes() error {
|
||||
if !found {
|
||||
err = netlink.RouteDel(&(routes[i]))
|
||||
if err != nil {
|
||||
log.Errorf("[route] error deleting route: %v", routes[i])
|
||||
log.Error("[route] deletion", "route", routes[i], "err", err)
|
||||
}
|
||||
log.Debugf("[route] deleted route: %v", routes[i])
|
||||
log.Debug("[route] deletion", "route", routes[i])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/wireguard"
|
||||
log "github.com/sirupsen/logrus"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/tools/leaderelection"
|
||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||
@@ -20,7 +21,7 @@ func (sm *Manager) startWireguard(id string) error {
|
||||
// want to step down
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
log.Infoln("reading wireguard peer configuration from Kubernetes secret")
|
||||
log.Info("reading wireguard peer configuration from Kubernetes secret")
|
||||
s, err := sm.clientSet.CoreV1().Secrets(sm.config.Namespace).Get(ctx, "wireguard", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -47,21 +48,21 @@ func (sm *Manager) startWireguard(id string) error {
|
||||
|
||||
ns, err = returnNameSpace()
|
||||
if err != nil {
|
||||
log.Warnf("unable to auto-detect namespace, dropping to [%s]", sm.config.Namespace)
|
||||
log.Warn("unable to auto-detect namespace", "dropping to", sm.config.Namespace)
|
||||
ns = sm.config.Namespace
|
||||
}
|
||||
|
||||
// Start a services watcher (all kube-vip pods will watch services), upon a new service
|
||||
// a lock based upon that service is created that they will all leaderElection on
|
||||
if sm.config.EnableServicesElection {
|
||||
log.Infof("beginning watching services, leaderelection will happen for every service")
|
||||
log.Info("beginning watching services, leaderelection will happen for every service")
|
||||
err = sm.startServicesWatchForLeaderElection(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
|
||||
log.Infof("beginning services leadership, namespace [%s], lock name [%s], id [%s]", ns, plunderLock, id)
|
||||
log.Info("beginning services leadership", "namespace", ns, "lock name", plunderLock, "id", id)
|
||||
// we use the Lease lock type since edits to Leases are less common
|
||||
// and fewer objects in the cluster watch "all Leases".
|
||||
lock := &resourcelock.LeaseLock{
|
||||
@@ -92,19 +93,21 @@ func (sm *Manager) startWireguard(id string) error {
|
||||
OnStartedLeading: func(ctx context.Context) {
|
||||
err = sm.servicesWatcher(ctx, sm.syncServices)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Error(err.Error())
|
||||
panic("")
|
||||
}
|
||||
},
|
||||
OnStoppedLeading: func() {
|
||||
// we can do cleanup here
|
||||
log.Infof("leader lost: %s", id)
|
||||
log.Info("leader lost", "id", id)
|
||||
for _, instance := range sm.serviceInstances {
|
||||
for _, cluster := range instance.clusters {
|
||||
cluster.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
log.Fatal("lost leadership, restarting kube-vip")
|
||||
log.Error("lost leadership, restarting kube-vip")
|
||||
panic("")
|
||||
},
|
||||
OnNewLeader: func(identity string) {
|
||||
// we're notified when new leader elected
|
||||
@@ -112,7 +115,7 @@ func (sm *Manager) startWireguard(id string) error {
|
||||
// I just got the lock
|
||||
return
|
||||
}
|
||||
log.Infof("new leader elected: %s", identity)
|
||||
log.Info("new leader elected", "id", identity)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -5,7 +5,8 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@@ -28,21 +29,21 @@ func applyNodeLabel(clientSet *kubernetes.Clientset, address, id, identity strin
|
||||
ctx := context.Background()
|
||||
node, err := clientSet.CoreV1().Nodes().Get(ctx, id, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("can't query node %s labels. error: %v", id, err)
|
||||
log.Error("can't query node labels", "node", id, "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Debugf("node %s labels: %+v", id, node.Labels)
|
||||
log.Debug(fmt.Sprintf("node %s labels: %+v", id, node.Labels))
|
||||
|
||||
value, ok := node.Labels[nodeLabelIndex]
|
||||
path := fmt.Sprintf("/metadata/labels/%s", nodeLabelJSONPath)
|
||||
log.Debugf("Received identity: %s - id: %s", identity, id)
|
||||
log.Debug(fmt.Sprintf("Received identity: %s - id: %s", identity, id))
|
||||
if ok && value == address {
|
||||
log.Debugf("removing node label `has-ip=%s` on %s", address, id)
|
||||
log.Debug(fmt.Sprintf("removing node label `has-ip=%s` on %s", address, id))
|
||||
// Remove label
|
||||
applyPatchLabels(ctx, clientSet, id, "remove", path, address)
|
||||
} else {
|
||||
log.Debugf("setting node label `has-ip=%s` on %s", address, id)
|
||||
log.Debug(fmt.Sprintf("setting node label `has-ip=%s` on %s", address, id))
|
||||
// Append label
|
||||
applyPatchLabels(ctx, clientSet, id, "add", path, address)
|
||||
}
|
||||
@@ -58,15 +59,15 @@ func applyPatchLabels(ctx context.Context, clientSet *kubernetes.Clientset,
|
||||
}}
|
||||
patchData, err := json.Marshal(patchLabels)
|
||||
if err != nil {
|
||||
log.Errorf("node patch marshaling failed. error: %v", err)
|
||||
log.Error("node patch marshaling failed", "err", err)
|
||||
return
|
||||
}
|
||||
// patch node
|
||||
node, err := clientSet.CoreV1().Nodes().Patch(ctx,
|
||||
name, types.JSONPatchType, patchData, metav1.PatchOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("can't patch node %s. error: %v", name, err)
|
||||
log.Error("node patch marshaling failed", "err", err)
|
||||
return
|
||||
}
|
||||
log.Debugf("updated node %s labels: %+v", name, node.Labels)
|
||||
log.Debug("updated", "node", name, "labels", node.Labels)
|
||||
}
|
||||
|
||||
@@ -8,9 +8,10 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/iptables"
|
||||
"github.com/kube-vip/kube-vip/pkg/vip"
|
||||
log "github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
@@ -58,7 +59,7 @@ func getSameFamilyCidr(sourceCidrs, ip string) string { //Todo: not sure how thi
|
||||
matchingFamily = append(matchingFamily, cidr)
|
||||
selectedCIDR, err := checkCIDR(ip, cidr)
|
||||
if err != nil {
|
||||
log.Warnf("IPv6 CIDR check failed: %s", err.Error())
|
||||
log.Warn("IPv6 CIDR check ", "err", err)
|
||||
continue
|
||||
}
|
||||
if selectedCIDR != "" {
|
||||
@@ -70,7 +71,7 @@ func getSameFamilyCidr(sourceCidrs, ip string) string { //Todo: not sure how thi
|
||||
matchingFamily = append(matchingFamily, cidr)
|
||||
selectedCidr, err := checkCIDR(ip, cidr)
|
||||
if err != nil {
|
||||
log.Warnf("IPv4 CIDR check failed: %s", err.Error())
|
||||
log.Warn("IPv4 CIDR check ", "err", err)
|
||||
continue
|
||||
}
|
||||
if selectedCidr != "" {
|
||||
@@ -121,7 +122,7 @@ func (sm *Manager) configureEgress(vipIP, podIP, namespace string, annotations m
|
||||
}
|
||||
|
||||
if discoverErr != nil {
|
||||
log.Warn(discoverErr)
|
||||
log.Warn("autodiscover CIDR", "err", discoverErr)
|
||||
}
|
||||
|
||||
if sm.config.EgressPodCidr != "" {
|
||||
@@ -156,21 +157,21 @@ func (sm *Manager) configureEgress(vipIP, podIP, namespace string, annotations m
|
||||
serviceCidr = defaultServiceCIDR
|
||||
}
|
||||
|
||||
log.Infof("[Egress] pod CIDR [%s], service CIDR [%s] for vip [%s] / pod [%s]", podCidr, serviceCidr, vipIP, podIP)
|
||||
log.Info("[Egress]", "pod CIDR", podCidr, " service CIDR", serviceCidr, "vip", serviceCidr, "pod", podIP)
|
||||
|
||||
// checking if all addresses are of the same IP family
|
||||
if vip.IsIPv4(podIP) != vip.IsIPv4CIDR(podCidr) {
|
||||
log.Errorf("[Egress] pod's IP [%s] and Pod CIDR [%s] family is not matching. Backing off...", podIP, podCidr)
|
||||
log.Error("[Egress] family is not matching. Backing off...", "pod", podIP, "podCIDR", podCidr)
|
||||
return nil
|
||||
}
|
||||
|
||||
if vip.IsIPv4(vipIP) != vip.IsIPv4CIDR(serviceCidr) {
|
||||
log.Errorf("[Egress] VIP's IP [%s] and Service CIDR [%s] family is not matching. Backing off...", podIP, podCidr)
|
||||
log.Error("[Egress] family is not matching. Backing off...", "pod", podIP, "serviceCIDR", serviceCidr)
|
||||
return nil
|
||||
}
|
||||
|
||||
if vip.IsIPv4(vipIP) != vip.IsIPv4(podIP) {
|
||||
log.Errorf("[Egress] VIP's IP [%s] and Pod's IP [%s] family is not matching. Backing off...", podIP, podCidr)
|
||||
log.Error("[Egress] family is not matching. Backing off...", "pod", podIP, "vipIP", vipIP)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -279,7 +280,7 @@ func (sm *Manager) configureEgress(vipIP, podIP, namespace string, annotations m
|
||||
}
|
||||
|
||||
func (sm *Manager) AutoDiscoverCIDRs() (serviceCIDR, podCIDR string, err error) {
|
||||
log.Debugf("Trying to automatically discover Service and Pod CIDRs")
|
||||
log.Debug("Trying to automatically discover Service and Pod CIDRs")
|
||||
options := v1.ListOptions{
|
||||
LabelSelector: "component=kube-controller-manager",
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -23,7 +24,7 @@ import (
|
||||
func (sm *Manager) syncServices(ctx context.Context, svc *v1.Service, wg *sync.WaitGroup) error {
|
||||
defer wg.Done()
|
||||
|
||||
log.Debugf("[STARTING] Service Sync")
|
||||
log.Debug("[STARTING] Service Sync")
|
||||
|
||||
// Iterate through the synchronising services
|
||||
foundInstance := false
|
||||
@@ -43,7 +44,7 @@ func (sm *Manager) syncServices(ctx context.Context, svc *v1.Service, wg *sync.W
|
||||
break
|
||||
}
|
||||
for _, newServiceAddress := range newServiceAddresses {
|
||||
log.Debugf("isDHCP: %t, newServiceAddress: %s", sm.serviceInstances[x].isDHCP, newServiceAddress)
|
||||
log.Debug("service", "isDHCP", sm.serviceInstances[x].isDHCP, "newServiceAddress", newServiceAddress)
|
||||
if sm.serviceInstances[x].serviceSnapshot.UID == newServiceUID {
|
||||
// If the found instance's DHCP configuration doesn't match the new service, delete it.
|
||||
if (sm.serviceInstances[x].isDHCP && newServiceAddress != "0.0.0.0") ||
|
||||
@@ -102,23 +103,23 @@ func (sm *Manager) addService(ctx context.Context, svc *v1.Service) error {
|
||||
if newService.isDHCP && len(newService.vipConfigs) == 1 {
|
||||
go func() {
|
||||
for ip := range newService.dhcpClient.IPChannel() {
|
||||
log.Debugf("IP %s may have changed", ip)
|
||||
log.Debug("IP changed", "ip", ip)
|
||||
newService.vipConfigs[0].VIP = ip
|
||||
newService.dhcpInterfaceIP = ip
|
||||
if !sm.config.DisableServiceUpdates {
|
||||
if err := sm.updateStatus(newService); err != nil {
|
||||
log.Warnf("error updating svc: %s", err)
|
||||
log.Warn("updating svc", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Debugf("IP update channel closed, stopping")
|
||||
log.Debug("IP update channel closed, stopping")
|
||||
}()
|
||||
}
|
||||
|
||||
sm.serviceInstances = append(sm.serviceInstances, newService)
|
||||
|
||||
if !sm.config.DisableServiceUpdates {
|
||||
log.Debugf("(svcs) will update [%s/%s]", newService.serviceSnapshot.Namespace, newService.serviceSnapshot.Name)
|
||||
log.Debug("service update", "namespace", newService.serviceSnapshot.Namespace, "name", newService.serviceSnapshot.Name)
|
||||
if err := sm.updateStatus(newService); err != nil {
|
||||
// delete service to collect garbage
|
||||
if deleteErr := sm.deleteService(newService.serviceSnapshot.UID); deleteErr != nil {
|
||||
@@ -132,26 +133,26 @@ func (sm *Manager) addService(ctx context.Context, svc *v1.Service) error {
|
||||
// Check if we need to flush any conntrack connections (due to some dangling conntrack connections)
|
||||
if svc.Annotations[flushContrack] == "true" {
|
||||
|
||||
log.Debugf("Flushing conntrack rules for service [%s]", svc.Name)
|
||||
log.Debug("Flushing conntrack rules", "service", svc.Name)
|
||||
for _, serviceIP := range serviceIPs {
|
||||
err = vip.DeleteExistingSessions(serviceIP, false, svc.Annotations[egressDestinationPorts], svc.Annotations[egressSourcePorts])
|
||||
if err != nil {
|
||||
log.Errorf("Error flushing any remaining egress connections [%s]", err)
|
||||
log.Error("flushing any remaining egress connections", "err", err)
|
||||
}
|
||||
err = vip.DeleteExistingSessions(serviceIP, true, svc.Annotations[egressDestinationPorts], svc.Annotations[egressSourcePorts])
|
||||
if err != nil {
|
||||
log.Errorf("Error flushing any remaining ingress connections [%s]", err)
|
||||
log.Error("flushing any remaining ingress connections", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if egress is enabled on the service, if so we'll need to configure some rules
|
||||
if svc.Annotations[egress] == "true" && len(serviceIPs) > 0 {
|
||||
log.Debugf("Enabling egress for the service [%s]", svc.Name)
|
||||
log.Debug("enabling egress", "service", svc.Name)
|
||||
// We will need to modify the iptables rules
|
||||
err = sm.iptablesCheck()
|
||||
if err != nil {
|
||||
log.Errorf("Error configuring egress for loadbalancer [%s]", err)
|
||||
log.Error("configuring egress", "service", svc.Name, "err", err)
|
||||
}
|
||||
var podIP string
|
||||
errList := []error{}
|
||||
@@ -168,7 +169,7 @@ func (sm *Manager) addService(ctx context.Context, svc *v1.Service) error {
|
||||
err = sm.configureEgress(serviceIP, podIP, svc.Namespace, svc.Annotations)
|
||||
if err != nil {
|
||||
errList = append(errList, err)
|
||||
log.Errorf("Error configuring egress for loadbalancer [%s]", err)
|
||||
log.Error("configuring egress", "service", svc.Name, "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,7 +183,7 @@ func (sm *Manager) addService(ctx context.Context, svc *v1.Service) error {
|
||||
err = sm.configureEgress(serviceIP, podIPs, svc.Namespace, svc.Annotations)
|
||||
if err != nil {
|
||||
errList = append(errList, err)
|
||||
log.Errorf("Error configuring egress for loadbalancer [%s]", err)
|
||||
log.Error("configuring egress", "service", svc.Name, "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -195,13 +196,13 @@ func (sm *Manager) addService(ctx context.Context, svc *v1.Service) error {
|
||||
}
|
||||
err = provider.updateServiceAnnotation(svc.Annotations[activeEndpoint], svc.Annotations[activeEndpointIPv6], svc, sm)
|
||||
if err != nil {
|
||||
log.Errorf("error configuring egress annotation for loadbalancer [%s]", err)
|
||||
log.Error("configuring egress", "service", svc.Name, "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finishTime := time.Since(startTime)
|
||||
log.Infof("[service] synchronised in %dms", finishTime.Milliseconds())
|
||||
log.Info("[service] synchronised", "in", fmt.Sprintf("%dms", finishTime.Milliseconds()))
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -215,7 +216,7 @@ func (sm *Manager) deleteService(uid types.UID) error {
|
||||
var serviceInstance *Instance
|
||||
found := false
|
||||
for x := range sm.serviceInstances {
|
||||
log.Debugf("Looking for [%s], found [%s]", uid, sm.serviceInstances[x].serviceSnapshot.UID)
|
||||
log.Debug("service lookup", "target UID", uid, "found UID ", sm.serviceInstances[x].serviceSnapshot.UID)
|
||||
// Add the running services to the new array
|
||||
if sm.serviceInstances[x].serviceSnapshot.UID != uid {
|
||||
updatedInstances = append(updatedInstances, sm.serviceInstances[x])
|
||||
@@ -269,17 +270,17 @@ func (sm *Manager) deleteService(uid types.UID) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("[BGP] error deleting BGP host: %v", err)
|
||||
}
|
||||
log.Debugf("[BGP] deleted host: %s", cidrVip)
|
||||
log.Debug("[BGP] delete", "host", cidrVip)
|
||||
}
|
||||
}
|
||||
|
||||
// We will need to tear down the egress
|
||||
if serviceInstance.serviceSnapshot.Annotations[egress] == "true" {
|
||||
if serviceInstance.serviceSnapshot.Annotations[activeEndpoint] != "" {
|
||||
log.Infof("service [%s] has an egress re-write enabled", serviceInstance.serviceSnapshot.Name)
|
||||
log.Info("egress re-write enabled", "service", serviceInstance.serviceSnapshot.Name)
|
||||
err := sm.TeardownEgress(serviceInstance.serviceSnapshot.Annotations[activeEndpoint], serviceInstance.serviceSnapshot.Spec.LoadBalancerIP, serviceInstance.serviceSnapshot.Namespace, serviceInstance.serviceSnapshot.Annotations)
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
log.Error("egress teardown", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -288,7 +289,7 @@ func (sm *Manager) deleteService(uid types.UID) error {
|
||||
// Update the service array
|
||||
sm.serviceInstances = updatedInstances
|
||||
|
||||
log.Infof("Removed [%s] from manager, [%d] advertised services remain", uid, len(sm.serviceInstances))
|
||||
log.Info("Removed instance from manager", "uid", uid, "remaining advertised services", len(sm.serviceInstances))
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -301,7 +302,7 @@ func (sm *Manager) upnpMap(ctx context.Context, s *Instance) {
|
||||
return
|
||||
}
|
||||
if !sm.upnp {
|
||||
log.Warnf("[UPNP] Found kube-vip.io/forwardUPNP on service while UPNP forwarding is disabled in the kube-vip config. Not forwarding service %s", s.serviceSnapshot.Name)
|
||||
log.Warn("[UPNP] Found kube-vip.io/forwardUPNP on service while UPNP forwarding is disabled in the kube-vip config. Not forwarding", "service", s.serviceSnapshot.Name)
|
||||
}
|
||||
// If upnp is enabled then update the gateway/router with the address
|
||||
// TODO - check if this implementation for dualstack is correct
|
||||
@@ -314,28 +315,28 @@ func (sm *Manager) upnpMap(ctx context.Context, s *Instance) {
|
||||
for _, vip := range fetchServiceAddresses(s.serviceSnapshot) {
|
||||
for _, port := range s.serviceSnapshot.Spec.Ports {
|
||||
for _, gw := range gateways {
|
||||
log.Infof("[UPNP] Adding map to [%s:%d - %s] on gateway %s", vip, port.Port, s.serviceSnapshot.Name, gw.WANIPv6FirewallControlClient.Location)
|
||||
log.Info("[UPNP] Adding map", "vip", vip, "port", port.Port, "service", s.serviceSnapshot.Name, "gateway", gw.WANIPv6FirewallControlClient.Location)
|
||||
|
||||
forwardSucessful := false
|
||||
if gw.WANIPv6FirewallControlClient != nil {
|
||||
pinholeID, pinholeErr := gw.WANIPv6FirewallControlClient.AddPinholeCtx(ctx, "0.0.0.0", uint16(port.Port), vip, uint16(port.Port), upnp.MapProtocolToIANA(string(port.Protocol)), 3600) //nolint TODO
|
||||
if pinholeErr == nil {
|
||||
forwardSucessful = true
|
||||
log.Infof("[UPNP] Service should be accessible externally on port [%d]; PinholeID is [%d]", port.Port, pinholeID)
|
||||
log.Info("[UPNP] Service should be accessible externally", "port", port.Port, "pinhold ID", pinholeID)
|
||||
} else {
|
||||
//TODO: Cleanup
|
||||
log.Errorf("[UPNP] Unable to map port to gateway using Pinhole API[%s]", pinholeErr.Error())
|
||||
log.Error("[UPNP] Unable to map port to gateway using Pinhole API", "err", pinholeErr.Error())
|
||||
}
|
||||
}
|
||||
// Fallback to PortForward
|
||||
if !forwardSucessful {
|
||||
portMappingErr := gw.ConnectionClient.AddPortMapping("0.0.0.0", uint16(port.Port), strings.ToUpper(string(port.Protocol)), uint16(port.Port), vip, true, s.serviceSnapshot.Name, 3600) //nolint TODO
|
||||
if portMappingErr == nil {
|
||||
log.Infof("[UPNP] Service should be accessible externally on port [%d]", port.Port)
|
||||
log.Info("[UPNP] Service should be accessible externally", "port", port.Port)
|
||||
forwardSucessful = true
|
||||
} else {
|
||||
//TODO: Cleanup
|
||||
log.Errorf("[UPNP] Unable to map port to gateway using PortForward API[%s]", portMappingErr.Error())
|
||||
log.Error("[UPNP] Unable to map port to gateway using PortForward API", "err", portMappingErr.Error())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,14 +380,14 @@ func (sm *Manager) updateStatus(i *Instance) error {
|
||||
}
|
||||
|
||||
if currentService.Annotations["development.kube-vip.io/synthetic-api-server-error-on-update"] == "true" {
|
||||
log.Errorf("(Synthetic error thrown) Error updating Service Spec [%s] : %v", i.serviceSnapshot.Name, err)
|
||||
log.Error("(Synthetic error ) updating Spec", "service", i.serviceSnapshot.Name, "err", err)
|
||||
return fmt.Errorf("(Synthetic) simulating api server errors")
|
||||
}
|
||||
|
||||
if !cmp.Equal(currentService, currentServiceCopy) {
|
||||
currentService, err = sm.clientSet.CoreV1().Services(currentServiceCopy.Namespace).Update(context.TODO(), currentServiceCopy, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("Error updating Service Spec [%s] : %v", i.serviceSnapshot.Name, err)
|
||||
log.Error("updating Spec", "service", i.serviceSnapshot.Name, "err", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -435,7 +436,7 @@ func (sm *Manager) updateStatus(i *Instance) error {
|
||||
currentService.Status.LoadBalancer.Ingress = ingresses
|
||||
_, err = sm.clientSet.CoreV1().Services(currentService.Namespace).UpdateStatus(context.TODO(), currentService, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("Error updating Service %s/%s Status: %v", i.serviceSnapshot.Namespace, i.serviceSnapshot.Name, err)
|
||||
log.Error("updating Service", "namespace", i.serviceSnapshot.Namespace, "name", i.serviceSnapshot.Name, "err", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -443,7 +444,7 @@ func (sm *Manager) updateStatus(i *Instance) error {
|
||||
})
|
||||
|
||||
if retryErr != nil {
|
||||
log.Errorf("Failed to set Services: %v", retryErr)
|
||||
log.Error("Failed to set Services", "err", retryErr)
|
||||
return retryErr
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -6,7 +6,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/tools/leaderelection"
|
||||
@@ -29,7 +30,7 @@ func (sm *Manager) startServicesWatchForLeaderElection(ctx context.Context) erro
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("Shutting down kube-Vip")
|
||||
log.Info("Shutting down kube-Vip")
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -37,7 +38,7 @@ func (sm *Manager) startServicesWatchForLeaderElection(ctx context.Context) erro
|
||||
// The startServicesWatchForLeaderElection function will start a services watcher, the
|
||||
func (sm *Manager) StartServicesLeaderElection(ctx context.Context, service *v1.Service, wg *sync.WaitGroup) error {
|
||||
serviceLease := fmt.Sprintf("kubevip-%s", service.Name)
|
||||
log.Infof("(svc election) service [%s], namespace [%s], lock name [%s], host id [%s]", service.Name, service.Namespace, serviceLease, sm.config.NodeName)
|
||||
log.Info("new leader election", "service", service.Name, "namespace", service.Namespace, "lock name", serviceLease, "host id", sm.config.NodeName)
|
||||
// we use the Lease lock type since edits to Leases are less common
|
||||
// and fewer objects in the cluster watch "all Leases".
|
||||
lock := &resourcelock.LeaseLock{
|
||||
@@ -73,16 +74,16 @@ func (sm *Manager) StartServicesLeaderElection(ctx context.Context, service *v1.
|
||||
// we run this in background as it's blocking
|
||||
wg.Add(1)
|
||||
if err := sm.syncServices(ctx, service, wg); err != nil {
|
||||
log.Error(err)
|
||||
log.Error("service sync", "err", err)
|
||||
childCancel()
|
||||
}
|
||||
},
|
||||
OnStoppedLeading: func() {
|
||||
// we can do cleanup here
|
||||
log.Infof("(svc election) service [%s] leader lost: [%s]", service.Name, sm.config.NodeName)
|
||||
log.Info("leadership lost", "service", service.Name, "leader", sm.config.NodeName)
|
||||
if activeService[string(service.UID)] {
|
||||
if err := sm.deleteService(service.UID); err != nil {
|
||||
log.Error(err)
|
||||
log.Error("service deletion", "err", err)
|
||||
}
|
||||
}
|
||||
// Mark this service is inactive
|
||||
@@ -94,10 +95,10 @@ func (sm *Manager) StartServicesLeaderElection(ctx context.Context, service *v1.
|
||||
// I just got the lock
|
||||
return
|
||||
}
|
||||
log.Infof("(svc election) new leader elected: %s", identity)
|
||||
log.Info("new leader", "leader", identity)
|
||||
},
|
||||
},
|
||||
})
|
||||
log.Infof("(svc election) for service [%s] stopping", service.Name)
|
||||
log.Info("stopping leader election", "service", service.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/bgp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
@@ -26,7 +27,7 @@ import (
|
||||
// present
|
||||
func (sm *Manager) annotationsWatcher() error {
|
||||
// Use a restartable watcher, as this should help in the event of etcd or timeout issues
|
||||
log.Infof("Kube-Vip is waiting for annotation prefix [%s] to be present on this node", sm.config.Annotations)
|
||||
log.Info("Kube-Vip is waiting for annotation prefix to be present on this node", "prefix", sm.config.Annotations)
|
||||
|
||||
labelSelector := metav1.LabelSelector{MatchLabels: map[string]string{"kubernetes.io/hostname": sm.config.NodeName}}
|
||||
listOptions := metav1.ListOptions{
|
||||
@@ -54,7 +55,7 @@ func (sm *Manager) annotationsWatcher() error {
|
||||
|
||||
// We got an error with the annotations, falling back to the watch until
|
||||
// they're as needed
|
||||
log.Warn(err)
|
||||
log.Warn(err.Error())
|
||||
|
||||
rw, err := watchtools.NewRetryWatcher(node.ResourceVersion, &cache.ListWatch{
|
||||
WatchFunc: func(_ metav1.ListOptions) (watch.Interface, error) {
|
||||
@@ -94,7 +95,7 @@ func (sm *Manager) annotationsWatcher() error {
|
||||
|
||||
bgpConfig, bgpPeer, err := parseBgpAnnotations(sm.config.BGPConfig, node, sm.config.Annotations)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -108,7 +109,7 @@ func (sm *Manager) annotationsWatcher() error {
|
||||
return fmt.Errorf("unable to parse Kubernetes Node from Kubernetes watcher")
|
||||
}
|
||||
|
||||
log.Infof("Node [%s] has been deleted", node.Name)
|
||||
log.Info("Node has been deleted", "name", node.Name)
|
||||
|
||||
case watch.Bookmark:
|
||||
// Un-used
|
||||
@@ -124,12 +125,12 @@ func (sm *Manager) annotationsWatcher() error {
|
||||
}
|
||||
|
||||
status := statusErr.ErrStatus
|
||||
log.Errorf("%v", status)
|
||||
log.Error(status.String())
|
||||
default:
|
||||
}
|
||||
}
|
||||
close(exitFunction)
|
||||
log.Infoln("Exiting Annotations watcher")
|
||||
log.Info("Exiting Annotations watcher")
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/kubevip"
|
||||
log "github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
discoveryv1 "k8s.io/api/discovery/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -85,17 +86,17 @@ func (ep *endpointsProvider) getLocalEndpoints(id string, _ *kubevip.Config) ([]
|
||||
|
||||
for _, subset := range ep.endpoints.Subsets {
|
||||
for _, address := range subset.Addresses {
|
||||
log.Debugf("[%s] processing endpoint [%s]", ep.label, address.IP)
|
||||
log.Debug("processing endpoint", "label", ep.label, "ip", address.IP)
|
||||
|
||||
// 1. Compare the Nodename
|
||||
if address.NodeName != nil && id == *address.NodeName {
|
||||
log.Debugf("[%s] found local endpoint - address: %s, hostname: %s, node: %s", ep.label, address.IP, address.Hostname, *address.NodeName)
|
||||
log.Debug("found local endpoint", "label", ep.label, "ip", address.IP, "hostname", address.Hostname, "nodename", *address.NodeName)
|
||||
localEndpoints = append(localEndpoints, address.IP)
|
||||
continue
|
||||
}
|
||||
// 2. Compare the Hostname (only useful if address.NodeName is not available)
|
||||
if id == address.Hostname {
|
||||
log.Debugf("[%s] found local endpoint - address: %s, hostname: %s", ep.label, address.IP, address.Hostname)
|
||||
log.Debug("found local endpoint", "label", ep.label, "ip", address.IP, "hostname", address.Hostname)
|
||||
localEndpoints = append(localEndpoints, address.IP)
|
||||
continue
|
||||
}
|
||||
@@ -122,14 +123,14 @@ func (ep *endpointsProvider) updateServiceAnnotation(endpoint string, _ string,
|
||||
|
||||
_, err = sm.clientSet.CoreV1().Services(currentService.Namespace).Update(context.TODO(), currentServiceCopy, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("[%s] error updating Service Spec [%s] : %v", ep.getLabel(), currentServiceCopy.Name, err)
|
||||
log.Error("error updating Service Spec", "label", ep.getLabel(), "name", currentServiceCopy.Name, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if retryErr != nil {
|
||||
log.Errorf("[%s] failed to set Services: %v", ep.getLabel(), retryErr)
|
||||
log.Error("failed to set Services", "label", ep.getLabel(), "err", retryErr)
|
||||
return retryErr
|
||||
}
|
||||
return nil
|
||||
@@ -144,7 +145,7 @@ func (ep *endpointsProvider) getProtocol() string {
|
||||
}
|
||||
|
||||
func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Service, wg *sync.WaitGroup, provider epProvider) error {
|
||||
log.Infof("[%s] watching for service [%s] in namespace [%s]", provider.getLabel(), service.Name, service.Namespace)
|
||||
log.Info("watching", "provide", provider.getLabel(), "service name", service.Name, "namespace", service.Namespace)
|
||||
// Use a restartable watcher, as this should help in the event of etcd or timeout issues
|
||||
leaderContext, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
@@ -161,21 +162,21 @@ func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Ser
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Debugf("[%s] context cancelled", provider.getLabel())
|
||||
log.Debug("context cancelled", "provider", provider.getLabel())
|
||||
// Stop the retry watcher
|
||||
rw.Stop()
|
||||
// Cancel the context, which will in turn cancel the leadership
|
||||
cancel()
|
||||
return
|
||||
case <-sm.shutdownChan:
|
||||
log.Debugf("[%s] shutdown called", provider.getLabel())
|
||||
log.Debug("shutdown called", "provider", provider.getLabel())
|
||||
// Stop the retry watcher
|
||||
rw.Stop()
|
||||
// Cancel the context, which will in turn cancel the leadership
|
||||
cancel()
|
||||
return
|
||||
case <-exitFunction:
|
||||
log.Debugf("[%s] function ending", provider.getLabel())
|
||||
log.Debug("function ending", "provider", provider.getLabel())
|
||||
// Stop the retry watcher
|
||||
rw.Stop()
|
||||
// Cancel the context, which will in turn cancel the leadership
|
||||
@@ -244,11 +245,11 @@ func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Ser
|
||||
if sm.config.EnableRoutingTable {
|
||||
if err := sm.TeardownEgress(lastKnownGoodEndpoint, service.Spec.LoadBalancerIP,
|
||||
service.Namespace, service.Annotations); err != nil {
|
||||
log.Warnf("error removing redundant egress rules: %s", err.Error())
|
||||
log.Warn("removing redundant egress rules", "err", err)
|
||||
}
|
||||
}
|
||||
if leaderElectionActive && (sm.config.EnableServicesElection || sm.config.EnableLeaderElection) {
|
||||
log.Warnf("[%s] existing [%s] has been removed, restarting leaderElection", provider.getLabel(), lastKnownGoodEndpoint)
|
||||
log.Warn(" existing endpoint has been removed, restarting leaderElection", "provider", provider.getLabel(), "endpoint", lastKnownGoodEndpoint)
|
||||
// Stop the existing leaderElection
|
||||
cancel()
|
||||
// disable last leaderElection flag
|
||||
@@ -272,7 +273,7 @@ func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Ser
|
||||
leaderElectionActive = true
|
||||
err := sm.StartServicesLeaderElection(leaderContext, service, wg)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
leaderElectionActive = false
|
||||
} else {
|
||||
@@ -303,15 +304,15 @@ func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Ser
|
||||
return fmt.Errorf("[%s] error updating existing routes: %w", provider.getLabel(), err)
|
||||
}
|
||||
if isUpdated {
|
||||
log.Debugf("[%s] updated route: %s", provider.getLabel(), cluster.Network[i].IP())
|
||||
log.Debug("updated route", "provider", provider.getLabel(), "ip", cluster.Network[i].IP())
|
||||
}
|
||||
} else {
|
||||
// If other error occurs, return error
|
||||
return fmt.Errorf("[%s] error adding route: %s", provider.getLabel(), err.Error())
|
||||
}
|
||||
} else {
|
||||
log.Infof("[%s] added route: %s, service: %s/%s, interface: %s, table: %d",
|
||||
provider.getLabel(), cluster.Network[i].IP(), service.Namespace, service.Name, cluster.Network[i].Interface(), sm.config.RoutingTableID)
|
||||
log.Info("added route", "provider",
|
||||
provider.getLabel(), "ip", cluster.Network[i].IP(), "service name", service.Name, "namespace", service.Namespace, "interface", cluster.Network[i].Interface(), "tableID", sm.config.RoutingTableID)
|
||||
configuredLocalRoutes.Store(string(service.UID), true)
|
||||
leaderElectionActive = true
|
||||
}
|
||||
@@ -326,13 +327,13 @@ func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Ser
|
||||
for _, cluster := range instance.clusters {
|
||||
for i := range cluster.Network {
|
||||
address := fmt.Sprintf("%s/%s", cluster.Network[i].IP(), sm.config.VIPCIDR)
|
||||
log.Debugf("[%s] attempting to advertise BGP service: %s", provider.getLabel(), address)
|
||||
log.Debug("attempting to advertise BGP service", "provider", provider.getLabel(), "ip", address)
|
||||
err := sm.bgpServer.AddHost(address)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] error adding BGP host %s\n", err.Error(), provider.getLabel())
|
||||
log.Error("error adding BGP hos", "provider", provider.getLabel(), "err", err)
|
||||
} else {
|
||||
log.Infof("[%s] added BGP host: %s, service: %s/%s",
|
||||
provider.getLabel(), address, service.Namespace, service.Name)
|
||||
log.Info("added BGP host", "provider",
|
||||
provider.getLabel(), "ip", address, "service name", service.Name, "namespace", service.Namespace)
|
||||
configuredLocalRoutes.Store(string(service.UID), true)
|
||||
leaderElectionActive = true
|
||||
}
|
||||
@@ -359,10 +360,10 @@ func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Ser
|
||||
address := fmt.Sprintf("%s/%s", cluster.Network[i].IP(), sm.config.VIPCIDR)
|
||||
err := sm.bgpServer.DelHost(address)
|
||||
if err != nil {
|
||||
log.Errorf("[%s] error deleting BGP host%s: %s\n", provider.getLabel(), address, err.Error())
|
||||
log.Error("deleting BGP host", "provider", provider.getLabel(), "ip", address, "err", err)
|
||||
} else {
|
||||
log.Infof("[%s] deleted BGP host: %s, service: %s/%s",
|
||||
provider.getLabel(), address, service.Namespace, service.Name)
|
||||
log.Info("deleted BGP host", "provider",
|
||||
provider.getLabel(), "ip", address, "service name", service.Name, "namespace", service.Namespace)
|
||||
configuredLocalRoutes.Store(string(service.UID), false)
|
||||
leaderElectionActive = false
|
||||
}
|
||||
@@ -374,9 +375,9 @@ func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Ser
|
||||
|
||||
// If there are no local endpoints, and we had one then remove it and stop the leaderElection
|
||||
if lastKnownGoodEndpoint != "" {
|
||||
log.Warnf("[%s] existing [%s] has been removed, no remaining endpoints for leaderElection", provider.getLabel(), lastKnownGoodEndpoint)
|
||||
log.Warn("existing endpoint has been removed, no remaining endpoints for leaderElection", "provider", provider.getLabel(), "endpoint", lastKnownGoodEndpoint)
|
||||
if err := sm.TeardownEgress(lastKnownGoodEndpoint, service.Spec.LoadBalancerIP, service.Namespace, service.Annotations); err != nil {
|
||||
log.Errorf("error removing redundant egress rules: %s", err.Error())
|
||||
log.Error("error removing redundant egress rules", "err", err)
|
||||
}
|
||||
|
||||
lastKnownGoodEndpoint = "" // reset endpoint
|
||||
@@ -391,8 +392,8 @@ func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Ser
|
||||
service.Annotations[activeEndpointAnnotation] = lastKnownGoodEndpoint
|
||||
}
|
||||
|
||||
log.Debugf("[%s watcher] service %s/%s: local endpoint(s) [%d], known good [%s], active election [%t]",
|
||||
provider.getLabel(), service.Namespace, service.Name, len(endpoints), lastKnownGoodEndpoint, leaderElectionActive)
|
||||
log.Debug("watcher", "provider",
|
||||
provider.getLabel(), "service name", service.Name, "namespace", service.Namespace, "endpoints", len(endpoints), "last endpoint", lastKnownGoodEndpoint, "active leader election", leaderElectionActive)
|
||||
|
||||
case watch.Deleted:
|
||||
// When no-leader-elecition mode
|
||||
@@ -426,17 +427,17 @@ func (sm *Manager) watchEndpoint(ctx context.Context, id string, service *v1.Ser
|
||||
|
||||
// Close the goroutine that will end the retry watcher, then exit the endpoint watcher function
|
||||
close(exitFunction)
|
||||
log.Infof("[%s] deleted stopping watching for [%s] in namespace [%s]", provider.getLabel(), service.Name, service.Namespace)
|
||||
log.Info("stopping watching", "provider", provider.getLabel(), "service name", service.Name, "namespace", service.Namespace)
|
||||
|
||||
return nil
|
||||
case watch.Error:
|
||||
errObject := apierrors.FromObject(event.Object)
|
||||
statusErr, _ := errObject.(*apierrors.StatusError)
|
||||
log.Errorf("[%s] -> %v", provider.getLabel(), statusErr)
|
||||
log.Error("watch error", "provider", provider.getLabel(), "err", statusErr)
|
||||
}
|
||||
}
|
||||
close(exitFunction)
|
||||
log.Infof("[%s] stopping watching for [%s] in namespace [%s]", provider.getLabel(), service.Name, service.Namespace)
|
||||
log.Info("stopping watching", "provider", provider.getLabel(), "service name", service.Name, "namespace", service.Namespace)
|
||||
return nil //nolint:govet
|
||||
}
|
||||
|
||||
@@ -450,11 +451,11 @@ func (sm *Manager) clearRoutes(service *v1.Service) []error {
|
||||
if sm.countRouteReferences(route) <= 1 {
|
||||
err := cluster.Network[i].DeleteRoute()
|
||||
if err != nil && !errors.Is(err, syscall.ESRCH) {
|
||||
log.Errorf("failed to delete route for %s: %s", cluster.Network[i].IP(), err.Error())
|
||||
log.Error("failed to delete route", "ip", cluster.Network[i].IP(), "err", err)
|
||||
errs = append(errs, err)
|
||||
}
|
||||
log.Debugf("deleted route: %s, service: %s/%s, interface: %s, table: %d",
|
||||
cluster.Network[i].IP(), service.Namespace, service.Name, cluster.Network[i].Interface(), sm.config.RoutingTableID)
|
||||
log.Debug("deleted route", "ip",
|
||||
cluster.Network[i].IP(), "service name", service.Name, "namespace", service.Namespace, "interface", cluster.Network[i].Interface(), "tableID", sm.config.RoutingTableID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -469,10 +470,10 @@ func (sm *Manager) clearBGPHosts(service *v1.Service) {
|
||||
address := fmt.Sprintf("%s/%s", cluster.Network[i].IP(), sm.config.VIPCIDR)
|
||||
err := sm.bgpServer.DelHost(address)
|
||||
if err != nil {
|
||||
log.Errorf("[endpoint] error deleting BGP host %s\n", err.Error())
|
||||
log.Error("[endpoint] error deleting BGP host", "err", err)
|
||||
} else {
|
||||
log.Debugf("[endpoint] deleted BGP host: %s, service: %s/%s",
|
||||
address, service.Namespace, service.Name)
|
||||
log.Debug("[endpoint] deleted BGP host", "ip",
|
||||
address, "service name", service.Name, "namespace", service.Namespace)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/kube-vip/kube-vip/pkg/kubevip"
|
||||
log "github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
discoveryv1 "k8s.io/api/discovery/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -67,14 +68,14 @@ func (ep *endpointslicesProvider) getLocalEndpoints(id string, _ *kubevip.Config
|
||||
continue
|
||||
}
|
||||
for _, address := range endpoint.Addresses {
|
||||
log.Debugf("[%s] processing endpoint [%s]", ep.label, address)
|
||||
log.Debug("processing endpoint", "provider", ep.label, "ip", address)
|
||||
|
||||
// 1. Compare the Nodename
|
||||
if endpoint.NodeName != nil && id == *endpoint.NodeName {
|
||||
if endpoint.Hostname != nil {
|
||||
log.Debugf("[%s] found endpoint - address: %s, hostname: %s, node: %s", ep.label, address, *endpoint.Hostname, *endpoint.NodeName)
|
||||
log.Debug("found endpoint", "provider", ep.label, "ip", address, "hostname", *endpoint.Hostname, "nodename", *endpoint.NodeName)
|
||||
} else {
|
||||
log.Debugf("[%s] found endpoint - address: %s, node: %s", ep.label, address, *endpoint.NodeName)
|
||||
log.Debug("found endpoint", "provider", ep.label, "ip", address, "nodename", *endpoint.NodeName)
|
||||
}
|
||||
localEndpoints = append(localEndpoints, address)
|
||||
continue
|
||||
@@ -82,7 +83,7 @@ func (ep *endpointslicesProvider) getLocalEndpoints(id string, _ *kubevip.Config
|
||||
|
||||
// 2. Compare the Hostname (only useful if endpoint.NodeName is not available)
|
||||
if endpoint.Hostname != nil && id == *endpoint.Hostname {
|
||||
log.Debugf("[%s] found endpoint - address: %s, hostname: %s", ep.label, address, *endpoint.Hostname)
|
||||
log.Debug("found endpoint", "provider", ep.label, "ip", address, "hostname", *endpoint.Hostname)
|
||||
localEndpoints = append(localEndpoints, address)
|
||||
}
|
||||
}
|
||||
@@ -109,14 +110,14 @@ func (ep *endpointslicesProvider) updateServiceAnnotation(endpoint, endpointIPv6
|
||||
|
||||
_, err = sm.clientSet.CoreV1().Services(currentService.Namespace).Update(context.TODO(), currentServiceCopy, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("[%s] error updating Service Spec [%s] : %v", ep.label, currentServiceCopy.Name, err)
|
||||
log.Error("error updating Service Spec", "provider", ep.label, "service name", currentServiceCopy.Name, "err", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if retryErr != nil {
|
||||
log.Errorf("[%s] failed to set Services: %v", ep.label, retryErr)
|
||||
log.Error("failed to set Services", "provider", ep.label, "err", retryErr)
|
||||
return retryErr
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -6,10 +6,11 @@ import (
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/kube-vip/kube-vip/pkg/vip"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -57,16 +58,16 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
// clean up traffic mirror related config
|
||||
err := sm.stopTrafficMirroringIfEnabled()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Error("Stopping traffic mirroring", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
if sm.config.ServiceNamespace == "" {
|
||||
// v1.NamespaceAll is actually "", but we'll stay with the const in case things change upstream
|
||||
sm.config.ServiceNamespace = v1.NamespaceAll
|
||||
log.Infof("(svcs) starting services watcher for all namespaces")
|
||||
log.Info("(svcs) starting services watcher for all namespaces")
|
||||
} else {
|
||||
log.Infof("(svcs) starting services watcher for services in namespace [%s]", sm.config.ServiceNamespace)
|
||||
log.Info("(svcs) starting services watcher", "namespace", sm.config.ServiceNamespace)
|
||||
}
|
||||
|
||||
// Use a restartable watcher, as this should help in the event of etcd or timeout issues
|
||||
@@ -115,7 +116,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
|
||||
// Check if we ignore this service
|
||||
if svc.Annotations["kube-vip.io/ignore"] == "true" {
|
||||
log.Infof("(svcs) [%s] has an ignore annotation for kube-vip", svc.Name)
|
||||
log.Info("ignore annotation for kube-vip", "service name", svc.Name)
|
||||
break
|
||||
}
|
||||
|
||||
@@ -143,10 +144,10 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
// log.Debugf("(svcs) Retreiving local addresses, to ensure that this modified address doesn't exist: %s", addr)
|
||||
f, err := vip.GarbageCollect(sm.config.Interface, addr)
|
||||
if err != nil {
|
||||
log.Errorf("(svcs) cleaning existing address error: [%s]", err.Error())
|
||||
log.Error("(svcs) cleaning existing address error", "err", err)
|
||||
}
|
||||
if f {
|
||||
log.Warnf("(svcs) already found existing address [%s] on adapter [%s]", addr, sm.config.Interface)
|
||||
log.Warn("(svcs) already found existing config", "address", addr, "adapter", sm.config.Interface)
|
||||
}
|
||||
}
|
||||
// This service has been modified, but it was also active..
|
||||
@@ -167,7 +168,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
}
|
||||
err = sm.deleteService(svc.UID)
|
||||
if err != nil {
|
||||
log.Errorf("(svc) unable to remove existing [%s]", svc.UID)
|
||||
log.Error("(svc) unable to remove", "service", svc.UID)
|
||||
}
|
||||
}
|
||||
// in theory this should never fail
|
||||
@@ -184,7 +185,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
//
|
||||
|
||||
if !activeService[string(svc.UID)] {
|
||||
log.Debugf("(svcs) [%s] has been added/modified with addresses [%s]", svc.Name, fetchServiceAddresses(svc))
|
||||
log.Debug("(svcs) has been added/modified with addresses", "service name", svc.Name, "ip", fetchServiceAddresses(svc))
|
||||
|
||||
wg.Add(1)
|
||||
activeServiceLoadBalancer[string(svc.UID)], activeServiceLoadBalancerCancel[string(svc.UID)] = context.WithCancel(ctx)
|
||||
@@ -210,7 +211,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
provider = &endpointslicesProvider{label: "endpointslices"}
|
||||
}
|
||||
if err = sm.watchEndpoint(activeServiceLoadBalancer[string(svc.UID)], sm.config.NodeName, svc, &wg, provider); err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
@@ -221,7 +222,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
go func() {
|
||||
err = serviceFunc(activeServiceLoadBalancer[string(svc.UID)], svc, &wg)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
@@ -241,7 +242,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
provider = &endpointslicesProvider{label: "endpointslices"}
|
||||
}
|
||||
if err = sm.watchEndpoint(activeServiceLoadBalancer[string(svc.UID)], sm.config.NodeName, svc, &wg, provider); err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
@@ -251,7 +252,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
go func() {
|
||||
err = serviceFunc(activeServiceLoadBalancer[string(svc.UID)], svc, &wg)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
@@ -263,14 +264,14 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
for {
|
||||
select {
|
||||
case <-activeServiceLoadBalancer[string(svc.UID)].Done():
|
||||
log.Warnf("(svcs) restartable service watcher ending for [%s]", svc.UID)
|
||||
log.Warn("(svcs) restartable service watcher ending", "uid", svc.UID)
|
||||
return
|
||||
default:
|
||||
log.Infof("(svcs) restartable service watcher starting for [%s]", svc.UID)
|
||||
log.Info("(svcs) restartable service watcher starting", "uid", svc.UID)
|
||||
err = serviceFunc(activeServiceLoadBalancer[string(svc.UID)], svc, &wg)
|
||||
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +283,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
wg.Add(1)
|
||||
err = serviceFunc(activeServiceLoadBalancer[string(svc.UID)], svc, &wg)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
@@ -302,7 +303,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
|
||||
// We can ignore this service
|
||||
if svc.Annotations["kube-vip.io/ignore"] == "true" {
|
||||
log.Infof("(svcs) [%s] has an ignore annotation for kube-vip", svc.Name)
|
||||
log.Info("(svcs)ignore annotation for kube-vip", "service name", svc.Name)
|
||||
break
|
||||
}
|
||||
|
||||
@@ -321,7 +322,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
// If this is an active service then and additional leaderElection will handle stopping
|
||||
err = sm.deleteService(svc.UID)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
log.Error(err.Error())
|
||||
}
|
||||
|
||||
// Calls the cancel function of the context
|
||||
@@ -339,7 +340,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
vipCidr := fmt.Sprintf("%s/%s", vip.VIP, vip.VIPCIDR)
|
||||
err = sm.bgpServer.DelHost(vipCidr)
|
||||
if err != nil {
|
||||
log.Errorf("error deleting host %s: %s", vipCidr, err.Error())
|
||||
log.Error("error deleting host", "ip", vipCidr, "err", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -347,7 +348,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("(svcs) [%s/%s] has been deleted", svc.Namespace, svc.Name)
|
||||
log.Info("(svcs) deleted", "service name", svc.Name, "namespace", svc.Namespace)
|
||||
case watch.Bookmark:
|
||||
// Un-used
|
||||
case watch.Error:
|
||||
@@ -361,7 +362,7 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
}
|
||||
|
||||
status := statusErr.ErrStatus
|
||||
log.Errorf("services -> %v", status)
|
||||
log.Error("services", "err", status)
|
||||
default:
|
||||
}
|
||||
}
|
||||
@@ -372,18 +373,18 @@ func (sm *Manager) servicesWatcher(ctx context.Context, serviceFunc func(context
|
||||
|
||||
func (sm *Manager) lbClassFilterLegacy(svc *v1.Service) bool {
|
||||
if svc == nil {
|
||||
log.Infof("(svcs) service is nil, ignoring")
|
||||
log.Info("(svcs) service is nil, ignoring")
|
||||
return true
|
||||
}
|
||||
if svc.Spec.LoadBalancerClass != nil {
|
||||
// if this isn't nil then it has been configured, check if it the kube-vip loadBalancer class
|
||||
if *svc.Spec.LoadBalancerClass != sm.config.LoadBalancerClassName {
|
||||
log.Infof("(svcs) [%s] specified the loadBalancer class [%s], ignoring", svc.Name, *svc.Spec.LoadBalancerClass)
|
||||
log.Info("(svcs) specified the wrong loadBalancer class", "service name", svc.Name, "lbClass", *svc.Spec.LoadBalancerClass)
|
||||
return true
|
||||
}
|
||||
} else if sm.config.LoadBalancerClassOnly {
|
||||
// if kube-vip is configured to only recognize services with kube-vip's lb class, then ignore the services without any lb class
|
||||
log.Infof("(svcs) kube-vip configured to only recognize services with kube-vip's lb class but the service [%s] didn't specify any loadBalancer class, ignoring", svc.Name)
|
||||
log.Info("(svcs) kube-vip configured to only recognize services with kube-vip's lb class but the service didn't specify any loadBalancer class, ignoring", "service name", svc.Name)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -391,18 +392,18 @@ func (sm *Manager) lbClassFilterLegacy(svc *v1.Service) bool {
|
||||
|
||||
func (sm *Manager) lbClassFilter(svc *v1.Service) bool {
|
||||
if svc == nil {
|
||||
log.Infof("(svcs) service is nil, ignoring")
|
||||
log.Info("(svcs) service is nil, ignoring")
|
||||
return true
|
||||
}
|
||||
if svc.Spec.LoadBalancerClass == nil && sm.config.LoadBalancerClassName != "" {
|
||||
log.Infof("(svcs) [%s] specified no loadBalancer class, expected [%s], ignoring", svc.Name, sm.config.LoadBalancerClassName)
|
||||
log.Info("(svcs) no loadBalancer class, ignoring", "service name", svc.Name, "expected lbClass", sm.config.LoadBalancerClassName)
|
||||
return true
|
||||
}
|
||||
if svc.Spec.LoadBalancerClass == nil && sm.config.LoadBalancerClassName == "" {
|
||||
return false
|
||||
}
|
||||
if *svc.Spec.LoadBalancerClass != sm.config.LoadBalancerClassName {
|
||||
log.Infof("(svcs) [%s] specified loadBalancer class [%s], expected [%s], ignoring", svc.Name, *svc.Spec.LoadBalancerClass, sm.config.LoadBalancerClassName)
|
||||
log.Info("(svcs) specified wrong loadBalancer class, ignoring", "service name", svc.Name, "wrong lbClass", *svc.Spec.LoadBalancerClass, "expected lbClass", sm.config.LoadBalancerClassName)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -4,7 +4,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
|
||||
"github.com/vishvananda/netlink"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
@@ -27,16 +28,15 @@ func MirrorTrafficFromNIC(fromNICName, toNICName string) error {
|
||||
return fmt.Errorf("failed to find nic %s: %v", toNICName, err)
|
||||
}
|
||||
toNICID := toNIC.Attrs().Index
|
||||
log.Debug(fmt.Sprintf("interface %s has index %d", fromNICName, fromNICID))
|
||||
log.Debug(fmt.Sprintf("interface %s has index %d", toNICName, toNICID))
|
||||
|
||||
log.Debugf("interface %s has index %d", fromNICName, fromNICID)
|
||||
log.Debugf("interface %s has index %d", toNICName, toNICID)
|
||||
|
||||
log.Debugf("clean up interface %s first in case it has stale qdsic", fromNICName)
|
||||
log.Debug(fmt.Sprintf("clean up interface %s first in case it has stale qdsic", fromNICName))
|
||||
if err := CleanupQDSICFromNIC(fromNICName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("step 1: tc qdisc add dev %s ingress", fromNICName)
|
||||
log.Debug(fmt.Sprintf("step 1: tc qdisc add dev %s ingress", fromNICName))
|
||||
qdisc1 := &netlink.Ingress{
|
||||
QdiscAttrs: netlink.QdiscAttrs{
|
||||
LinkIndex: fromNICID,
|
||||
@@ -48,7 +48,7 @@ func MirrorTrafficFromNIC(fromNICName, toNICName string) error {
|
||||
return fmt.Errorf("failed to add qdisc for interface %s: %v", fromNICName, err)
|
||||
}
|
||||
|
||||
log.Debugf("step 2: tc filter add dev %s parent ffff: protocol ip u32 match u8 0 0 action mirred egress mirror dev %s", fromNICName, toNICName)
|
||||
log.Debug(fmt.Sprintf("step 2: tc filter add dev %s parent ffff: protocol ip u32 match u8 0 0 action mirred egress mirror dev %s", fromNICName, toNICName))
|
||||
// add a filter to mirror traffic from index1 to index2
|
||||
filter1 := &netlink.U32{
|
||||
FilterAttrs: netlink.FilterAttrs{
|
||||
@@ -71,7 +71,7 @@ func MirrorTrafficFromNIC(fromNICName, toNICName string) error {
|
||||
return fmt.Errorf("failed to add filter for interface %s: %v", fromNICName, err)
|
||||
}
|
||||
|
||||
log.Debugf("step 3: tc qdisc add dev %s ingress", fromNICName)
|
||||
log.Debug(fmt.Sprintf("step 3: tc qdisc add dev %s ingress", fromNICName))
|
||||
qdiscTemp := netlink.NewPrio(netlink.QdiscAttrs{
|
||||
LinkIndex: fromNICID,
|
||||
Parent: netlink.HANDLE_ROOT,
|
||||
@@ -90,7 +90,7 @@ func MirrorTrafficFromNIC(fromNICName, toNICName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("step 4: tc filter add dev %s parent %d: protocol ip u32 match u8 0 0 action mirred egress mirror dev %s", fromNICName, qdiscID, toNICName)
|
||||
log.Debug(fmt.Sprintf("step 4: tc filter add dev %s parent %d: protocol ip u32 match u8 0 0 action mirred egress mirror dev %s", fromNICName, qdiscID, toNICName))
|
||||
|
||||
filter2 := &netlink.U32{
|
||||
FilterAttrs: netlink.FilterAttrs{
|
||||
@@ -113,7 +113,7 @@ func MirrorTrafficFromNIC(fromNICName, toNICName string) error {
|
||||
return fmt.Errorf("failed to add filter for interface %s: %v", fromNICName, err)
|
||||
}
|
||||
|
||||
log.Infof("traffic mirroring has been set up from interface %s to interface %s", toNICName, fromNICName)
|
||||
log.Info("traffic mirroring has been set up", "src", toNICName, "dst", fromNICName)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ func CleanupQDSICFromNIC(nicName string) error {
|
||||
}
|
||||
nicID := toNIC.Attrs().Index
|
||||
|
||||
log.Debugf("interface %s has index %d", nicName, nicID)
|
||||
log.Debug(fmt.Sprintf("interface %s has index %d", nicName, nicID))
|
||||
|
||||
log.Debug("step 1: delete ingress qdisc")
|
||||
if err := tryCleanupQdiscByType(nicID, nicName, "ingress"); err != nil {
|
||||
@@ -138,7 +138,7 @@ func CleanupQDSICFromNIC(nicName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("finished cleaning up all qdisc config on interface %s", nicName)
|
||||
log.Info("finished cleaning up all qdisc config", "interface", nicName)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ func getQdiscFromInterfaceByType(nicID int, nicName string, qType string) (uint3
|
||||
return q.Attrs().Handle, nil
|
||||
}
|
||||
}
|
||||
log.Errorf("no qdisc under interface %s is %s type", nicName, qType)
|
||||
log.Error("no qdisc", "interface", nicName, "is of type", qType)
|
||||
return 0, errQdiscNotFound
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ func tryCleanupQdiscByType(nicID int, nicName, qType string) error {
|
||||
_, err := getQdiscFromInterfaceByType(nicID, nicName, qType)
|
||||
if err != nil {
|
||||
if err == errQdiscNotFound {
|
||||
log.Debugf("%s type qdisc doesn't exist on interface %s, skip deleting", qType, nicName)
|
||||
log.Debug(fmt.Sprintf("%s type qdisc doesn't exist on interface %s, skip deleting", qType, nicName))
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
||||
@@ -4,9 +4,10 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/huin/goupnp"
|
||||
"github.com/huin/goupnp/dcps/internetgateway2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
@@ -47,7 +48,7 @@ func GetGatewayClients(ctx context.Context) []Gateway {
|
||||
if wanipv6clients, err := internetgateway2.NewWANIPv6FirewallControl1ClientsByURLCtx(ctx, gatewayURL); err == nil {
|
||||
gatewayClients[i].WANIPv6FirewallControlClient = wanipv6clients[0]
|
||||
} else {
|
||||
log.Warnf("[UPNP] Unable to find WANIPv6FirewallControl1Clients for Gateway %s [%s]", gatewayURL, err.Error())
|
||||
log.Warn("[UPNP] Unable to find WANIPv6FirewallControl1Clients", "Gateway", gatewayURL, "err", err)
|
||||
}
|
||||
}
|
||||
return gatewayClients
|
||||
@@ -84,7 +85,7 @@ func GetConnectionClients(ctx context.Context) []ConnectionClient {
|
||||
var routers []ConnectionClient
|
||||
|
||||
if err := tasks.Wait(); err != nil {
|
||||
log.Errorf("[UPNP] Could not finish querying UPNP connection clients [%s]", err.Error())
|
||||
log.Error("[UPNP] Could not finish querying UPNP connection clients", "err", err.Error())
|
||||
return routers
|
||||
}
|
||||
|
||||
@@ -92,7 +93,7 @@ func GetConnectionClients(ctx context.Context) []ConnectionClient {
|
||||
errors = append(errors, ppp1Error...)
|
||||
|
||||
for _, e := range errors {
|
||||
log.Warnf("[UPNP] UPNP Gateway responded with an error while querying WAN Connection Client [%s]", e.Error())
|
||||
log.Warn("[UPNP] UPNP Gateway responded with an error while querying WAN Connection Client", "err", e)
|
||||
}
|
||||
|
||||
for _, c := range ip1Clients {
|
||||
|
||||
@@ -8,8 +8,9 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
"github.com/vishvananda/netlink/nl"
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -343,7 +344,7 @@ func (configurator *network) addIptablesRulesToLimitTrafficPorts() error {
|
||||
if err := insertCommonIPTablesRules(ipt, vip, comment); err != nil {
|
||||
return fmt.Errorf("could not add common iptables rules: %w", err)
|
||||
}
|
||||
log.Debugf("add iptables rules, vip: %s, ports: %+v", vip, configurator.ports)
|
||||
log.Debug("add iptables rules", "vip", vip, "ports", configurator.ports)
|
||||
if err := configurator.insertIPTablesRulesForServicePorts(ipt, vip, comment); err != nil {
|
||||
return fmt.Errorf("could not add iptables rules for service ports: %v", err)
|
||||
}
|
||||
@@ -448,7 +449,7 @@ func (configurator *network) removeIptablesRuleToLimitTrafficPorts() error {
|
||||
return fmt.Errorf("could not delete common iptables rules: %w", err)
|
||||
}
|
||||
|
||||
log.Debugf("remove iptables rules, vip: %s, ports: %+v", vip, configurator.ports)
|
||||
log.Debug("remove iptables rules", "vip", vip, "ports", configurator.ports)
|
||||
for _, port := range configurator.ports {
|
||||
// iptables -D INPUT -d <VIP> -p <protocol> --dport <port> -j ACCEPT
|
||||
if err := ipt.DeleteIfExists(iptables.TableFilter, iptables.ChainInput, "-d", vip, "-p", string(port.Protocol),
|
||||
|
||||
@@ -5,8 +5,9 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// DDNSManager will start a dhclient to retrieve and keep the lease for the IP
|
||||
@@ -55,7 +56,7 @@ func (ddns *ddnsManager) Start() (string, error) {
|
||||
client.Stop()
|
||||
return "", errors.New("failed to get IP from dhcp for ddns in 1 minutes")
|
||||
case ip = <-client.IPChannel():
|
||||
log.Info("got ip from dhcp: ", ip)
|
||||
log.Info("got address from dhcp", "ip", ip)
|
||||
}
|
||||
|
||||
// lease.FixedAddress.String() could return <nil>
|
||||
@@ -74,7 +75,7 @@ func (ddns *ddnsManager) Start() (string, error) {
|
||||
client.Stop()
|
||||
return
|
||||
case ip := <-client.IPChannel():
|
||||
log.Info("got ip from dhcp: ", ip)
|
||||
log.Info("got address from dhcp", "ip", ip)
|
||||
}
|
||||
}
|
||||
}(ddns.ctx)
|
||||
|
||||
@@ -8,10 +8,11 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||
"github.com/insomniacslk/dhcp/dhcpv4/nclient4"
|
||||
"github.com/jpillora/backoff"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const dhcpClientPort = "68"
|
||||
@@ -129,7 +130,7 @@ func (c *DHCPClient) Start() {
|
||||
// Set up two ticker to renew/rebind regularly
|
||||
t1Timeout := c.lease.ACK.IPAddressLeaseTime(defaultDHCPRenew) / 2
|
||||
t2Timeout := (c.lease.ACK.IPAddressLeaseTime(defaultDHCPRenew) / 8) * 7
|
||||
log.Debugf("t1 %v t2 %v", t1Timeout, t2Timeout)
|
||||
log.Debug("dhcp timeouts", "timeout1", t1Timeout, "timeoute2", t2Timeout)
|
||||
t1, t2 := time.NewTicker(t1Timeout), time.NewTicker(t2Timeout)
|
||||
|
||||
for {
|
||||
@@ -143,25 +144,25 @@ func (c *DHCPClient) Start() {
|
||||
lease, err := c.renew()
|
||||
if err == nil {
|
||||
c.lease = lease
|
||||
log.Infof("renew, lease: %+v", lease)
|
||||
log.Info("renew", "lease", lease)
|
||||
t2.Reset(t2Timeout)
|
||||
} else {
|
||||
log.Errorf("renew failed, error: %s", err.Error())
|
||||
log.Error("renew failed", "err", err)
|
||||
}
|
||||
case <-t2.C:
|
||||
// rebind is just like a request, but forcing to provide a new IP address
|
||||
lease, err := c.request(true)
|
||||
if err == nil {
|
||||
c.lease = lease
|
||||
log.Infof("rebind, lease: %+v", lease)
|
||||
log.Info("rebind", "lease", lease)
|
||||
} else {
|
||||
if _, ok := err.(*nclient4.ErrNak); !ok {
|
||||
t1.Stop()
|
||||
t2.Stop()
|
||||
log.Errorf("rebind failed, error: %s", err.Error())
|
||||
log.Error("rebind failed", "err", err)
|
||||
return
|
||||
}
|
||||
log.Warnf("ip %s may have changed: %s", c.lease.ACK.YourIPAddr, err.Error())
|
||||
log.Warn("ip may have changed", "ip", c.lease.ACK.YourIPAddr, "err", err)
|
||||
c.initRebootFlag = false
|
||||
c.lease = c.requestWithBackoff()
|
||||
}
|
||||
@@ -171,9 +172,9 @@ func (c *DHCPClient) Start() {
|
||||
case <-c.stopChan:
|
||||
// release is a unicast request of the IP release.
|
||||
if err := c.release(); err != nil {
|
||||
log.Errorf("release lease failed, error: %s, lease: %+v", err.Error(), c.lease)
|
||||
log.Error("release lease failed", "lease", lease, "err", err)
|
||||
} else {
|
||||
log.Infof("release, lease: %+v", c.lease)
|
||||
log.Info("release", "lease", lease)
|
||||
}
|
||||
t1.Stop()
|
||||
t2.Stop()
|
||||
@@ -205,18 +206,18 @@ func (c *DHCPClient) requestWithBackoff() *nclient4.Lease {
|
||||
var err error
|
||||
|
||||
for {
|
||||
log.Debugf("trying to get a new IP, attempt %f", backoff.Attempt())
|
||||
log.Debug("trying to get a new IP", "attempt", backoff.Attempt())
|
||||
lease, err = c.request(false)
|
||||
if err != nil {
|
||||
dur := backoff.Duration()
|
||||
if backoff.Attempt() > maxBackoffAttempts-1 {
|
||||
errMsg := fmt.Errorf("failed to get an IP address after %d attempts, error %s, giving up", maxBackoffAttempts, err.Error())
|
||||
log.Error(errMsg)
|
||||
log.Error(errMsg.Error())
|
||||
c.errorChan <- errMsg
|
||||
c.Stop()
|
||||
return nil
|
||||
}
|
||||
log.Errorf("request failed, error: %s (waiting %v)", err.Error(), dur)
|
||||
log.Error("request failed", "err", err.Error(), "waiting", dur)
|
||||
time.Sleep(dur)
|
||||
continue
|
||||
}
|
||||
@@ -225,7 +226,7 @@ func (c *DHCPClient) requestWithBackoff() *nclient4.Lease {
|
||||
}
|
||||
|
||||
if c.ipChan != nil {
|
||||
log.Debugf("using channel")
|
||||
log.Debug("using channel")
|
||||
c.ipChan <- lease.ACK.YourIPAddr.String()
|
||||
}
|
||||
|
||||
@@ -251,13 +252,13 @@ func (c *DHCPClient) request(rebind bool) (*nclient4.Lease, error) {
|
||||
|
||||
// if initRebootFlag is set, this means we have an IP already set on c.requestedIP that should be used
|
||||
if c.initRebootFlag {
|
||||
log.Debugf("init-reboot ip %s", c.requestedIP)
|
||||
log.Debug("init-reboot", "ip", c.requestedIP)
|
||||
modifiers = append(modifiers, dhcpv4.WithOption(dhcpv4.OptRequestedIPAddress(c.requestedIP)))
|
||||
}
|
||||
|
||||
// if this is a rebind, then the IP we should set is the one that already exists in lease
|
||||
if rebind {
|
||||
log.Debugf("rebinding ip %s", c.lease.ACK.YourIPAddr)
|
||||
log.Debug("rebinding", "ip", c.lease.ACK.YourIPAddr)
|
||||
modifiers = append(modifiers, dhcpv4.WithOption(dhcpv4.OptRequestedIPAddress(c.lease.ACK.YourIPAddr)))
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
)
|
||||
|
||||
// IPUpdater is the interface to plug dns updaters
|
||||
@@ -29,7 +29,7 @@ func (d *ipUpdater) Run(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
log.Infof("stop ipUpdater")
|
||||
log.Info("stop ipUpdater")
|
||||
return
|
||||
default:
|
||||
mode := "ipv4"
|
||||
@@ -39,18 +39,18 @@ func (d *ipUpdater) Run(ctx context.Context) {
|
||||
|
||||
ip, err := LookupHost(d.vip.DNSName(), mode)
|
||||
if err != nil {
|
||||
log.Warnf("cannot lookup %s: %v", d.vip.DNSName(), err)
|
||||
log.Warn("cannot lookup", "name", d.vip.DNSName(), "err", err)
|
||||
// fallback to renewing the existing IP
|
||||
ip = []string{d.vip.IP()}
|
||||
}
|
||||
|
||||
log.Infof("setting %s as an IP", ip)
|
||||
log.Info("setting IP", "address", ip)
|
||||
if err := d.vip.SetIP(ip[0]); err != nil {
|
||||
log.Errorf("setting %s as an IP: %v", ip, err)
|
||||
log.Error("setting IP", "address", ip, "err", err)
|
||||
}
|
||||
|
||||
if err := d.vip.AddIP(false); err != nil {
|
||||
log.Errorf("error adding virtual IP: %v", err)
|
||||
log.Error("error adding virtual IP", "err", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
iptables "github.com/kube-vip/kube-vip/pkg/iptables"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
ct "github.com/florianl/go-conntrack"
|
||||
)
|
||||
@@ -39,7 +40,7 @@ func CreateIptablesClient(nftables bool, namespace string, protocol iptables.Pro
|
||||
if protocol == iptables.ProtocolIPv6 {
|
||||
proto = "IPv6"
|
||||
}
|
||||
log.Infof("[egress] Creating an iptables client, nftables mode [%t], protocol [%s]", nftables, proto)
|
||||
log.Info("[egress] Creating an iptables client", "nftables", nftables, "protocol", proto)
|
||||
e := new(Egress)
|
||||
var err error
|
||||
|
||||
@@ -56,7 +57,7 @@ func CreateIptablesClient(nftables bool, namespace string, protocol iptables.Pro
|
||||
}
|
||||
|
||||
func (e *Egress) CheckMangleChain(name string) (bool, error) {
|
||||
log.Infof("[egress] Checking for Chain [%s]", name)
|
||||
log.Info("[egress] chain exists", "name", name)
|
||||
return e.ipTablesClient.ChainExists("mangle", name)
|
||||
}
|
||||
|
||||
@@ -73,7 +74,7 @@ func (e *Egress) DeleteMangleReturnForNetwork(name, network string) error {
|
||||
}
|
||||
|
||||
func (e *Egress) DeleteMangleMarking(podIP, name string) error {
|
||||
log.Infof("[egress] Stopping marking packets on network [%s]", podIP)
|
||||
log.Info("[egress] Stopping marking packets on network", "podIP", podIP)
|
||||
|
||||
exists, _ := e.ipTablesClient.Exists("mangle", name, "-s", podIP, "-j", "MARK", "--set-mark", "64/64", "-m", "comment", "--comment", e.comment)
|
||||
|
||||
@@ -84,7 +85,7 @@ func (e *Egress) DeleteMangleMarking(podIP, name string) error {
|
||||
}
|
||||
|
||||
func (e *Egress) DeleteMangleMarkingForNetwork(podIP, name, network string) error {
|
||||
log.Infof("[egress] Stopping marking packets from [%s] to [%s]", podIP, network)
|
||||
log.Info("[egress] Stopping marking packets", "podIP", podIP, "network", network)
|
||||
|
||||
// exists, _ := e.ipTablesClient.Exists("mangle", name, "-s", podIP, "-d", network, "-j", "MARK", "--set-mark", "64/64", "-m", "comment", "--comment", e.comment)
|
||||
|
||||
@@ -95,7 +96,7 @@ func (e *Egress) DeleteMangleMarkingForNetwork(podIP, name, network string) erro
|
||||
}
|
||||
|
||||
func (e *Egress) DeleteSourceNat(podIP, vip string) error {
|
||||
log.Infof("[egress] Removing source nat from [%s] => [%s]", podIP, vip)
|
||||
log.Info("[egress] Removing source nat", "podIP", podIP, "vip", vip)
|
||||
|
||||
exists, _ := e.ipTablesClient.Exists("nat", "POSTROUTING", "-s", podIP+"/32", "-m", "mark", "--mark", "64/64", "-j", "SNAT", "--to-source", vip, "-m", "comment", "--comment", e.comment)
|
||||
|
||||
@@ -106,7 +107,7 @@ func (e *Egress) DeleteSourceNat(podIP, vip string) error {
|
||||
}
|
||||
|
||||
func (e *Egress) DeleteSourceNatForDestinationPort(podIP, vip, port, proto string) error {
|
||||
log.Infof("[egress] Removing source nat from [%s] => [%s], with destination port [%s]", podIP, vip, port)
|
||||
log.Info("[egress] Removing source nat", "podIP", podIP, "vip", vip, "destination port", port)
|
||||
|
||||
exists, _ := e.ipTablesClient.Exists("nat", "POSTROUTING", "-s", podIP+"/32", "-m", "mark", "--mark", "64/64", "-j", "SNAT", "--to-source", vip, "-p", proto, "--dport", port, "-m", "comment", "--comment", e.comment)
|
||||
|
||||
@@ -118,13 +119,13 @@ func (e *Egress) DeleteSourceNatForDestinationPort(podIP, vip, port, proto strin
|
||||
|
||||
func (e *Egress) CreateMangleChain(name string) error {
|
||||
|
||||
log.Infof("[egress] Creating Chain [%s]", name)
|
||||
log.Info("[egress] Creating Chain", "name", name)
|
||||
// Creates a new chain in the mangle table
|
||||
return e.ipTablesClient.NewChain("mangle", name)
|
||||
|
||||
}
|
||||
func (e *Egress) AppendReturnRulesForDestinationSubnet(name, subnet string) error {
|
||||
log.Infof("[egress] Adding jump for subnet [%s] to RETURN to previous chain/rules", subnet)
|
||||
log.Info("[egress] Adding jump for subnet to RETURN to previous chain/rules", "subnet", subnet)
|
||||
exists, _ := e.ipTablesClient.Exists("mangle", name, "-d", subnet, "-j", "RETURN", "-m", "comment", "--comment", e.comment)
|
||||
if !exists {
|
||||
return e.ipTablesClient.Append("mangle", name, "-d", subnet, "-j", "RETURN", "-m", "comment", "--comment", e.comment)
|
||||
@@ -133,7 +134,7 @@ func (e *Egress) AppendReturnRulesForDestinationSubnet(name, subnet string) erro
|
||||
}
|
||||
|
||||
func (e *Egress) AppendReturnRulesForMarking(name, subnet string) error {
|
||||
log.Infof("[egress] Marking packets on network [%s]", subnet)
|
||||
log.Info("[egress] Marking packets on network", "subnet", subnet)
|
||||
exists, _ := e.ipTablesClient.Exists("mangle", name, "-s", subnet, "-j", "MARK", "--set-mark", "64/64", "-m", "comment", "--comment", e.comment)
|
||||
if !exists {
|
||||
return e.ipTablesClient.Append("mangle", name, "-s", subnet, "-j", "MARK", "--set-mark", "64/64", "-m", "comment", "--comment", e.comment)
|
||||
@@ -142,7 +143,7 @@ func (e *Egress) AppendReturnRulesForMarking(name, subnet string) error {
|
||||
}
|
||||
|
||||
func (e *Egress) AppendReturnRulesForMarkingForNetwork(name, subnet, destination string) error {
|
||||
log.Infof("[egress] Marking packets on network [%s]", subnet)
|
||||
log.Info("[egress] Marking packets on network", "subnet", subnet)
|
||||
exists, _ := e.ipTablesClient.Exists("mangle", name, "-s", subnet, "-d", destination, "-j", "MARK", "--set-mark", "64/64", "-m", "comment", "--comment", e.comment)
|
||||
if !exists {
|
||||
return e.ipTablesClient.Append("mangle", name, "-s", subnet, "-d", destination, "-j", "MARK", "--set-mark", "64/64", "-m", "comment", "--comment", e.comment)
|
||||
@@ -151,7 +152,7 @@ func (e *Egress) AppendReturnRulesForMarkingForNetwork(name, subnet, destination
|
||||
}
|
||||
|
||||
func (e *Egress) InsertMangeTableIntoPrerouting(name string) error {
|
||||
log.Infof("[egress] Adding jump from mangle prerouting to [%s]", name)
|
||||
log.Info("[egress] Adding jump from mangle prerouting", "destination", name)
|
||||
if exists, err := e.ipTablesClient.Exists("mangle", "PREROUTING", "-j", name, "-m", "comment", "--comment", e.comment); err != nil {
|
||||
return err
|
||||
} else if exists {
|
||||
@@ -164,7 +165,7 @@ func (e *Egress) InsertMangeTableIntoPrerouting(name string) error {
|
||||
}
|
||||
|
||||
func (e *Egress) InsertSourceNat(vip, podIP string) error {
|
||||
log.Infof("[egress] Adding source nat from [%s] => [%s]", podIP, vip)
|
||||
log.Info("[egress] Adding source nat", "original source", podIP, "new source", vip)
|
||||
if exists, err := e.ipTablesClient.Exists("nat", "POSTROUTING", "-s", podIP+"/32", "-m", "mark", "--mark", "64/64", "-j", "SNAT", "--to-source", vip, "-m", "comment", "--comment", e.comment); err != nil {
|
||||
return err
|
||||
} else if exists {
|
||||
@@ -177,17 +178,17 @@ func (e *Egress) InsertSourceNat(vip, podIP string) error {
|
||||
}
|
||||
|
||||
func (e *Egress) InsertSourceNatForDestinationPort(vip, podIP, port, proto string) error {
|
||||
log.Infof("[egress] Adding source nat from [%s] => [%s], with destination port [%s]", podIP, vip, port)
|
||||
log.Info("[egress] Adding source nat", "from", podIP, "to", vip, "port", port)
|
||||
natRules, err := e.ipTablesClient.List("nat", "POSTROUTING")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
foundNatRules := e.findExistingVIP(natRules, vip)
|
||||
log.Warnf("[egress] Cleaning [%d] existing postrouting nat rules for vip [%s]", len(foundNatRules), vip)
|
||||
log.Warn("[egress] Cleaning existing postrouting nat rules for vip", "rulecount", len(foundNatRules), "vip", vip)
|
||||
for x := range foundNatRules {
|
||||
err = e.ipTablesClient.Delete("nat", "POSTROUTING", foundNatRules[x][2:]...)
|
||||
if err != nil {
|
||||
log.Errorf("[egress] Error removing rule [%v]", err)
|
||||
log.Error("[egress] removing rule", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,13 +207,13 @@ func DeleteExistingSessions(sessionIP string, destination bool, destinationPorts
|
||||
|
||||
nfct, err := ct.Open(&ct.Config{})
|
||||
if err != nil {
|
||||
log.Errorf("could not create nfct: %v", err)
|
||||
log.Error("create conntrack client", "err", err)
|
||||
return err
|
||||
}
|
||||
defer nfct.Close()
|
||||
sessions, err := nfct.Dump(ct.Conntrack, ct.IPv4)
|
||||
if err != nil {
|
||||
log.Errorf("could not dump sessions: %v", err)
|
||||
log.Error("could not dump sessions", "err", err)
|
||||
return err
|
||||
}
|
||||
destPortProtocol := make(map[uint16]uint8)
|
||||
@@ -239,7 +240,7 @@ func DeleteExistingSessions(sessionIP string, destination bool, destinationPorts
|
||||
case strings.ToLower("sctp"):
|
||||
destPortProtocol[uint16(port)] = ProtocolSCTP
|
||||
default:
|
||||
log.Errorf("[egress] annotation protocol [%s] isn't supported", data[0])
|
||||
log.Error("[egress] annotation protocol isn't supported", "protocol ID", data[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -265,7 +266,7 @@ func DeleteExistingSessions(sessionIP string, destination bool, destinationPorts
|
||||
case strings.ToLower("sctp"):
|
||||
srcPortProtocol[uint16(port)] = ProtocolSCTP
|
||||
default:
|
||||
log.Errorf("[egress] annotation protocol [%s] isn't supported", data[0])
|
||||
log.Error("[egress] annotation protocol isn't supported", "protocol ID", data[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -278,14 +279,14 @@ func DeleteExistingSessions(sessionIP string, destination bool, destinationPorts
|
||||
if destinationPorts != "" {
|
||||
proto := destPortProtocol[*session.Origin.Proto.DstPort]
|
||||
if proto == *session.Origin.Proto.Number {
|
||||
log.Infof("[egress] cleaning existing connection Source [%s] -> [%s:%d] proto: [%d] ", session.Origin.Src.String(), session.Origin.Dst.String(), *session.Origin.Proto.DstPort, *session.Origin.Proto.Number)
|
||||
log.Info("[egress] cleaning existing connection", "src", session.Origin.Src.String(), "dst", session.Origin.Dst.String(), "dst port", *session.Origin.Proto.DstPort, "protocol", *session.Origin.Proto.Number)
|
||||
err = nfct.Delete(ct.Conntrack, ct.IPv4, session)
|
||||
}
|
||||
} else {
|
||||
err = nfct.Delete(ct.Conntrack, ct.IPv4, session)
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("could not delete sessions: %v", err)
|
||||
log.Error("could not delete sessions", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -298,14 +299,14 @@ func DeleteExistingSessions(sessionIP string, destination bool, destinationPorts
|
||||
if srcPorts != "" {
|
||||
proto := srcPortProtocol[*session.Origin.Proto.DstPort]
|
||||
if proto == *session.Origin.Proto.Number {
|
||||
log.Infof("[egress] cleaning existing connection Source [%s] -> [%s:%d] proto: [%d] ", session.Origin.Src.String(), session.Origin.Dst.String(), *session.Origin.Proto.DstPort, *session.Origin.Proto.Number)
|
||||
log.Info("[egress] cleaning existing connection", "src", session.Origin.Src.String(), "dst", session.Origin.Dst.String(), "dst port", *session.Origin.Proto.DstPort, "protocol", *session.Origin.Proto.Number)
|
||||
err = nfct.Delete(ct.Conntrack, ct.IPv4, session)
|
||||
}
|
||||
} else {
|
||||
err = nfct.Delete(ct.Conntrack, ct.IPv4, session)
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("could not delete sessions: %v", err)
|
||||
log.Error("could not delete sessions", "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -317,13 +318,13 @@ func DeleteExistingSessions(sessionIP string, destination bool, destinationPorts
|
||||
// Debug functions
|
||||
|
||||
func (e *Egress) DumpChain(name string) error {
|
||||
log.Infof("Dumping chain [%s]", name)
|
||||
log.Info("Dumping chain", "name", name)
|
||||
c, err := e.ipTablesClient.List("mangle", name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for x := range c {
|
||||
log.Infof("Rule -> %s", c[x])
|
||||
log.Info("", "rule", c[x])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -334,16 +335,16 @@ func (e *Egress) CleanIPtables() error {
|
||||
return err
|
||||
}
|
||||
foundNatRules := e.findRules(natRules)
|
||||
log.Warnf("[egress] Cleaning [%d] dangling postrouting nat rules", len(foundNatRules))
|
||||
log.Warn("[egress] Cleaning dangling postrouting nat rules", "rulecount", len(foundNatRules))
|
||||
for x := range foundNatRules {
|
||||
err = e.ipTablesClient.Delete("nat", "POSTROUTING", foundNatRules[x][2:]...)
|
||||
if err != nil {
|
||||
log.Errorf("[egress] Error removing rule [%v]", err)
|
||||
log.Error("[egress] Error removing rule", "err", err)
|
||||
}
|
||||
}
|
||||
exists, err := e.CheckMangleChain(MangleChainName)
|
||||
if err != nil {
|
||||
log.Debugf("[egress] No Mangle chain exists [%v]", err)
|
||||
log.Debug("[egress] No Mangle chain exists", "err", err)
|
||||
}
|
||||
if exists {
|
||||
mangleRules, err := e.ipTablesClient.List("mangle", MangleChainName)
|
||||
@@ -351,11 +352,11 @@ func (e *Egress) CleanIPtables() error {
|
||||
return err
|
||||
}
|
||||
foundNatRules = e.findRules(mangleRules)
|
||||
log.Warnf("[egress] Cleaning [%d] dangling prerouting mangle rules", len(foundNatRules))
|
||||
log.Warn("[egress] Cleaning dangling prerouting mangle rules", "rulecount", len(foundNatRules))
|
||||
for x := range foundNatRules {
|
||||
err = e.ipTablesClient.Delete("mangle", MangleChainName, foundNatRules[x][2:]...)
|
||||
if err != nil {
|
||||
log.Errorf("[egress] Error removing rule [%v]", err)
|
||||
log.Error("[egress] Error removing rule", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +368,7 @@ func (e *Egress) CleanIPtables() error {
|
||||
// log.Errorf("[egress] Error removing flushing table [%v]", err)
|
||||
// }
|
||||
} else {
|
||||
log.Warnf("No existing mangle chain [%s] exists", MangleChainName)
|
||||
log.Warn("No existing mangle chain exists", "chain name", MangleChainName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -408,13 +409,13 @@ func (e *Egress) findExistingVIP(rules []string, vip string) [][]string {
|
||||
func ClearIPTables(useNftables bool, namespace string, protocol iptables.Protocol) {
|
||||
i, err := CreateIptablesClient(useNftables, namespace, protocol)
|
||||
if err != nil {
|
||||
log.Warnf("[egress] Unable to clean any dangling egress rules [%v]", err)
|
||||
log.Warn("[egress] Unable to clean any dangling egress rules", "err", err)
|
||||
log.Warn("[egress] Can be ignored in non iptables release of kube-vip")
|
||||
} else {
|
||||
log.Info("[egress] Cleaning any dangling kube-vip egress rules")
|
||||
cleanErr := i.CleanIPtables()
|
||||
if cleanErr != nil {
|
||||
log.Errorf("Error cleaning rules [%v]", cleanErr)
|
||||
log.Error("Error cleaning rules", "err", cleanErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/mdlayher/ndp"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
)
|
||||
|
||||
// NdpResponder defines the parameters for the NDP connection.
|
||||
@@ -50,7 +50,7 @@ func (n *NdpResponder) SendGratuitous(address string) error {
|
||||
return fmt.Errorf("failed to parse address %s", ip)
|
||||
}
|
||||
|
||||
log.Infof("Broadcasting NDP update for %s (%s) via %s", address, n.hardwareAddr, n.intf)
|
||||
log.Info("Broadcasting NDP update", "ip", address, "hwaddr", n.hardwareAddr, "interface", n.intf)
|
||||
return n.advertise(netip.IPv6LinkLocalAllNodes(), ip, true)
|
||||
}
|
||||
|
||||
@@ -66,6 +66,6 @@ func (n *NdpResponder) advertise(dst, target netip.Addr, gratuitous bool) error
|
||||
},
|
||||
},
|
||||
}
|
||||
log.Infof("ndp: %v", m)
|
||||
log.Debug("ndp", "advertisement", m)
|
||||
return n.conn.WriteTo(m, nil, dst)
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
log "log/slog"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/vishvananda/netlink"
|
||||
)
|
||||
|
||||
@@ -167,7 +168,7 @@ func MonitorDefaultInterface(ctx context.Context, defaultIF *net.Interface) erro
|
||||
for {
|
||||
select {
|
||||
case r := <-routeCh:
|
||||
log.Debugf("type: %d, route: %+v", r.Type, r.Route)
|
||||
log.Debug(fmt.Sprintf("type: %d, route: %+v", r.Type, r.Route))
|
||||
if r.Type == syscall.RTM_DELROUTE && (r.Dst == nil || r.Dst.String() == "0.0.0.0/0") && r.LinkIndex == defaultIF.Index {
|
||||
return fmt.Errorf("default route deleted and the default interface may be invalid")
|
||||
}
|
||||
@@ -191,7 +192,7 @@ func GenerateMac() (mac string) {
|
||||
* - https://macaddress.io/database-download
|
||||
*/
|
||||
mac = fmt.Sprintf("%s:%s:%s:%02x:%02x:%02x", "00", "00", "6C", buf[0], buf[1], buf[2])
|
||||
log.Infof("Generated mac: %s", mac)
|
||||
log.Info("Generated mac", "address", mac)
|
||||
return mac
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
log "log/slog"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
Reference in New Issue
Block a user