244 Commits

Author SHA1 Message Date
Cat C
c869af25a3
build: Dependency bumps to prep for release 2.9.0 (#2063)
* build: Dependency bumps to prep for release 2.9.0
* fix(typos): Update typos config to match IZ on txt files in testdata
* chore(lint): Address issues from newer versions of golangci-lint
* fix(dockerfile): Update iptables-wrapper install according to updated installation instructions
2026-04-27 22:03:39 -07:00
Cat C
8fc453c9e9
Merge commit from fork
fix: Make GoBGP server address configurable. Default it to localhost
2026-04-27 16:44:42 -07:00
Cat C
4f4be8e515 fix: Add CLI flag to make GoBGP server address configurable, and default it to localhost. Update docs to match new flag. 2026-04-26 20:45:47 -07:00
Manuel Rüger
99e0011527 chore: fix gofmt, perfsprint, and staticcheck lint issues
- Fix import ordering in lballoc.go (gofmt)
- Replace static fmt.Errorf with errors.New across multiple files (perfsprint)
- Replace fmt.Sprintf string-only calls with concatenation (perfsprint)
- Replace fmt.Sprint(int) with strconv.Itoa/FormatUint (perfsprint)
- Replace fmt.Sprintf("%x") with hex.EncodeToString (perfsprint)
- Lowercase capitalized error strings to follow Go conventions (staticcheck ST1005)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 16:01:52 -05:00
Manuel Rüger
5f0361188f fact: modernize Go primitives to use 1.13+ stdlib features
- Replace fmt.Errorf %s/%v + err.Error() with %w for proper error
  wrapping and errors.Is/As chain support across all packages
- Replace errors.New("msg" + err.Error()) with fmt.Errorf("msg: %w", err)
- Replace strings.Contains(err.Error(), ...) with errors.Is(err,
  syscall.EEXIST) and errors.Is(err, syscall.ESRCH) in linux_networking.go
- Remove now-unused IfaceHasAddr and IpvsServerExists string constants
- Replace sort.Strings with slices.Sort in bgp_policies.go, ipset.go,
  and testhelpers
- Replace sort.SliceStable with slices.SortStableFunc in bgp_policies.go
- Replace reflect.DeepEqual on []string with slices.Equal in bgp_policies.go
  (also fixes bug: was comparing map to slice instead of slice to slice)
- Replace reflect.DeepEqual on []*gobgpapi.Prefix with slices.EqualFunc
  comparing exported fields to avoid protobuf internal state comparison
- Replace strings.Index + manual slicing with strings.Cut in docker.go
  and classify.go
- Update cni_test.go to use assert.EqualError instead of assert.Equal
  for wrapped error comparison

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 16:01:52 -05:00
Cat C
878eebbd01 fix(NRC): Remove debug logging of raw node annotations that leaks BGP password. Credit to: @offset 2026-04-02 18:45:22 -07:00
Cat C
a051e0eec7
Merge pull request #2017 from 1fabi0/feature_kep-1860
feat(services): support ipMode Proxy for LoadBalancer ingresses
2026-03-31 19:28:21 -07:00
Aprazors
01f8216d24 fix(NRC): extend atomic.Bool to initSrcDstCheckDone and ec2IamAuthorized
bgpServerStarted was already fixed. This commit applies the same pattern
to initSrcDstCheckDone and ec2IamAuthorized, which are written from Run()
and the AWS src-dst-check path and read from syncInternalPeers() via
bgp_peers.go — potential data race under concurrent BGP peer syncs.

Also adds TestAtomicBoolFieldsNoConcurrentDataRace to
network_routes_controller_test.go to exercise all three fields under
the race detector.
2026-03-31 20:21:44 -05:00
Aprazors
fc89d09356 fix(NRC): use atomic.Bool for bgpServerStarted to prevent data race
bgpServerStarted is written in Run() on the controller goroutine and
read from informer callbacks (OnNodeUpdate, handleServiceUpdate,
handleServiceDelete, OnEndpointsAdd, OnEndpointsUpdate) which run on
a separate goroutine. This is a data race.

Replace the plain bool with sync/atomic.Bool, using Store() for writes
and Load() for reads, to make cross-goroutine access safe without
requiring the caller to hold nrc.mu.
2026-03-31 20:21:44 -05:00
Kamp, Fabian
421fd43623 feat(services): support ipMode Proxy for LoadBalancer ingresses
This implements support for KEP-1860. When a LoadBalancer ingress has ipMode set to 'Proxy', kube-router will skip adding the IP to the local IPVS table and will not hijack the traffic. If ipMode is 'VIP' or unset, the current behavior is maintained.

Fixes #2014
2026-03-24 16:58:26 +01:00
Aaron U'Ren
a1f0b2eea3
fix: validate external IPs and LB IPs against configured ranges
Moves all Service VIP range configurations into pkg/svcip this is where
validation and querying of ranges goes rather than passing each range to
each controller.

It also centralizes the validation logic since NRC and NSC need
basically equivalent logic. It additionally adds a RangeQuerier
interface for the NPC and LBC controllers which require knowing the
literal ranges.
2026-03-15 20:46:54 -05:00
Aaron U'Ren
070d9565db feat(lint): add basic typos checker to ensure less spelling mistakes in the future 2026-03-15 12:29:17 -07:00
Roman Kuzmitskii
b1a34ed438 feat(gobgp): add kube_router_bgp_peer_info metric
Replace the misleading kube_router_controller_bgp_peers gauge
  which only counts 'cluster nodes' with a new per peer metric
  kube_router_bgp_peer_info with 'GaugeVec' that exposes actual
  BGP session state from gobgp. labels include peer address, asn,
  type, and state. Metric value is 1 if established and 0 otherwise.

Closes: https://github.com/cloudnativelabs/kube-router/issues/848
Signed-off-by: Roman Kuzmitskii <roman@damex.org>
2026-03-07 18:41:29 -10:00
Aaron U'Ren
a8dd0c23c1 fix(aws.go): load region before attempting to assume a role 2026-02-15 12:08:37 -06:00
Aaron U'Ren
ae9c04c4dd feat(gobgp): update v3.37.0 -> v4.2.0 2026-02-13 14:31:16 -08:00
Aaron U'Ren
59814eb67b fix: convert ginkgo tests to standard go tests 2026-01-31 12:15:35 -06:00
Aaron U'Ren
790d53ee51 fact(bgp_peers.go): migrate for loop -> slices.Contains 2026-01-26 10:20:51 -06:00
Aaron U'Ren
827cb4ae7b fix(BGP): always configure AFI SAFI
Changes AFI SAFI configuration to:
* Use consolidated logic for AFI SAFI configuration for both internal
  peers and external peers
* Configure AFI SAFI regardless of GracefulRestart enablement
  * This is important because by default GoBGP only configures a default
    AFI SAFI configuration for the address family of its configured
    peering IP. Which means that previously dual-stack configurations
    that did not enable GracefulRestart would not work (see: #1992)
2026-01-26 10:20:51 -06:00
Cat C
440ad4d0a1 fix: Replace all netlink functions that throw ErrDumpInterrupted with a retry wrapper 2026-01-09 09:17:43 -06:00
Cat C
ed79de5ccd feat(NRC): Restructures the PeerConfig struct introduced in
the previous commit to make the API easier to understanding and use.
2025-12-15 22:46:22 -06:00
Cat C
9e091b8875 feat(NRC): This commit adds support for a consolidated annotation for configuring
a node's BGP peer settings while maintaining backwards support for the existing
annotations to address #1393.
2025-12-15 22:46:22 -06:00
sunhuanran
052151f285 fix: do not advertise Pod IPv4 CIDR in a Cluster composed of IPv6-only Nodes) 2025-11-22 12:28:12 -06:00
ccoVeille
1e8976bd79 build(deps): update github.com/ccoveille/go-safecast to v2.0.0 2025-11-08 01:13:51 +01:00
ccoVeille
e8a59fda2e build(deps): bump github.com/ccoveille/go-safecast to 1.8.1 2025-11-03 12:04:58 +01:00
Aaron U'Ren
846fbd8500 fix(ipset): don't strip inet6 prefixing of ipsets
The problem here stems from the fact that when netpol generates its list of expected ipsets, it includes the inet6:
prefix, however, when the proxy and routing controller sent their list of expected ipsets, they did not do so. This
meant that no matter how we handled it in ipset.go it was wrong for one or the other use-cases.

I decided to standardize on the netpol way of sending the list of expected ipset names so that BuildIPSetRestore() can
function in the same way for all invocations.
2025-10-27 21:25:33 -05:00
Aaron U'Ren
f44598bcb1 test(ipset): add unit tests for ipset regression testing 2025-10-27 21:25:33 -05:00
Aaron U'Ren
6c44013bc5 fix(ipset): ignore non-kube-router ipsets
Attempt to filter out sets that we are not authoritative for to avoid
race conditions with other operators (like Istio) that might be
attempting to modify ipsets at the same time.
2025-10-04 18:30:28 -05:00
Aaron U'Ren
a4fb70a095 feat(lint): update golangci-lint v2.0.2 -> v2.4.0 2025-09-20 16:30:54 -05:00
Aaron U'Ren
d7214cec4f feat(Endpoints): convert Endpoints -> EndpointSlices 2025-09-06 16:27:03 -05:00
Aaron U'Ren
f2b0d785a0 fact: add ip utils library & add unit testing
Consolidate IP utility functions into a new file and add proper unit
testing. Additionally consolidate logic and references to default route
subnets.
2025-06-29 17:42:18 -05:00
Manuel Rüger
6a1d15c24c Use golangci-lint 2.0.2 2025-04-23 22:56:24 +02:00
Aaron U'Ren
d8cac914ab feat(options): allow disabling GoBGP grpc port 2025-03-30 19:40:16 -05:00
Aaron U'Ren
de3e2186a1 feat(options): add flag for GoBGP grpc port 2025-03-30 19:40:16 -05:00
Manuel Rüger
ff8d42fd83
Update aws-sdk to v2 2025-03-28 21:42:44 -05:00
Aaron U'Ren
760fcd5c85 fix(lint): remove non-constant format string (govet) 2025-02-14 14:18:26 -06:00
Aaron U'Ren
858fdf659d fix(lint): prevent against integer overflow errors 2025-02-14 14:18:26 -06:00
Aaron U'Ren
6ce2c6dbf2 fix(NRC): find all node IPs for NAT exclusion
Back in commit 9fd46cc when I was pulling out the krnode struct I made a
mistake in the `syncNodeIPSets()` function and didn't grab the IPs of
all nodes, instead I only grabbed the IP of the current node multiple
times.

This caused other nodes (besides the current one) to get removed from
the `kube-router-node-ips` ipset which ensures that we don't NAT traffic
from pods to nodes (daemons and HostNetwork'd items).

This should fix that problem.
2024-12-13 09:22:41 -06:00
Aaron U'Ren
44439d6069 feat(NSC): change service.local internal traffic policy posture
Over time, feedback from users has been that our interpretation of how
the kube-router service.local annotation interacts with the internal
traffic policy has been that it is too restrictive.

It seems like tuning it to fall in line with the local internal traffic
policy is too restrictive. This commit changes that posture, by equating
the service.local annotation with External Traffic Policy Local and
Internal Traffic Policy Cluster.

This means that when service.local is set the following will be true:

* ExternalIPs / LoadBalancer IPs will only be available on a node that
  hosts the workload
* ExternalIPs / LoadBalancer IPs will only be BGP advertised (when
  enabled) by nodes that host the workload
* Services will have the same posture as External Traffic Policy set to
  local
* ClusterIPs will be available on all nodes for LoadBalancing
* ClusterIPs will only be BGP advertised (when enabled) by nodes that
  host the workload
* Cluster IP services will have the same posture as Internal Traffic
  Policy set to cluster

For anyone desiring the original functionality of the service.local
annotation that has been in place since kube-router v2.1.0, all that
would need to be done is to set `internalTrafficPolicy` to Local as
described here: https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/
2024-12-04 08:14:52 +01:00
Aaron U'Ren
8c5cc3e4cb feat(route_sync): add metrics 2024-11-21 15:24:09 +01:00
Aaron U'Ren
da6ef9b270 feat(route_sync): add health checking 2024-11-21 15:24:09 +01:00
Aaron U'Ren
0ac15b273e fact(healthcontroller): make more robust
Make the health controller more robust and extensible by adding in
constants for heart beats instead of 3 character random strings that are
easy to get wrong.
2024-11-21 15:24:09 +01:00
Aaron U'Ren
2071aecd6a fix(ecmp_vip.go): logging levels to be more helpful 2024-11-21 15:24:09 +01:00
Aaron U'Ren
d867a79e6b fix(injectRoute): ensure routes is removed from map
There are a couple of items that have typically ended up in a no-op for
us when considering routes to inject. However, now that we have a route
map where we track route state, we need this not just to be no-ops, but
also update the route state cache as well to ensure that the route
doesn't get replaced in the future.

When we find tunnels to clean up, we need to not only remove the tunnel
and the route to that tunnel, but also remove the route from the state
map.

When we discover that no route needs to be added to the host because
it's not in the same subnet and we weren't supposed to create a tunnel,
then we also clean it up and ensure that it isn't in our state as well.
2024-11-21 15:24:09 +01:00
Aaron U'Ren
2896ae4d1a fix(node_test.go): some minor unit test errors & verbiage 2024-11-21 15:24:09 +01:00
Aaron U'Ren
416dc9e742 test: reduce unit test run time 2024-10-21 15:44:07 -05:00
Aaron U'Ren
d99b7e9fea fix: add PR review suggestions 2024-10-09 15:15:23 -05:00
Aaron U'Ren
c9b75b4f80 fact(bgp): separate bgp functionality into new package 2024-10-09 15:15:23 -05:00
Aaron U'Ren
374e832701 fact(tunnels): separate linux tunneling functionality 2024-10-09 15:15:23 -05:00
Aaron U'Ren
fd93127436 fact(pbr): move to routes package 2024-10-09 15:15:23 -05:00
Aaron U'Ren
20682fc5b8 fact(routes): begin separating linux routing functionality 2024-10-09 15:15:23 -05:00