Compare commits

..

1335 Commits

Author SHA1 Message Date
Dan Finneran
83d2092fec Move this error to a warning
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-12-01 14:53:29 +00:00
Daniel Finneran
6c9c5af373 Merge pull request #1334 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.20.10
Bump anchore/sbom-action from 0.20.9 to 0.20.10
2025-11-27 09:02:30 +00:00
Daniel Finneran
509eeea1d4 Merge pull request #1339 from tbjorklund78/bgp_annotation
Add annotation to service when using BGP and not just ARP
2025-11-26 18:15:29 +00:00
Daniel Finneran
c00a61f45e Merge pull request #1338 from mkhpalm/patch-upnp
Do not run UPnP refresher if UPnP is disabled
2025-11-26 18:14:47 +00:00
Daniel Finneran
0ea24655eb Merge pull request #1336 from ivucica/patch-1
Avoid access inside WANIPv6FirewallControlClient when it might be nil
2025-11-26 18:14:28 +00:00
Ivan Vučica
288cd9a8b0 Avoid access inside WANIPv6FirewallControlClient when it might be nil
This moves the `log.Info` call inside the check for nil-ness of the
`gw.WANIPv6FirewallControlClient`. A UPnP portmap device that
has no IPv6 support crashes without this check.

To compensate, this adds logging statements for the `PortForward`
case.

Signed-off-by: Ivan Vučica <ivan@vucica.net>
Signed-off-by: Ivan Vučica <ivucica@google.com>
Fixes: #1335
2025-11-26 15:51:10 +00:00
Thomas Björklund
2c00d2bc05 Also add annotation to the service when using BGP and not just ARP to faciliate
using kube-vip to allow for high availability ciliumegressgatewaypolicies.cilium.io
using for example https://github.com/angeloxx/cilium-haegress-operator

Signed-off-by: Thomas Björklund <thomas@netnod.se>
2025-11-26 00:26:45 +01:00
Mike Palmer
5cf899c88c Do not run UPnP refresher if UPnP is disabled
Signed-off-by: Mike Palmer <mkhpalm@gmail.com>
2025-11-25 10:38:56 -07:00
dependabot[bot]
16fa1bcc26 Bump google.golang.org/grpc from 1.76.0 to 1.77.0 (#1330)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.76.0 to 1.77.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.76.0...v1.77.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.77.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 13:29:34 +01:00
dependabot[bot]
a67ef25c15 Bump go.uber.org/zap from 1.27.0 to 1.27.1 (#1329)
Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.27.0 to 1.27.1.
- [Release notes](https://github.com/uber-go/zap/releases)
- [Changelog](https://github.com/uber-go/zap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uber-go/zap/compare/v1.27.0...v1.27.1)

---
updated-dependencies:
- dependency-name: go.uber.org/zap
  dependency-version: 1.27.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 13:29:16 +01:00
dependabot[bot]
c82738633c Bump actions/checkout from 5 to 6 (#1333)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 07:52:48 +01:00
dependabot[bot]
11e419595b Bump k8s.io/api from 0.34.1 to 0.34.2 (#1331)
Bumps [k8s.io/api](https://github.com/kubernetes/api) from 0.34.1 to 0.34.2.
- [Commits](https://github.com/kubernetes/api/compare/v0.34.1...v0.34.2)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-version: 0.34.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 07:35:17 +01:00
dependabot[bot]
1db99a10dc Bump go.etcd.io/etcd/client/v3 from 3.6.5 to 3.6.6 (#1332)
Bumps [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) from 3.6.5 to 3.6.6.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.6.5...v3.6.6)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/v3
  dependency-version: 3.6.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 07:34:42 +01:00
dependabot[bot]
f51f3276b5 Bump anchore/sbom-action from 0.20.9 to 0.20.10
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.20.9 to 0.20.10.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.20.9...v0.20.10)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-version: 0.20.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 02:06:26 +00:00
Daniel Finneran
199bc43c5c Merge pull request #1327 from kube-vip/dependabot/go_modules/golang.org/x/crypto-0.45.0
Bump golang.org/x/crypto from 0.41.0 to 0.45.0
2025-11-21 09:13:31 +00:00
dependabot[bot]
16afc9c1d4 Bump golang.org/x/crypto from 0.41.0 to 0.45.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.41.0 to 0.45.0.
- [Commits](https://github.com/golang/crypto/compare/v0.41.0...v0.45.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.45.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-20 02:49:20 +00:00
Daniel Finneran
76156b3f3b Update Makefile
Ready for new release
2025-11-19 20:03:29 +00:00
Daniel Finneran
5a1e8c1a3f Merge pull request #1323 from kube-vip/dependabot/github_actions/docker/metadata-action-5.9.0
Bump docker/metadata-action from 5.8.0 to 5.9.0
2025-11-19 19:59:50 +00:00
Daniel Finneran
2d0f0734c4 Merge pull request #1326 from kube-vip/k8s_dump 2025-11-19 19:05:09 +00:00
Dan Finneran
42b97175e3 adds UUID to output
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-11-19 18:34:36 +00:00
Dan Finneran
eec091af23 Now returns the internal kubernetes configuration of services and endpoints
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-11-19 18:32:01 +00:00
Daniel Finneran
6f4f870800 Merge pull request #1322 from kube-vip/dependabot/docker/golang-1.25.4-alpine3.22
Bump golang from 1.25.3-alpine3.22 to 1.25.4-alpine3.22
2025-11-19 17:22:07 +00:00
Daniel Finneran
3a5a59ae64 Merge pull request #1319 from kube-vip/dependabot/go_modules/golang.org/x/sync-0.18.0
Bump golang.org/x/sync from 0.17.0 to 0.18.0
2025-11-19 17:21:51 +00:00
dependabot[bot]
e8484fa1f3 Bump golang.org/x/sync from 0.17.0 to 0.18.0
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.17.0 to 0.18.0.
- [Commits](https://github.com/golang/sync/compare/v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-19 16:13:52 +00:00
Daniel Finneran
55ccb8cd87 Merge pull request #1321 from kube-vip/dependabot/go_modules/golang.org/x/sys-0.38.0
Bump golang.org/x/sys from 0.37.0 to 0.38.0
2025-11-19 16:12:42 +00:00
Daniel Finneran
09edf341ab Merge pull request #1320 from kube-vip/dependabot/go_modules/github.com/docker/docker-28.5.2incompatible
Bump github.com/docker/docker from 28.5.1+incompatible to 28.5.2+incompatible
2025-11-19 16:12:25 +00:00
Daniel Finneran
8380e4f07e Merge pull request #1309 from kube-vip/dependabot/github_actions/actions/upload-artifact-5
Bump actions/upload-artifact from 4 to 5
2025-11-19 16:11:33 +00:00
Daniel Finneran
4a07466467 Merge pull request #1308 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.20.9
Bump anchore/sbom-action from 0.20.6 to 0.20.9
2025-11-19 16:11:14 +00:00
Daniel Finneran
cbdc86ac8f Merge pull request #1298 from kube-vip/dependabot/github_actions/github/codeql-action-4
Bump github/codeql-action from 3 to 4
2025-11-19 16:11:00 +00:00
Daniel Finneran
7ea39fa7b5 Merge pull request #1325 from kube-vip/nft_fump
Adds the capability to dump the nftables config
2025-11-19 16:10:33 +00:00
Daniel Finneran
7eed2a33dc Merge pull request #1306 from slimm609/preserve_vip_leadership
Feat: preserve vip on leadership loss
2025-11-19 16:09:51 +00:00
Brian Davis
95bb7b9a85 fix dns.go formatting
Signed-off-by: Brian Davis <dbrian@vmware.com>
2025-11-19 08:59:19 -05:00
Brian Davis
2762fb624c fix go formatting
Signed-off-by: Brian Davis <dbrian@vmware.com>
2025-11-19 08:35:19 -05:00
Dan Finneran
3924a57168 lint fixesm
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-11-17 20:22:31 +00:00
Dan Finneran
8750b3331c Adds the capability to dump the nftables config
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-11-17 20:10:43 +00:00
Daniel Finneran
be9415fef1 Merge pull request #1324 from kube-vip/modules_warn
Moves the kernel modules to a warning as they can be loaded during th…
2025-11-17 16:54:16 +00:00
Dan Finneran
df13a69e26 Moves the kernel modules to a warning as they can be loaded during the rule creation.
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-11-17 16:06:01 +00:00
Brian Davis
6b60780d6c handle ipv6 indepedently
- ipv6 has duplicate address dectection which prevents perserving the VIP on the old node

Signed-off-by: Brian Davis <slimm609@gmail.com>
Signed-off-by: Brian Davis <dbrian@vmware.com>
2025-11-13 10:21:26 -05:00
Brian Davis
9786aa9446 feat: preserve vip on leadership loss
When in arp mode, when preserveVipOnLeadershipLoss is true, when a node loses leadership (or can't keep it),
this will stop performing ARPs but will wait until a new leader is elected before deleting the arp.

when the flag is set to false (default) it continue to function like normal.

Signed-off-by: Brian Davis <slimm609@gmail.com>
Signed-off-by: Brian Davis <dbrian@vmware.com>
2025-11-13 10:21:26 -05:00
dependabot[bot]
71ca2614d2 Bump docker/metadata-action from 5.8.0 to 5.9.0
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.8.0 to 5.9.0.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/v5.8.0...v5.9.0)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-version: 5.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 02:06:25 +00:00
dependabot[bot]
3d171a937e Bump golang from 1.25.3-alpine3.22 to 1.25.4-alpine3.22
Bumps golang from 1.25.3-alpine3.22 to 1.25.4-alpine3.22.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.4-alpine3.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 02:06:06 +00:00
dependabot[bot]
2663a1b222 Bump golang.org/x/sys from 0.37.0 to 0.38.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.37.0 to 0.38.0.
- [Commits](https://github.com/golang/sys/compare/v0.37.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 02:03:23 +00:00
dependabot[bot]
51ebcc40f0 Bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 28.5.1+incompatible to 28.5.2+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.5.1...v28.5.2)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 28.5.2+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 02:03:20 +00:00
dependabot[bot]
95c45b0b32 Bump github.com/onsi/ginkgo/v2 from 2.26.0 to 2.27.2 (#1314)
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.26.0 to 2.27.2.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.26.0...v2.27.2)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-version: 2.27.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-07 01:00:01 +01:00
dependabot[bot]
a3c5be3242 Bump golang.org/x/sys from 0.36.0 to 0.37.0 (#1296)
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.36.0 to 0.37.0.
- [Commits](https://github.com/golang/sys/compare/v0.36.0...v0.37.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-07 00:59:41 +01:00
Daniel Finneran
c5c920f341 Merge pull request #1315 from thc1006/feature/sigusr1-config-dump
Add SIGUSR1 signal handler for runtime configuration dumps
2025-11-04 22:13:24 +04:00
Patryk Strusiewicz-Surmacki
2e2951b35b Fixed DDNS nil pointer dereference (1305) (#1310)
* Fixed DDNS nil pointer dereference (1305)

Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>

* Using constants instead of values

Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>

---------

Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
Co-authored-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-11-04 19:09:55 +01:00
Seungtae Moon
4b741e767a fix: normalize IPv6 to 32-hex (fixes #1302) (#1313)
Signed-off-by: seungtae62 <seungtae.moon62@gmail.com>
2025-11-04 19:08:12 +01:00
thc1006
66adbd4abb Add SIGUSR1 signal handler for runtime configuration dumps
Implements Issue #1301 - Adds support for dumping current configuration
when SIGUSR1 signal is received by the kube-vip process.

Changes:
- Add SIGUSR1 signal handling in all manager start methods
- Implement configuration dump functionality in pkg/manager/manager_dump.go:
  * dumpConfiguration() - Main dump coordinator
  * 7 helper methods for different configuration sections
- Update signal handlers to use switch statement pattern
- Add comprehensive unit tests (5 tests, all passing)
- Add E2E test for signal handling

Implementation details:
- Thread-safe with mutex protection
- Non-disruptive: process continues after dump
- Output format: human-readable plaintext via stdout
- File organization follows project convention (manager_*.go pattern)

Co-authored-by: SteveYi <steveyiyo@steveyi.net>
Signed-off-by: thc1006 <84045975+thc1006@users.noreply.github.com>
2025-11-04 11:24:59 +08:00
dependabot[bot]
c9e4e7aea1 Bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 28.5.0+incompatible to 28.5.1+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.5.0...v28.5.1)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 28.5.1+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 02:16:11 +01:00
dependabot[bot]
56a441f700 Bump google.golang.org/grpc from 1.75.1 to 1.76.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.75.1 to 1.76.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.75.1...v1.76.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.76.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 02:15:56 +01:00
dependabot[bot]
f9951bac77 Bump alpine from 3.22.1 to 3.22.2
Bumps alpine from 3.22.1 to 3.22.2.

---
updated-dependencies:
- dependency-name: alpine
  dependency-version: 3.22.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 02:15:42 +01:00
dependabot[bot]
d7a66ce20f Bump golang from 1.25.1-alpine3.22 to 1.25.3-alpine3.22
Bumps golang from 1.25.1-alpine3.22 to 1.25.3-alpine3.22.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.3-alpine3.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-04 02:15:21 +01:00
dependabot[bot]
73d9ce7f44 Bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 02:09:23 +00:00
dependabot[bot]
14ff1b9fec Bump anchore/sbom-action from 0.20.6 to 0.20.9
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.20.6 to 0.20.9.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.20.6...v0.20.9)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-version: 0.20.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-27 02:07:05 +00:00
dependabot[bot]
9a9c5998d8 Bump github/codeql-action from 3 to 4
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 02:07:05 +00:00
dependabot[bot]
edb9dcb626 Bump github.com/onsi/ginkgo/v2 from 2.25.3 to 2.26.0
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.25.3 to 2.26.0.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.25.3...v2.26.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-version: 2.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-08 12:45:35 +02:00
dependabot[bot]
89559b97af Bump sigs.k8s.io/kind from 0.29.0 to 0.30.0
Bumps [sigs.k8s.io/kind](https://github.com/kubernetes-sigs/kind) from 0.29.0 to 0.30.0.
- [Release notes](https://github.com/kubernetes-sigs/kind/releases)
- [Commits](https://github.com/kubernetes-sigs/kind/compare/v0.29.0...v0.30.0)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/kind
  dependency-version: 0.30.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 07:43:26 +02:00
dependabot[bot]
cc1d9ac16d Bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 28.4.0+incompatible to 28.5.0+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.4.0...v28.5.0)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 28.5.0+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-06 07:43:07 +02:00
dependabot[bot]
1d9454c61b Bump google.golang.org/protobuf from 1.36.8 to 1.36.9
Bumps google.golang.org/protobuf from 1.36.8 to 1.36.9.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-version: 1.36.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-05 23:16:31 +02:00
Cellebyte
8409073e7a Release v1.0.1 2025-10-05 22:56:55 +02:00
dependabot[bot]
6d419f32bc Bump anchore/sbom-action from 0.20.5 to 0.20.6
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.20.5 to 0.20.6.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.20.5...v0.20.6)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-version: 0.20.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-05 22:50:14 +02:00
dependabot[bot]
9d68054e9a Bump github.com/spf13/cobra from 1.9.1 to 1.10.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.9.1 to 1.10.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.9.1...v1.10.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-version: 1.10.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-05 22:49:53 +02:00
dependabot[bot]
5dcfb8742f Bump go.etcd.io/etcd/client/v3 from 3.6.4 to 3.6.5
Bumps [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) from 3.6.4 to 3.6.5.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.6.4...v3.6.5)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/v3
  dependency-version: 3.6.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-05 22:49:00 +02:00
dependabot[bot]
7e6f70b027 Bump github.com/gookit/slog from 0.5.8 to 0.6.0
Bumps [github.com/gookit/slog](https://github.com/gookit/slog) from 0.5.8 to 0.6.0.
- [Release notes](https://github.com/gookit/slog/releases)
- [Commits](https://github.com/gookit/slog/compare/v0.5.8...v0.6.0)

---
updated-dependencies:
- dependency-name: github.com/gookit/slog
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-05 22:48:47 +02:00
dependabot[bot]
3e10aa85d0 Bump google.golang.org/grpc from 1.75.0 to 1.75.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.75.0 to 1.75.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.75.0...v1.75.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.75.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-05 22:48:25 +02:00
Marcel Fest
16b9f6767e refactored BGP configs, kubevip pkg and more.
* Moved functions from mod pkg vip to pkg utils
* remove the dependency of the kubevip config pkg on the bgp pkg
* introduce BGPConfig and BGPPeer to kubevip package and migrate label from node labeler
* Use the new BGPConfig and BGPPeer type of the kubevip pkg
* Removed utils functions from vip pkg and refactor to call utils instead
* migrate from pkg vip to utils for generic IP funcs
* migrate common annotations and labels into a central place + support for hostnames
* if any change happens we want to reconcile it here
* fix e2e tests which relied also on the vip package instead of utils
* Better debug logging
* Added info if it is egress
* added missing condition to dhcp specific actions
* Disable the service before cancelling the context
* lets try auto,auto instead of /32 and nothing
* Let's reset svcCtx to be nil to ensure a new context when the previous was garbage collected
* Added a space for project wide constants
---------

Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-10-05 22:47:21 +02:00
Alex Krasnov
d8a9727ff5 extend existing e2e tests with node labeling switch (disabled as is)
Signed-off-by: Alex Krasnov <askrasnov@gmail.com>
2025-09-19 12:20:08 +02:00
Alex Krasnov
016a899e60 refactor to interface and separate NoOP node labeler implementation
Signed-off-by: Alex Krasnov <askrasnov@gmail.com>
2025-09-19 12:20:08 +02:00
Alex Krasnov
68b39a83e0 skip node labeling when control-plane mode enabled
Signed-off-by: Alex Krasnov <askrasnov@gmail.com>
2025-09-19 12:20:08 +02:00
Alex Krasnov
93dabff000 fix case with nil clientset (eg, with etcd leader election)
Signed-off-by: Alex Krasnov <askrasnov@gmail.com>
2025-09-19 12:20:08 +02:00
Alex Krasnov
630be48010 add node labels for services
Signed-off-by: Alex Krasnov <askrasnov@gmail.com>
2025-09-19 12:20:08 +02:00
Cellebyte
ea78d291ce use slices.Compact correctly
Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-09-18 17:41:57 +02:00
Cellebyte
2074be2939 use the new vip.LookupHost for manifest creation
Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-09-18 17:41:57 +02:00
dependabot[bot]
7946c17c00 Bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 28.3.3+incompatible to 28.4.0+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.3.3...v28.4.0)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 28.4.0+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-15 18:21:12 +02:00
dependabot[bot]
a0295d6a2f Bump golang.org/x/sync from 0.16.0 to 0.17.0
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/sync/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-15 18:20:47 +02:00
dependabot[bot]
d70068b1a0 Bump github.com/onsi/ginkgo/v2 from 2.23.4 to 2.25.3
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.23.4 to 2.25.3.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.23.4...v2.25.3)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-version: 2.25.3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-15 18:20:30 +02:00
dependabot[bot]
89baba07f5 Bump k8s.io/client-go from 0.33.3 to 0.34.1
Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.33.3 to 0.34.1.
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.33.3...v0.34.1)

---
updated-dependencies:
- dependency-name: k8s.io/client-go
  dependency-version: 0.34.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-15 18:20:14 +02:00
Patryk Strusiewicz-Surmacki
95995500bc Added common lease for multiple services for all modes and service election for BGP
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-09-15 18:19:50 +02:00
Thorsten Bonhagen
b1183e8a93 fix unit test error
Signed-off-by: Thorsten Bonhagen <Thorsten.Bonhagen@tbon.de>
2025-09-15 15:16:03 +02:00
Thorsten Bonhagen
101f722110 rebase
Signed-off-by: Thorsten Bonhagen <Thorsten.Bonhagen@tbon.de>
2025-09-15 15:16:03 +02:00
Thorsten Bonhagen
3f390120c1 remove condition for adding IP in service
orig was not working and inverse condition might not work for all

Signed-off-by: Thorsten Bonhagen <Thorsten.Bonhagen@tbon.de>
2025-09-15 15:16:03 +02:00
Thorsten Bonhagen
7baa8a3141 reformat with go fmt
Signed-off-by: Thorsten Bonhagen <Thorsten.Bonhagen@tbon.de>
2025-09-15 15:16:03 +02:00
Thorsten Bonhagen
6435581674 fix cp and svc not running on same instance
fix table addIP missing
add more debug lines
start service listener before content plane because content plane is blocking main thread

Signed-off-by: Thorsten Bonhagen <Thorsten.Bonhagen@tbon.de>
2025-09-15 15:16:03 +02:00
dependabot[bot]
7eb730c0ef Bump github.com/prometheus/client_golang from 1.22.0 to 1.23.2
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.22.0 to 1.23.2.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.22.0...v1.23.2)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.23.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 23:25:41 +02:00
dependabot[bot]
f6a7aeb130 Bump docker/metadata-action from 5.7.0 to 5.8.0
Bumps [docker/metadata-action](https://github.com/docker/metadata-action) from 5.7.0 to 5.8.0.
- [Release notes](https://github.com/docker/metadata-action/releases)
- [Commits](https://github.com/docker/metadata-action/compare/v5.7.0...v5.8.0)

---
updated-dependencies:
- dependency-name: docker/metadata-action
  dependency-version: 5.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 23:25:32 +02:00
dependabot[bot]
29296a9dc2 Bump actions/setup-go from 5 to 6
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5 to 6.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 22:56:33 +02:00
dependabot[bot]
4d4a2f0ee1 Bump golang.org/x/sys from 0.33.0 to 0.36.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.33.0 to 0.36.0.
- [Commits](https://github.com/golang/sys/compare/v0.33.0...v0.36.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.36.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 22:56:08 +02:00
dependabot[bot]
e4e398bfcf Bump golang from 1.24.6-alpine3.22 to 1.25.1-alpine3.22
Bumps golang from 1.24.6-alpine3.22 to 1.25.1-alpine3.22.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.1-alpine3.22
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 22:55:33 +02:00
dependabot[bot]
8bd2c26a8f Bump actions/checkout from 4 to 5
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 22:54:59 +02:00
dependabot[bot]
bd8f30d67d Bump google.golang.org/grpc from 1.73.0 to 1.75.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.73.0 to 1.75.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.73.0...v1.75.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.75.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 22:54:30 +02:00
dependabot[bot]
a3a429b2b9 Bump anchore/sbom-action from 0.20.4 to 0.20.5
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.20.4 to 0.20.5.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.20.4...v0.20.5)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-version: 0.20.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 22:54:16 +02:00
dependabot[bot]
4f7ce8a1c8 Bump go.etcd.io/etcd/client/v3 from 3.6.1 to 3.6.4
Bumps [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) from 3.6.1 to 3.6.4.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.6.1...v3.6.4)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/v3
  dependency-version: 3.6.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 22:54:01 +02:00
Cellebyte
d2ecf22edd fix images in the kind clusters when manifest is used
Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-09-04 18:54:57 +02:00
Abhishek Pareek
3963172e49 rename var to conform to standards
Signed-off-by: Abhishek Pareek <makeittotop@users.noreply.github.com>
Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-09-04 18:54:57 +02:00
Abhishek Pareek
80c6b0bde4 substitute local image into the ds
Signed-off-by: Abhishek Pareek <makeittotop@users.noreply.github.com>
Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-09-04 18:54:57 +02:00
Abhishek Pareek
4f59df38f3 use a lease Identifier to uniquely identify a svc lease
Signed-off-by: Abhishek Pareek <makeittotop@users.noreply.github.com>
Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-09-04 18:54:57 +02:00
Abhishek Pareek
1a3e6c9d5f uniquely identify a service lease combining namespace + service name
Signed-off-by: Abhishek Pareek <makeittotop@users.noreply.github.com>
Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-09-04 18:54:57 +02:00
Cellebyte
0635ec9e01 Fix linting issues 2025-09-03 22:03:51 +02:00
Yuval Weisz
3fff60a64a fix: Update file permissions in tests to 0600 for security compliance
- Change os.WriteFile permissions from 0644 to 0600 in config_file_test.go
- Addresses GoSec G306 linter requirement for secure file permissions
- Ensures test files are readable/writable by owner only

Signed-off-by: Yuval Weisz <yuval.weisz@vastdata.com>
2025-09-03 15:54:17 +02:00
Yuval Weisz
f05f0469cc test: Add comprehensive tests for configuration file functionality
This commit adds extensive unit tests for the new configuration file features:

Test Coverage:
- LoadConfigFromFile() function with YAML and JSON parsing
- MergeConfigFromFile() function with priority logic testing
- Configuration merging with complex nested structures (BGP, leader election)
- Error handling for invalid files, unsupported formats, and missing files
- Environment variable integration for config_file
- Priority validation: CLI flags > env vars > config file
- Boolean flag merging behavior
- BGP configuration merging
- Leader election configuration merging

Files:
- pkg/kubevip/config_file_test.go: New comprehensive test suite (550+ lines)
- pkg/kubevip/config_generator_test.go: Enhanced with config_file env var tests

Test Structure:
- TestLoadConfigFromFile: Tests JSON/YAML parsing and error cases
- TestMergeConfigFromFile: Tests configuration priority and merging
- TestMergeConfigValues: Tests detailed field-by-field merging logic
- TestParseEnvironmentConfigFile: Tests config_file environment variable

The tests validate all aspects of the configuration file implementation
including edge cases, error scenarios, and complex configuration structures.
All tests follow Go testing best practices with table-driven test patterns.

Signed-off-by: Yuval Weisz <yuval.weisz@vastdata.com>
2025-09-03 15:54:17 +02:00
Yuval Weisz
00337a756b feat: Add --config-file flag and config_file environment variable
This commit implements configuration file support for kube-vip, allowing
users to specify configuration through JSON or YAML files.

Features:
- Added --config-file command line flag that accepts JSON/YAML file paths
- Added config_file environment variable support
- Implemented proper configuration priority: CLI flags > env vars > config file
- Added comprehensive configuration merging for all fields including BGP,
  leader election, routing table, and load balancer settings
- Supports both JSON and YAML file formats with automatic detection
- Maintains full backward compatibility with existing deployments

Changes:
- pkg/kubevip/config_envvar.go: Added configFile constant
- pkg/kubevip/config_types.go: Added ConfigFile field to Config struct
- pkg/kubevip/config_environment.go: Added LoadConfigFromFile() and
  MergeConfigFromFile() functions with comprehensive merging logic
- cmd/kube-vip.go: Integrated config file loading into service and manager commands

Usage:
  kube-vip manager --config-file /etc/kube-vip/config.yaml
  export config_file=/etc/kube-vip/config.json && kube-vip manager

This enhancement significantly improves configuration management for complex
kube-vip deployments while maintaining the existing behavior and patterns.

Signed-off-by: Yuval Weisz <yuval.weisz@vastdata.com>
2025-09-03 15:54:17 +02:00
Thorsten Bonhagen
d3473b5d68 change startup order of ControlPlane and Services
Fix: ControlPlane was blocking main thread so Services could not start in parallel
Signed-off-by: Thorsten Bonhagen <thbo@uhurutec.com>
2025-09-03 15:53:58 +02:00
Patryk Strusiewicz-Surmacki
889d442288 Fixed nil pointer reference when endpoints serving condition is not set
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-09-03 15:53:30 +02:00
Daniel Finneran
b2c04c9058 Merge pull request #1240 from hensur/check-snat-error
check conn.Flush error in nftables SNAT
2025-09-01 15:20:38 +01:00
Mark Riedel
0889ebed7d Fix deletion of ConfiguredNetworks entry after deleting BGP host
Signed-off-by: Mark Riedel <5668435+rmarkdev@users.noreply.github.com>
2025-08-25 17:04:10 +02:00
Henning Surmeier
d1430e79e2 check conn.Flush error in nftables SNAT
Signed-off-by: Henning Surmeier <h.surmeier@mittwald.de>
2025-08-18 14:28:03 +02:00
Patryk Strusiewicz-Surmacki
31eca367ab Added logs as CI artifact
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-08-15 07:50:51 +02:00
Dan Finneran
bdd353d0fd Unintentionally created duplicate functions that can't be used
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-08-14 09:55:16 +02:00
dependabot[bot]
4deb0592f6 Bump golang from 1.24.5-alpine3.22 to 1.24.6-alpine3.22
Bumps golang from 1.24.5-alpine3.22 to 1.24.6-alpine3.22.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.24.6-alpine3.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-14 09:54:24 +02:00
Daniel Finneran
d8877072d4 Merge pull request #1219 from kube-vip/v1-release
Version ONE DOT ZERO
2025-07-31 16:42:23 +01:00
Dan Finneran
89a8dc7de1 default setting to 0
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-31 16:09:10 +02:00
Dan Finneran
704c346f5e naming convention lint fix
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-31 16:09:10 +02:00
Dan Finneran
65061c5cd9 Adds an annotation to set the return path filter for a macvlan nic
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-31 16:09:10 +02:00
Daniel Finneran
32233918b4 Version ONE DOT ZERO 2025-07-31 12:34:37 +01:00
Daniel Finneran
76169da60f Merge pull request #1216 from kube-vip/dependabot/go_modules/github.com/docker/docker-28.3.3incompatible
Bump github.com/docker/docker from 28.3.0+incompatible to 28.3.3+incompatible
2025-07-31 12:33:44 +01:00
Daniel Finneran
9bcf1413f0 Merge pull request #1211 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.20.4
Bump anchore/sbom-action from 0.20.1 to 0.20.4
2025-07-31 12:33:28 +01:00
Daniel Finneran
8e428e875f Merge pull request #1203 from kube-vip/dependabot/docker/alpine-3.22.1
Bump alpine from 3.22.0 to 3.22.1
2025-07-31 12:33:14 +01:00
dependabot[bot]
2fbecc25e5 Bump alpine from 3.22.0 to 3.22.1
Bumps alpine from 3.22.0 to 3.22.1.

---
updated-dependencies:
- dependency-name: alpine
  dependency-version: 3.22.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-30 15:17:21 +00:00
Daniel Finneran
02e77271d0 Merge pull request #1202 from kube-vip/dependabot/docker/golang-1.24.5-alpine3.22 2025-07-30 16:16:18 +01:00
Daniel Finneran
3d61888e58 Merge pull request #1192 from kube-vip/dependabot/go_modules/sigs.k8s.io/kind-0.29.0 2025-07-30 16:15:52 +01:00
dependabot[bot]
efe75f491b Bump sigs.k8s.io/kind from 0.27.0 to 0.29.0
Bumps [sigs.k8s.io/kind](https://github.com/kubernetes-sigs/kind) from 0.27.0 to 0.29.0.
- [Release notes](https://github.com/kubernetes-sigs/kind/releases)
- [Commits](https://github.com/kubernetes-sigs/kind/compare/v0.27.0...v0.29.0)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/kind
  dependency-version: 0.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-30 13:55:46 +00:00
Daniel Finneran
000c139004 Merge pull request #1194 from kube-vip/dependabot/go_modules/github.com/vishvananda/netlink-1.3.1 2025-07-30 14:50:38 +01:00
Daniel Finneran
c39b84f0a9 Merge pull request #1193 from kube-vip/dependabot/go_modules/github.com/osrg/gobgp/v3-3.37.0 2025-07-30 14:50:25 +01:00
dependabot[bot]
ee958addaa Bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 28.3.0+incompatible to 28.3.3+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.3.0...v28.3.3)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 28.3.3+incompatible
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-30 13:48:44 +00:00
Daniel Finneran
8fe53351f8 Merge pull request #1215 from kube-vip/endpointslice 2025-07-30 14:47:26 +01:00
Daniel Finneran
bc9d860d83 Merge pull request #1213 from kube-vip/egress_internal 2025-07-30 14:47:07 +01:00
Dan Finneran
332a23e543 Bump k8s api and endpointslices as default
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-29 13:36:32 +00:00
Dan Finneran
b20713b50f linting issue with port out of bounds.
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-28 16:18:47 +00:00
Dan Finneran
94e96581ef typo and add SCTP
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-28 16:13:20 +00:00
Dan Finneran
61be6d0b6a fighting with merge conflicts
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-28 16:08:53 +00:00
Dan Finneran
be22805a7d sigh
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-28 16:08:22 +00:00
Dan Finneran
25f6253286 Adds the internal egress functionality
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-28 16:01:00 +00:00
dependabot[bot]
f3e9fb6ea9 Bump github.com/osrg/gobgp/v3 from 3.36.0 to 3.37.0
Bumps [github.com/osrg/gobgp/v3](https://github.com/osrg/gobgp) from 3.36.0 to 3.37.0.
- [Release notes](https://github.com/osrg/gobgp/releases)
- [Changelog](https://github.com/osrg/gobgp/blob/master/.goreleaser.yml)
- [Commits](https://github.com/osrg/gobgp/compare/v3.36.0...v3.37.0)

---
updated-dependencies:
- dependency-name: github.com/osrg/gobgp/v3
  dependency-version: 3.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-28 15:17:29 +00:00
Patryk Strusiewicz-Surmacki
0f3dda02c4 Refactoring services-watcher code
Co-authored-by: Cellebyte <marcel.fest@live.de>
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-07-28 17:14:09 +02:00
Dan Finneran
a2873b5465 Adds the internal egress functionality
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-07-28 13:57:50 +00:00
dependabot[bot]
202d45e5ab Bump anchore/sbom-action from 0.20.1 to 0.20.4
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.20.1 to 0.20.4.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.20.1...v0.20.4)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-version: 0.20.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-28 03:11:16 +00:00
Daniel Finneran
f5e4612c03 Merge pull request #1210 from kube-vip/fix/ci 2025-07-27 22:14:39 +01:00
Cellebyte
de888c501c split ci into two files
Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-07-27 23:02:09 +02:00
Cellebyte
47bc83c248 Don't execute the e2e-tests in parallel
Signed-off-by: Cellebyte <marcel.fest@live.de>
2025-07-27 23:02:09 +02:00
Patryk Strusiewicz-Surmacki
1cf637c569 Moved endpoint-related code from pkg/manager to pkg/endpoints
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-07-24 08:07:23 +02:00
Patryk Strusiewicz-Surmacki
ae2571e241 Refactoring endpoint-watcher code
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-07-24 08:07:23 +02:00
Patryk Strusiewicz-Surmacki
86f5e9b8b2 Removed insecure client use in E2E tests
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-07-24 08:07:00 +02:00
Patryk Strusiewicz-Surmacki
ce61ff085a Use insecure client only in E2E tests
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-07-21 17:54:12 +02:00
dependabot[bot]
b816e154cf Bump golang from 1.24.4-alpine3.22 to 1.24.5-alpine3.22
Bumps golang from 1.24.4-alpine3.22 to 1.24.5-alpine3.22.

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.24.5-alpine3.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-14 03:15:14 +00:00
Patryk Strusiewicz-Surmacki
ac1238c337 Rebase
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-07-10 17:50:15 +02:00
Patryk Strusiewicz-Surmacki
10dbf2c0ef Refactoring endpoint-watcher code
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-07-10 17:50:15 +02:00
Jan-Philipp Litza
cf68f8639c Add VIPs as deprecated
This causes IPv6 source address selection according to RFC 3484 to
ignore VIPs when choosing which address the host should use for egress
communication.

Signed-off-by: Jan-Philipp Litza <janphilipp@litza.de>
2025-07-09 10:54:28 +02:00
Daniel Finneran
b114c11b0f Merge pull request #1191 from kube-vip/thebsdbox-patch-1
Update README.md
2025-07-03 09:59:49 +01:00
Patryk Strusiewicz-Surmacki
42b7a8152b Basic e2e tests for BGP mode
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-07-01 12:36:33 +02:00
mushrushu
f7821c7fb3 fixed vars formatting & log statement
Signed-off-by: mushrushu <mushrushu@outlook.com>
2025-07-01 12:34:43 +02:00
mushrushu
42478905d0 added zebra integration and its configuration
Signed-off-by: mushrushu <mushrushu@outlook.com>
2025-07-01 12:34:43 +02:00
dependabot[bot]
8d55bd3b63 Bump github.com/vishvananda/netlink from 1.3.0 to 1.3.1
Bumps [github.com/vishvananda/netlink](https://github.com/vishvananda/netlink) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/vishvananda/netlink/releases)
- [Commits](https://github.com/vishvananda/netlink/compare/v1.3.0...v1.3.1)

---
updated-dependencies:
- dependency-name: github.com/vishvananda/netlink
  dependency-version: 1.3.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-30 03:20:14 +00:00
Daniel Finneran
16247fc3a3 Update README.md
Adds health of project badges! (looking healthy) 😄
2025-06-27 14:20:14 +01:00
Marcel Fest
b56b80cd30 Bump version to v0.9.2
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-24 19:02:31 +02:00
dependabot[bot]
ba25e0e583 Bump github.com/prometheus/client_golang from 1.21.0 to 1.22.0
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.21.0 to 1.22.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.21.0...v1.22.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-24 18:59:16 +02:00
dependabot[bot]
8f1fe355fc Bump github.com/onsi/gomega from 1.36.2 to 1.37.0
Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.36.2 to 1.37.0.
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/gomega/compare/v1.36.2...v1.37.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-version: 1.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-24 16:29:41 +02:00
dependabot[bot]
649d9bf0ef Bump golang.org/x/sys from 0.32.0 to 0.33.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.32.0 to 0.33.0.
- [Commits](https://github.com/golang/sys/compare/v0.32.0...v0.33.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.33.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-23 09:20:35 +02:00
dependabot[bot]
a5108a69aa Bump anchore/sbom-action from 0.19.0 to 0.20.1
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.19.0 to 0.20.1.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.19.0...v0.20.1)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-version: 0.20.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-20 17:53:00 +02:00
dependabot[bot]
c74a496299 Bump go.etcd.io/etcd/client/v3 from 3.5.18 to 3.6.1
Bumps [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) from 3.5.18 to 3.6.1.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.18...v3.6.1)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/v3
  dependency-version: 3.6.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-17 12:06:43 +02:00
dependabot[bot]
b74c274466 Bump alpine from 3.21.3 to 3.22.0
Bumps alpine from 3.21.3 to 3.22.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-version: 3.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-17 11:57:04 +02:00
Dan Finneran
56b3867e57 typo fix 2025-06-17 11:56:43 +02:00
Dan Finneran
66d237bfbc adds kernel module check for nftables 2025-06-17 11:56:43 +02:00
Patryk Strusiewicz-Surmacki
68071b214e Fixed BGP clear deadlock
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-06-17 11:55:49 +02:00
Patryk Strusiewicz-Surmacki
a82ca5576b Updated go version to 1.24.4
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-06-17 09:53:57 +02:00
Patryk Strusiewicz-Surmacki
81dd386b4e Fixed service-tests
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
Co-authored-by: Marcel Fest <marcel@fest4.eu>
2025-06-10 22:26:02 +02:00
Patryk Strusiewicz-Surmacki
b61a74396d Moved configuredRoutes map to serviceContext struct
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-06-10 22:26:02 +02:00
Daniel Finneran
105fbc522a Merge pull request #1163 from p-strusiewiczsurmacki-mobica/rt-tests
Added ARP/NDP services tests and Routing Table services tests
2025-06-10 11:34:15 -07:00
Dan Finneran
2b52c39242 Small change to reduce pointless errors 2025-06-10 13:31:06 +02:00
Patryk Strusiewicz-Surmacki
25d39bca09 Added TODO for insecure discovery client
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-06-06 16:18:38 +02:00
Marcel Fest
644226321e fix typo
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Marcel Fest
3928dda541 move lock for cleanRoutes feature at start of kube-vip
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Patryk Strusiewicz-Surmacki
d9a7f413a6 Moved code to use sync.Maps
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Patryk Strusiewicz-Surmacki
eb300bb634 Fixed deadlock
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Marcel Fest
c30fd9e7be fix tests + refactor func
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Marcel Fest
2fc969b848 Move the check into the function
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Marcel Fest
47884088ec remove AI code
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Marcel Fest
70e1212396 remove redundant condition
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Marcel Fest
d947c2abcc refactor syncServices to be lockable at all
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Marcel Fest
e2efb64aea Use the mutext in callbacks as well
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Marcel Fest
01279d45e3 Added function to create ip array from statu LB ingress field
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-06-05 17:26:55 +02:00
Patryk Strusiewicz-Surmacki
f2a7cad218 Added ARP/NDP services tests and Routing Table services tests
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-05-23 11:59:14 +02:00
Nathan Przybyszewski
98163341d3 Replace invalid verb "endpoints" with "update"
Signed-off-by: Nathan Przybyszewski <172687074+nprzy@users.noreply.github.com>
2025-05-01 10:28:43 +02:00
Marcel Fest
a71d361d15 Bump version
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-28 16:33:49 +02:00
dependabot[bot]
cf24ad835d Bump github.com/onsi/ginkgo/v2 from 2.22.2 to 2.23.4
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.22.2 to 2.23.4.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.22.2...v2.23.4)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-version: 2.23.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-28 14:21:36 +02:00
dependabot[bot]
0c04088b16 Bump github.com/cloudflare/ipvs from 0.10.3 to 0.11.0
Bumps [github.com/cloudflare/ipvs](https://github.com/cloudflare/ipvs) from 0.10.3 to 0.11.0.
- [Release notes](https://github.com/cloudflare/ipvs/releases)
- [Commits](https://github.com/cloudflare/ipvs/compare/v0.10.3...v0.11.0)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/ipvs
  dependency-version: 0.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-28 14:07:42 +02:00
dependabot[bot]
22489ad095 Bump golang.org/x/sys from 0.31.0 to 0.32.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.31.0 to 0.32.0.
- [Commits](https://github.com/golang/sys/compare/v0.31.0...v0.32.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.32.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-28 14:07:29 +02:00
dependabot[bot]
1fa3da45fa Bump github.com/gookit/slog from 0.5.7 to 0.5.8
Bumps [github.com/gookit/slog](https://github.com/gookit/slog) from 0.5.7 to 0.5.8.
- [Release notes](https://github.com/gookit/slog/releases)
- [Commits](https://github.com/gookit/slog/compare/v0.5.7...v0.5.8)

---
updated-dependencies:
- dependency-name: github.com/gookit/slog
  dependency-version: 0.5.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-28 14:07:18 +02:00
Patryk Strusiewicz-Surmacki
d497df3767 Fixed instance finding and route deletion in RT mode
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-28 14:06:20 +02:00
dependabot[bot]
bdd3c5c191 Bump anchore/sbom-action from 0.18.0 to 0.19.0
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.18.0 to 0.19.0.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-version: 0.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-28 07:17:13 +02:00
Shawn Wilsher
5b41db2246 feat: Add opencontainers annotations during release
This change relies on `docker/metadata-action` to generate the
appropriate labels.

Fixes #1044

Signed-off-by: Shawn Wilsher <656602+sdwilsh@users.noreply.github.com>
2025-04-27 21:52:29 +02:00
Shawn Wilsher
1eb35774a5 fix: s/endoints/endpoints/ in RBAC manifest generation code
While moving over to using the RBAC manifest generator, this stood out as a clear typo.

Signed-off-by: Shawn Wilsher <me@shawnwilsher.com>
2025-04-27 09:27:12 +02:00
Daniel Finneran
7d7036fae9 Merge pull request #1130 from kube-vip/fix/upnp
fix #1127 as we have a nil deref if router does not support IPv6
2025-04-15 17:15:23 +01:00
Marcel Fest
1a4bf13819 fix #1127 as we have a nil deref if router does not support IPv6
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 23:20:29 +02:00
dependabot[bot]
3e225bf51f Bump go.etcd.io/etcd/api/v3 from 3.5.18 to 3.5.21
Bumps [go.etcd.io/etcd/api/v3](https://github.com/etcd-io/etcd) from 3.5.18 to 3.5.21.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.18...v3.5.21)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/api/v3
  dependency-version: 3.5.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 23:16:09 +02:00
dependabot[bot]
d6837cbe7d Bump github.com/osrg/gobgp/v3 from 3.35.0 to 3.36.0
Bumps [github.com/osrg/gobgp/v3](https://github.com/osrg/gobgp) from 3.35.0 to 3.36.0.
- [Release notes](https://github.com/osrg/gobgp/releases)
- [Changelog](https://github.com/osrg/gobgp/blob/master/.goreleaser.yml)
- [Commits](https://github.com/osrg/gobgp/compare/v3.35.0...v3.36.0)

---
updated-dependencies:
- dependency-name: github.com/osrg/gobgp/v3
  dependency-version: 3.36.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 22:56:35 +02:00
dependabot[bot]
40994e0464 Bump go.etcd.io/etcd/client/pkg/v3 from 3.5.18 to 3.5.21
Bumps [go.etcd.io/etcd/client/pkg/v3](https://github.com/etcd-io/etcd) from 3.5.18 to 3.5.21.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.18...v3.5.21)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/pkg/v3
  dependency-version: 3.5.21
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 22:54:20 +02:00
dependabot[bot]
4e18ad189d Bump google.golang.org/protobuf from 1.36.5 to 1.36.6
Bumps google.golang.org/protobuf from 1.36.5 to 1.36.6.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-version: 1.36.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 22:39:06 +02:00
dependabot[bot]
a0ed07913e Bump golang.org/x/sync from 0.11.0 to 0.13.0
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.11.0 to 0.13.0.
- [Commits](https://github.com/golang/sync/compare/v0.11.0...v0.13.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-14 22:20:57 +02:00
Patryk Strusiewicz-Surmacki
3d9ca62031 Removed dependancy for endpoint counter in ARP mode
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Patryk Strusiewicz-Surmacki
e0f4520437 Fixed ARP multiple references issues
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk.pawel.strusiewicz-surmacki@external.telekom.de>
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
3a5ebd184d Setup ipv4 and ipv6 subnet mask in template
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
a7d19c15f1 rename forgotten envvar
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
9822d92bed remove wrong if condition
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
4d8b7750ae fix error wrap
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Patryk Strusiewicz-Surmacki
3bcf783020 Fixed E2E tests
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
1b3a7bb5de improved log messages
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
0d5ac98209 Simplify validation check and remove unused code
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
e2472e509b fix tests?
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
08388496bc Updated logic to not be as redundant
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
f4eab023e8 Refactor and condense code, we always want to set SubnetMask
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
c5e854f323 Breaking: Remove vip_cidr in favor of vip_subnet from config interface
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
e7b9439161 Breaking Change do to retirement of vip_cidr
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
555ca2b830 fix ci
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Marcel Fest
271f21f203 Try to add dual-stack support for BGP mode
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-14 21:41:34 +02:00
Daniel Finneran
de54fcbd11 Merge pull request #1126 from kube-vip/add/rbac-manifest-generation
Added support for RBAC manifest generation
2025-04-10 15:50:40 +01:00
Patryk Strusiewicz-Surmacki
46cad395e1 Fixed service IP address deletion on service modification bug
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-09 23:15:43 +02:00
Marcel Fest
3466947f69 Added doc string for RBAC manifest generation
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-09 23:06:22 +02:00
Marcel Fest
8696f80525 added missing inCluster flag back
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-09 23:06:22 +02:00
Marcel Fest
51527d3e6c Added support for RBAC manifest generation
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-09 23:06:20 +02:00
Marcel Fest
c8a9189bf6 Remove the packet env var constants
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-09 21:11:39 +02:00
Deveshi Dwivedi
896b0983e4 remove remaining providerConfig references
Signed-off-by: Deveshi Dwivedi <deveshigurgaon@gmail.com>
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-09 21:11:39 +02:00
Deveshi Dwivedi
d55b124251 change annotations format back
Signed-off-by: Deveshi Dwivedi <deveshigurgaon@gmail.com>
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-09 21:11:39 +02:00
Deveshi Dwivedi
72b6e22d90 remove equinix-metal code
Signed-off-by: Deveshi Dwivedi <deveshigurgaon@gmail.com>
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2025-04-09 21:11:39 +02:00
Marcel Fest
3272bc1f8b Update golang-ci-lint to use kubernetes 1.24.x 2025-04-04 16:54:39 +02:00
dependabot[bot]
1e754703e8 Bump k8s.io/client-go from 0.32.1 to 0.32.3
Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.32.1 to 0.32.3.
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.32.1...v0.32.3)

---
updated-dependencies:
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-04 16:54:39 +02:00
dependabot[bot]
119424bb9b Bump k8s.io/api from 0.32.1 to 0.32.3
Bumps [k8s.io/api](https://github.com/kubernetes/api) from 0.32.1 to 0.32.3.
- [Commits](https://github.com/kubernetes/api/compare/v0.32.1...v0.32.3)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-04 16:54:39 +02:00
Marcel Fest
d8926ebea5 bump golang 2025-04-04 16:54:39 +02:00
dependabot[bot]
6b1a0a7ea8 Bump github.com/osrg/gobgp/v3 from 3.34.0 to 3.35.0
Bumps [github.com/osrg/gobgp/v3](https://github.com/osrg/gobgp) from 3.34.0 to 3.35.0.
- [Release notes](https://github.com/osrg/gobgp/releases)
- [Changelog](https://github.com/osrg/gobgp/blob/master/.goreleaser.yml)
- [Commits](https://github.com/osrg/gobgp/compare/v3.34.0...v3.35.0)

---
updated-dependencies:
- dependency-name: github.com/osrg/gobgp/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-03 16:52:27 +02:00
dependabot[bot]
c92d01b957 Bump golang.org/x/net from 0.34.0 to 0.36.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.34.0 to 0.36.0.
- [Commits](https://github.com/golang/net/compare/v0.34.0...v0.36.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-03 16:51:26 +02:00
dependabot[bot]
d6c6d8e529 Bump sigs.k8s.io/kind from 0.26.0 to 0.27.0
Bumps [sigs.k8s.io/kind](https://github.com/kubernetes-sigs/kind) from 0.26.0 to 0.27.0.
- [Release notes](https://github.com/kubernetes-sigs/kind/releases)
- [Commits](https://github.com/kubernetes-sigs/kind/compare/v0.26.0...v0.27.0)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/kind
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-03 16:50:41 +02:00
dependabot[bot]
1d086b2d5c Bump golang from 1.24.0-alpine3.20 to 1.24.1-alpine3.20
Bumps golang from 1.24.0-alpine3.20 to 1.24.1-alpine3.20.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-03 16:49:48 +02:00
dependabot[bot]
e5d967dcf4 Bump github.com/spf13/cobra from 1.8.1 to 1.9.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.1 to 1.9.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.1...v1.9.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-03 16:49:15 +02:00
Patryk Strusiewicz-Surmacki
21a5533936 Fixes for IPv6 and dualstack clusters
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-03 16:19:06 +02:00
Patryk Strusiewicz-Surmacki
d21fec6c7d Cancel leaderelection if forwarding mode is local and no local endpoints are present
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-03 16:19:06 +02:00
Patryk Strusiewicz-Surmacki
9c4ae86937 Added IPv6 related configuration for IPVS
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-03 16:19:06 +02:00
Patryk Strusiewicz-Surmacki
9c67660b94 Added permission check for IPVS info
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-03 16:19:06 +02:00
Patryk Strusiewicz-Surmacki
96d020b6ad Disable IPVS related iptables rules if LB is not enabled
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-03 16:19:06 +02:00
Patryk Strusiewicz-Surmacki
bc42c3e2c3 Added sysctl check
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-03 16:19:06 +02:00
Patryk Strusiewicz-Surmacki
ea45dafcf3 Fixed IPVS deletion issues
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-03 16:19:06 +02:00
Patryk Strusiewicz-Surmacki
3e3fd21c16 Fixed route deletion issue when 2 services referenced same endpoint
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-04-03 16:04:11 +02:00
Patryk Strusiewicz-Surmacki
70b83664a9 Less strict service status update error handling
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-03-27 15:27:26 +01:00
Patryk Strusiewicz-Surmacki
9650a00157 Fixed service/endpoints discovery concurrent issue
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-03-10 12:12:23 +01:00
Patryk Strusiewicz-Surmacki
f851ddbcaf Fixed service update in BGP and ARP mode
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-03-08 08:43:00 +01:00
Daniel Finneran
a5ee4d969b Merge pull request #1091 from p-strusiewiczsurmacki-mobica/ipvs-re-add-cp
Fixed IPVS backend re-add
2025-03-06 17:15:24 +01:00
Patryk Strusiewicz-Surmacki
2dfd46decb Fixed IPVS backend re-add
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-03-04 15:42:45 +01:00
Daniel Finneran
6752dc0fdd Merge pull request #1084 from kube-vip/dependabot/go_modules/github.com/prometheus/client_golang-1.21.0
Bump github.com/prometheus/client_golang from 1.20.5 to 1.21.0
2025-02-26 15:45:38 +01:00
Daniel Finneran
c7174d3c94 Merge pull request #1083 from kube-vip/dependabot/go_modules/github.com/google/go-cmp-0.7.0
Bump github.com/google/go-cmp from 0.6.0 to 0.7.0
2025-02-26 15:45:25 +01:00
Daniel Finneran
d33ba7e22e Merge pull request #1079 from kube-vip/health
This adds a health check
2025-02-26 15:44:29 +01:00
dependabot[bot]
9b552a4d29 Bump github.com/prometheus/client_golang from 1.20.5 to 1.21.0
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.20.5 to 1.21.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.20.5...v1.21.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 02:57:33 +00:00
dependabot[bot]
5fc04a24f8 Bump github.com/google/go-cmp from 0.6.0 to 0.7.0
Bumps [github.com/google/go-cmp](https://github.com/google/go-cmp) from 0.6.0 to 0.7.0.
- [Release notes](https://github.com/google/go-cmp/releases)
- [Commits](https://github.com/google/go-cmp/compare/v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: github.com/google/go-cmp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 02:57:30 +00:00
Daniel Finneran
122b18a81d Merge pull request #1070 from kube-vip/dependabot/go_modules/google.golang.org/protobuf-1.36.5
Bump google.golang.org/protobuf from 1.36.1 to 1.36.5
2025-02-20 12:42:39 +01:00
Daniel Finneran
c9bc005abe Merge pull request #1075 from kube-vip/dependabot/go_modules/github.com/cloudflare/ipvs-0.10.3
Bump github.com/cloudflare/ipvs from 0.10.2 to 0.10.3
2025-02-20 12:42:26 +01:00
Daniel Finneran
ee0f0668ab Merge pull request #1076 from kube-vip/dependabot/docker/alpine-3.21.3
Bump alpine from 3.21.2 to 3.21.3
2025-02-20 12:42:09 +01:00
Daniel Finneran
826bb6fc8a Merge pull request #1077 from kube-vip/dependabot/docker/golang-1.24.0-alpine3.20
Bump golang from 1.23.5-alpine3.20 to 1.24.0-alpine3.20
2025-02-20 12:41:57 +01:00
Dan Finneran
b9aa99a208 more lint goodness 2025-02-17 17:23:01 +00:00
Dan Finneran
2b0aa825b5 lint fix 2025-02-17 17:21:20 +00:00
dependabot[bot]
24b1524aee Bump google.golang.org/protobuf from 1.36.1 to 1.36.5
Bumps google.golang.org/protobuf from 1.36.1 to 1.36.5.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 17:18:22 +00:00
Daniel Finneran
cf7c7f2f25 Merge pull request #1069 from kube-vip/dependabot/go_modules/golang.org/x/sync-0.11.0
Bump golang.org/x/sync from 0.10.0 to 0.11.0
2025-02-17 18:17:01 +01:00
Dan Finneran
c082688e67 This adds a health check 2025-02-17 17:16:29 +00:00
dependabot[bot]
18bfe6a8d2 Bump golang.org/x/sync from 0.10.0 to 0.11.0
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/sync/compare/v0.10.0...v0.11.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 15:16:50 +00:00
Daniel Finneran
c367434798 Merge pull request #1068 from kube-vip/dependabot/go_modules/github.com/osrg/gobgp/v3-3.34.0
Bump github.com/osrg/gobgp/v3 from 3.33.0 to 3.34.0
2025-02-17 16:15:09 +01:00
Daniel Finneran
f1ca914e92 Merge pull request #1067 from kube-vip/dependabot/go_modules/golang.org/x/sys-0.30.0
Bump golang.org/x/sys from 0.29.0 to 0.30.0
2025-02-17 16:14:57 +01:00
Daniel Finneran
2763c7e417 Merge pull request #1072 from p-strusiewiczsurmacki-mobica/mask-fix
Fixed network mask setting function
2025-02-17 16:14:43 +01:00
Daniel Finneran
f9f0004d3f Merge pull request #1064 from kube-vip/resolver
Resolver, this will ensure that an address that is not an IP address is resolved first to determine the CIDR
2025-02-17 16:14:22 +01:00
Daniel Finneran
958eaefb40 Merge pull request #1062 from kube-vip/bgp_port
You can now specify the port as the fifth argument to peer config
2025-02-17 16:14:05 +01:00
Daniel Finneran
3752695000 Merge pull request #1060 from kube-vip/waitgroup
remove the waitgroups as we never wait
2025-02-17 16:13:38 +01:00
Daniel Finneran
d6eb7c4f26 Merge pull request #1059 from kube-vip/drop_all
drop all other capabilities
2025-02-17 16:13:21 +01:00
dependabot[bot]
b88769e109 Bump golang from 1.23.5-alpine3.20 to 1.24.0-alpine3.20
Bumps golang from 1.23.5-alpine3.20 to 1.24.0-alpine3.20.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 02:38:59 +00:00
dependabot[bot]
eddbcf0801 Bump alpine from 3.21.2 to 3.21.3
Bumps alpine from 3.21.2 to 3.21.3.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 02:38:56 +00:00
dependabot[bot]
886f183108 Bump github.com/cloudflare/ipvs from 0.10.2 to 0.10.3
Bumps [github.com/cloudflare/ipvs](https://github.com/cloudflare/ipvs) from 0.10.2 to 0.10.3.
- [Release notes](https://github.com/cloudflare/ipvs/releases)
- [Commits](https://github.com/cloudflare/ipvs/compare/v0.10.2...v0.10.3)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/ipvs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 02:15:06 +00:00
Patryk Strusiewicz-Surmacki
aba1d53699 Changed initConfig.Logging to be int32
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-02-13 19:36:39 +01:00
Patryk Strusiewicz-Surmacki
d05530e030 Fixed logging level configuration with command line argument
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-02-13 19:36:39 +01:00
Patryk Strusiewicz-Surmacki
7d52dbbbd5 Return error instead of logging warning
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-02-12 11:51:07 +01:00
Patryk Strusiewicz-Surmacki
53185bd58d Fixed ENV log level setting
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-02-10 21:24:48 +01:00
Patryk Strusiewicz-Surmacki
8997c4b1a8 Fixed network mask setting function
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-02-10 15:46:55 +01:00
dependabot[bot]
ce4665bbec Bump github.com/osrg/gobgp/v3 from 3.33.0 to 3.34.0
Bumps [github.com/osrg/gobgp/v3](https://github.com/osrg/gobgp) from 3.33.0 to 3.34.0.
- [Release notes](https://github.com/osrg/gobgp/releases)
- [Changelog](https://github.com/osrg/gobgp/blob/master/.goreleaser.yml)
- [Commits](https://github.com/osrg/gobgp/compare/v3.33.0...v3.34.0)

---
updated-dependencies:
- dependency-name: github.com/osrg/gobgp/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 02:10:52 +00:00
dependabot[bot]
e1ecca42c5 Bump golang.org/x/sys from 0.29.0 to 0.30.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.29.0 to 0.30.0.
- [Commits](https://github.com/golang/sys/compare/v0.29.0...v0.30.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 02:10:48 +00:00
Dan Finneran
c6cb548763 This ensures a hostname is resolved if passed as the api address 2025-02-05 14:51:22 +00:00
Dan Finneran
b52c90f865 You can now specify the port as the fifth argument to peer config 2025-02-05 13:37:41 +00:00
Daniel Finneran
2ceba7f5ad Update ci.yaml
Remove the original control plane tests as everything is 1.29+ at this point
2025-02-05 12:32:22 +00:00
Daniel Finneran
c3121a97f1 Update README.md 2025-02-05 12:29:53 +00:00
Daniel Finneran
b7cc63bfd6 Merge pull request #1048 from kube-vip/dependabot/go_modules/k8s.io/api-0.32.1
Bump k8s.io/api from 0.32.0 to 0.32.1
2025-02-05 12:41:22 +01:00
Daniel Finneran
3a4d859457 Merge pull request #1047 from kube-vip/dependabot/go_modules/k8s.io/client-go-0.32.1
Bump k8s.io/client-go from 0.32.0 to 0.32.1
2025-02-05 12:41:02 +01:00
Dan Finneran
964b248108 remove the waitgroups as we never wait 2025-02-05 11:37:48 +00:00
Daniel Finneran
b6e87418a2 Merge pull request #1055 from kube-vip/dependabot/go_modules/go.etcd.io/etcd/client/v3-3.5.18
Bump go.etcd.io/etcd/client/v3 from 3.5.17 to 3.5.18
2025-02-05 12:01:27 +01:00
Dan Finneran
473fd6f4f8 drop all other capabilities 2025-02-05 09:58:14 +00:00
Daniel Finneran
c49afdb44d Merge branch 'main' into dependabot/go_modules/go.etcd.io/etcd/client/v3-3.5.18 2025-02-05 10:56:55 +01:00
dependabot[bot]
f0182fcb0c Bump k8s.io/api from 0.32.0 to 0.32.1
Bumps [k8s.io/api](https://github.com/kubernetes/api) from 0.32.0 to 0.32.1.
- [Commits](https://github.com/kubernetes/api/compare/v0.32.0...v0.32.1)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-05 09:55:47 +00:00
Daniel Finneran
7424df98a5 Merge pull request #1054 from kube-vip/dependabot/go_modules/go.etcd.io/etcd/client/pkg/v3-3.5.18
Bump go.etcd.io/etcd/client/pkg/v3 from 3.5.17 to 3.5.18
2025-02-05 10:55:39 +01:00
Daniel Finneran
b4c4cfd365 Merge pull request #1053 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.18.0
Bump anchore/sbom-action from 0.17.9 to 0.18.0
2025-02-05 10:55:27 +01:00
Daniel Finneran
7878be3847 Merge branch 'main' into dependabot/go_modules/k8s.io/client-go-0.32.1 2025-02-05 10:54:25 +01:00
Daniel Finneran
1dc75f9f21 Merge pull request #1046 from kube-vip/dependabot/go_modules/k8s.io/apimachinery-0.32.1
Bump k8s.io/apimachinery from 0.32.0 to 0.32.1
2025-02-05 10:53:34 +01:00
Daniel Finneran
cbe4cd150e Merge pull request #1043 from kube-vip/slog
Refactor to slog
2025-02-05 10:53:12 +01:00
Dan Finneran
99e1fb3fc6 linting 2025-02-05 09:38:20 +00:00
Dan Finneran
e1481db95c cleanup of messages 2025-02-05 09:24:39 +00:00
Daniel Finneran
efc7ba5646 Merge pull request #1045 from kube-vip/dependabot/docker/golang-1.23.5-alpine3.20
Bump golang from 1.23.4-alpine3.20 to 1.23.5-alpine3.20
2025-02-04 11:50:23 +00:00
Daniel Finneran
90552b73dc Merge pull request #1003 from p-strusiewiczsurmacki-mobica/feature/mp-bgp
Support for MP-BGP
2025-02-04 11:42:17 +00:00
Dan Finneran
81c0b4faf5 lint fix 2025-02-04 08:42:42 +00:00
Dan Finneran
95be514b8f fixes to slog formatting 2025-02-01 14:01:27 +00:00
Daniel Finneran
d289efc862 Merge branch 'main' into slog 2025-02-01 12:18:26 +00:00
Daniel Finneran
e388b2d1c9 Merge pull request #1056 from kube-vip/ndp_error
Ndp error
2025-02-01 12:12:52 +00:00
Dan Finneran
7ca0d79250 superflous error return 2025-02-01 11:49:09 +00:00
Dan Finneran
20b375770c reduced duplicated code and cleaned messages 2025-02-01 11:44:28 +00:00
Dan Finneran
6b3ada8402 NDP link-local messages 2025-02-01 11:07:48 +00:00
Dan Finneran
c12bb65b4b adds some testing for Cilium, not for CI 2025-01-29 14:27:05 +00:00
dependabot[bot]
2e0dddba60 Bump go.etcd.io/etcd/client/v3 from 3.5.17 to 3.5.18
Bumps [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) from 3.5.17 to 3.5.18.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.17...v3.5.18)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-27 02:24:49 +00:00
dependabot[bot]
8e6767c606 Bump go.etcd.io/etcd/client/pkg/v3 from 3.5.17 to 3.5.18
Bumps [go.etcd.io/etcd/client/pkg/v3](https://github.com/etcd-io/etcd) from 3.5.17 to 3.5.18.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.17...v3.5.18)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/pkg/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-27 02:24:45 +00:00
dependabot[bot]
419051c762 Bump anchore/sbom-action from 0.17.9 to 0.18.0
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.9 to 0.18.0.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.17.9...v0.18.0)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-27 02:09:46 +00:00
Dan Finneran
9e432d1178 Fixes to swallowed errors 2025-01-24 09:20:55 +00:00
Patryk Strusiewicz-Surmacki
0832a7227c Added MP-BGP for IPv4 over IPv6 session and config flags
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2025-01-22 17:36:39 +01:00
Christopher Dziomba
3b16caa38c Messy prototype of MP-BGP with kube-vip 2025-01-21 12:10:07 +01:00
dependabot[bot]
1d4e57a754 Bump k8s.io/client-go from 0.32.0 to 0.32.1
Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.32.0 to 0.32.1.
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.32.0...v0.32.1)

---
updated-dependencies:
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 02:36:19 +00:00
dependabot[bot]
c36585ce98 Bump k8s.io/apimachinery from 0.32.0 to 0.32.1
Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.32.0 to 0.32.1.
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.32.0...v0.32.1)

---
updated-dependencies:
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 02:36:11 +00:00
dependabot[bot]
af1280be1a Bump golang from 1.23.4-alpine3.20 to 1.23.5-alpine3.20
Bumps golang from 1.23.4-alpine3.20 to 1.23.5-alpine3.20.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-20 02:32:12 +00:00
Dan Finneran
c01fb8fca7 fix_spelling 2025-01-16 18:39:02 +00:00
Dan Finneran
1d6d860153 set default loglevel 2025-01-16 17:46:11 +00:00
Dan Finneran
2136e69a82 Big refactor to log/slog 2025-01-16 17:45:09 +00:00
Daniel Finneran
cb438d289b Merge pull request #1040 from kube-vip/restart_on_modification
Restart on modification
2025-01-16 12:50:20 +00:00
Dan Finneran
ded08ddf5c Fixing nits 2025-01-16 10:45:36 +00:00
Dan Finneran
79b24875ec le sigh 2025-01-16 09:46:18 +00:00
Daniel Finneran
b423cbdb89 Merge branch 'main' into restart_on_modification 2025-01-16 09:26:52 +00:00
Daniel Finneran
600c1db24b Merge pull request #1036 from kube-vip/logic_clean
This removes some weird pointless code
2025-01-16 09:25:56 +00:00
Dan Finneran
b2979be25c Linting fixes 2025-01-15 11:19:09 +00:00
Dan Finneran
462b511b9f This change means that a modification to an existing LB results in updating the settings. 2025-01-15 11:10:19 +00:00
Daniel Finneran
19e660d4a6 Update Makefile 2025-01-14 13:29:35 +00:00
Daniel Finneran
cfa11d1a88 Merge pull request #1037 from kube-vip/dependabot/go_modules/github.com/onsi/ginkgo/v2-2.22.2
Bump github.com/onsi/ginkgo/v2 from 2.22.1 to 2.22.2
2025-01-14 13:29:16 +00:00
Daniel Finneran
bf283f1252 Merge pull request #1038 from kube-vip/dependabot/docker/alpine-3.21.2
Bump alpine from 3.21.0 to 3.21.2
2025-01-14 13:29:00 +00:00
dependabot[bot]
839b860eee Bump alpine from 3.21.0 to 3.21.2
Bumps alpine from 3.21.0 to 3.21.2.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-13 02:54:42 +00:00
dependabot[bot]
e134e5682e Bump github.com/onsi/ginkgo/v2 from 2.22.1 to 2.22.2
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.22.1 to 2.22.2.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.22.1...v2.22.2)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-13 02:26:18 +00:00
Dan Finneran
ebc4cdccb9 more_lint 2025-01-12 13:02:08 +00:00
Dan Finneran
baed70dbfc fix_linting 2025-01-12 12:53:05 +00:00
Dan Finneran
b8aff1d348 fix_lint 2025-01-12 12:52:58 +00:00
Dan Finneran
aa5f0cc267 This removes some weird pointless code 2025-01-12 11:36:30 +00:00
Daniel Finneran
316c3bbdd4 Merge pull request #1034 from murphp15/feature/release_the_lock_if_you_cant_advertise_service
release lock if unable to sync service correctly.
2025-01-10 16:17:37 +00:00
paul.murphy
dbc02485d9 release lock if unable to sync service correctly. 2025-01-10 15:54:08 +00:00
paul.murphy
6442ce26fc release lock if unable to sync service correctly. 2025-01-10 15:37:41 +00:00
Paul Murphy
ccd1137606 Merge branch 'kube-vip:main' into feature/release_the_lock_if_you_cant_advertise_service 2025-01-10 14:47:32 +00:00
Daniel Finneran
96d79774b5 Merge pull request #1035 from kube-vip/print_build_info
by default print build
2025-01-10 14:22:12 +00:00
Dan Finneran
829a1fced6 by default print build 2025-01-10 14:20:35 +00:00
paul.murphy
0c5dd3c890 release lock if unable to sync service correctly. 2025-01-10 10:49:51 +00:00
paul.murphy
51aad755c3 release lock if unable to sync service correctly. 2025-01-10 10:49:34 +00:00
paul.murphy
635950e329 release lock if unable to sync service correctly. 2025-01-10 10:45:33 +00:00
paul.murphy
7eb93bec0b Merge branch 'main' into feature/release_the_lock_if_you_cant_advertise_service 2025-01-10 10:39:19 +00:00
paul.murphy
cf8384fb1f release lock if unable to sync service correctly. 2025-01-10 10:36:45 +00:00
Daniel Finneran
6da951056c Merge pull request #1030 from kube-vip/services_fix
Ensure watcher is restarted as expected
2025-01-09 11:35:41 +00:00
Daniel Finneran
a50e476d7e Merge pull request #1029 from kube-vip/watcher-fix
Fixes an issue with watchers having an old reference
2025-01-09 11:21:37 +00:00
Dan Finneran
329e0940da Ensure watcher is restarted as expected 2025-01-09 11:05:03 +00:00
Dan Finneran
7a43646e62 Fixes an issue with watchers having an old reference 2025-01-08 18:27:30 +00:00
Daniel Finneran
dd8f2d13d2 Update Makefile 2025-01-06 13:47:49 +00:00
Daniel Finneran
f119c890a1 Merge pull request #1024 from kube-vip/small_fix
Fix linting issue
2025-01-06 13:46:49 +00:00
Dan Finneran
714b80225f Fix linting issue 2025-01-06 10:52:48 +00:00
Daniel Finneran
49297980b0 Merge pull request #923 from cdtzabra/main
Ensuring nodelabel will be always present
2025-01-06 10:51:31 +00:00
Daniel Finneran
e7beb9c9c3 Merge pull request #1012 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.17.9
Bump anchore/sbom-action from 0.17.5 to 0.17.9
2025-01-06 10:23:02 +00:00
dependabot[bot]
5e66a62c32 Bump anchore/sbom-action from 0.17.5 to 0.17.9
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.5 to 0.17.9.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.17.5...v0.17.9)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-06 09:54:08 +00:00
Daniel Finneran
fbbf83d9d0 Merge pull request #1008 from kube-vip/dependabot/docker/golang-1.23.4-alpine3.20
Bump golang from 1.23.2-alpine3.20 to 1.23.4-alpine3.20
2025-01-06 09:51:24 +00:00
Daniel Finneran
7e244084e1 Merge pull request #1022 from kube-vip/deps
update deps
2025-01-06 09:50:40 +00:00
Dan Finneran
089ad123b6 losing hope 2025-01-05 17:12:35 +00:00
Dan Finneran
fdc50efc86 clutching at straws now 2025-01-05 17:10:24 +00:00
Dan Finneran
7644cb720e attempt 2 2025-01-05 17:05:48 +00:00
Dan Finneran
299c9e1ebb updatae go.mod 2025-01-05 16:02:06 +00:00
Dan Finneran
b82b733dde CI fix 2025-01-05 15:58:58 +00:00
Dan Finneran
e339d12b40 update deps 2025-01-05 15:53:34 +00:00
dependabot[bot]
3ea17b134d Bump golang from 1.23.2-alpine3.20 to 1.23.4-alpine3.20
Bumps golang from 1.23.2-alpine3.20 to 1.23.4-alpine3.20.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-05 15:30:03 +00:00
Daniel Finneran
ea410e7490 Merge pull request #1007 from kube-vip/dependabot/docker/alpine-3.21.0
Bump alpine from 3.20.3 to 3.21.0
2025-01-05 15:29:04 +00:00
Daniel Finneran
430efae598 Merge pull request #1019 from kube-vip/egress_annotations
Adds a bunch of flexability around egress
2025-01-05 15:27:29 +00:00
Dan Finneran
c96cdb6cd2 test fix 2025-01-05 15:03:53 +00:00
Dan Finneran
ffe2e9c808 Various fixes to CI 2025-01-05 14:59:51 +00:00
Dan Finneran
545f9a4a47 fix to modules and workflow 2024-12-20 16:38:56 +00:00
Dan Finneran
2555dd8101 Adds a bunch of flexability around egress 2024-12-20 16:25:06 +00:00
dependabot[bot]
f7b4ab5b42 Bump alpine from 3.20.3 to 3.21.0
Bumps alpine from 3.20.3 to 3.21.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-09 02:39:44 +00:00
Daniel Finneran
4c70d87381 Update Makefile 2024-11-20 09:08:47 +00:00
Dan Finneran
894e56458f remove commented out code 2024-11-15 17:07:51 +01:00
Dan Finneran
de5659e7b2 Services aren't removed when there are no endpoints. 2024-11-15 17:07:51 +01:00
Marcel Fest
e4b0b2a71f Use the new release version in Makefile
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2024-11-11 08:56:48 +01:00
Daniel Finneran
dd06c3fb82 Merge pull request #987 from p-strusiewiczsurmacki-mobica/rwclient-ipvs-fix
Fixed null pointer exception when IPVS loadbalancer is used
2024-11-04 11:31:28 +00:00
Patryk Strusiewicz-Surmacki
8ee952cf3e Fixed null pointer exception when IPVS loadbalancer is used
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-11-04 11:50:34 +01:00
Daniel Finneran
57bcea9646 Merge pull request #984 from kube-vip/fix/retry-watch
initialize the config for the rwclient separately
2024-11-01 11:33:00 +00:00
Cellebyte
907696a4a3 initialize the config for the rwclient separately
Signed-off-by: Cellebyte <marcel.fest@live.de>
2024-11-01 10:50:09 +01:00
Daniel Finneran
78cdf8d5b6 Merge pull request #981 from kube-vip/New-release-0.8.5 2024-10-31 12:59:10 +00:00
Daniel Finneran
5a7edbe825 Merge pull request #976 from l0wl3vel/upnp-gateway-ip 2024-10-31 12:47:35 +00:00
Daniel Finneran
de8300a40a Merge pull request #961 from p-strusiewiczsurmacki-mobica/auto-svc-subnet 2024-10-31 12:46:10 +00:00
Patryk Strusiewicz-Surmacki
73e6ade0ea Added auto subnet discovery for services in ARP mode
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-31 10:31:39 +01:00
Benjamin Ritter
4def2c784e Update Gateway IPs on UPNP refresh
Signed-off-by: Benjamin Ritter <Benjamin.Ritter@protonmail.com>
2024-10-30 17:51:00 +01:00
Benjamin Ritter
1c8ce223d7 Reduce UPNP refresh interval to 5 minutes
Reduces impact on availibility when the
gateway external IP changes

Signed-off-by: Benjamin Ritter <Benjamin.Ritter@protonmail.com>
2024-10-30 17:51:00 +01:00
Benjamin Ritter
02d00bf99c Annotate UPNP Gateway IPs on the service
Signed-off-by: Benjamin Ritter <Benjamin.Ritter@protonmail.com>
2024-10-30 17:51:00 +01:00
Daniel Finneran
4433243fa6 Update Makefile
This PR should be the last merged PR for the 0.8.5 release, which should also be the last of the `0.8.x` releases.
2024-10-30 15:21:43 +00:00
Daniel Finneran
a8ae976bb2 Merge pull request #968 from kube-vip/dependabot/go_modules/github.com/cloudflare/ipvs-0.10.2
Bump github.com/cloudflare/ipvs from 0.10.1 to 0.10.2
2024-10-30 14:38:40 +00:00
Daniel Finneran
1559b21cfb Merge pull request #954 from l0wl3vel/upnp-igd2
Use IGD:2 and Pinhole Port Forwarding
2024-10-30 14:37:34 +00:00
Daniel Finneran
f55aed4382 Merge pull request #979 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.17.5
Bump anchore/sbom-action from 0.17.3 to 0.17.5
2024-10-30 14:36:21 +00:00
Daniel Finneran
cc12fcb0f6 Merge pull request #970 from p-strusiewiczsurmacki-mobica/egress-rules-fix
Egress rules deletion fix
2024-10-30 14:36:00 +00:00
Patryk Strusiewicz-Surmacki
95dfc47e47 Added info on egress protocol
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-30 14:31:41 +01:00
Patryk Strusiewicz-Surmacki
0bf38f57f7 Fixed logging issues
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-29 11:46:24 +01:00
Patryk Strusiewicz-Surmacki
7f4116417c Fixed typo
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-29 11:46:24 +01:00
Patryk Strusiewicz-Surmacki
5763400c15 Added safeguards for IP family
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-29 11:46:24 +01:00
Patryk Strusiewicz-Surmacki
6b136efff3 Added changes to CIDR discovery from auto-svc-subnet branch
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-29 11:46:24 +01:00
Patryk Strusiewicz-Surmacki
1f089fe71c Added routing table ID fix
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-29 11:46:24 +01:00
Patryk Strusiewicz-Surmacki
1bc26b5827 Fixed e2e
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-29 11:46:24 +01:00
Patryk Strusiewicz-Surmacki
40674a12b6 Fixed route deleting issue in table mode
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-29 11:46:24 +01:00
Patryk Strusiewicz-Surmacki
ef2f6ebaa0 Fixed auto CIDR discovery priority
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-29 11:46:24 +01:00
Patryk Strusiewicz-Surmacki
625030dfb6 Fixed retry-watcher timeout issue (#974)
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-28 20:14:05 +01:00
Benjamin Ritter
779fc5641f Add context to UPNP logging
Signed-off-by: Benjamin Ritter <Benjamin.Ritter@protonmail.com>
2024-10-28 15:24:18 +01:00
dependabot[bot]
971e794639 Bump anchore/sbom-action from 0.17.3 to 0.17.5
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.3 to 0.17.5.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.17.3...v0.17.5)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-28 02:36:00 +00:00
Patryk Strusiewicz-Surmacki
89c6002f92 Fixed NDP responder (#973)
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-27 22:27:55 +01:00
Benjamin Ritter
6b0e45da96 Clean up UPNP client handling
Signed-off-by: Benjamin Ritter <Benjamin.Ritter@protonmail.com>
2024-10-27 20:50:32 +01:00
Benjamin Ritter
7bde7a4845 feat: Add perpetual UPNP Forward refreshing
Signed-off-by: Benjamin Ritter <Benjamin.Ritter@protonmail.com>
2024-10-24 21:54:44 +02:00
Benjamin Ritter
eda0bd69b3 Use IGD:2 and Pinhole Port Forwarding
Signed-off-by: Benjamin Ritter <Benjamin.Ritter@protonmail.com>
2024-10-24 21:54:30 +02:00
dependabot[bot]
2a56bdb0c8 Bump github.com/cloudflare/ipvs from 0.10.1 to 0.10.2
Bumps [github.com/cloudflare/ipvs](https://github.com/cloudflare/ipvs) from 0.10.1 to 0.10.2.
- [Release notes](https://github.com/cloudflare/ipvs/releases)
- [Commits](https://github.com/cloudflare/ipvs/compare/v0.10.1...v0.10.2)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/ipvs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 02:20:18 +00:00
Daniel Finneran
de0375610d Merge pull request #965 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.17.3
Bump anchore/sbom-action from 0.17.2 to 0.17.3
2024-10-18 11:18:27 +02:00
Daniel Finneran
382024104a Merge pull request #964 from kube-vip/dependabot/go_modules/github.com/spf13/cobra-1.8.1
Bump github.com/spf13/cobra from 1.8.0 to 1.8.1
2024-10-18 11:18:08 +02:00
dependabot[bot]
e896b55c25 Bump anchore/sbom-action from 0.17.2 to 0.17.3
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.2 to 0.17.3.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.17.2...v0.17.3)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-14 02:50:27 +00:00
dependabot[bot]
53ce87755a Bump github.com/spf13/cobra from 1.8.0 to 1.8.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-14 02:31:14 +00:00
Daniel Finneran
750f78164f Merge pull request #918 from kube-vip/dependabot/go_modules/k8s.io/klog/v2-2.130.1
Bump k8s.io/klog/v2 from 2.120.1 to 2.130.1
2024-10-10 09:41:30 +01:00
Daniel Finneran
bf6cb8e39e Merge pull request #887 from kube-vip/dependabot/github_actions/docker/build-push-action-6
Bump docker/build-push-action from 5 to 6
2024-10-10 09:39:55 +01:00
Daniel Finneran
f58e110057 Update Makefile 2024-10-10 09:39:28 +01:00
dependabot[bot]
98db46c817 Bump k8s.io/klog/v2 from 2.120.1 to 2.130.1
Bumps [k8s.io/klog/v2](https://github.com/kubernetes/klog) from 2.120.1 to 2.130.1.
- [Release notes](https://github.com/kubernetes/klog/releases)
- [Changelog](https://github.com/kubernetes/klog/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes/klog/compare/v2.120.1...v2.130.1)

---
updated-dependencies:
- dependency-name: k8s.io/klog/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-10 08:28:26 +00:00
Daniel Finneran
da9b440f1e Merge pull request #939 from kube-vip/dependabot/docker/alpine-3.20.3
Bump alpine from 3.20.0 to 3.20.3
2024-10-10 09:27:48 +01:00
dependabot[bot]
a18039373d Bump docker/build-push-action from 5 to 6
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-10 08:27:05 +00:00
Daniel Finneran
a9753fafd2 Merge pull request #960 from kube-vip/dependabot/docker/golang-1.23.2-alpine3.20
Bump golang from 1.23.1-alpine3.20 to 1.23.2-alpine3.20
2024-10-10 09:26:45 +01:00
Daniel Finneran
8aa0a6b9e0 Merge pull request #958 from p-strusiewiczsurmacki-mobica/control-plane-table-e2e
Added e2e tests for control-plane in routing table mode, fixed IPv6 issue
2024-10-07 17:00:48 +01:00
dependabot[bot]
8f16021e4c Bump golang from 1.23.1-alpine3.20 to 1.23.2-alpine3.20
Bumps golang from 1.23.1-alpine3.20 to 1.23.2-alpine3.20.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-07 02:27:00 +00:00
Patryk Strusiewicz-Surmacki
456d52d507 Added e2e tests for control-plane in routing table mode and fixed IPv6 issue
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-03 17:11:57 +02:00
Daniel Finneran
4da24fb64f Merge pull request #957 from p-strusiewiczsurmacki-mobica/control-plane-table-mode
Routing Table mode for Control Plane
2024-10-03 11:27:15 +02:00
Daniel Finneran
c27044b521 Merge pull request #952 from l0wl3vel/upnp-forward-multiple-ports
UPNP: Assume that multiple ports can exist on a service
2024-10-02 13:23:20 +02:00
Patryk Strusiewicz-Surmacki
810cf89f97 Routing Table mode for Control Plane
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-01 18:00:59 +02:00
Patryk Strusiewicz-Surmacki
d65af2c84f Fixed lastKnownGoodEndpoint not being set when in non-leader-election mode (#955)
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-10-01 14:29:42 +02:00
Daniel Finneran
d30fda1d9d Merge pull request #956 from tenyo/lo-iface-scope
Add loInterfaceGlobalScope flag for enabling global scope for vip lo interface
2024-09-30 14:24:42 +02:00
tenyo
b6d4aa1632 add loInterfaceGlobalScope flag for enabling global scope for vip lo interface
Signed-off-by: tenyo <tgrozev@equinix.com>
2024-09-27 20:21:51 +00:00
Benjamin Ritter
b024d04d91 Assume that multiple ports can exist on a service
Fixes UPNP exposing only the port with the lowest numeric value. #951

Signed-off-by: Benjamin Ritter <Benjamin.Ritter@protonmail.com>
2024-09-24 16:06:43 +02:00
Daniel Finneran
6cdc7a86c4 Merge pull request #950 from l0wl3vel/upnp-per-service
Enable UPNP Port forwarding per service
2024-09-24 08:47:26 +01:00
Benjamin Ritter
c6f1c740fd feat: Gate UPNP port forwarding behind kube-vip.io/forwardUPNP annotation
Signed-off-by: Benjamin Ritter <Benjamin.Ritter@protonmail.com>
2024-09-22 10:31:32 +02:00
Daniel Finneran
95c43472e9 Update Makefile 2024-09-09 13:34:45 +01:00
dependabot[bot]
c8a222e244 Bump alpine from 3.20.0 to 3.20.3
Bumps alpine from 3.20.0 to 3.20.3.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 08:30:04 +00:00
Daniel Finneran
37abb44a64 Merge pull request #940 from kube-vip/dependabot/docker/golang-1.23.1-alpine3.20
Bump golang from 1.22.6-alpine3.20 to 1.23.1-alpine3.20
2024-09-09 09:25:34 +01:00
dependabot[bot]
b4e6725a1a Bump golang from 1.22.6-alpine3.20 to 1.23.1-alpine3.20
Bumps golang from 1.22.6-alpine3.20 to 1.23.1-alpine3.20.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 02:29:55 +00:00
Daniel Finneran
b6410d9b4d Merge pull request #927 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.17.2
Bump anchore/sbom-action from 0.17.0 to 0.17.2
2024-09-06 16:11:49 +03:00
Daniel Finneran
4bdfeffc96 Merge pull request #937 from thebsdbox/ipv6_egress
This adds ipv6 egress & test
2024-09-06 16:11:35 +03:00
Daniel Finneran
a32804dfee Update pkg/vip/util.go
I like it

Co-authored-by: Patryk Strusiewicz-Surmacki <137421299+p-strusiewiczsurmacki-mobica@users.noreply.github.com>
2024-09-06 12:31:03 +01:00
Dan Finneran
b24ce18d55 Fix test
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-09-05 12:40:24 +00:00
Dan Finneran
5512a08aac restored the exact behaviour for IPv4
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-09-05 12:22:41 +00:00
Dan Finneran
f438367d6e This adds ipv6 egress & test
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-09-05 12:08:39 +00:00
cdtzabra
62a724122c Update node_labeling.go 2024-09-03 12:19:51 +02:00
Daniel Finneran
fb86cb8687 Merge pull request #929 from linsite/cleanup-makefile
clean up Makefile
2024-09-02 15:59:31 +03:00
linmaolin
29a0dc6c07 clean up Makefile
fmt target is stale, just removing it, also simplify target is not working under 1.21 toolchain,
update it as well.

Signed-off-by: Lin Lin <linlin152@foxmail.com>
2024-08-28 11:57:40 +08:00
dependabot[bot]
82f3c6a491 Bump anchore/sbom-action from 0.17.0 to 0.17.2
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.17.0 to 0.17.2.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.17.0...v0.17.2)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 02:53:48 +00:00
Daniel Finneran
fbb2746d07 Merge pull request #926 from p-strusiewiczsurmacki-mobica/svc-auto-interface
Auto network interface discovery for services
2024-08-23 17:55:26 +01:00
Patryk Strusiewicz-Surmacki
185d8bc484 Auto network interface discovery for services
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-08-23 15:15:11 +02:00
cdtzabra
db88185c40 Merge pull request #1 from cdtzabra/cdtzabra-patch-1
Ensuring nodelabel will be always present
2024-08-21 18:24:01 +02:00
cdtzabra
611cb0288f Ensuring nodelabel will be always present 2024-08-21 18:22:57 +02:00
Daniel Finneran
b18bdd0fb9 Merge pull request #872 from kube-vip/dependabot/go_modules/github.com/stretchr/testify-1.9.0
Bump github.com/stretchr/testify from 1.8.4 to 1.9.0
2024-08-15 12:46:28 +01:00
Daniel Finneran
8ef0d459c0 Merge pull request #902 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.17.0
Bump anchore/sbom-action from 0.16.0 to 0.17.0
2024-08-12 15:16:44 +02:00
Daniel Finneran
41bc78bc8f Merge pull request #915 from kube-vip/dependabot/docker/golang-1.22.6-alpine3.20
Bump golang from 1.22.4-alpine3.20 to 1.22.6-alpine3.20
2024-08-12 15:16:30 +02:00
Daniel Finneran
05984b9860 Merge pull request #910 from M0NsTeRRR/fix/ipv6-port-join
fix: ipv6 host and port join
2024-08-12 15:16:13 +02:00
dependabot[bot]
82b1e8536b Bump golang from 1.22.4-alpine3.20 to 1.22.6-alpine3.20
Bumps golang from 1.22.4-alpine3.20 to 1.22.6-alpine3.20.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 02:26:32 +00:00
Daniel Finneran
425cb92dee Merge pull request #904 from M0NsTeRRR/main
fix: set vip_cidr default value
2024-08-07 10:37:53 +02:00
Ludovic Ortega
9470edbea9 fix: ipv6 host and port join
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-08-07 00:48:59 +02:00
Ludovic Ortega
a5d6846608 fix: set vip_cidr default value
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-07-23 21:15:12 +02:00
Daniel Finneran
04ce471366 Update Makefile 2024-07-23 09:27:46 +01:00
Daniel Finneran
6c090701ea Merge pull request #897 from TilBlechschmidt/bug/dhcp-renew-failure
Change service interface to `macvlan` when using DHCP
2024-07-23 09:25:41 +01:00
dependabot[bot]
87fd49ac98 Bump anchore/sbom-action from 0.16.0 to 0.17.0
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.16.0 to 0.17.0.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 02:47:10 +00:00
Til Blechschmidt
a0a19ea3fa Change service interface to macvlan when using DHCP
When using DHCP for LB services, the resulting IP was assigned to the
`serviceInterface` while most (not all) DHCP communication was done
through a per-service `macvlan` interface that is created on demand.

This has been the cause of DHCP lease renewal failures for some users,
as the response packets from the server never reached kube-vip. For more
details, see issue #871.

To remedy this, the primary interface used for a service is now being
set to the `macvlan`. Consequently, the IP address is also assigned to
it.

As a result, all traffic related to an LB service (DHCP or not) is now
originating from and sent to the per-service `macvlan` interface that
is tied to the user-configured `serviceInterface`.

Fixes #871

Signed-off-by: Til Blechschmidt <me@tibl.dev>
2024-07-19 12:26:43 +02:00
Daniel Finneran
a571d0a9c2 Merge pull request #894 from thebsdbox/manifest_fix
Manifest fix
2024-07-11 09:14:40 +01:00
Dan Finneran
6f267462bb linting fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-07-11 08:03:51 +00:00
Dan Finneran
a52e9a1818 adds CI test
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-07-10 15:24:32 +00:00
Dan Finneran
e883c1ea5d fixes manifest generation
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-07-10 15:15:24 +00:00
Marcel Fest
59951cbd4b [Bugfix] Parse the routingTableID correctly (#889)
* Parse the routingTableID correctly [rtnetlink.h](55027e6899/include/uapi/linux/rtnetlink.h\#L354C15-L354C25) says RT_TABLE_MAX=0xFFFFFFFF

Signed-off-by: Marcel Fest <marcel.fest@telekom.de>

* Better error handling for int check

Signed-off-by: Marcel Fest <marcel.fest@telekom.de>

* Better error message + typo fix

Signed-off-by: Marcel Fest <marcel.fest@telekom.de>

* Use MaxInt instead of MaxUint

Signed-off-by: Marcel Fest <marcel.fest@telekom.de>

---------

Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2024-06-26 12:29:07 +02:00
Daniel Finneran
9abce4a215 Update Makefile 2024-06-21 15:31:03 +01:00
Daniel Finneran
0b33aa64fc Merge pull request #884 from thebsdbox/go_security
bump golang for security fix
2024-06-21 15:30:47 +01:00
Dan Finneran
57980bd23f bump golang for security fix
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-06-21 14:18:58 +00:00
Daniel Finneran
69f4c389c5 Merge pull request #883 from thebsdbox/prometheus_fix
This allows prometheus configuration to be specified in the cli
2024-06-21 15:18:28 +01:00
Dan Finneran
f56c9b7480 This allows prometheus configuration to be specified in the cli
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-06-21 13:47:14 +00:00
dependabot[bot]
f8af9c37af Bump github.com/stretchr/testify from 1.8.4 to 1.9.0
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.4 to 1.9.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 02:59:36 +00:00
Daniel Finneran
c16f634cf7 Merge pull request #869 from kube-vip/dependabot/go_modules/github.com/osrg/gobgp/v3-3.27.0
Bump github.com/osrg/gobgp/v3 from 3.25.0 to 3.27.0
2024-06-05 11:06:15 +01:00
dependabot[bot]
5df534a1e7 Bump github.com/osrg/gobgp/v3 from 3.25.0 to 3.27.0
Bumps [github.com/osrg/gobgp/v3](https://github.com/osrg/gobgp) from 3.25.0 to 3.27.0.
- [Release notes](https://github.com/osrg/gobgp/releases)
- [Changelog](https://github.com/osrg/gobgp/blob/master/.goreleaser.yml)
- [Commits](https://github.com/osrg/gobgp/compare/v3.25.0...v3.27.0)

---
updated-dependencies:
- dependency-name: github.com/osrg/gobgp/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-04 13:20:19 +00:00
Daniel Finneran
ee535938b4 Merge pull request #861 from kube-vip/dependabot/go_modules/github.com/onsi/ginkgo/v2-2.19.0
Bump github.com/onsi/ginkgo/v2 from 2.17.2 to 2.19.0
2024-06-04 14:19:14 +01:00
Daniel Finneran
0df8a0dff4 Merge pull request #862 from kube-vip/dependabot/docker/alpine-3.20.0
Bump alpine from 3.19.1 to 3.20.0
2024-06-04 14:17:22 +01:00
Daniel Finneran
0e2a10535b Merge pull request #860 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.16.0
Bump anchore/sbom-action from 0.15.11 to 0.16.0
2024-06-04 14:17:08 +01:00
Daniel Finneran
b5d9ede6f8 Merge pull request #855 from p-strusiewiczsurmacki-mobica/lbclass-filtering
New service class filtering behavior
2024-06-04 14:16:51 +01:00
Daniel Finneran
94bad6d53b Merge pull request #868 from murphp15/main
Small correction to docs on retryPeriod property
2024-06-04 14:16:38 +01:00
Paul Murphy
927bb95ead Update kube-vip.go 2024-06-04 13:33:20 +01:00
Paul Murphy
7b96ebc7d4 Update config_types.go 2024-06-04 12:34:41 +01:00
Paul Murphy
5b05f365f1 Update kube-vip.go 2024-06-04 12:33:19 +01:00
dependabot[bot]
cd3d8a592c Bump alpine from 3.19.1 to 3.20.0
Bumps alpine from 3.19.1 to 3.20.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 02:42:31 +00:00
dependabot[bot]
e69fadf19b Bump github.com/onsi/ginkgo/v2 from 2.17.2 to 2.19.0
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.17.2 to 2.19.0.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.17.2...v2.19.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 02:35:13 +00:00
dependabot[bot]
5ded2d7574 Bump anchore/sbom-action from 0.15.11 to 0.16.0
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.15.11 to 0.16.0.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.15.11...v0.16.0)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-27 02:12:43 +00:00
Marcel Fest
c683bb879e Merge pull request #854 from kube-vip/hotfix/route-deletion
[Hotfix] Routes get not deleted when kube-vip is running without LeaderElection/ServiceElection in Table Mode
2024-05-17 15:53:57 +02:00
Daniel Finneran
392583d460 Merge pull request #853 from M0NsTeRRR/main
feat: generate VIPCIDR if not value is set
2024-05-17 14:15:23 +01:00
Patryk Strusiewicz-Surmacki
abf49f2fa6 New service class filtering behavior
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-05-17 14:45:30 +02:00
Marcel Fest
25c2532e74 when in table mode we always want to clean routes
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2024-05-17 12:30:53 +02:00
Ludovic Ortega
28918e839f feat: generate VIPCIDR if not value is set
Signed-off-by: Ludovic Ortega <ludovic.ortega@adminafk.fr>
2024-05-16 22:42:53 +02:00
Daniel Finneran
1620e4c890 Merge pull request #846 from testwill/close_file
fix: close file
2024-05-16 09:19:24 +01:00
guoguangwu
c8bdf61a87 fix: close file
Signed-off-by: guoguangwu <guoguangwug@gmail.com>
2024-05-15 19:13:41 +08:00
Daniel Finneran
e9835aa981 Merge pull request #847 from kube-vip/dependabot/docker/golang-1.22.3-alpine3.18
Bump golang from 1.22.2-alpine3.18 to 1.22.3-alpine3.18
2024-05-15 11:59:21 +01:00
dependabot[bot]
ca3dad817d Bump golang from 1.22.2-alpine3.18 to 1.22.3-alpine3.18
Bumps golang from 1.22.2-alpine3.18 to 1.22.3-alpine3.18.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-13 02:39:51 +00:00
Daniel Finneran
cb29d7cb17 Merge pull request #840 from kube-vip/dependabot/go_modules/github.com/onsi/gomega-1.33.1
Bump github.com/onsi/gomega from 1.32.0 to 1.33.1
2024-05-09 08:49:20 +01:00
Daniel Finneran
0fa7cbdab8 Merge pull request #834 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.15.11
Bump anchore/sbom-action from 0.15.10 to 0.15.11
2024-05-09 08:49:08 +01:00
dependabot[bot]
0038c27fec Bump github.com/onsi/gomega from 1.32.0 to 1.33.1
Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.32.0 to 1.33.1.
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/gomega/compare/v1.32.0...v1.33.1)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-08 14:01:32 +00:00
Daniel Finneran
4c19a3370c Merge pull request #826 from kube-vip/dependabot/go_modules/github.com/prometheus/client_golang-1.19.0
Bump github.com/prometheus/client_golang from 1.18.0 to 1.19.0
2024-05-08 14:59:30 +01:00
Daniel Finneran
25abee70cd Merge pull request #833 from kube-vip/dependabot/go_modules/github.com/onsi/ginkgo/v2-2.17.2
Bump github.com/onsi/ginkgo/v2 from 2.15.0 to 2.17.2
2024-05-08 14:58:37 +01:00
Daniel Finneran
057a32d191 Merge pull request #838 from p-strusiewiczsurmacki-mobica/route-deletion-fix
Fixed route deletion when route is used by more than one service
2024-05-08 14:58:21 +01:00
Daniel Finneran
b33a7b6d32 Merge pull request #837 from starbops/fix-835
fix: set service's uid in activeService map for inactive services
2024-05-08 14:57:58 +01:00
Patryk Strusiewicz-Surmacki
ba0c9282e7 Fixed route deletion when route is used by more than one service
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-04-30 14:44:26 +02:00
Zespre Schmidt
a431daab42 fix: set service's uid in activeService map for inactive services
Signed-off-by: Zespre Schmidt <starbops@zespre.com>
2024-04-30 16:31:10 +08:00
dependabot[bot]
54e4334b9f Bump anchore/sbom-action from 0.15.10 to 0.15.11
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.15.10 to 0.15.11.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.15.10...v0.15.11)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-29 02:55:01 +00:00
dependabot[bot]
6545a5aaab Bump github.com/onsi/ginkgo/v2 from 2.15.0 to 2.17.2
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.15.0 to 2.17.2.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.15.0...v2.17.2)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-29 02:13:32 +00:00
Daniel Finneran
2872256a89 Merge pull request #832 from ShivanshVij/main
fix: unecessary string modification
2024-04-25 08:26:35 +01:00
Shivansh Vij
a1ae304d07 fix: unecessary string modification
Signed-off-by: Shivansh Vij <shivanshvij@loopholelabs.io>
2024-04-24 12:32:27 -07:00
dependabot[bot]
c90d2043f0 Bump github.com/prometheus/client_golang from 1.18.0 to 1.19.0
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.18.0 to 1.19.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.18.0...v1.19.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-22 02:47:11 +00:00
Daniel Finneran
722c47fc08 Update Makefile 2024-04-18 18:11:51 +01:00
Daniel Finneran
27fae664fe Merge pull request #821 from kube-vip/dependabot/go_modules/go.etcd.io/etcd/client/v3-3.5.13
Bump go.etcd.io/etcd/client/v3 from 3.5.11 to 3.5.13
2024-04-18 15:12:18 +01:00
Daniel Finneran
7349576e5b Merge pull request #820 from thebsdbox/bgp_err
Errors are being ignored
2024-04-18 14:59:08 +01:00
dependabot[bot]
1ab5047941 Bump go.etcd.io/etcd/client/v3 from 3.5.11 to 3.5.13
Bumps [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) from 3.5.11 to 3.5.13.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.11...v3.5.13)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-18 13:52:10 +00:00
Dan Finneran
950264e403 lint fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-04-18 13:44:08 +00:00
Dan Finneran
0686b92376 Errors are being ignored
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-04-18 13:38:38 +00:00
Daniel Finneran
b7ebb21dc0 Merge pull request #796 from kube-vip/dependabot/go_modules/github.com/onsi/gomega-1.32.0
Bump github.com/onsi/gomega from 1.30.0 to 1.32.0
2024-04-18 14:22:50 +01:00
Daniel Finneran
ab904e2e18 Merge pull request #819 from thebsdbox/example
Examples and fixes to annotation interface
2024-04-18 14:22:37 +01:00
Dan Finneran
a5d4d0ca98 Examples and fixes to annotation interface
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-04-18 13:02:21 +00:00
dependabot[bot]
7fb301d3b3 Bump github.com/onsi/gomega from 1.30.0 to 1.32.0
Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.30.0 to 1.32.0.
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/gomega/compare/v1.30.0...v1.32.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-18 10:01:12 +00:00
Daniel Finneran
aa4da2f72a Merge pull request #816 from thebsdbox/interface_annotation
Adds annotation support for service interfaces.
2024-04-18 11:00:33 +01:00
Daniel Finneran
5dc91e6b3b Merge pull request #806 from kube-vip/dependabot/go_modules/github.com/osrg/gobgp/v3-3.25.0
Bump github.com/osrg/gobgp/v3 from 3.22.0 to 3.25.0
2024-04-18 10:58:29 +01:00
dependabot[bot]
658ca8697e Bump github.com/osrg/gobgp/v3 from 3.22.0 to 3.25.0
Bumps [github.com/osrg/gobgp/v3](https://github.com/osrg/gobgp) from 3.22.0 to 3.25.0.
- [Release notes](https://github.com/osrg/gobgp/releases)
- [Changelog](https://github.com/osrg/gobgp/blob/master/.goreleaser.yml)
- [Commits](https://github.com/osrg/gobgp/compare/v3.22.0...v3.25.0)

---
updated-dependencies:
- dependency-name: github.com/osrg/gobgp/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-18 09:47:41 +00:00
Daniel Finneran
979c016d98 Merge pull request #817 from thebsdbox/linting
fixes to linting
2024-04-18 10:45:32 +01:00
Dan Finneran
8e4abea78e fixes to linting
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-04-18 09:35:04 +00:00
Daniel Finneran
3caedde7fe Merge pull request #801 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.15.10
Bump anchore/sbom-action from 0.15.8 to 0.15.10
2024-04-18 10:24:13 +01:00
Daniel Finneran
fb43a48a87 Merge pull request #792 from kube-vip/dependabot/go_modules/k8s.io/apimachinery-0.29.3
Bump k8s.io/apimachinery from 0.29.1 to 0.29.3
2024-04-18 10:23:50 +01:00
Daniel Finneran
12e298bb22 Merge pull request #807 from kube-vip/dependabot/docker/golang-1.22.2-alpine3.18
Bump golang from 1.22.0-alpine3.18 to 1.22.2-alpine3.18
2024-04-18 10:23:32 +01:00
Daniel Finneran
f514269408 Merge pull request #778 from thebsdbox/remove_start
Removal of deprecated start command
2024-04-18 10:22:55 +01:00
Daniel Finneran
2c5d366487 Merge pull request #770 from lubronzhan/topic/lubron/fix-589
Mirror traffic of service interface to a dest interface
2024-04-18 10:22:32 +01:00
Daniel Finneran
fea05fa3ad Merge branch 'main' into topic/lubron/fix-589 2024-04-18 10:10:23 +01:00
Dan Finneran
5c515f0c0d Adds annotation support for service interfaces.
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-04-18 08:56:36 +00:00
Daniel Finneran
b0acf844ca Merge pull request #812 from wyike/fix_masquerade_issues
Fixes on masquerade forwarding mode
2024-04-18 09:54:11 +01:00
Daniel Finneran
bd3df6b616 Merge pull request #811 from d-uzlov/fix-nodename
Use node name for service election and lease holder name instead of hostname
2024-04-17 15:32:16 +01:00
Yike Wang
5100cd0e9a Fixes on masquerade forwarding mode
Signed-off-by: Yike Wang <yikew@vmware.com>
2024-04-17 08:59:44 +08:00
Danil Uzlov
04d863310b improve readability
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-11 03:35:02 +07:00
Danil Uzlov
29713acfeb fix golangci-lint better
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-11 03:32:49 +07:00
Danil Uzlov
8d607b89be fix golangci-lint
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-11 03:27:33 +07:00
Danil Uzlov
877ee75e75 go fmt
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-11 03:20:54 +07:00
Danil Uzlov
d3da4d934a check node names in services test
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-11 02:04:41 +07:00
Debian
c3e9a13f1c add hostname e2e test
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-11 02:04:36 +07:00
Danil Uzlov
59ad5ec9a2 fix e2e tests
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-10 21:28:09 +07:00
Danil Uzlov
8a80a72d94 fix golangci-lint
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-10 18:21:15 +07:00
Danil Uzlov
cb1e63c302 fix unit tests
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-10 17:58:20 +07:00
Danil Uzlov
e87ef6b3b8 go fmt
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-10 17:44:58 +07:00
Danil Uzlov
f87665c67f add fallback for hostname when node name is not available
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-10 17:43:53 +07:00
Daniel Finneran
c9d11e7123 Merge pull request #795 from adavis10006/fix-ddns
fix: add ddns address as a network
2024-04-10 09:59:55 +01:00
Daniel Finneran
51512201ea Merge pull request #809 from starbops/iptables-legacy
fix: add iptables-legacy package
2024-04-10 09:59:25 +01:00
Danil Uzlov
e37091c900 use node name instead of hostname
Signed-off-by: Danil Uzlov <36223296+d-uzlov@users.noreply.github.com>
2024-04-09 18:37:11 +07:00
Zespre Schmidt
b484be799e fix: add iptables-legacy package
Signed-off-by: Zespre Schmidt <starbops@zespre.com>
2024-04-08 15:21:56 +08:00
Shang-Kuei, Chen
2134c6b1fe fix: add ddns address as a network
Signed-off-by: Shang-Kuei, Chen <adavis10006@gmail.com>
2024-04-08 14:37:16 +08:00
dependabot[bot]
fbc6904fa0 Bump golang from 1.22.0-alpine3.18 to 1.22.2-alpine3.18
Bumps golang from 1.22.0-alpine3.18 to 1.22.2-alpine3.18.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-08 02:41:21 +00:00
Marcel Fest
0cedf6a97d Merge pull request #805 from Bao0ne/offline
fix: Modify the ImagePullPolicy used by cli manifest
2024-04-07 11:50:42 +02:00
wang
932fe09870 fix: Modify the ImagePullPolicy used by cli manifest
Signed-off-by: wang <wanglei@tdology.com>
2024-04-06 17:11:01 +08:00
Daniel Finneran
f1cf044eae Merge pull request #782 from lou-lan/fix/masquerade
Add masquerade mode
2024-04-02 11:06:22 +01:00
dependabot[bot]
a10a478f24 Bump anchore/sbom-action from 0.15.8 to 0.15.10
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.15.8 to 0.15.10.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.15.8...v0.15.10)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-01 02:11:42 +00:00
lou-lan
d1541c3464 Add masquerade mode
Signed-off-by: lou-lan <loulan@loulan.me>
2024-03-20 19:23:05 +08:00
dependabot[bot]
4e3717f089 Bump k8s.io/apimachinery from 0.29.1 to 0.29.3
Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.29.1 to 0.29.3.
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.29.1...v0.29.3)

---
updated-dependencies:
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-18 02:47:29 +00:00
Daniel Finneran
2aa799c9d0 Merge pull request #773 from kube-vip/dependabot/go_modules/go.uber.org/zap-1.27.0
Bump go.uber.org/zap from 1.26.0 to 1.27.0
2024-03-10 16:31:49 +00:00
Daniel Finneran
bb08489898 Merge pull request #783 from lubronzhan/topic/lubron/fix-781
Fix netmask of ipvs to consider ipv6 case
2024-03-10 16:30:49 +00:00
Daniel Finneran
1ea277f43e Merge pull request #777 from thebsdbox/egress_fix
Fixes conntrack deleting wrong connections and cleaning old SNAT rules
2024-03-10 16:23:45 +00:00
Daniel Finneran
2c4ff6949a Update Makefile for next release 2024-03-10 17:23:30 +01:00
lubronzhan
1a4bd01332 Refactor
Signed-off-by: lubronzhan <lubronzhan@gmail.com>
2024-03-10 09:13:16 -07:00
lubronzhan
9e2a13c133 Fix netmask of ipvs to consider ipv6 case
Signed-off-by: lubronzhan <lubronzhan@gmail.com>
2024-03-09 22:38:07 -08:00
Dan Finneran
39fbbc57ac linting fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-03-01 14:14:56 +00:00
Dan Finneran
b9f8c3b0f5 Removal of deprecated start command
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-03-01 12:29:05 +00:00
Daniel Finneran
ac5895a311 Merge pull request #775 from lubronzhan/topic/lubron/change_fatal
Exit(1) if service's leaderelection.onStartedLeading error out instead of silently continue
2024-03-01 11:05:44 +00:00
Daniel Finneran
e7eaa70fd4 Merge pull request #776 from lubronzhan/topic/lubron/fix-771
Fix flaky e2e test
2024-03-01 11:05:23 +00:00
Dan Finneran
76cf59c7a7 Fixes issues around conntrack deleting wrong connections and cleaning up old vip SNAT entries
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-03-01 10:54:50 +00:00
lubronzhan
a05ecbccb7 Consider 500 status code as a positive result of reaching control plane VIP
Signed-off-by: lubronzhan <lubronzhan@gmail.com>
2024-02-29 22:25:22 -08:00
lubronzhan
c531414542 Exit 1 if service's leaderelection onStartedLeading error out instead of silently continue
Signed-off-by: lubronzhan <lubronzhan@gmail.com>
2024-02-29 21:58:29 -08:00
lubronzhan
70b4728492 Resolve comments
Signed-off-by: lubronzhan <lubronzhan@gmail.com>
2024-02-29 21:48:20 -08:00
Lubron Zhan
835007b07a Refactor
Signed-off-by: Lubron Zhan <lubronzhan@gmail.com>
2024-02-29 21:48:20 -08:00
Lubron Zhan
6d0c132519 Try clean up before deleting
Signed-off-by: Lubron Zhan <lubronzhan@gmail.com>
2024-02-29 21:48:20 -08:00
Lubron Zhan
485cf6a0dd Fix the variable
Signed-off-by: Lubron Zhan <lubronzhan@gmail.com>
2024-02-29 21:48:20 -08:00
Lubron Zhan
1338e4fcd3 Move mirroring traffic code to servicesWatcher
Signed-off-by: Lubron Zhan <lubronzhan@gmail.com>
2024-02-29 21:48:20 -08:00
lubronzhan
981355d910 Mirror traffic of service interface to a dest interface
Signed-off-by: lubronzhan <lubronzhan@gmail.com>
2024-02-29 21:48:20 -08:00
Daniel Finneran
3d5f1a6fa3 Update Makefile for new release 2024-02-26 09:45:58 +00:00
dependabot[bot]
e89d6f9f00 Bump go.uber.org/zap from 1.26.0 to 1.27.0
Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.26.0 to 1.27.0.
- [Release notes](https://github.com/uber-go/zap/releases)
- [Changelog](https://github.com/uber-go/zap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uber-go/zap/compare/v1.26.0...v1.27.0)

---
updated-dependencies:
- dependency-name: go.uber.org/zap
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 02:56:34 +00:00
Daniel Finneran
a5ec16e1e8 Merge pull request #768 from thebsdbox/egress_fix
fixes a bug that wouldn't return CIDRs for egress
2024-02-21 16:11:42 +00:00
Dan Finneran
8de44b9253 fixes a bug that wouldn't return CIDRs for egress
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-02-21 15:25:40 +00:00
Daniel Finneran
911d4c0796 Merge pull request #757 from kube-vip/dependabot/go_modules/go.etcd.io/etcd/api/v3-3.5.12
Bump go.etcd.io/etcd/api/v3 from 3.5.11 to 3.5.12
2024-02-21 14:35:19 +00:00
Daniel Finneran
b370681de4 Merge pull request #759 from kube-vip/dependabot/go_modules/golang.org/x/sys-0.17.0
Bump golang.org/x/sys from 0.16.0 to 0.17.0
2024-02-21 14:34:48 +00:00
Daniel Finneran
9b63a6e77a Merge pull request #764 from kube-vip/dependabot/go_modules/sigs.k8s.io/kind-0.22.0
Bump sigs.k8s.io/kind from 0.20.0 to 0.22.0
2024-02-21 14:34:33 +00:00
Daniel Finneran
56d57e7fae Merge pull request #763 from p-strusiewiczsurmacki-mobica/clean-routes
Added possibility to remove redundant routes
2024-02-21 14:31:13 +00:00
Patryk Strusiewicz-Surmacki
ba061e4475 Add protocol to legacy routes
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-02-21 11:41:51 +01:00
Daniel Finneran
6ddd053bce Merge pull request #765 from lou-lan/fix/ipvs
Fix IPVS service error: netlink receive invalid argument
2024-02-20 09:13:52 +00:00
Patryk Strusiewicz-Surmacki
f12d340134 Fixed concurrent map writes issue
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-02-20 10:08:29 +01:00
Patryk Strusiewicz-Surmacki
262ce70310 Changed default port, fixed typo, added route clean enable flag
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-02-19 14:41:17 +01:00
Patryk Strusiewicz-Surmacki
cce895e071 Added possibility to remove redundant routes
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-02-19 14:41:17 +01:00
lou-lan
388b6ca27f Fix IPVS service error: netlink receive invalid argument
Signed-off-by: lou-lan <loulan@loulan.me>
2024-02-19 16:39:14 +08:00
dependabot[bot]
0d27273ded Bump sigs.k8s.io/kind from 0.20.0 to 0.22.0
Bumps [sigs.k8s.io/kind](https://github.com/kubernetes-sigs/kind) from 0.20.0 to 0.22.0.
- [Release notes](https://github.com/kubernetes-sigs/kind/releases)
- [Commits](https://github.com/kubernetes-sigs/kind/compare/v0.20.0...v0.22.0)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/kind
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 02:07:51 +00:00
Daniel Finneran
7b7746b55f Merge pull request #760 from kube-vip/dependabot/docker/golang-1.22.0-alpine3.18
Bump golang from 1.21.6-alpine3.18 to 1.22.0-alpine3.18
2024-02-15 17:13:28 +00:00
Daniel Finneran
b666a95961 Merge pull request #761 from p-strusiewiczsurmacki-mobica/endpoints-common
Added common endpoint provider interface and fixed route deletion iss…
2024-02-15 17:13:11 +00:00
Patryk Strusiewicz-Surmacki
3534116d70 Fixed BGP issues
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-02-14 17:30:37 +01:00
Patryk Strusiewicz-Surmacki
107464fa1a Changed exist error chack from syscall to os
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-02-13 16:32:51 +01:00
Patryk Strusiewicz-Surmacki
814bf3d18f Added common endpoint provider interface and fixed route deletion issues in routing table mode
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-02-13 16:14:13 +01:00
dependabot[bot]
6503d7bec5 Bump golang from 1.21.6-alpine3.18 to 1.22.0-alpine3.18
Bumps golang from 1.21.6-alpine3.18 to 1.22.0-alpine3.18.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 03:03:12 +00:00
dependabot[bot]
c5e00d8660 Bump golang.org/x/sys from 0.16.0 to 0.17.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/sys/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 02:54:17 +00:00
dependabot[bot]
409e188469 Bump go.etcd.io/etcd/api/v3 from 3.5.11 to 3.5.12
Bumps [go.etcd.io/etcd/api/v3](https://github.com/etcd-io/etcd) from 3.5.11 to 3.5.12.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.11...v3.5.12)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 02:54:07 +00:00
Daniel Finneran
8ccfdeca05 Merge pull request #750 from Wielewout/gen-manifests
fix: print manifests to stdout
2024-02-06 19:53:41 +01:00
Wout Van De Wiel
f933079da0 fix: print manifests to stdout
Signed-off-by: Wout Van De Wiel <wout.vandewiel@accelleran.com>
2024-02-06 18:42:01 +01:00
Daniel Finneran
b64243a3da Update ci.yaml
fixes issue with file descriptors
2024-02-06 11:01:44 +01:00
Daniel Finneran
d277c0ff23 Merge pull request #737 from kube-vip/dependabot/go_modules/k8s.io/client-go-0.29.1
Bump k8s.io/client-go from 0.29.0 to 0.29.1
2024-02-06 09:45:27 +01:00
dependabot[bot]
e9d2542c46 Bump k8s.io/client-go from 0.29.0 to 0.29.1
Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.29.0 to 0.29.1.
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.29.0...v0.29.1)

---
updated-dependencies:
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-06 08:36:33 +00:00
Daniel Finneran
57445329f1 Merge pull request #747 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.15.8
Bump anchore/sbom-action from 0.15.3 to 0.15.8
2024-02-06 09:36:00 +01:00
Daniel Finneran
66b224ed79 Merge pull request #736 from kube-vip/dependabot/go_modules/k8s.io/apimachinery-0.29.1
Bump k8s.io/apimachinery from 0.29.0 to 0.29.1
2024-02-06 09:35:42 +01:00
Daniel Finneran
67fbfe8973 Merge pull request #727 from kube-vip/dependabot/docker/golang-1.21.6-alpine3.18
Bump golang from 1.21.5-alpine3.18 to 1.21.6-alpine3.18
2024-02-06 09:31:37 +01:00
dependabot[bot]
55c6e6418f Bump k8s.io/apimachinery from 0.29.0 to 0.29.1
Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.29.0 to 0.29.1.
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.29.0...v0.29.1)

---
updated-dependencies:
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-06 08:24:47 +00:00
Daniel Finneran
d1ef0f443f Merge pull request #742 from kube-vip/dependabot/docker/alpine-3.19.1
Bump alpine from 3.19.0 to 3.19.1
2024-02-06 09:23:41 +01:00
Daniel Finneran
495bde2668 Merge pull request #735 from kube-vip/dependabot/go_modules/github.com/onsi/ginkgo/v2-2.15.0
Bump github.com/onsi/ginkgo/v2 from 2.13.2 to 2.15.0
2024-02-06 09:23:26 +01:00
Daniel Finneran
01b889bfce Merge pull request #734 from kube-vip/dependabot/go_modules/k8s.io/klog/v2-2.120.1
Bump k8s.io/klog/v2 from 2.120.0 to 2.120.1
2024-02-06 09:23:04 +01:00
Daniel Finneran
a337127fc4 Merge pull request #746 from ii2day/pr/ii2day/format-log
fix: Using log instead of fmt.print
2024-02-06 09:22:00 +01:00
dependabot[bot]
c994b09f27 Bump anchore/sbom-action from 0.15.3 to 0.15.8
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.15.3 to 0.15.8.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.15.3...v0.15.8)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-05 02:55:11 +00:00
ii2day
7a93f6fd04 fix: Using log instead of fmt.print
Signed-off-by: ii2day <ii2day.zoro@gmail.com>
2024-02-05 09:58:32 +08:00
Daniel Finneran
34a4352fae Merge pull request #740 from p-strusiewiczsurmacki-mobica/no-leader-election-bgp
No-leader-election mode for BGP and fixes for routing table mode
2024-02-02 12:39:42 +01:00
Patryk Strusiewicz-Surmacki
e6e2e2b0a0 Fixed typo
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-31 11:40:09 +01:00
dependabot[bot]
fe9b669fc3 Bump alpine from 3.19.0 to 3.19.1
Bumps alpine from 3.19.0 to 3.19.1.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-29 02:19:46 +00:00
Patryk Strusiewicz-Surmacki
947c7bc8c0 Increased http test timeout
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-25 18:41:14 +01:00
Patryk Strusiewicz-Surmacki
fa1b2c965a No-leader-election mode for BGP and fixes for routing table mode
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-24 18:25:36 +01:00
dependabot[bot]
e85d8cd6c7 Bump github.com/onsi/ginkgo/v2 from 2.13.2 to 2.15.0
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.13.2 to 2.15.0.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.13.2...v2.15.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-22 02:09:10 +00:00
dependabot[bot]
deb0afb3a3 Bump k8s.io/klog/v2 from 2.120.0 to 2.120.1
Bumps [k8s.io/klog/v2](https://github.com/kubernetes/klog) from 2.120.0 to 2.120.1.
- [Release notes](https://github.com/kubernetes/klog/releases)
- [Changelog](https://github.com/kubernetes/klog/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes/klog/compare/v2.120.0...v2.120.1)

---
updated-dependencies:
- dependency-name: k8s.io/klog/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-22 02:09:00 +00:00
Daniel Finneran
cb2ae0a2b6 Merge pull request #725 from kube-vip/dependabot/go_modules/k8s.io/klog/v2-2.120.0
Bump k8s.io/klog/v2 from 2.110.1 to 2.120.0
2024-01-18 13:47:58 +00:00
Daniel Finneran
9bc4489ebc Merge pull request #718 from kube-vip/dependabot/go_modules/github.com/prometheus/client_golang-1.18.0
Bump github.com/prometheus/client_golang from 1.17.0 to 1.18.0
2024-01-18 13:47:39 +00:00
Daniel Finneran
6329cd0536 Merge pull request #717 from kube-vip/dependabot/go_modules/github.com/osrg/gobgp/v3-3.22.0
Bump github.com/osrg/gobgp/v3 from 3.19.0 to 3.22.0
2024-01-18 13:47:20 +00:00
Daniel Finneran
fe41b06277 Merge pull request #733 from thebsdbox/bgp_log_fix
Consistent logging
2024-01-18 13:46:54 +00:00
Dan Finneran
2e39d510e4 Consistent logging
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-18 12:47:08 +00:00
dependabot[bot]
1c4c11098e Bump github.com/osrg/gobgp/v3 from 3.19.0 to 3.22.0
Bumps [github.com/osrg/gobgp/v3](https://github.com/osrg/gobgp) from 3.19.0 to 3.22.0.
- [Release notes](https://github.com/osrg/gobgp/releases)
- [Changelog](https://github.com/osrg/gobgp/blob/master/.goreleaser.yml)
- [Commits](https://github.com/osrg/gobgp/compare/v3.19.0...v3.22.0)

---
updated-dependencies:
- dependency-name: github.com/osrg/gobgp/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-18 12:44:21 +00:00
dependabot[bot]
bbb0c86812 Bump github.com/prometheus/client_golang from 1.17.0 to 1.18.0
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.17.0 to 1.18.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.17.0...v1.18.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-18 12:43:50 +00:00
Daniel Finneran
3d100662d5 Merge pull request #716 from kube-vip/dependabot/go_modules/golang.org/x/sys-0.16.0
Bump golang.org/x/sys from 0.15.0 to 0.16.0
2024-01-18 12:43:21 +00:00
Daniel Finneran
6b6ebdcafa Merge pull request #726 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.15.3
Bump anchore/sbom-action from 0.15.1 to 0.15.3
2024-01-18 12:42:55 +00:00
Daniel Finneran
2b8d62279c Merge pull request #715 from kube-vip/dependabot/go_modules/github.com/packethost/packngo-0.31.0
Bump github.com/packethost/packngo from 0.30.0 to 0.31.0
2024-01-18 12:42:40 +00:00
Daniel Finneran
81f94fac36 Merge pull request #722 from p-strusiewiczsurmacki-mobica/dualstack-support
Minimal implementation of DualStack Services support
2024-01-18 09:37:56 +00:00
Daniel Finneran
dae044a2ab Merge pull request #730 from Cellebyte/fix/bgp
Added cli-options for bgp holdtime and keepalive
2024-01-16 13:22:02 +00:00
Marcel Fest
bb2c03335f Added cli-options for the bgp holdtime and keepalive
Signed-off-by: Marcel Fest <marcel.fest@telekom.de>
2024-01-16 14:05:42 +01:00
Patryk Strusiewicz-Surmacki
eff0d21820 Fixed typo
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-16 13:31:39 +01:00
Patryk Strusiewicz-Surmacki
8ced01382f Reintroduced e2e test changes
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-15 21:41:17 +01:00
Patryk Strusiewicz-Surmacki
3d559ba0ce Minimal implementation of DualStack Services support
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-15 21:27:58 +01:00
Daniel Finneran
a2129b04df Merge pull request #720 from p-strusiewiczsurmacki-mobica/endpointslices-support
Non-leader-election for routing table mode
2024-01-15 15:16:54 +00:00
dependabot[bot]
c3209d5c17 Bump golang from 1.21.5-alpine3.18 to 1.21.6-alpine3.18
Bumps golang from 1.21.5-alpine3.18 to 1.21.6-alpine3.18.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 03:01:12 +00:00
dependabot[bot]
7f67c71582 Bump anchore/sbom-action from 0.15.1 to 0.15.3
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.15.1 to 0.15.3.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.15.1...v0.15.3)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 02:47:32 +00:00
dependabot[bot]
40508a4c6d Bump k8s.io/klog/v2 from 2.110.1 to 2.120.0
Bumps [k8s.io/klog/v2](https://github.com/kubernetes/klog) from 2.110.1 to 2.120.0.
- [Release notes](https://github.com/kubernetes/klog/releases)
- [Changelog](https://github.com/kubernetes/klog/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes/klog/compare/v2.110.1...v2.120.0)

---
updated-dependencies:
- dependency-name: k8s.io/klog/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 02:35:34 +00:00
Daniel Finneran
1dc52ed0d4 Merge pull request #724 from Cellebyte/fix/723
fix #723 and allow short hostnames as well
2024-01-13 19:10:30 +00:00
Cellebyte
29f7536083 fix #723 and allow short hostnames as well 2024-01-13 12:22:57 +01:00
Patryk Strusiewicz-Surmacki
d9fc6a5848 Fixed typos and removed error check after route deletion
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-12 13:27:00 +01:00
Patryk Strusiewicz-Surmacki
70a436ddf3 Improved logging. Fixed issue with endpointslices deletion event.
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-12 11:09:19 +01:00
Patryk Strusiewicz-Surmacki
9d640c5c44 Fixed linter issue
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-11 11:37:29 +01:00
Marcel Fest
7dda7b42c1 Added non-leader-election mode for routing table mode and preliminary support for endpointslices.
Signed-off-by: Patryk Strusiewicz-Surmacki <patryk-pawel.strusiewicz-surmacki@external.telekom.de>
2024-01-10 18:32:23 +01:00
dependabot[bot]
7dec367960 Bump golang.org/x/sys from 0.15.0 to 0.16.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.15.0 to 0.16.0.
- [Commits](https://github.com/golang/sys/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-08 02:07:48 +00:00
dependabot[bot]
444b4a9c0d Bump github.com/packethost/packngo from 0.30.0 to 0.31.0
Bumps [github.com/packethost/packngo](https://github.com/packethost/packngo) from 0.30.0 to 0.31.0.
- [Release notes](https://github.com/packethost/packngo/releases)
- [Changelog](https://github.com/packethost/packngo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/packethost/packngo/compare/v0.30.0...v0.31.0)

---
updated-dependencies:
- dependency-name: github.com/packethost/packngo
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-08 02:07:44 +00:00
Daniel Finneran
3c0e5e327e Update ci.yaml 2024-01-07 16:15:27 +00:00
Daniel Finneran
61d3d7ab45 Merge pull request #713 from thebsdbox/conf_path
Allows a configurable path to the kubernetes config
2024-01-07 15:45:59 +00:00
Dan Finneran
6ef860da52 Last fix
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-07 15:28:17 +00:00
Dan Finneran
748d60147d rage
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-07 15:13:15 +00:00
Dan Finneran
879b5337dc extensive fudging of the CI tests
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-07 15:04:13 +00:00
Dan Finneran
1aba51c70f v129 fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-07 14:38:08 +00:00
Dan Finneran
c60660d4d9 fix for IPv6
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-07 11:39:37 +00:00
Dan Finneran
6a7c198df0 remove lb step
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-07 11:24:43 +00:00
Dan Finneran
e0f9b195af grasping at straws
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-06 17:43:34 +00:00
Dan Finneran
80241ecc74 align timeouts
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-06 16:29:55 +00:00
Dan Finneran
047fe8f444 Additional tests
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-06 16:16:21 +00:00
Dan Finneran
d29b8d1bd8 Allows a configurable path to the kubernetes config
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-05 16:00:40 +00:00
Daniel Finneran
8fb2a7dc07 Merge pull request #712 from thebsdbox/build_nudge
Bumps the Makefile for a new release
2024-01-05 15:15:05 +00:00
Daniel Finneran
f5810f028f Merge pull request #700 from AHB102/master
Removed docs as described in Remove /docs #549
2024-01-05 14:02:10 +00:00
Dan Finneran
7901b8d50c Bumps the Makefile for a new release
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-05 14:00:49 +00:00
Daniel Finneran
c7b0a55718 Merge pull request #710 from thebsdbox/ipvs
fixes to the new ipvs import
2024-01-03 18:03:37 +00:00
Dan Finneran
98d6579d9d fixes to the new ipvs import
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-03 17:53:38 +00:00
Daniel Finneran
7dad075682 Merge pull request #660 from kube-vip/dependabot/go_modules/github.com/cloudflare/ipvs-0.10.1
Bump github.com/cloudflare/ipvs from 0.9.1 to 0.10.1
2024-01-03 17:48:07 +00:00
Daniel Finneran
eac6f6f75a Merge branch 'main' into dependabot/go_modules/github.com/cloudflare/ipvs-0.10.1 2024-01-03 17:48:01 +00:00
Daniel Finneran
0c98c1e28a Merge pull request #648 from amragaey/patch-1
#647 Update Dependencies for Security Patch
2024-01-03 15:13:16 +00:00
Daniel Finneran
5b00d30966 Merge branch 'main' into patch-1 2024-01-03 15:12:58 +00:00
Daniel Finneran
29ddbbbe04 Merge pull request #709 from thebsdbox/linter_actions_fix
More fixes
2024-01-03 15:12:18 +00:00
Dan Finneran
03467dd085 More fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-03 14:26:47 +00:00
Daniel Finneran
fc00d19271 Merge pull request #704 from kube-vip/dependabot/go_modules/go.etcd.io/etcd/client/v3-3.5.11
Bump go.etcd.io/etcd/client/v3 from 3.5.10 to 3.5.11
2024-01-03 14:15:40 +00:00
Daniel Finneran
3500d84fed Merge branch 'main' into dependabot/go_modules/go.etcd.io/etcd/client/v3-3.5.11 2024-01-03 14:15:29 +00:00
Daniel Finneran
09ab08b0ae Merge pull request #702 from kube-vip/dependabot/go_modules/go.etcd.io/etcd/api/v3-3.5.11
Bump go.etcd.io/etcd/api/v3 from 3.5.10 to 3.5.11
2024-01-03 14:14:43 +00:00
Daniel Finneran
0fa5e96037 Merge pull request #703 from kube-vip/dependabot/go_modules/k8s.io/client-go-0.29.0
Bump k8s.io/client-go from 0.28.3 to 0.29.0
2024-01-03 14:12:05 +00:00
Daniel Finneran
e6d56f7eb0 Update codeql-analysis.yml 2024-01-03 14:07:53 +00:00
Daniel Finneran
9b73b3c87b Merge pull request #708 from thebsdbox/workflow_fix
Workflow update for go 1.21
2024-01-03 13:57:03 +00:00
Dan Finneran
a342c75a65 Workflow update for go 1.21
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-03 13:56:43 +00:00
Daniel Finneran
377545e835 Merge pull request #707 from thebsdbox/apiserver_depbot_fix
fixes go modules
2024-01-03 13:52:41 +00:00
Dan Finneran
66c86e995b fixes go modules
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2024-01-03 13:52:13 +00:00
dependabot[bot]
52776f4a75 Bump k8s.io/client-go from 0.28.3 to 0.29.0
Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.28.3 to 0.29.0.
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.28.3...v0.29.0)

---
updated-dependencies:
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-03 13:51:16 +00:00
dependabot[bot]
f82b4a08b4 Bump go.etcd.io/etcd/client/v3 from 3.5.10 to 3.5.11
Bumps [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) from 3.5.10 to 3.5.11.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.10...v3.5.11)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-03 13:50:51 +00:00
dependabot[bot]
ec1288074e Bump go.etcd.io/etcd/api/v3 from 3.5.10 to 3.5.11
Bumps [go.etcd.io/etcd/api/v3](https://github.com/etcd-io/etcd) from 3.5.10 to 3.5.11.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.10...v3.5.11)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/api/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-03 13:50:18 +00:00
Daniel Finneran
a388fdf156 Merge pull request #688 from kube-vip/dependabot/go_modules/k8s.io/apimachinery-0.29.0
Bump k8s.io/apimachinery from 0.28.3 to 0.29.0
2024-01-03 13:49:16 +00:00
dependabot[bot]
0212e78dc6 Bump k8s.io/apimachinery from 0.28.3 to 0.29.0
Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.28.3 to 0.29.0.
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.28.3...v0.29.0)

---
updated-dependencies:
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-03 13:45:25 +00:00
Archit H Barve
12638aee85 Removed docs 2023-12-29 15:46:54 +05:30
Daniel Finneran
55a40bf771 Merge pull request #696 from zifeo/main
docs: fix directroute forwarding method
2023-12-28 16:31:01 +00:00
Daniel Finneran
3a7c331061 Merge pull request #673 from kube-vip/dependabot/go_modules/k8s.io/api-0.28.4
Bump k8s.io/api from 0.28.3 to 0.28.4
2023-12-28 16:28:45 +00:00
Daniel Finneran
35077570ff Merge branch 'main' into dependabot/go_modules/k8s.io/api-0.28.4 2023-12-28 16:28:34 +00:00
Daniel Finneran
24e3780792 Merge pull request #690 from kube-vip/dependabot/go_modules/golang.org/x/crypto-0.17.0
Bump golang.org/x/crypto from 0.14.0 to 0.17.0
2023-12-28 16:27:35 +00:00
Daniel Finneran
c7c772e40d Merge pull request #697 from kube-vip/dependabot/go_modules/github.com/spf13/cobra-1.8.0
Bump github.com/spf13/cobra from 1.7.0 to 1.8.0
2023-12-28 16:27:20 +00:00
Daniel Finneran
2d498d9161 Merge pull request #699 from thebsdbox/k8s_client
Updates to the client to auto-detect
2023-12-28 15:29:12 +00:00
Dan Finneran
52ad35d462 disable local tests
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-12-28 14:24:44 +00:00
Dan Finneran
2cfe326b9c Updates to the client to auto-detect
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-12-28 14:19:35 +00:00
dependabot[bot]
5308dfc055 Bump github.com/spf13/cobra from 1.7.0 to 1.8.0
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-25 02:22:51 +00:00
Teo Stocco
4438fcb6d3 docs: fix directroute forwarding method 2023-12-24 15:33:39 +01:00
dependabot[bot]
88dbd0f45d Bump golang.org/x/crypto from 0.14.0 to 0.17.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.14.0 to 0.17.0.
- [Commits](https://github.com/golang/crypto/compare/v0.14.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-22 12:25:40 +00:00
Daniel Finneran
69306d471c Merge pull request #672 from kube-vip/dependabot/go_modules/github.com/onsi/ginkgo/v2-2.13.2
Bump github.com/onsi/ginkgo/v2 from 2.13.0 to 2.13.2
2023-12-22 12:24:29 +00:00
Daniel Finneran
82e7399f60 Merge pull request #680 from kube-vip/dependabot/docker/golang-1.21.5-alpine3.18
Bump golang from 1.21.4-alpine3.18 to 1.21.5-alpine3.18
2023-12-22 12:23:13 +00:00
Daniel Finneran
0215a0e39e Merge pull request #678 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.15.1
Bump anchore/sbom-action from 0.15.0 to 0.15.1
2023-12-22 12:22:56 +00:00
Daniel Finneran
2190a91df7 Merge pull request #689 from kube-vip/dependabot/github_actions/github/codeql-action-3
Bump github/codeql-action from 2 to 3
2023-12-22 12:22:40 +00:00
Daniel Finneran
17a07e6e4c Merge pull request #679 from kube-vip/dependabot/github_actions/actions/setup-go-5
Bump actions/setup-go from 4 to 5
2023-12-22 12:22:28 +00:00
Daniel Finneran
93fe008cc6 Merge pull request #674 from kube-vip/dependabot/go_modules/github.com/prometheus/client_golang-1.17.0
Bump github.com/prometheus/client_golang from 1.16.0 to 1.17.0
2023-12-22 12:22:05 +00:00
Daniel Finneran
eb880a2885 Merge pull request #681 from kube-vip/dependabot/docker/alpine-3.19.0
Bump alpine from 3.18.4 to 3.19.0
2023-12-22 08:03:48 +00:00
Daniel Finneran
dbf3233250 Merge pull request #695 from marc-cerebras/marc-cerebras/bgp-timer-cfg
Add config options for BGP timers
2023-12-22 08:03:24 +00:00
Daniel Finneran
2123ecf9c0 Merge pull request #687 from flawedmatrix/handle-dualstack-lb-ips
Dualstack support for Loadbalancer Services
2023-12-22 08:02:33 +00:00
marc-cerebras
06285210d0 update tests 2023-12-21 14:58:37 -08:00
marc-cerebras
fb062f7a55 add overlay for annotation driven cfg 2023-12-21 14:36:07 -08:00
marc-cerebras
5b63e4a181 add cfg opts for bgp timers 2023-12-21 12:56:01 -08:00
Daniel Finneran
0ae3ff840c Merge pull request #693 from thebsdbox/k8s_e2e
Adds capability to use your own images for e2e
2023-12-20 16:18:31 +00:00
Dan Finneran
20b3a3c00b Adds capability to use your own images for e2e
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-12-20 16:07:53 +00:00
Edwin Xie
e22ee4de74 Add service test for dualstack LB services
Signed-off-by: Edwin Xie <exie@vmware.com>
2023-12-19 18:55:04 +00:00
Edwin Xie
d21ce886a2 Preliminary support for dualstack loadbalancer services
Signed-off-by: Edwin Xie <exie@vmware.com>
2023-12-19 18:54:56 +00:00
dependabot[bot]
9c79e88ccb Bump github/codeql-action from 2 to 3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2 to 3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 02:19:34 +00:00
dependabot[bot]
079423f218 Bump k8s.io/api from 0.28.3 to 0.28.4
Bumps [k8s.io/api](https://github.com/kubernetes/api) from 0.28.3 to 0.28.4.
- [Commits](https://github.com/kubernetes/api/compare/v0.28.3...v0.28.4)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-12 16:09:01 +00:00
dependabot[bot]
dfd8b38268 Bump github.com/onsi/ginkgo/v2 from 2.13.0 to 2.13.2
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.13.0 to 2.13.2.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.13.0...v2.13.2)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-12 16:07:59 +00:00
Daniel Finneran
c03b7edb5f Merge pull request #671 from kube-vip/dependabot/go_modules/golang.org/x/sys-0.15.0
Bump golang.org/x/sys from 0.13.0 to 0.15.0
2023-12-12 16:06:51 +00:00
dependabot[bot]
be404237bd Bump alpine from 3.18.4 to 3.19.0
Bumps alpine from 3.18.4 to 3.19.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 02:36:33 +00:00
dependabot[bot]
5b48797f8a Bump golang from 1.21.4-alpine3.18 to 1.21.5-alpine3.18
Bumps golang from 1.21.4-alpine3.18 to 1.21.5-alpine3.18.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 02:36:30 +00:00
dependabot[bot]
b0c344298c Bump actions/setup-go from 4 to 5
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 02:31:01 +00:00
dependabot[bot]
c79fff8d86 Bump anchore/sbom-action from 0.15.0 to 0.15.1
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.15.0 to 0.15.1.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.15.0...v0.15.1)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 02:30:58 +00:00
dependabot[bot]
b72ae63060 Bump github.com/prometheus/client_golang from 1.16.0 to 1.17.0
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.16.0...v1.17.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 02:35:08 +00:00
dependabot[bot]
9835fd4410 Bump golang.org/x/sys from 0.13.0 to 0.15.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.13.0 to 0.15.0.
- [Commits](https://github.com/golang/sys/compare/v0.13.0...v0.15.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-04 02:34:43 +00:00
Daniel Finneran
6a642c788a Merge pull request #670 from thebsdbox/lint_fix_routing
Fixes to linting for routing table
2023-12-03 10:38:40 +00:00
Daniel Finneran
47924247c4 Merge pull request #607 from hellt/patch-1
Added create rbac settings section for kind deployment
2023-12-03 10:36:40 +00:00
dependabot[bot]
100da0a3a5 Bump github.com/cloudflare/ipvs from 0.9.1 to 0.10.1
Bumps [github.com/cloudflare/ipvs](https://github.com/cloudflare/ipvs) from 0.9.1 to 0.10.1.
- [Release notes](https://github.com/cloudflare/ipvs/releases)
- [Commits](https://github.com/cloudflare/ipvs/compare/v0.9.1...v0.10.1)

---
updated-dependencies:
- dependency-name: github.com/cloudflare/ipvs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-03 10:35:14 +00:00
Daniel Finneran
945167cab4 Merge branch 'main' into patch-1 2023-12-03 10:33:53 +00:00
Dan Finneran
b0f7aa1698 Fixes to linting for routing table
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-12-03 10:32:51 +00:00
Daniel Finneran
2cee4723d4 Merge pull request #606 from CopernicaMarketingSoftware/main
Add environment variable for routing table type
2023-12-03 10:27:37 +00:00
Daniel Finneran
f33a0b7481 Merge branch 'main' into main 2023-12-03 10:26:03 +00:00
Daniel Finneran
f54595d8f7 Merge pull request #669 from thebsdbox/cleanup
Cleanup
2023-12-02 17:56:24 +00:00
Dan Finneran
68c9e49480 linting fixes.
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-12-02 16:38:56 +00:00
Dan Finneran
cfa2e93c76 Further cleaning
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-12-02 16:32:30 +00:00
Dan Finneran
1f1c7fe819 Tidies up logging messages and redundant logic
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-12-02 16:32:12 +00:00
Daniel Finneran
c7abf75c17 Merge pull request #655 from kube-vip/dependabot/go_modules/go.etcd.io/etcd/client/v3-3.5.10
Bump go.etcd.io/etcd/client/v3 from 3.5.9 to 3.5.10
2023-12-02 16:10:09 +00:00
Daniel Finneran
befe2b92aa Merge branch 'main' into dependabot/go_modules/go.etcd.io/etcd/client/v3-3.5.10 2023-12-02 16:09:58 +00:00
Daniel Finneran
cd86f70a20 Merge pull request #661 from kube-vip/dependabot/go_modules/github.com/onsi/gomega-1.30.0
Bump github.com/onsi/gomega from 1.27.10 to 1.30.0
2023-12-02 16:08:55 +00:00
Daniel Finneran
0a4a1dc12d Merge pull request #659 from kube-vip/dependabot/docker/golang-1.21.4-alpine3.18
Bump golang from 1.21.3-alpine3.18 to 1.21.4-alpine3.18
2023-12-02 16:08:39 +00:00
Daniel Finneran
99dcf88cb2 Merge pull request #657 from kube-vip/dependabot/github_actions/docker/setup-buildx-action-3
Bump docker/setup-buildx-action from 1 to 3
2023-12-02 16:08:09 +00:00
Daniel Finneran
b53b340649 Merge pull request #668 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.15.0
Bump anchore/sbom-action from 0.14.3 to 0.15.0
2023-12-02 16:07:45 +00:00
Daniel Finneran
8d90a805b4 Merge pull request #656 from kube-vip/dependabot/github_actions/docker/login-action-3
Bump docker/login-action from 1 to 3
2023-12-02 16:07:08 +00:00
Daniel Finneran
0626053eb5 Merge pull request #654 from kube-vip/dependabot/go_modules/go.etcd.io/etcd/client/pkg/v3-3.5.10
Bump go.etcd.io/etcd/client/pkg/v3 from 3.5.9 to 3.5.10
2023-12-02 16:06:47 +00:00
Daniel Finneran
de7a454462 Merge pull request #653 from kube-vip/dependabot/go_modules/sigs.k8s.io/yaml-1.4.0
Bump sigs.k8s.io/yaml from 1.3.0 to 1.4.0
2023-12-02 16:06:31 +00:00
Daniel Finneran
247cffb006 Merge pull request #664 from shkuviak/feature/service-dhcp-hostname
Add annotation to specify DHCP lease hostname
2023-12-02 16:06:10 +00:00
dependabot[bot]
0f29b97dd4 Bump anchore/sbom-action from 0.14.3 to 0.15.0
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.14.3 to 0.15.0.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.14.3...v0.15.0)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-27 02:25:46 +00:00
Nicolas JENDROWIAK
e7b68cfd3a Add upgrade command in Dockerfile_iptables
Fix trivy warning on vulnerable libcrypto package
-> No newer alpine image on dockerhub

Signed-off-by: Nicolas JENDROWIAK <75165555+shkuviak@users.noreply.github.com>
2023-11-25 18:22:14 +01:00
Nicolas JENDROWIAK
08abd3812a Added trivy command in makefile
Signed-off-by: Nicolas JENDROWIAK <75165555+shkuviak@users.noreply.github.com>
2023-11-25 18:22:14 +01:00
Nicolas JENDROWIAK
f0de6767a3 lint
Signed-off-by: Nicolas JENDROWIAK <nico.jendrowiak@gmail.com>
2023-11-24 17:13:03 +01:00
Daniel Finneran
b42b78283c Merge pull request #650 from aarnaud/doc/k0sctl
Add doc for static pods on k0s using k0sctl
2023-11-21 17:06:11 -01:00
Daniel Finneran
a0fed6b166 Merge branch 'main' into patch-1 2023-11-19 08:24:45 +00:00
Nicolas JENDROWIAK
a295b44d83 [svc] Add annotation to specify DHCP lease host
Signed-off-by: Nicolas JENDROWIAK <nico.jendrowiak@gmail.com>
2023-11-16 12:16:09 +01:00
dependabot[bot]
259b31cef2 Bump github.com/onsi/gomega from 1.27.10 to 1.30.0
Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.27.10 to 1.30.0.
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/gomega/compare/v1.27.10...v1.30.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 02:36:55 +00:00
dependabot[bot]
16c8deb0fe Bump golang from 1.21.3-alpine3.18 to 1.21.4-alpine3.18
Bumps golang from 1.21.3-alpine3.18 to 1.21.4-alpine3.18.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 02:25:42 +00:00
dependabot[bot]
cf9fa5b30b Bump docker/setup-buildx-action from 1 to 3
Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 1 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v1...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 02:59:03 +00:00
dependabot[bot]
334590b88c Bump docker/login-action from 1 to 3
Bumps [docker/login-action](https://github.com/docker/login-action) from 1 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v1...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 02:58:58 +00:00
dependabot[bot]
f0987424ef Bump go.etcd.io/etcd/client/v3 from 3.5.9 to 3.5.10
Bumps [go.etcd.io/etcd/client/v3](https://github.com/etcd-io/etcd) from 3.5.9 to 3.5.10.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.9...v3.5.10)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 02:58:36 +00:00
dependabot[bot]
864bacfb13 Bump go.etcd.io/etcd/client/pkg/v3 from 3.5.9 to 3.5.10
Bumps [go.etcd.io/etcd/client/pkg/v3](https://github.com/etcd-io/etcd) from 3.5.9 to 3.5.10.
- [Release notes](https://github.com/etcd-io/etcd/releases)
- [Commits](https://github.com/etcd-io/etcd/compare/v3.5.9...v3.5.10)

---
updated-dependencies:
- dependency-name: go.etcd.io/etcd/client/pkg/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 02:58:25 +00:00
dependabot[bot]
6e528fef90 Bump sigs.k8s.io/yaml from 1.3.0 to 1.4.0
Bumps [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/kubernetes-sigs/yaml/releases)
- [Changelog](https://github.com/kubernetes-sigs/yaml/blob/master/RELEASE.md)
- [Commits](https://github.com/kubernetes-sigs/yaml/compare/v1.3.0...v1.4.0)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/yaml
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-30 02:58:13 +00:00
Anthony ARNAUD
14c27ff839 Add doc for static pods on k0s using k0sctl
Signed-off-by: Anthony ARNAUD <github@anthony-arnaud.fr>
2023-10-26 12:11:35 -04:00
Daniel Finneran
063cc2fb8d Merge pull request #643 from kube-vip/dependabot/go_modules/k8s.io/client-go-0.28.3
Bump k8s.io/client-go from 0.27.4 to 0.28.3
2023-10-26 12:06:20 +02:00
Daniel Finneran
f5091a4650 Merge pull request #640 from kube-vip/dependabot/github_actions/actions/checkout-4
Bump actions/checkout from 2 to 4
2023-10-26 12:06:07 +02:00
Daniel Finneran
7ea481b904 Merge pull request #637 from kube-vip/dependabot/docker/alpine-3.18.4
Bump alpine from 3.18.3 to 3.18.4
2023-10-26 12:05:51 +02:00
Daniel Finneran
9b7ef5db31 Merge pull request #649 from kube-vip/dependabot/go_modules/google.golang.org/grpc-1.57.1
Bump google.golang.org/grpc from 1.57.0 to 1.57.1
2023-10-26 12:05:09 +02:00
dependabot[bot]
a25cc92daa Bump k8s.io/client-go from 0.27.4 to 0.28.3
Bumps [k8s.io/client-go](https://github.com/kubernetes/client-go) from 0.27.4 to 0.28.3.
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.27.4...v0.28.3)

---
updated-dependencies:
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-26 09:51:15 +00:00
dependabot[bot]
08d71536e9 Bump google.golang.org/grpc from 1.57.0 to 1.57.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.57.0 to 1.57.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.57.0...v1.57.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-26 09:51:00 +00:00
Daniel Finneran
256743758b Merge pull request #644 from kube-vip/dependabot/go_modules/github.com/osrg/gobgp/v3-3.19.0
Bump github.com/osrg/gobgp/v3 from 3.17.0 to 3.19.0
2023-10-26 11:49:10 +02:00
Daniel Finneran
b4593b2c9e Merge pull request #641 from kube-vip/dependabot/go_modules/github.com/onsi/ginkgo/v2-2.13.0
Bump github.com/onsi/ginkgo/v2 from 2.12.1 to 2.13.0
2023-10-26 11:48:49 +02:00
Daniel Finneran
f024f5ebbc Merge pull request #645 from kube-vip/dependabot/go_modules/go.uber.org/zap-1.26.0
Bump go.uber.org/zap from 1.21.0 to 1.26.0
2023-10-26 11:48:27 +02:00
Daniel Finneran
b643453816 Merge pull request #639 from kube-vip/dependabot/github_actions/docker/build-push-action-5
Bump docker/build-push-action from 2 to 5
2023-10-26 11:48:09 +02:00
dependabot[bot]
1eb9bddb9c Bump alpine from 3.18.3 to 3.18.4
Bumps alpine from 3.18.3 to 3.18.4.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-26 09:47:13 +00:00
Daniel Finneran
ace7001e91 Merge pull request #638 from kube-vip/dependabot/github_actions/anchore/sbom-action-0.14.3
Bump anchore/sbom-action from 0.12.0 to 0.14.3
2023-10-26 11:47:09 +02:00
dependabot[bot]
3ea0b629ac Bump actions/checkout from 2 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-26 09:46:42 +00:00
Daniel Finneran
fb9d80aaaa Merge pull request #636 from kube-vip/dependabot/github_actions/github/codeql-action-2
Bump github/codeql-action from 1 to 2
2023-10-26 11:45:56 +02:00
Daniel Finneran
ed0281b243 Merge pull request #635 from kube-vip/dependabot/github_actions/docker/setup-qemu-action-3
Bump docker/setup-qemu-action from 1 to 3
2023-10-26 11:45:45 +02:00
Daniel Finneran
4d7409f18f Merge pull request #634 from kube-vip/dependabot/docker/golang-1.21.3-alpine3.18
Bump golang from 1.20.8-alpine3.18 to 1.21.3-alpine3.18
2023-10-26 11:45:18 +02:00
Amr Ragaey
305572359d update go-restful version 2023-10-26 11:57:20 +03:00
Amr Ragaey
12ab991048 update Go version 2023-10-26 11:52:37 +03:00
dependabot[bot]
2a8e981b49 Bump go.uber.org/zap from 1.21.0 to 1.26.0
Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.21.0 to 1.26.0.
- [Release notes](https://github.com/uber-go/zap/releases)
- [Changelog](https://github.com/uber-go/zap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uber-go/zap/compare/v1.21.0...v1.26.0)

---
updated-dependencies:
- dependency-name: go.uber.org/zap
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 20:34:02 +00:00
dependabot[bot]
1cde04e8a1 Bump github.com/osrg/gobgp/v3 from 3.17.0 to 3.19.0
Bumps [github.com/osrg/gobgp/v3](https://github.com/osrg/gobgp) from 3.17.0 to 3.19.0.
- [Release notes](https://github.com/osrg/gobgp/releases)
- [Changelog](https://github.com/osrg/gobgp/blob/master/.goreleaser.yml)
- [Commits](https://github.com/osrg/gobgp/compare/v3.17.0...v3.19.0)

---
updated-dependencies:
- dependency-name: github.com/osrg/gobgp/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 20:33:46 +00:00
dependabot[bot]
52bacaa03c Bump github.com/onsi/ginkgo/v2 from 2.12.1 to 2.13.0
Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.12.1 to 2.13.0.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/onsi/ginkgo/compare/v2.12.1...v2.13.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 20:31:39 +00:00
dependabot[bot]
4e88e32e56 Bump docker/build-push-action from 2 to 5
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 2 to 5.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v2...v5)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 20:29:36 +00:00
dependabot[bot]
202274d4f1 Bump anchore/sbom-action from 0.12.0 to 0.14.3
Bumps [anchore/sbom-action](https://github.com/anchore/sbom-action) from 0.12.0 to 0.14.3.
- [Release notes](https://github.com/anchore/sbom-action/releases)
- [Commits](https://github.com/anchore/sbom-action/compare/v0.12.0...v0.14.3)

---
updated-dependencies:
- dependency-name: anchore/sbom-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 20:29:32 +00:00
dependabot[bot]
f20fa9df3e Bump github/codeql-action from 1 to 2
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 1 to 2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v1...v2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 20:29:29 +00:00
dependabot[bot]
70e94d24f4 Bump docker/setup-qemu-action from 1 to 3
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 1 to 3.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v1...v3)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 20:29:24 +00:00
dependabot[bot]
a8914af861 Bump golang from 1.20.8-alpine3.18 to 1.21.3-alpine3.18
Bumps golang from 1.20.8-alpine3.18 to 1.21.3-alpine3.18.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-23 20:29:23 +00:00
Daniel Finneran
5a0715dc50 Merge pull request #633 from mrueg/dependabot 2023-10-23 22:29:03 +02:00
Manuel Rüger
31955fedf7 .github: Add a dependabot config
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2023-10-23 19:24:45 +02:00
Daniel Finneran
888eff1317 Merge pull request #628 from kube-vip/dependabot/go_modules/golang.org/x/net-0.17.0
Bump golang.org/x/net from 0.12.0 to 0.17.0
2023-10-17 11:28:44 +02:00
Daniel Finneran
29d7773064 Merge pull request #629 from g-gaston/fix-etcd-e2e-test-action
Fix etcd e2e tests in GitHub actions
2023-10-17 11:21:45 +02:00
Guillermo Gaston
b5bf507546 Fix etcd e2e tests in GitHub actions
In order to run the kubelet in kind containers on the vms provided by
github, the kubelet needed some extra configuration.

Signed-off-by: Guillermo Gaston <gaslor@amazon.com>
2023-10-17 00:23:49 +00:00
dependabot[bot]
04bdc57434 Bump golang.org/x/net from 0.12.0 to 0.17.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.12.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.12.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-14 11:20:58 +00:00
Daniel Finneran
fa26d779a0 Merge pull request #626 from g-gaston/etcd-vip
Add leader election using etcd as a backend
2023-10-14 13:19:56 +02:00
Guillermo Gaston
ae307f8cad Add leader election using etcd as a backend
This adds a new leader election mode that instead of using the kube api
server to obtain a lease, it relies solely on etcd.

By removing the dependency on the api server, we can use it even before
the api server is up, before cluster creation.

In an external etcd topology, this way we can make the api server point
to the VIPs instead of to the etcd machines IPs. This configuration
isolates the CP configuration from the etcd machine IPS. It's is super
convenient to avoid having to roll new control plane nodes when the etcd
nodes change.

Signed-off-by: Guillermo Gaston <gaslor@amazon.com>
2023-10-06 17:03:03 +00:00
Daniel Finneran
cbcc68e69d Update Makefile
Bump for new release
2023-10-04 09:37:41 +01:00
Daniel Finneran
a09a1db44c Merge pull request #623 from thebsdbox/fatal_interface
Call fatal when interface fails
2023-10-04 10:36:46 +02:00
Daniel Finneran
8d362d9d67 Merge pull request #624 from g-gaston/unit-tests
Enable unit and e2e tests in CI
2023-10-04 10:36:31 +02:00
Guillermo Gaston
72410cc6f7 Enable unit and e2e tests in CI
* Fix 2 broken tests
* Fix e2e ARP tests: killing one node in a 2 CP node cluster makes etcd
  lose quorum. So it can't elect a new leader if the node we happen to
  kill was the etcd leader.
* Separate unit tests, e2e tests, linter and scans in different jobs so
  they run concurrently.

Signed-off-by: Guillermo Gaston <gaslor@amazon.com>
2023-10-03 22:00:09 +00:00
Dan Finneran
36bccb723e Call fatal when interface fails
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-10-03 14:47:44 +00:00
Daniel Finneran
bfa6a9a9ac Merge pull request #622 from Willena/feat/svc-lock-configurable-in-arp-mode
Allow svc lock name to be configurable in arp mode.
2023-10-03 16:38:07 +02:00
Guillaume Villena
e41abf0f88 Allow svc lock name to be configurable in arp mode.
Signed-off-by: Guillaume Villena <guillaume@villena.me>
2023-10-01 01:12:37 +02:00
Daniel Finneran
0def3c0346 Merge pull request #621 from thebsdbox/endpoint_fqdn
Adds logic and debugging around fqdn endpoints
2023-09-29 17:02:56 +02:00
Dan Finneran
0ad1ccbf2f Adds logic and debugging around fqdn endpoints
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-09-28 12:38:54 +00:00
Daniel Finneran
219bc19bc2 Update ci.yaml
Adds Trivy scanning
2023-09-28 11:39:46 +01:00
Daniel Finneran
565e6dc550 Merge pull request #619 from thebsdbox/alpine_bump
This bumps the base images for vulnerabilities
2023-09-27 11:33:05 +02:00
Dan Finneran
d69a92f312 This bumps the base images for vulnerabilities
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-09-27 09:20:31 +00:00
Daniel Finneran
cc96d65b14 Merge pull request #612 from mjtrangoni/chore 2023-09-22 22:45:00 +02:00
Daniel Finneran
bad938105f Merge pull request #613 from mjtrangoni/handle-prom-root 2023-09-22 22:44:41 +02:00
Daniel Finneran
a826649886 Merge pull request #617 from mjtrangoni/add-node-labeling 2023-09-22 22:44:09 +02:00
Mario Trangoni
5ac633f319 ARP: Add node labeling for ARP mode DaemonSet deployment.
This feature is related to #611, to configure the
`CiliumEgressGatewayPolicy` EgressIP correctly.

As this is not a very common usage for this project, there is a default
disabled configuration flag added, `enable_node_labeling`.

Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2023-09-19 13:47:44 +02:00
Mario Trangoni
d8ed0e5296 prometheus: Handle root path
Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2023-09-14 14:26:01 +02:00
Mario Trangoni
06e41bae50 chore: Fix some misspellings found by codespell
Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2023-09-14 11:11:44 +02:00
Mario Trangoni
99e9579de5 Ignore kube-vip binary
Signed-off-by: Mario Trangoni <mjtrangoni@gmail.com>
2023-09-14 11:07:47 +02:00
Timo Sluis
31b7aad6c0 revert go.mod and go.sum
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-09-11 13:14:04 +02:00
Timo Sluis
991587c294 fix formatting + add route to link + remove route on shutdown
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-09-11 11:06:48 +02:00
Timo Sluis
89d883d0ec add routing table id as envvar
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-09-08 15:50:24 +02:00
Timo Sluis
724ec2ab10 specify different scope for local routes
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-09-08 15:28:45 +02:00
Timo Sluis
8afe5ca155 add comment about valid values
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-09-07 13:34:51 +02:00
Roman Dodin
6d47329f7c added create rbac settings section for kind 2023-09-04 20:47:56 +02:00
Timo Sluis
9fbe98c5d9 gofmt
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-09-04 16:45:47 +02:00
Timo Sluis
55398e6cfc add routing table type environment variable
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-09-04 16:35:09 +02:00
Daniel Finneran
f7666067a4 Update Makefile for new release 2023-08-24 09:01:16 +01:00
Daniel Finneran
a47e46ce84 Merge pull request #601 from usiegl00/main
Fix dos through checking for remaining services before releasing ip. …
2023-08-18 09:37:15 +01:00
usiegl00
9c84c56959 Fix formatting to pass lint.
Signed-off-by: usiegl00 <50933431+usiegl00@users.noreply.github.com>
2023-08-18 03:42:46 +09:00
usiegl00
b4f5554670 Fix dos through checking for remaining services before releasing ip. Fixes #600
Signed-off-by: usiegl00 <50933431+usiegl00@users.noreply.github.com>
2023-08-17 05:03:36 +09:00
Daniel Finneran
96541380b5 Merge pull request #599 from thebsdbox/codeql
action fix
2023-08-15 19:41:15 +01:00
Dan Finneran
92338ae74f action fix
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-15 18:40:47 +00:00
Daniel Finneran
4e69ada00c Merge pull request #598 from thebsdbox/fix_main
Fix to main
2023-08-15 19:26:20 +01:00
Dan Finneran
baba79e6ad Fix to main
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-15 18:16:58 +00:00
Daniel Finneran
cfdd5d1c42 Merge pull request #575 from megakid/patch-1
Increase client QPS to reduce clientside k8api throttling
2023-08-15 19:14:41 +01:00
Daniel Finneran
57c008b6da Merge pull request #595 from jkossis/update-makefile-0.6.1
Updating version in makefile
2023-08-15 18:01:56 +01:00
Daniel Finneran
778886e426 Merge pull request #597 from thebsdbox/watch_fix
This makes sure we check if a services is active
2023-08-15 18:01:17 +01:00
Daniel Finneran
203de87a85 Merge pull request #596 from thebsdbox/e2e-2-death
Some BIG OLDE e2e tests!
2023-08-15 18:00:31 +01:00
Dan Finneran
a18e26dbc3 more_lint
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-15 16:46:19 +00:00
Dan Finneran
bc63ed2ee5 lint fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-15 15:32:25 +00:00
Dan Finneran
6a71e264da This makes sure we check if a services is active
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-15 15:25:30 +00:00
Dan Finneran
aa9cb9a49b Some BIG OLDE e2e tests!
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-15 15:21:32 +00:00
James Connor
74f6785f34 Compilation fixes again 2023-08-15 15:24:20 +01:00
James Connor
7a5d80bf35 Merge branch 'kube-vip:main' into patch-1 2023-08-15 15:21:49 +01:00
Jason Kossis
5f9dc0a997 initial commit
Signed-off-by: Jason Kossis <jason.kossis@aexp.com>
2023-08-14 08:17:47 -04:00
Daniel Finneran
18fadf25a2 Merge pull request #593 from thebsdbox/ginko_bump
Fixes to ginko
2023-08-14 08:25:46 +01:00
Dan Finneran
92e13761e4 MORE AND MORE FIXES
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-13 15:04:39 +00:00
Dan Finneran
ab7ceb8933 more fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-13 14:45:16 +00:00
Dan Finneran
bac763e3f4 more tidying
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-13 14:04:33 +00:00
Dan Finneran
c2215e5d98 Fixes to ginko
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-13 13:57:12 +00:00
Daniel Finneran
c54994e9b7 Merge pull request #592 from thebsdbox/e2e_fixes
Fixes to e2e tests and re-enabling
2023-08-13 14:28:12 +01:00
Dan Finneran
1da54e6d8e lint fixes.
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-13 13:13:18 +00:00
Dan Finneran
9bfbb295dd Fixes to e2e tests and re-enabling
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-08-13 13:09:41 +00:00
Daniel Finneran
5a06a8888d Merge pull request #576 from mrueg/update-deps-0623
Update go dependencies
2023-08-12 10:27:30 +01:00
Manuel Rüger
7b64893703 Update golangci-lint
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2023-08-01 14:06:21 +02:00
Manuel Rüger
f36b433093 Update go dependencies
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2023-08-01 14:06:21 +02:00
Daniel Finneran
ec5a5139c8 Merge pull request #587 from rikatz/fix-dhcp-workflow-part1 2023-07-27 22:21:26 +01:00
Ricardo Katz
3d357a452b Fix linter error
Signed-off-by: Ricardo Katz <ricardo.katz@gmail.com>
2023-07-27 16:41:41 -03:00
Ricardo Katz
702a27bb1e Add proper backoff and max errors on dhcp client
Signed-off-by: Ricardo Katz <ricardo.katz@gmail.com>
2023-07-24 12:15:07 -03:00
Ricardo Katz
0060d36694 Update the DHCP workflows
Signed-off-by: Ricardo Katz <ricardo.katz@gmail.com>
2023-07-24 12:15:07 -03:00
Daniel Finneran
bdb9b0ef91 Merge pull request #585 from timosluis/lease_annotations
Allow specifying annotations for created Lease resources
2023-07-18 09:35:44 +01:00
Daniel Finneran
1ad0ae7740 Merge pull request #583 from kube-vip/dependabot/go_modules/google.golang.org/grpc-1.53.0
Bump google.golang.org/grpc from 1.51.0 to 1.53.0
2023-07-18 09:35:27 +01:00
Daniel Finneran
8c0791db19 Merge pull request #579 from runsisi/wip-fix-target
Fix makefile default target
2023-07-18 09:35:04 +01:00
Daniel Finneran
ec80533f81 Merge pull request #578 from marc-cerebras/marc-cerebras/bgp-cp-leaderelect
enable leaderelection for bgp in CP mode
2023-07-18 09:34:51 +01:00
Timo Sluis
64f8ebd865 fix formatting
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-07-12 11:27:49 +02:00
Timo Sluis
9667c7766f add lease annotations
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-07-12 11:14:14 +02:00
dependabot[bot]
23492519ed Bump google.golang.org/grpc from 1.51.0 to 1.53.0
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.51.0 to 1.53.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.51.0...v1.53.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-05 21:37:26 +00:00
runsisi
f2f7d362c7 Fix makefile default target
Signed-off-by: runsisi <runsisi@hust.edu.cn>
2023-06-21 07:53:43 +08:00
marc-cerebras
2dcd9e50c9 enable leaderelection for bgp in CP mode
Signed-off-by: marc-cerebras <marc.spehlmann@cerebras.net>
2023-06-19 11:25:13 -07:00
James Connor
c3ab677ad1 PR Fixes 2023-06-02 17:22:21 +01:00
James Connor
09daa0c57f Merge branch 'kube-vip:main' into patch-1 2023-06-02 17:20:04 +01:00
Daniel Finneran
c3a700ba3f Merge pull request #573 from timosluis/main
Use configurable LeaseName instead of hardcoded
2023-06-02 08:45:49 +01:00
James Connor
6f2acf0198 Increase client QPS to reduce clientside k8api throttling 2023-05-30 12:54:46 +01:00
Daniel Finneran
af86209d63 Merge pull request #571 from lubronzhan/topic/lubron/check_lb_cancel_func
Check activeServiceLoadBalancerCancel is nil or not before calling it
2023-05-25 16:19:18 +01:00
Timo Sluis
313c4c04f8 use config leasename instead of hardcoded
Signed-off-by: Timo Sluis <timo.sluis@live.nl>
2023-05-25 16:37:21 +02:00
lubronzhan
cd29e3d70a Check activeServiceLoadBalancerCancel is nil or not before calling it
Signed-off-by: lubronzhan <lzhan@vmware.com>
2023-05-22 14:36:15 -07:00
Daniel Finneran
6e8b3a9747 Merge pull request #569 from kube-vip/revert-502-iptables-nft
Revert "adding iptables-wrappers script to entrypoint"
2023-05-19 22:53:47 +01:00
Daniel Finneran
ef4995841a Revert "adding iptables-wrappers script to entrypoint" 2023-05-19 22:52:48 +01:00
Chris Privitere
0efed56a2a Merge pull request #502 from dockerpac/iptables-nft
adding iptables-wrappers script to entrypoint
2023-05-19 16:25:21 -05:00
Chris Privitere
fa248cca13 Merge pull request #567 from enkelprifti98/main
Add support for multiple BGP peers when using Equinix Metal annotations
2023-05-19 16:23:47 -05:00
Chris Privitere
24588d006a fix: formatting spaces on 217 2023-05-19 16:16:32 -05:00
Enkel Prifti
d7f4abafb8 Add support for multiple BGP peers when using Equinix Metal annotations
Using Equinix Metal annotations was limited to only the first BGP peer. This PR adds support for multiple BGP peer by looking at all bgp peer node annotations.

Signed-off-by: Enkel Prifti <enkelprifti@live.com>
2023-05-19 16:56:37 -04:00
Daniel Finneran
731545c666 Merge pull request #565 from enkelprifti98/main
Add BGP password support for Equinix Metal
2023-05-19 15:52:22 +01:00
Enkel Prifti
2a21b87b77 Add BGP password support for Equinix Metal
The Equinix Metal API integration was missing support for BGP session passwords so this PR adds the BGP password parameter.

Signed-off-by: Enkel Prifti <enkelprifti@live.com>
2023-05-18 20:09:26 -04:00
Daniel Finneran
b594d459fc Update Makefile 2023-05-15 12:29:34 +01:00
Daniel Finneran
8ea53f2b54 Merge pull request #562 from yaocw2020/ignoreServiceSecurity
Add annotation kube-vip.io/ignore-service-security
2023-05-15 09:49:05 +01:00
Canwu Yao
9ec6b3e8f5 Add annotation kube-vip.io/ignore-service-security
Skip service security configuration for the service whose annotation kube-vip.io/ignore-service-security is true

Signed-off-by: Canwu Yao <yaocanwu@gmail.com>
2023-05-15 11:24:50 +08:00
Daniel Finneran
2796185267 Merge pull request #557 from sykesm/kill-pkg-service 2023-05-11 19:29:35 +01:00
Matthew Sykes
cc362f7774 checks - fix things flagged by linting
Signed-off-by: Matthew Sykes <matthew.sykes@gmail.com>
2023-05-11 11:39:23 -04:00
Matthew Sykes
cfbf9b0458 Move helper from pkg/service and remove package
The pkg/service package is no longer used.

Signed-off-by: Matthew Sykes <matthew.sykes@gmail.com>
2023-05-11 11:38:45 -04:00
Daniel Finneran
ed59a13f10 Merge pull request #560 from yaocw2020/0502
Set iptables rules to restrict user access to ports other than the load balancer service port through the VIP
2023-05-11 08:49:43 +01:00
Canwu Yao
f2f73c00d0 Set iptables rules to limit traffic ports
Signed-off-by: Canwu Yao <yaocanwu@gmail.com>
2023-05-10 23:32:04 +08:00
Daniel Finneran
f03917e63f Merge pull request #561 from DrBu7cher/add_bgp_metrics_v1 2023-05-10 09:54:24 +01:00
Daniel Finneran
17eee86f2c Update main.yaml
Allow on-request builds.
2023-05-08 15:15:40 +01:00
Daniel Finneran
834aa94f75 Merge pull request #558 from thebsdbox/egress_namespace_isolation
This ensures rule cleaning only happens in a NS
2023-05-08 13:33:59 +01:00
Jonas Badstübner
4a2e72e811 refactor(metrics): better memory efficiency
Signed-off-by: Jonas Badstübner <jonas.badstuebner@hetzner-cloud.de>
2023-05-08 10:17:51 +02:00
Jonas Badstübner
68e6a940a2 feat(metrics): implement bgp_session_info
Signed-off-by: Jonas Badstübner <jonas.badstuebner@hetzner-cloud.de>
2023-05-08 10:17:51 +02:00
Jonas Badstübner
386d1514c2 feat(metrics): add bgp_session_info
Signed-off-by: Jonas Badstübner <jonas.badstuebner@hetzner-cloud.de>
2023-05-08 10:17:51 +02:00
Jonas Badstübner
640743a2de feat(bgp-server): add peer state change callback
Signed-off-by: Jonas Badstübner <jonas.badstuebner@hetzner-cloud.de>
2023-05-08 10:17:51 +02:00
Canwu Yao
1474fcf369 Support changing load balancer IP
Signed-off-by: Canwu Yao <yaocanwu@gmail.com>
2023-05-07 12:00:44 +08:00
Dan Finneran
e6e4d1cf08 This ensures rule cleaning only happens in a NS
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-05-05 16:51:03 +00:00
Daniel Finneran
60957d64aa Merge pull request #555 from sykesm/ipvs-ipv6
Ignore different family on IPVS delete
2023-05-03 16:08:08 +02:00
Matthew Sykes
37364882fd Ignore different family on IPVS delete
Signed-off-by: Matthew Sykes <matthew.sykes@gmail.com>
2023-05-03 08:31:29 -04:00
Daniel Finneran
e0a9e70664 Merge pull request #553 from tuxtof/fix-lb-annotation
fix LB annotations
2023-05-03 10:48:52 +02:00
Daniel Finneran
839011c29d Merge pull request #554 from sykesm/ipvs-ipv6
Use correct address family for ipvs destinations
2023-05-03 10:48:29 +02:00
Matthew Sykes
7fcf0f1b65 Use correct address family for ipvs destinations
When IPv6 addresses are present in node.Status.Addresses, the
IPVSLoadBalancer parses the addresses and attempts to add them as an
IPv4 destinations. This results in useless entries in the service table
that only hold the last 32 bits of address.

This change does two things:
- uses the appropriate address family when creating the service
- ignores backend addresses that use a different address family than the
  service

This avoids the immediate problem of using the wrong address family for
IPv6 destinations and the useless entries in the service table.

Signed-off-by: Matthew Sykes <matthew.sykes@gmail.com>
2023-04-30 17:38:14 -04:00
Christophe Jauffret
b33da242e8 fix LB annotations
Signed-off-by: Christophe Jauffret <reg-github@geo6.net>
2023-04-29 08:11:05 +02:00
Daniel Finneran
27444b31ee Merge pull request #546 from W1zzardTPU/main
Add support for lbClassName
2023-04-26 16:08:03 +02:00
W1zzardTPU
f1eef8f07d Add support for lbClassName 2023-04-23 20:36:59 +02:00
Daniel Finneran
e4f42a3a44 Merge pull request #540 from thebsdbox/iptables
Adds nftables as an option, and fixes a panic
2023-04-14 09:35:07 +01:00
Dan Finneran
6c5b39b02a Merge branch 'iptables' of github.com:thebsdbox/kube-vip into iptables 2023-04-14 08:30:01 +00:00
Dan Finneran
e8319a6464 dont lint old files
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-04-14 08:29:51 +00:00
Daniel Finneran
7e4f596b5d Merge branch 'main' into iptables 2023-04-14 09:14:42 +01:00
Dan Finneran
eac9d2b8be Adds nftables as an option, and fixes a panic
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-04-14 08:13:27 +00:00
Chris Privitere
2b7c02c614 Merge pull request #538 from lubronzhan/topic/lubron/kube-vip_update_version_variable
Update makefile to accept variable to update version
2023-04-05 08:57:01 -05:00
lubronzhan
aa7eabd4fb Update makefile to accept variable to update version
Signed-off-by: lubronzhan <lzhan@vmware.com>
2023-04-04 22:48:59 -07:00
Daniel Finneran
aeabe547ff Merge pull request #536 from thebsdbox/iptables
Adds ability to specifc iptables or nftables
2023-04-04 15:11:25 +01:00
Daniel Finneran
8febca00ee Update ci.yaml 2023-04-04 15:02:33 +01:00
Daniel Finneran
6037cc7a6e Merge pull request #531 from lubronzhan/topic/lubron/fix_doc_link
Fix the doc link
2023-04-04 14:53:35 +01:00
Dan Finneran
9119597b94 final fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-04-04 13:52:45 +00:00
Dan Finneran
9e88b0003f Further linting fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-04-04 13:44:03 +00:00
Dan Finneran
f4d193f7fb Merge branch 'iptables' of github.com:thebsdbox/kube-vip into iptables 2023-04-04 08:46:58 +00:00
Dan Finneran
e604e4fe26 lint fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-04-04 08:45:56 +00:00
Daniel Finneran
8590fefa05 Merge branch 'main' into iptables 2023-04-03 18:19:30 +01:00
Dan Finneran
ae25e6bcf3 Adds ability to specifc iptables or nftables
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-04-03 17:18:00 +00:00
Daniel Finneran
8af0391bc9 Merge pull request #528 from lubronzhan/topic/lubron/deprecate_loadbalancerip
Deprecate loadbalancerIP, use annotation to fetch service loadbalancerIP
2023-03-16 16:23:32 +00:00
Pierre-Antoine Couaillier
e1bafbe699 Merge branch 'kube-vip:main' into iptables-nft 2023-03-09 14:22:36 +01:00
lubronzhan
cc63a13303 Fix the doc link
Signed-off-by: lubronzhan <lubronzhan@gmail.com>
2023-03-09 00:15:26 -08:00
Daniel Finneran
fb66fe0708 Merge pull request #529 from lubronzhan/topic/lubron/update_readme 2023-03-07 07:00:00 +00:00
lubronzhan
332546dd13 Update readme
Signed-off-by: lubronzhan <lzhan@vmware.com>
2023-03-06 16:01:31 -08:00
lubronzhan
a9932ec148 Deprecate loadbalancerIP
Add new annotation kube-vip.io/loadbalancerIPs to specify the loadbalancer ip for service
Now ip address fetched from loadbalancer service are first fetched from annotation, then fallback to service spec
Unit test

Signed-off-by: lubronzhan <lzhan@vmware.com>
2023-03-06 15:53:38 -08:00
Daniel Finneran
a422d246bb Merge pull request #526 from mrueg/bump-deps 2023-03-06 18:21:44 +00:00
Manuel Rüger
798b9c4b8f go.mod: Bump dependencies
Also replace github.com/ghodss/yaml with sigs.k8s.io/yaml (maintained
fork).

Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2023-03-05 12:40:54 +01:00
Daniel Finneran
c7536f180e Merge pull request #524 from tylerschultz/recreate-vip-on-dadfailed
Readd VIP if address has dadfailed flag
2023-03-02 17:48:52 +01:00
Tyler Schultz
61d5deb0b9 Readd VIP if address has dadfailed flag
Remove the address from in the interface case that a duplicate address is detected.
Without this change, kube-vip will take no corrective action, and the
address will remain in dadfailed state. Removing and re adding the
address causes duplicate address detection to happen again, hopefully
successfully the next time.

We suspect dadfailed happens when a new leader is elected and the old
leader is too slow or fails to delete the IP address.

Co-authored-by: Aidan Obley <aobley@vmware.com>
Co-authored-by: Christian Ang <angc@vmware.com>
Signed-off-by: Tyler Schultz <tschultz@vmware.com>
2023-03-01 22:41:10 +00:00
Daniel Finneran
49c871bd93 Merge pull request #521 from ocobleseqx/support_new_equinix_ccm_annotations
check for new equinix ccm annotations
2023-02-27 11:58:56 +01:00
Daniel Finneran
9c6b87c43c Update README.md 2023-02-27 09:44:42 +00:00
ocobleseqx
0320d256f3 replace packet with equinix metal in comments and logs
Signed-off-by: ocobleseqx <oscar.cobles@eu.equinix.com>
2023-02-24 13:33:16 +01:00
ocobleseqx
a691b3f128 check for new equinix ccm annotations
Signed-off-by: ocobleseqx <oscar.cobles@eu.equinix.com>
2023-02-23 19:41:20 +01:00
Daniel Finneran
a92c536de2 Update main.yaml 2023-02-21 08:56:40 +00:00
Daniel Finneran
323f054ca5 Merge pull request #519 from kube-vip/final-0.5.x-release
Update Makefile
2023-02-20 18:44:38 +01:00
Daniel Finneran
53d33d79f4 Update Makefile 2023-02-20 17:36:39 +00:00
Daniel Finneran
a31d9a65f2 Merge pull request #515 from kube-vip/dependabot/go_modules/golang.org/x/net-0.7.0
Bump golang.org/x/net from 0.2.0 to 0.7.0
2023-02-20 17:00:31 +01:00
Daniel Finneran
bcaa8bede6 Merge pull request #518 from thebsdbox/actions_fixes
Actions fixes
2023-02-20 16:53:38 +01:00
Dan Finneran
18d11ea252 Set correct labels.
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-20 15:53:10 +00:00
Dan Finneran
3971c7de0b Tidies actions.
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-20 15:51:33 +00:00
Daniel Finneran
0c14497985 Update anchore-syft.yml 2023-02-20 09:33:36 +00:00
Daniel Finneran
3caa8fdec2 Merge pull request #517 from thebsdbox/2e2eLint
lint fixes
2023-02-20 10:04:14 +01:00
Daniel Finneran
23fda78b45 Update ci.yaml
removes random manifest generate
2023-02-20 08:41:38 +00:00
Dan Finneran
aed43b2def final fix to makefile
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-19 16:39:08 +00:00
Dan Finneran
790d0b5291 lint fix
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-19 16:27:27 +00:00
Dan Finneran
7802027f67 lint fixes
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-19 16:09:25 +00:00
Daniel Finneran
606f3e30d5 Update ci.yaml 2023-02-19 16:02:42 +00:00
Daniel Finneran
90f6234d71 Merge pull request #516 from thebsdbox/e2eServices
Adds e2e testing of services
2023-02-19 16:59:13 +01:00
Dan Finneran
98c885dff5 Adds e2e testing of services
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-19 15:58:03 +00:00
dependabot[bot]
acea12d09a Bump golang.org/x/net from 0.2.0 to 0.7.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.2.0 to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/compare/v0.2.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-17 14:14:28 +00:00
Daniel Finneran
9d15cbe8ca Merge pull request #494 from fimmicon/patch-1
Fix broken link in docs
2023-02-17 15:11:51 +01:00
Daniel Finneran
a3644baa7d Merge pull request #513 from thebsdbox/endpoint_fixes
Fixes and testing for endpoints
2023-02-15 15:09:22 +01:00
Dan Finneran
c10b4105b9 Fixes and testing for endpoints
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-15 13:52:25 +00:00
Daniel Finneran
62d826fbe5 Merge pull request #512 from thebsdbox/endpoint_leadership
Ensures a leadership will be restarted
2023-02-10 19:30:25 +00:00
Dan Finneran
285f4e514c this should be it
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-10 18:14:17 +00:00
Dan Finneran
71b490d735 stupid linter
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-10 18:09:55 +00:00
Dan Finneran
b62b331be8 more linting
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-10 18:02:46 +00:00
Dan Finneran
9ab8b909bf linter fix
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-10 16:41:48 +00:00
Dan Finneran
d93e0cdf9c Ensures a leadership will be restarted
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-10 16:36:20 +00:00
Daniel Finneran
4f0c163b89 Merge pull request #510 from spideyfusion/fix-service-delete
Fix service deletion not registering
2023-02-10 16:35:41 +00:00
Daniel Finneran
a66b84a77e Update Makefile 2023-02-08 14:05:37 +00:00
Daniel Finneran
b446a80d9b Merge pull request #511 from thebsdbox/context_fix
Adds services testing and fixes missing context
2023-02-08 14:05:13 +00:00
Dan Finneran
aa296d8211 Fixes to linting
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-08 13:57:01 +00:00
Dan Finneran
3a8a94fcc9 Adds services testing and fixes missing context
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-08 12:58:44 +00:00
Daniel Finneran
3ff1eb2f99 Merge pull request #509 from thebsdbox/main
Fixes to negative waitgroup
2023-02-07 08:59:43 +00:00
Petar Obradović
9f728278fd Fix service deletion not registering
Signed-off-by: Petar Obradović <petar.obradovic@sofascore.com>
2023-02-02 11:58:41 +01:00
Dan Finneran
7ad4e27084 Fixes to negative waitgroup
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-02-02 10:30:35 +00:00
Daniel Finneran
1b4bba0800 New Release 2023-01-19 15:10:21 +00:00
Daniel Finneran
1d1a8bbd55 Merge pull request #503 from thebsdbox/api_failure
Keep watching services after losing leadership
2023-01-19 15:09:59 +00:00
Dan Finneran
631960fb0c Keep watching services after losing leadership
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2023-01-16 20:57:34 +00:00
Pierre-Antoine Couaillier
af5860633b adding iptables-wrappers script to entrypoint
Signed-off-by: Pierre-Antoine Couaillier <pa.couaillier@gmail.com>
2023-01-16 16:47:56 +00:00
Daniel Finneran
c9ce2cf779 Merge pull request #498 from kriansa/patch-1
Fix watching for endpoints RBAC rule
2023-01-09 16:38:34 +00:00
Daniel Finneran
f28a448d0b Merge pull request #500 from imzyxwvu/fix/ipv6-path
Enable IPv6 peering and VIP advertisement and improve BGP support.
2023-01-09 16:36:52 +00:00
zyxwvu Shi
d01903194b doc: Update bgp_peers description
Signed-off-by: zyxwvu Shi <i@shiyc.cn>
2023-01-08 16:51:17 +08:00
zyxwvu Shi
1dfda79af8 bgp: Make password and multiHop params optional
Also fix a CodeQL alert.

Signed-off-by: zyxwvu Shi <i@shiyc.cn>
2023-01-08 16:51:17 +08:00
zyxwvu Shi
b83a993805 bgp: Allow IPv6 BGP peer to be specified with brackets
Ability to specify BGP port is removed, for two reasons:
1. IPv6 peer addresses contain colons, and the SpiltN func breaks IPv6 addresses.
2. Typical network devices do not allow changing BGP port, so this is rarely used.

Signed-off-by: zyxwvu Shi <i@shiyc.cn>
2023-01-08 16:51:17 +08:00
zyxwvu Shi
95ae62e9eb bgp: Remove unused Config fields
Signed-off-by: zyxwvu Shi <i@shiyc.cn>
2023-01-08 16:51:17 +08:00
zyxwvu Shi
35a93d8275 bgp: Advertise IPv6 host prefix using MpReachNLRIAttribute
MP-BGP protocol requires IPv6 prefixes to be advertised in a path attribute called MP_REACH_NLRI. Without the attribute non-IPv4 prefixes can not be advertised. This prevents IPv6 loadBalancerIps and control plane addresses from being advertised to the network.

Signed-off-by: zyxwvu Shi <i@shiyc.cn>
2023-01-08 16:51:17 +08:00
zyxwvu Shi
1dc74c4249 bgp: Let gobgp figure out NEXT_HOP path attribute
According to UpdatePathAttrs in gobgp internal/pkg/table/path.go, gobgp will fill NEXT_HOP with BGP session local address if given NEXT_HOP is an unspecified address, such as 0.0.0.0 and ::. It is better to use that address as NEXT_HOP, since the BGP TCP connection ensures the address reaches the node.

See: https://github.com/osrg/gobgp/blob/v3.10.0/internal/pkg/table/path.go#L223

Signed-off-by: zyxwvu Shi <i@shiyc.cn>
2023-01-06 22:51:41 +08:00
Daniel Finneran
c69edfe1e6 Merge pull request #493 from GeorgeGedox/patch-1
Update broken links in k3s docs
2022-12-30 16:03:33 +00:00
Daniel Pereira
9c7a1e60be fix: endpoints watcher
Without this specific ClusterRole rule, kube-vip would not be able to listen for `endpoints` changes when deployed as a DaemonSet, thus causing the IP addresses not being announced and the following error message every second:

```
E1227 20:37:20.290479       1 retrywatcher.go:130] "Watch failed" err="unknown (get endpoints)"
```
2022-12-27 17:46:44 -03:00
Efim
9c60351867 Fix broken link in docs 2022-12-06 14:27:18 +02:00
George V
45aae3ee7c Update broken links in k3s docs
Fix broken documentation links
2022-12-04 00:01:44 +02:00
Daniel Finneran
f830b389da Update Makefile 2022-12-01 11:23:21 +00:00
Daniel Finneran
3026769caf Merge pull request #490 from thebsdbox/goroutine_gc
garbage collection for goroutines
2022-12-01 11:19:20 +00:00
Dan Finneran
1e4ef9f2b1 garbage collection for goroutines
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2022-12-01 11:09:54 +00:00
Daniel Finneran
26f1b9ae67 Merge pull request #489 from lubronzhan/cve_2022_nov_28
Fix CVE
2022-11-29 20:16:24 +00:00
lubronzhan
f4a9e1b65b Fix several CVEs
Signed-off-by: lubronzhan <lzhan@vmware.com>
2022-11-28 18:11:51 -08:00
Daniel Finneran
96134ccbe5 Merge pull request #487 from stevesloka/linter-errors
linter: Clean up some linter errors
2022-11-28 13:44:12 +00:00
Steve Sloka
6d5533ca58 linter: Clean up some linter errors
Cleans up errors found when running `make` that golangci-lint
found.

Signed-off-by: Steve Sloka <steve@stevesloka.com>
2022-11-26 11:57:17 -05:00
Daniel Finneran
99b261a685 Merge pull request #485 from thebsdbox/reconcilliation_testing
added testing
2022-11-17 16:18:15 +00:00
Dan Finneran
f84c4aaa8b added testing
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2022-11-17 16:17:18 +00:00
Daniel Finneran
0aa339ec00 Merge pull request #484 from thebsdbox/flush_conntrack
Adds an annotation for flushing conntrack rules
2022-11-16 14:54:42 +00:00
Dan Finneran
139add9d51 Adds an annotation for flushing conntrack rules
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2022-11-16 13:20:17 +00:00
Daniel Finneran
06c5f784b8 Merge pull request #483 from thebsdbox/address_annotation
Tidies the annotations
2022-11-16 13:04:12 +00:00
Dan Finneran
dc40c4dc0b Tidies the annotations
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2022-11-16 13:03:27 +00:00
Daniel Finneran
76c5711129 Merge pull request #482 from thebsdbox/egress_clean_fix
Fix to egress rules
2022-11-10 11:28:42 +00:00
Daniel Finneran
7ebb54961b Update release.yaml
Allows manual trigger
2022-11-10 10:58:33 +00:00
Dan Finneran
47a8832d89 Fix to egress rules
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2022-11-10 10:52:53 +00:00
Daniel Finneran
1dc035f606 Update Makefile
Bumping for a new release!
2022-11-09 17:10:02 +00:00
Daniel Finneran
63e513ee34 Merge pull request #480 from thebsdbox/further_fixes
logging and fixed an issue with multiple elections
2022-11-09 17:09:32 +00:00
Dan Finneran
e599a33330 logging and fixed an issue with multiple elections
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2022-11-09 16:49:33 +00:00
Daniel Finneran
46d662ac14 Merge pull request #478 from thebsdbox/dangling_rules
Fixes to where iptables are gc
2022-11-07 13:41:26 -05:00
Dan Finneran
ccaf8119da Fixes to where iptables are gc
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2022-11-07 18:40:48 +00:00
Daniel Finneran
d8654781a9 Merge pull request #477 from thebsdbox/subnet
Adds capability to specify a subnet for the VIP
2022-11-07 12:46:09 -05:00
Dan Finneran
5e38c81290 Adds capability to specify a subnet for the VIP
Signed-off-by: Dan Finneran <daniel.finneran@gmail.com>
2022-11-07 17:43:55 +00:00
Daniel Finneran
f052777b6b Merge pull request #476 from thebsdbox/rule_cleaning
Adds tags to rules so that we can garbage collect.
2022-11-07 10:41:46 -05:00
Dan Finneran
af1a1e51c8 Adds tags to rules so that we can garbage collect. 2022-11-07 15:25:34 +00:00
Daniel Finneran
315fa695f4 Merge pull request #474 from thebsdbox/cached_services
This fixes an issue with the cache being wiped
2022-11-02 13:28:29 -04:00
thebsdbox
ccaef3d750 This fixes an issue with the cache being wiped
Signed-off-by: thebsdbox <dan@thebsdbox.co.uk>
2022-11-02 16:18:17 +00:00
Daniel Finneran
3d7c1229e5 Merge pull request #473 from thebsdbox/cidr
Adds the capability to exclude egress traffic
2022-10-31 12:16:47 -04:00
thebsdbox
f173c5f979 Adds the capability to exclude egress traffic
Signed-off-by: thebsdbox <dan@thebsdbox.co.uk>
2022-10-31 16:07:35 +00:00
Daniel Finneran
28eb301d32 Merge pull request #472 from thebsdbox/leaderElection
Fixes all leaderElection code to use config
2022-10-31 11:53:03 -04:00
thebsdbox
a4b11e6854 Fixes all leaderElection code to use config
Signed-off-by: thebsdbox <dan@thebsdbox.co.uk>
2022-10-31 15:52:29 +00:00
Daniel Finneran
4073cc3a8b Merge pull request #470 from thebsdbox/logging
Fixes to logging
2022-10-31 10:29:54 -04:00
thebsdbox
8687d28eb4 Fixes to logging
Signed-off-by: thebsdbox <dan@thebsdbox.co.uk>
2022-10-31 13:22:17 +00:00
Daniel Finneran
5330992f9b Merge pull request #469 from thebsdbox/testing_adds
Adds some additional checking scripts
2022-10-31 08:55:59 -04:00
thebsdbox
6c52800bd4 Adds some additional checking scripts 2022-10-31 12:54:53 +00:00
Daniel Finneran
76d5ad8a49 Merge pull request #467 from abhay-krishna/fix-typo
Fix typo in EnableControlPlane config option
2022-10-19 09:26:00 +01:00
Abhay Krishna Arunachalam
7321a06dae Fix typo in EnableControlPlane config option
Signed-off-by: Abhay Krishna Arunachalam <arnchlm@amazon.com>
2022-10-18 22:22:58 -07:00
Daniel Finneran
34b05aa525 Merge pull request #460 from mrueg/update-deps
Update deps / build with go 1.19
2022-10-12 09:22:32 +01:00
Manuel Rüger
6004892920 go.mod: Update dependencies
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2022-10-11 20:08:13 +02:00
Manuel Rüger
ea7ab1e4d6 Update to go 1.19
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2022-10-11 20:08:11 +02:00
Daniel Finneran
c9a4d584b4 Delete release_iptables.yaml 2022-10-11 13:13:45 +01:00
Daniel Finneran
bc260ce03a Update release.yaml 2022-10-11 13:13:31 +01:00
Daniel Finneran
28b58dc013 Create release_iptables.yaml 2022-10-11 09:45:07 +01:00
Daniel Finneran
256f866d43 Update release.yaml 2022-10-11 09:44:23 +01:00
Daniel Finneran
56362fb47e Update release.yaml 2022-10-10 20:27:10 +01:00
Daniel Finneran
5c859f42f5 Update Makefile 2022-10-10 16:25:16 +01:00
Daniel Finneran
834b5aae54 Merge pull request #459 from thebsdbox/egress_ports
Adds ports and namespaces
2022-10-10 16:24:10 +01:00
thebsdbox
daa7d852ab linting fixes 2022-10-10 14:12:36 +01:00
thebsdbox
651038ada2 Adds ports and namespaces 2022-10-10 13:48:54 +01:00
Daniel Finneran
97eae7c528 Merge pull request #456 from thebsdbox/egress_stability
Adds stability and warnings to egress
2022-09-28 12:06:16 +01:00
Daniel Finneran
c41df19a36 Update mainiptables.yaml 2022-09-28 12:01:22 +01:00
Daniel Finneran
88af581958 Update mainiptables.yaml 2022-09-28 11:56:39 +01:00
Daniel Finneran
00cd131e2e Update mainiptables.yaml 2022-09-28 11:55:16 +01:00
Daniel Finneran
e6ae07f404 Create mainiptables.yaml 2022-09-28 11:54:38 +01:00
Daniel Finneran
2a1152f4d0 Merge pull request #449 from daper/main
Add random MAC address generation for DHCP
2022-09-28 11:44:55 +01:00
thebsdbox
36f42300c4 Adds stability and warnings to egress 2022-09-28 11:44:02 +01:00
Daniel Finneran
65c175d185 Merge pull request #445 from thebsdbox/egress
This adds the initial code for egress (SNAT).
2022-09-15 15:45:28 +03:00
thebsdbox
6620440c95 Final first push at Egress 2022-09-15 13:41:42 +01:00
daper
023ddbafd1 Add random MAC address generation for DHCP
Signed-off-by: David Peralta <david@daper.email>
2022-09-13 16:37:01 +02:00
thebsdbox
98f5c73919 Fixes to iptables and endpoint watcher 2022-09-13 09:09:20 +01:00
Daniel Finneran
de206eb46a Merge pull request #440 from cprivitere/Build-fixes
Build-fixes
2022-09-11 08:52:06 +01:00
Daniel Finneran
0b82de9dcf Merge pull request #446 from alexandrevilain/fix/wrong-env-var 2022-09-07 20:29:33 +01:00
Alexandre Vilain
db1ed82510 fix --table flag should add vip_routingtable env var not vip_wireguard
Signed-off-by: Alexandre Vilain <alexandre.vilain@me.com>
2022-09-07 21:03:17 +02:00
thebsdbox
ba20ae1725 This adds the initial code for egress (SNAT). 2022-09-06 15:18:48 +01:00
Daniel Finneran
bb4c815c5c Update anchore-syft.yml 2022-08-30 14:28:10 +01:00
Daniel Finneran
8a0eb9a661 Update anchore-syft.yml 2022-08-30 14:26:29 +01:00
Chris Privitere
8eaafee0f5 Add ReadHeaderTimeout
Resolves golanglint-ci complaint

Signed-off-by: Chris Privitere <23177737+cprivitere@users.noreply.github.com>
2022-08-29 15:30:10 -05:00
Chris Privitere
7e97ef0eef go fmt
Signed-off-by: Chris Privitere <23177737+cprivitere@users.noreply.github.com>
2022-08-29 15:29:42 -05:00
Daniel Finneran
85cb26d305 Update anchore-syft.yml 2022-08-26 12:52:07 +01:00
Daniel Finneran
6b12d18ab2 Update anchore-syft.yml 2022-08-26 09:39:04 +01:00
Daniel Finneran
a29cf4ea80 Update anchore-syft.yml
Fixes buildkit dependency
2022-08-26 09:36:29 +01:00
Daniel Finneran
494283d511 Add Anchore SBOM creation 2022-08-26 09:31:34 +01:00
Daniel Finneran
bb0d1a3db0 Merge pull request #435 from abhinavmpandey08/exclusive-lb-class 2022-08-15 19:05:38 +01:00
Abhinav Pandey
c50465c09c Enable kube-vip to only respond to svc with kube-vip's lb class
Signed-off-by: Abhinav Pandey <abhinavmpandey08@gmail.com>
2022-08-15 11:00:25 -07:00
Daniel Finneran
ff040f2def Merge pull request #434 from valtzu/main
Allow fixed virtual MAC for DHCP VIPs
2022-08-10 11:25:30 +01:00
valtzu
14100f0aec Allow fixed virtual MAC for VIPs via DHCP
Closes #354

Signed-off-by: valtzu <valtzu@gmail.com>
2022-08-08 00:13:27 +03:00
Daniel Finneran
708f4b3ebf Update FUNDING.yml 2022-08-07 12:24:32 +01:00
Daniel Finneran
1ef3592305 Update Makefile 2022-07-22 09:27:24 +01:00
Daniel Finneran
a00040dd40 Merge pull request #427 from thebsdbox/add-route-on-lead
Adds a route if leader
2022-07-21 14:32:02 +01:00
thebsdbox
31786074a8 Adds a route if leader 2022-07-21 14:30:54 +01:00
Daniel Finneran
a70b965b52 Update FUNDING.yml 2022-07-15 22:34:04 +01:00
Daniel Finneran
579d9dd89f Merge pull request #423 from kube-vip/thebsdbox-sponsor
Create FUNDING.yml
2022-07-15 09:03:02 +01:00
Daniel Finneran
ef78dcc5e5 Create FUNDING.yml 2022-07-15 08:53:50 +01:00
Daniel Finneran
49f4516209 Merge pull request #422 from scuzhanglei/fix-close-nil-chanel-panic
Fixes close nil channel panic
2022-07-14 13:10:59 +01:00
zhanglei
e6048c3eab Fixes close nil channel panic
Signed-off-by: zhanglei <zhanglei@smartx.com>
2022-07-14 19:40:16 +08:00
Daniel Finneran
d533e40796 Merge pull request #417 from thebsdbox/prometheus
prometheus changes
2022-07-05 14:15:38 +01:00
thebsdbox
93dfe4d372 prometheus changes 2022-07-01 17:01:59 +01:00
Daniel Finneran
c7c4f8d31a Merge pull request #416 from thebsdbox/table_mode
Table mode is now added to kube-vip
2022-06-30 14:17:34 +01:00
thebsdbox
9d15e0ac8b fixes to missing env 2022-06-30 11:25:40 +01:00
thebsdbox
1bcd101b53 Table mode is now added to kube-vip 2022-06-29 16:08:02 +01:00
Daniel Finneran
c6f37f433a Merge pull request #414 from thebsdbox/loadBalancerClass
Adds loadBalancerClass
2022-06-27 19:07:02 +01:00
thebsdbox
46b4325187 linting fix 2022-06-27 18:59:25 +01:00
thebsdbox
169eb0c7aa Adds loadBalancerClass 2022-06-27 18:08:09 +01:00
Daniel Finneran
b8d3ec8087 Merge pull request #412 from thebsdbox/wireguard
Wireguard support (basic)
2022-06-27 18:06:14 +01:00
thebsdbox
fcb24e7eab Fixes to the design 2022-06-27 17:41:33 +01:00
thebsdbox
8d0db81225 linter fixes 2022-06-25 16:57:10 +01:00
thebsdbox
ccee5ab7bd Wireguard support (basic) 2022-06-25 16:42:26 +01:00
Daniel Finneran
3c2eac15d4 Merge pull request #410 from thebsdbox/traffic_policy
This enables local traffic policy
2022-06-21 19:21:36 +01:00
thebsdbox
5485bbdcab This enables local traffic policy 2022-06-21 15:53:41 +01:00
Daniel Finneran
d815d3cb79 Merge pull request #407 from thebsdbox/leader_per_service
Initial design of leaderElection per service
2022-06-21 15:52:58 +01:00
thebsdbox
f51aa1f60f formatting fixes 2022-06-21 15:19:59 +01:00
thebsdbox
efea371edc Security fixes 2022-06-21 15:14:47 +01:00
thebsdbox
7d9062fd0e linting 2022-06-21 13:59:27 +01:00
thebsdbox
8d4f0e5206 annotations and working leaderElection 2022-06-21 13:57:13 +01:00
thebsdbox
b2df1cba3d Fixes to function signature 2022-06-08 13:14:38 +01:00
thebsdbox
840a2ba2b1 Initial design of leaderElection per service 2022-06-08 12:57:56 +01:00
Daniel Finneran
f22f6d4e93 Merge pull request #405 from thebsdbox/e2e
e2e test
2022-06-01 17:15:38 +02:00
thebsdbox
7c22c78a75 e2e test 2022-06-01 16:14:55 +01:00
Daniel Finneran
0487080505 Merge pull request #404 from thebsdbox/ignore_wrong_services
Ignore services that aren't LoadBalancers
2022-06-01 13:04:24 +02:00
thebsdbox
cef1852099 Ignore services that aren't LoadBalancers 2022-06-01 11:52:19 +01:00
Daniel Finneran
ac53446f33 Merge pull request #396 from AxiomSamarth/get-lease
set kubernetes:6443 as default hostname
2022-05-30 17:54:19 +02:00
Daniel Finneran
ca61bfdbe3 Merge pull request #401 from thebsdbox/em_annotations
Packet to equinixmetal
2022-05-30 17:54:05 +02:00
thebsdbox
f8d3152e93 disable new annotations 2022-05-30 13:30:20 +01:00
thebsdbox
f1841f70ef Packet to equinixmetal 2022-05-30 11:15:07 +01:00
AxiomSamarth
da7ba0b9a6 set kubernetes:6443 as default hostname
Signed-off-by: AxiomSamarth <sdeyagond@microsoft.com>
2022-05-14 13:00:19 +05:30
Daniel Finneran
b9014ae32a Update README.md 2022-05-13 15:32:47 +01:00
Daniel Finneran
51a1a0bb61 Merge pull request #395 from AxiomSamarth/get-lease
Set api-endpoint to host for incluster deployment
2022-05-13 14:20:38 +01:00
AxiomSamarth
75a2323448 set api-endpoint to host for incluster deployment
Signed-off-by: AxiomSamarth <sdeyagond@microsoft.com>
2022-05-13 18:28:09 +05:30
Daniel Finneran
7a7425efdf Update Makefile 2022-04-21 09:24:11 +01:00
Daniel Finneran
d4683401b6 Merge pull request #351 from yaocw2020/release-bug
Fix DHCP release bug
2022-04-21 09:12:07 +01:00
yaocw2020
e6edf3a3de Fix DHCP release bug
The macvlan interface could not be deleted until the DHCP client has
released the IP.

If the network manager in the operating system uses DHCP to obtain an IP
for the network card, it will occupy the DHCP client port. In this case
the release function will fail because the unicast connection with UDP
socket need the same port. Update dhcp package and use a raw socket.

Signed-off-by: yaocw2020 <yaocanwu@gmail.com>
2022-04-21 12:38:01 +08:00
Daniel Finneran
40cff6bc50 Merge pull request #389 from claudio4/main
Treat interfaces with unknown state as valid
2022-04-18 10:00:16 +01:00
Claudio Yanes
428d306030 Fix missing interface name in warning message
Signed-off-by: Claudio Yanes <me@claudio4.com>
2022-04-14 13:34:09 +01:00
Claudio Yanes
5fbb11fa06 Treat interfaces with unknown state as valid
Previous commits addressed the issue of interface being incorrectly marked as
down for loopback (1a4465e) and point-to-point (051bb1f) interfaces by directly
passing the test when the interface is identified a any of those types. Both
commits failed to address the core issue, those interfaces (and many others) do
not publish their operational state resulting in the state UNKOWN. With this
commit, now interfaces with unknown status are accepted but the user is warned as
he needs to manually ensure that the interface is ready to handle traffic.
Fix #385

Signed-off-by: Claudio Yanes <me@claudio4.com>
2022-04-14 13:34:09 +01:00
Daniel Finneran
8185df46b9 Merge pull request #388 from mrueg/ignore-p2p 2022-04-09 14:08:20 +01:00
Manuel Rüger
051bb1f414 Don't check status on Point-To-Point interfaces
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2022-04-09 00:20:16 +02:00
Daniel Finneran
b883939f6e Merge pull request #387 from mrueg/gobgpv
Update to gobgp/v3, ndp/v0.10.0 / go 1.18
2022-04-05 14:07:06 +01:00
Manuel Rüger
88c9075116 Update golangci-lint
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2022-04-05 00:31:42 +02:00
Manuel Rüger
fae208e459 Update to gobgp/v3, ndp/v0.10.0 / go 1.18
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2022-04-05 00:31:42 +02:00
Daniel Finneran
1279570f11 Merge pull request #386 from thebsdbox/testing_n_logs
Update to automated testing and clear msg
2022-04-04 20:54:45 +01:00
thebsdbox
d7b49a0f0f Update to automated testing and clear msg 2022-04-04 14:49:38 +01:00
Daniel Finneran
7b0bd4061f Update Makefile 2022-04-01 15:59:54 +01:00
Daniel Finneran
342161068a Merge pull request #384 from yaocw2020/supportChangingVIP
support changing the VIP of services
2022-04-01 15:57:58 +01:00
yaocw2020
c81c8c1865 support changing the VIP of services
- Support changing the VIP of services
- Refactory the manager.syncServices to improve code readability

Signed-off-by: yaocw2020 <yaocanwu@gmail.com>
2022-03-29 00:23:13 +08:00
Daniel Finneran
344cb491eb Merge pull request #383 from yaocw2020/gratuitous-arp 2022-03-24 15:35:52 +00:00
yaocw2020
9bd837f0c6 The gratuitous arp should be sent periodically
Related issue: https://github.com/kube-vip/kube-vip/issues/382

Signed-off-by: yaocw2020 <yaocanwu@gmail.com>
2022-03-24 12:24:55 +08:00
Daniel Finneran
b609330c48 Merge pull request #370 from rohitsakala/main
Add s390x arch support
2022-02-28 17:19:54 +00:00
Venkata Krishna Rohit Sakala
8afd9487ff Add s390x arch support
Signed-off-by: Venkata Krishna Rohit Sakala <rohitsakala@gmail.com>
2022-02-28 14:35:20 +01:00
Daniel Finneran
48add4ddeb Merge pull request #366 from mrueg/go-1.17
Build with go-1.17, bump dependencies
2022-02-28 10:02:31 +00:00
Daniel Finneran
ac83920e2c Merge pull request #365 from thebsdbox/retry_update
Adds retry to status update
2022-02-28 10:02:09 +00:00
Manuel Rüger
3f91c045d4 Build with go-1.17, bump dependencies
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2022-02-18 13:23:08 +01:00
Daniel Finneran
027703ec0f Merge pull request #364 from rawkode/fix/correctly-spell-prometheus
fix: spell prometheus correctly
2022-02-17 14:43:39 +00:00
thebsdbox
58da24127e Adds retry to status update 2022-02-17 14:42:56 +00:00
David Flanagan
1fb1de9990 fix: spell prometheus correctly 2022-02-14 18:50:46 +00:00
Daniel Finneran
7038960a24 Merge pull request #362 from thebsdbox/new_release
New release
2022-02-09 07:52:01 -05:00
thebsdbox
ff3a010a8d Security fix for unit 2022-02-09 11:37:47 +00:00
thebsdbox
e9ea905693 Fix environment variable and tidy 2022-02-09 11:16:42 +00:00
thebsdbox
8448c1224e Bump new release to 4.2 2022-02-09 11:10:37 +00:00
Chris Privitere
c5049407c7 Merge pull request #350 from kube-vip:cprivite/issue349
Merge pull request #348 from cprivite/cprivite/issue342
2022-01-11 16:14:34 -06:00
Chris Privitere
1e0523fa8a Use same formatting for main and release.
Signed-off-by: Chris Privitere <cprivite@users.noreply.github.com>
2022-01-11 15:28:56 -06:00
Chris Privitere
d1aa8bcb6f Switch to doing the tags with a github context.
Signed-off-by: Chris Privitere <cprivite@users.noreply.github.com>
2022-01-11 15:09:22 -06:00
Chris Privitere
ae22483f08 Add id as per docker-build-push pattern.
Signed-off-by: Chris Privitere <cprivite@users.noreply.github.com>
2022-01-11 15:08:50 -06:00
Chris Privitere
ad355fb6f6 Add login for github packages.
Signed-off-by: Chris Privitere <cprivite@users.noreply.github.com>
2022-01-11 15:08:30 -06:00
Chris Privitere
777eddafd8 Move from env vars to github contexts.
Signed-off-by: Chris Privitere <cprivite@users.noreply.github.com>
2022-01-11 15:08:05 -06:00
Chris Privitere
0d5a140f0d Rename to docker since it's also building.
Signed-off-by: Chris Privitere <cprivite@users.noreply.github.com>
2022-01-11 15:07:19 -06:00
Daniel Finneran
4b269dcdfd Merge pull request #348 from cprivite/cprivite/issue342
Don't check interface is up if it's loopback.
2022-01-10 17:51:47 +00:00
Chris Privitere
1a4465ebcc Don't check interface is up if it's loopback.
Signed-off-by: Chris Privitere <cprivite@users.noreply.github.com>
2022-01-10 11:22:54 -06:00
Daniel Finneran
41dc5e9914 Merge pull request #347 from yaocw2020/main
Build and publish the main image every day
2022-01-07 09:57:29 +00:00
yaocw2020
c037ac3561 Build and publish the main image every day
Signed-off-by: yaocw2020 <yaocanwu@gmail.com>
2022-01-07 00:52:47 +08:00
Daniel Finneran
056a6c5c16 Update readme with correct URL for logo 2021-12-23 10:23:56 +00:00
Daniel Finneran
ec0014d9ea Add logo 2021-12-23 10:23:05 +00:00
Daniel Finneran
ce37958c39 Merge pull request #341 from yaocw2020/debugLog
set route event log as debug level
2021-12-22 15:49:39 +00:00
yaocw2020
98f0a9505b set route event log as debug level
Signed-off-by: yaocw2020 <yaocanwu@gmail.com>
2021-12-22 22:46:26 +08:00
Daniel Finneran
36f1b33e94 Merge pull request #338 from mrueg/manifests-0.4.1
docs: Generate manifests for 0.4.1
2021-12-22 13:31:55 +00:00
Daniel Finneran
bad7b5f92c Merge pull request #339 from yaocw2020/checkDefaultIF
Monitor default VIP interface
2021-12-22 13:31:31 +00:00
Daniel Finneran
ac6cbad0eb Merge pull request #340 from mrueg/common-labels
config: Use recommended labels in manifests
2021-12-22 13:20:46 +00:00
Manuel Rüger
afd9029474 config: Use recommended labels in manifests
https://kubernetes.io/docs/concepts/overview/working-with-objects/common-labels/

Fixes: https://github.com/kube-vip/kube-vip/issues/315

Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2021-12-22 13:52:32 +01:00
yaocw2020
306ce2440e Monitor default VIP interface
The kube-vip chooses the default interface based on the default
route. Once the default route changes, the default interface may be
invalid. In this case, it would be better to crash the process. The pod
will restart immediately if the kube-vip is deployed as a daemonset.

Signed-off-by: yaocw2020 <yaocanwu@gmail.com>
2021-12-22 20:37:58 +08:00
Manuel Rüger
0f391a0032 docs: Generate manifests for 0.4.1
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2021-12-22 13:32:38 +01:00
Daniel Finneran
94ab16575f Merge pull request #337 from thebsdbox/new_release
New 0.4.1 release
2021-12-22 11:35:16 +00:00
thebsdbox
179cfef6e2 New 0.4.1 release 2021-12-22 11:06:55 +00:00
Daniel Finneran
fdf7773d29 Merge pull request #334 from mrueg/update
Update golang to 1.16.12 and golang dependencies
2021-12-22 10:44:32 +00:00
Daniel Finneran
2e554c9d49 Merge pull request #336 from thebsdbox/SYS_TIME
removes an incorrect CAP
2021-12-22 10:44:16 +00:00
thebsdbox
3507c46a51 Removes redundant config generation and e2e fix 2021-12-22 10:25:19 +00:00
thebsdbox
7f58bf4012 removes an incorrect CAP 2021-12-22 10:14:20 +00:00
Manuel Rüger
cd5fa620d5 pkg/vip/ndp.go: Rename Dial to Listen
Function was renamed.
See: 9dc889e435

Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2021-12-22 00:37:28 +01:00
Manuel Rüger
19d84bb50b go.mod: Update dependencies
github.com/cloudflare/ipvs v0.0.0-20210114211356-96b2597859b3 -> v0.8.0
github.com/insomniacslk/dhcp v0.0.0-20210621130208-1cac67f12b1e -> v0.0.0-20211214070828-5297eed8f489
github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567 -> v0.0.0-20210831201139-f982b8766fb5
github.com/mdlayher/raw v0.0.0-20210412142147-51b895745faf -> v0.0.0-20211126142749-4eae47f3d54b
github.com/onsi/ginkgo v1.14.0 -> v1.14.2
github.com/packethost/packngo v0.13.0 -> v0.20.0
github.com/prometheus/client_golang v0.10.0 -> v0.11.0
github.com/spf13/cobra v1.1.3 -> v1.3.0
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f -> v0.0.0-20211101163701-50045581ed74
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d -> v0.0.0-20211216030914-fe4d6282115f
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 -> v0.0.0-20211216021012-1d35b9e2eb4e
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 -> v0.0.0-20210927222741-03fcf44c2211
k8s.io/api v0.22.2 -> v0.22.5
k8s.io/apimachinery v0.22.2 -> v0.22.5
k8s.io/client-go v0.22.2 -> v0.22.5
k8s.io/klog/v2 v2.9.0 -> v2.40.1
sigs.k8s.io/kind v0.10.0 -> v0.11.1

Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2021-12-22 00:37:28 +01:00
Manuel Rüger
09088a9c17 Dockerfile: Update to go 1.16.12 and alpine 3.15 base
Signed-off-by: Manuel Rüger <manuel@rueg.eu>
2021-12-21 23:22:03 +01:00
Daniel Finneran
a5b0eab318 Adding static analysis as part of CNCF onboarding 2021-12-21 09:33:52 +00:00
Daniel Finneran
1deb91a93d Merge pull request #332 from thebsdbox/vip_services_doc
Adds missing flag/env for services interface
2021-12-20 13:21:55 +00:00
thebsdbox
dd621131c6 Adds missing flag/env for services interface 2021-12-20 13:11:35 +00:00
Daniel Finneran
f442e61fd3 Merge pull request #329 from yaocw2020/validateInterface
Check interface
2021-12-19 11:22:33 +00:00
yaocw2020
df539cbc6e Check interface
In some cases, kube-vip will start to serve before the interface is not
existed or not up. We should make sure the interface is valid.

Signed-off-by: yaocw2020 <yaocanwu@gmail.com>
2021-12-17 00:02:18 +08:00
Daniel Finneran
1d39a5b34a Merge pull request #326 from spectrocloud/ddns-fix
fix ddns support
2021-12-13 11:52:39 +00:00
Deepak Sharma
a642f32414 add client id to request
Signed-off-by: Deepak Sharma <deepak@spectrocloud.com>
2021-12-13 16:18:00 +05:30
Daniel Finneran
ccc97b9bc5 Merge pull request #327 from jbguerraz/lbforwardingtype
allow to configure the ipvs forwarding method
2021-12-13 09:11:20 +00:00
Jean-Baptiste Guerraz
0649fb01eb allow to configure the ipvs forwarding method 2021-12-11 23:21:13 +00:00
Deepak Sharma
3855ed4553 ddns fix
gofmt file

Signed-off-by: Deepak Sharma <deepak@spectrocloud.com>
2021-12-10 17:03:47 +05:30
Daniel Finneran
3979c1fcce Merge pull request #320 from lewisdiamond/patch-3
Fix typo in log (s/addded/added/)
2021-12-06 12:42:55 +00:00
Daniel Finneran
af52f4f9fd Merge pull request #323 from sykesm/address-no-vip-panic
Pass resolved VIP from Network.IP() to NewIPVSLB
2021-12-06 12:42:05 +00:00
Daniel Finneran
4e1bb7f77a Merge pull request #321 from sykesm/control-plane-label
Update label selector for control-plane nodes
2021-12-02 11:19:22 +00:00
Lewis Diamond
92f6ad4395 Fix typo in log (s/addded/added/)
Signed-off-by: Lewis Diamond <git@lewisdiamond.com>
2021-11-29 11:27:31 -05:00
Matthew Sykes
2d14d63ef2 Pass resolved VIP from Network.IP() to NewIPVSLB
When the manager process is started without the `--vip` flag, it will
panic during initialization. This is because the `nil` result from
`net.ParseIP("")` is passed to `ipvs.NewIP()`.

This change passes the resolved address from `cluster.Network.IP()`
instead of the possibly-empty VIP from the configuration.

Signed-off-by: Matthew Sykes <matthew.sykes@gmail.com>
2021-11-27 21:16:38 -05:00
Matthew Sykes
022b62caca Update label selector for control-plane nodes
The current node watcher uses a label selector of the form
`node-role.kubernetes.io/control-plane=`; this does not work correctly.

The label selector should be `node-role.kubernetes.io/control-plane" or
`node-role.kubernetes.io/control-plane=true` to select the control-plane
nodes.

Without these changes, the IPVS tables are never updated with the
control plane nodes and clients making requests to the VIP will fail
with a "connection refused" error.

```
$ kubectl get nodes -l node-role.kubernetes.io/control-plane=
No resources found

$ kubectl get nodes -l node-role.kubernetes.io/control-plane=true
NAME     STATUS   ROLES                       AGE   VERSION
pi4-00   Ready    control-plane,etcd,master   21h   v1.22.3+k3s1
pi4-01   Ready    control-plane,etcd,master   20h   v1.22.3+k3s1
pi4-02   Ready    control-plane,etcd,master   20h   v1.22.3+k3s1

$ kubectl get nodes -l node-role.kubernetes.io/control-plane
NAME     STATUS   ROLES                       AGE   VERSION
pi4-00   Ready    control-plane,etcd,master   21h   v1.22.3+k3s1
pi4-01   Ready    control-plane,etcd,master   20h   v1.22.3+k3s1
pi4-02   Ready    control-plane,etcd,master   20h   v1.22.3+k3s1
```

Signed-off-by: Matthew Sykes <matthew.sykes@gmail.com>
2021-11-27 14:00:01 -05:00
Daniel Finneran
2a2cb7b5fa Update index.md 2021-11-25 09:45:27 +00:00
Daniel Finneran
0783c006b8 Update index.md
Fixes header
2021-11-25 09:44:43 +00:00
Daniel Finneran
147ae7ae5f Merge pull request #316 from thebsdbox/ipvs_race_condition
IPVS fixes
2021-11-23 19:19:31 +00:00
Daniel Finneran
0a3f963578 Merge pull request #313 from chipzoller/main
Extensive linting, corrections, expansions
2021-11-23 19:19:19 +00:00
Chip Zoller
48fc7bd4a1 Merge branch 'main' into main 2021-11-23 10:22:11 -05:00
Chip Zoller
8ad1620844 fix conflicts
Signed-off-by: Chip Zoller <chipzoller@gmail.com>
2021-11-23 10:20:29 -05:00
Chip Zoller
a36d33e4e5 further edits; revamp K3s docs
Signed-off-by: Chip Zoller <chipzoller@gmail.com>
2021-11-23 10:17:26 -05:00
thebsdbox
135a6b55e2 Final fixes to IPVS 2021-11-23 15:17:24 +00:00
Daniel Finneran
17fd21aeda Merge pull request #317 from lewisdiamond/patch-2
Various KIND documentation fixes
2021-11-23 15:02:24 +00:00
Lewis Diamond
0b6d0be44b Various KIND documentation fixes
KVVERSION needs to be preceeded with `$` for shell expansion of the variable.
`kubectl` is unlikely to be a binary in the current directory and is likely to be in `$PATH`
2021-11-22 16:55:09 -05:00
thebsdbox
82db862a1a IPVS fixes 2021-11-22 20:00:05 +00:00
Chip Zoller
6f18708ec2 address PR comments
Signed-off-by: Chip Zoller <chipzoller@gmail.com>
2021-11-22 12:25:27 -05:00
Chip Zoller
c1c9635bf4 updates
Signed-off-by: Chip Zoller <chipzoller@gmail.com>
2021-11-22 10:06:25 -05:00
Chip Zoller
f5e8e05271 more work
Signed-off-by: Chip Zoller <chipzoller@gmail.com>
2021-11-22 09:17:17 -05:00
Chip Zoller
2ec0510a37 more linting
Signed-off-by: Chip Zoller <chipzoller@gmail.com>
2021-11-21 20:01:31 -05:00
Chip Zoller
31e4958c99 linting
Signed-off-by: Chip Zoller <chipzoller@gmail.com>
2021-11-21 19:39:17 -05:00
Chip Zoller
a377b6e2a8 linting, typos
Signed-off-by: Chip Zoller <chipzoller@gmail.com>
2021-11-21 19:32:04 -05:00
Chip Zoller
f5a2bd8e59 Extensive linting, corrections, expansions
Signed-off-by: Chip Zoller <chipzoller@gmail.com>
2021-11-21 19:23:00 -05:00
Daniel Finneran
88d6df058b Merge pull request #308 from thebsdbox/custom_ipvs_port
Allows setting an API server port
2021-11-10 16:37:29 +00:00
thebsdbox
b11b9ba396 Allows setting an API server port 2021-11-10 15:59:35 +00:00
Daniel Finneran
4585812e0e Merge pull request #306 from thebsdbox/0.4-release
New release v0.4.0
2021-11-09 13:26:52 +00:00
thebsdbox
7b79084ae2 New release v0.4.0 2021-11-09 13:01:23 +00:00
Daniel Finneran
fd61ee4d49 Merge pull request #305 from thebsdbox/more_docs
Fix manifests and old generator
2021-11-09 12:56:18 +00:00
Daniel Finneran
e190256f92 Merge pull request #303 from thebsdbox/code_dedupe
Removes duplicated code and tidies function names
2021-11-09 12:56:02 +00:00
thebsdbox
4c1fd117d5 Fix manifests and old generator 2021-11-09 12:53:41 +00:00
Daniel Finneran
6ffa87e42b Merge pull request #304 from thebsdbox/0.4docs
Docs for upcoming 0.4 release
2021-11-09 11:44:06 +00:00
Daniel Finneran
1c73f15bef Merge branch 'main' into 0.4docs 2021-11-09 11:43:42 +00:00
thebsdbox
27e889e8a6 Docs for upcoming 0.4 release 2021-11-09 11:42:07 +00:00
thebsdbox
a75a53c47e lint fix ! 2021-11-08 12:21:31 +00:00
thebsdbox
c0a5c7a762 Removal of more duplicate code 2021-11-08 12:17:53 +00:00
thebsdbox
35f7d816f4 Removes duplicated code and tidies function names 2021-11-07 14:56:48 +00:00
Daniel Finneran
cfc6aa04ba Merge pull request #302 from RZRCDR/main
Add hostAliases to kube-vip-arp-ds.yaml on v0.3.9
2021-11-06 14:26:57 +00:00
Daniel Finneran
259091d019 Merge pull request #301 from shibumi/shibumi/update-image
update images
2021-11-02 09:18:48 +00:00
Dirkco du Plessis
0cef76ff4a Add hostAliases to kube-vip-arp-ds.yaml on v0.3.9
Signed-off-by: Dirkco du Plessis <dduplessis@credogroup.com>
2021-10-30 12:02:41 +01:00
Christian Rebischke
a79d5e61e9 update images
Signed-off-by: Christian Rebischke <chris@shibumi.dev>
2021-10-30 03:29:32 +02:00
Daniel Finneran
066c046cf5 Merge pull request #296 from thebsdbox/ipvs
Replace IPVS as the API server LoadBalancer
2021-10-28 15:54:51 +01:00
thebsdbox
08d38f5520 Final fixes to the IPVS work 2021-10-26 15:03:00 +01:00
thebsdbox
81975220c6 Fixed missing import 2021-10-26 13:52:25 +01:00
Daniel Finneran
93cca8e938 Merge branch 'main' into ipvs 2021-10-26 13:48:26 +01:00
thebsdbox
e1bfcb1aa6 Tidying up of redundant code, fixes to fwdtype lb 2021-10-26 13:47:13 +01:00
Daniel Finneran
8a05989122 Merge pull request #298 from stevesloka/refactork8sClient
Refactor the Kubernetes client generation into a single package
2021-10-26 13:32:10 +01:00
Steve Sloka
9b65c1e63c Refactor the Kubernetes client generation into a single place inside a new k8s package.
Signed-off-by: Steve Sloka <slokas@vmware.com>
2021-10-25 15:30:23 -04:00
Daniel Finneran
e4ab718bc9 Merge pull request #297 from mikenabhan/patch-1
Fix spelling in documentation
2021-10-25 08:56:32 +01:00
Mike Nabhan
cf122a3239 Fix spelling in documentation 2021-10-24 18:03:38 -06:00
thebsdbox
6c759fcd74 Lint fixes 2021-10-22 15:53:59 +01:00
thebsdbox
7a759e41f7 Replace IPVS as the API server LoadBalancer 2021-10-22 09:28:41 +01:00
Daniel Finneran
a35df41b46 Merge pull request #294 from thebsdbox/leaderElection
Removes local leaderElection fix
2021-10-20 17:30:23 +01:00
thebsdbox
843c3ebf94 Removes local leaderElection fix 2021-10-20 17:21:12 +01:00
Daniel Finneran
638c521d36 Merge pull request #295 from kube-vip/thebsdbox-patch-1
Update ci.yaml
2021-10-20 17:18:25 +01:00
Daniel Finneran
e2e2183e57 Update ci.yaml
Moves from Go 1.15 to 1.16
2021-10-20 17:09:41 +01:00
Daniel Finneran
65363c21ec Merge pull request #291 from thebsdbox/ignore_service
Ability for Kube-Vip to ignore a service
2021-10-20 15:55:18 +01:00
Daniel Finneran
903a341873 Merge branch 'main' into ignore_service 2021-10-20 15:46:54 +01:00
Daniel Finneran
b544e5b729 Merge pull request #290 from stevesloka/fixupLintErrors
Adds golangci-lint to check for code errors + clean up resulting findings
2021-10-20 15:46:10 +01:00
Daniel Finneran
c140e6afa5 Merge pull request #292 from kube-vip/Adds-golangci-lint
Update ci.yaml
2021-10-20 15:17:38 +01:00
Daniel Finneran
2cd9b36fac Update ci.yaml 2021-10-20 15:08:09 +01:00
Steve Sloka
2e9c2244c1 Adds golangci-lint to check for code errors + clean up resulting findings after running.
Signed-off-by: Steve Sloka <slokas@vmware.com>
2021-10-20 13:55:34 +00:00
thebsdbox
ec6fbfd162 Fixes order for reading env vars, and ignore svc 2021-10-20 14:53:19 +01:00
Daniel Finneran
70f14a5bfd Merge pull request #289 from thebsdbox/main
Auto detect default interface for VIP
2021-10-19 16:04:58 +01:00
thebsdbox
821a488e15 Removed autoInterface option 2021-10-19 14:34:54 +01:00
thebsdbox
0d492faaf0 Auto detect default interface for VIP 2021-10-19 11:17:33 +01:00
Daniel Finneran
c94c15a6b9 Merge pull request #285 from thebsdbox/localhost
Use localhost to connect to manager
2021-10-13 11:10:37 +01:00
thebsdbox
e2c8e4d724 Automates the changes required for callback to API server 2021-10-13 10:48:17 +01:00
thebsdbox
1f7ff01bec Use localhost to connect to manager 2021-10-12 11:41:44 +01:00
Daniel Finneran
53ac3868e8 Merge pull request #284 from thebsdbox/testing_fix
Adds easier moving between Kubernetes versions
2021-10-12 10:50:01 +01:00
thebsdbox
74fa77735b Adds easier moving between Kubernetes versions 2021-10-12 10:49:08 +01:00
Daniel Finneran
9f244e4d7d Merge pull request #278 from larrymapacket/larry-kubevip
update Metal's doc
2021-10-08 14:23:36 +01:00
larrymapacket
a46042e548 update the Equinix Metal kube-vip doc.
Signed-off-by: larrymapacket <larry@packet.com>
2021-10-04 17:09:57 -05:00
larrymapacket
0c82f3e00b Changing EquiniMetal usage document to add a few missing information and links.
Signed-off-by: larrymapacket <larry@packet.com>
2021-09-28 17:09:54 -05:00
Daniel Finneran
c333e2a1eb Merge pull request #274 from elmariofredo/patch-1
Add link to Equinix Metal  metal-gateway guide
2021-09-18 09:51:36 +01:00
Mario Vejlupek
96c7dc5f15 Add link to Equinix Metal metal-gateway guide
Signed-off-by: Mario Vejlupek <mario@vejlupek.cz>
2021-09-16 09:47:10 +02:00
Daniel Finneran
6bfed9c454 Merge pull request #272 from detiber/bumpgobgp 2021-09-10 21:39:00 +02:00
Jason DeTiberus
975b892e6d Bump gobgp dependency to the latest v2.31.0
Signed-off-by: Jason DeTiberus <detiber@users.noreply.github.com>
2021-09-10 14:07:03 -04:00
Daniel Finneran
ab19d4a4a4 Merge pull request #266 from thebsdbox/nic_seperation 2021-09-04 15:03:24 +02:00
thebsdbox
5f751cc321 Fixes from feedback 2021-09-03 13:37:43 +01:00
Daniel Finneran
59ce702b5e Merge pull request #268 from detiber/creds 2021-09-02 22:37:27 +02:00
Jason DeTiberus
7bfa79750d Support use Equinix Metal credentials from config
Use Equinix Metal credentials when available with EIP configuration
not just BGP configuration.

Signed-off-by: Jason DeTiberus <detiber@users.noreply.github.com>
2021-09-02 16:21:19 -04:00
Daniel Finneran
2ec44596b3 Merge pull request #267 from detiber/nodeAffinity
Update DaemonSet generation to improve scheduling
2021-09-02 21:28:10 +02:00
Jason DeTiberus
9addea6149 Update DaemonSet generation to improve scheduling
- Tolerate more than just the node-role.kubernetes.io/master taint, this allows
  the daemonset to schedule prior to CNI being deployed.

- Switch from using a nodeSelector to using nodeAffinity
  - Allows scheduling even if the node label does not match the value (for the node-role label, the value is generally ignored).
  - Add support for the control-plane node role rather than just master.

Signed-off-by: Jason DeTiberus <detiber@users.noreply.github.com>
2021-09-02 14:09:23 -04:00
thebsdbox
d06176a56b Implements a secondary interface just for services 2021-09-02 10:07:17 +01:00
Daniel Finneran
cc0fe1e870 Merge pull request #265 from thebsdbox/src_annotation
This will set source IP for BGP from annotations
2021-09-01 16:41:15 +02:00
thebsdbox
306a75ff84 This will set source IP for BGP from annotations 2021-09-01 14:53:55 +01:00
Daniel Finneran
3e565851e8 Merge pull request #264 from thebsdbox/docs_fix
Fixes Docs
2021-09-01 10:52:13 +02:00
thebsdbox
0a57816567 Fixes Docs 2021-09-01 09:51:00 +01:00
Daniel Finneran
8021ef7bf6 Updates Makefile to correct version 2021-09-01 09:42:11 +01:00
Daniel Finneran
3cc6b17916 Merge pull request #263 from detiber/useProjectID
[metal] Use provided provider id in config if defined
2021-09-01 10:13:22 +02:00
Jason DeTiberus
925b3bdc20 [packet] Support Address config in addition to VIP
Signed-off-by: Jason DeTiberus <detiber@users.noreply.github.com>
2021-08-31 18:20:57 -04:00
Jason DeTiberus
4a814f2427 [metal] Use provided provider id in config if defined
Signed-off-by: Jason DeTiberus <detiber@users.noreply.github.com>
2021-08-31 17:34:15 -04:00
Daniel Finneran
b72c984d5c Merge pull request #262 from thebsdbox/password_bug
Fixes the broken logic in password parsing
2021-08-31 18:34:34 +02:00
thebsdbox
fab9be29f0 Fixes the broken logic in password parsing 2021-08-31 17:18:16 +01:00
Daniel Finneran
a93b8382ac Merge pull request #261 from thebsdbox/BGP_Source
This change allows to specify either an adapter on an address to peer from
2021-08-26 13:14:55 +02:00
thebsdbox
54615fa750 Remove duplicate flag 2021-08-25 16:00:51 +01:00
thebsdbox
2b0345cc86 Adds BGP Source 2021-08-25 15:58:11 +01:00
Daniel Finneran
165b2ebb40 Merge pull request #255 from kplimack/advertise 2021-08-17 06:49:23 +01:00
Jake Plimack
9188f554ab spelling
Signed-off-by: Jake Plimack <jplimack@tesla.com>
2021-08-16 18:05:44 -06:00
Daniel Finneran
c92bec91b7 Merge pull request #253 from panpan0000/fix_ServiceType
fix typo of ServiceType. There's no svc.spec.type = ServiceTypeLoadBalancer
2021-08-05 08:30:47 +01:00
panpan0000
a42a5e7493 fix typo of ServiceType 2021-08-05 02:19:14 -04:00
Daniel Finneran
c46887c0bc Merge pull request #249 from rawkode/fix/annotations-first-pass
fix: ensure node annotations are checked before watch
2021-07-26 11:45:27 +01:00
David McKay
76dbce050c chore: add tests for parseBgpAnnotations 2021-07-26 11:33:02 +01:00
David McKay
7c644d680d chore: use node ResourceVersion 2021-07-26 11:01:40 +01:00
David McKay
fc24064e2a fix: ensure node annotations are checked before watch 2021-07-26 09:40:25 +01:00
Daniel Finneran
092eb5423a Merge pull request #248 from rawkode/chore/use-ghcr-default 2021-07-24 21:45:32 +01:00
David McKay
a26288a1d0 chore: encourage useage of GHCR instead of rate limited Docker Hub 2021-07-24 16:53:57 +01:00
David McKay
39043ce0f8 fix: backticks are deprecated and not POSIX compat, replace with $() 2021-07-24 16:35:11 +01:00
David McKay
31448255e8 chore: use git to fetch latest tag 2021-07-24 16:34:37 +01:00
Daniel Finneran
976d2f64fb Update Makefile 2021-07-23 17:52:51 +01:00
Daniel Finneran
0e751402eb Merge pull request #245 from mkumatag/support_ppc64le
Add support for ppc64le architecture
2021-07-23 09:08:55 +01:00
Manjunath A Kumatagi
df8a3addc1 Add support for ppc64le architecture 2021-07-23 09:38:35 +05:30
Daniel Finneran
aa155cd7d5 Update index.md 2021-07-21 15:43:59 +01:00
Daniel Finneran
81f7338dbd Update index.md 2021-07-21 15:42:43 +01:00
Daniel Finneran
cb6d8ac1a7 Merge pull request #237 from abhinavmpandey08/main 2021-07-12 17:57:02 +01:00
Abhinav Pandey
c395d45200 Add example manifest for kube-vip:v0.3.5 2021-07-12 09:01:33 -07:00
Daniel Finneran
8a64752585 Merge pull request #236 from thebsdbox/VIP_race
Fixes re-application of VIP
2021-07-09 17:00:04 +01:00
thebsdbox
27451767c3 Fixes re-application of VIP 2021-07-09 11:37:47 +01:00
Daniel Finneran
2d37e0e8df Merge pull request #229 from yaocw2020/main
Refactor the DHCP client
2021-07-07 09:59:46 +01:00
yaocw2020
e906270eb2 Refactor the DHCP client
Signed-off-by: yaocw2020 <yaocanwu@gmail.com>
2021-07-07 12:19:11 +08:00
Daniel Finneran
de5ca6a88e Merge pull request #232 from thebsdbox/kind_doc
Adds documentation for KIND
2021-07-06 17:22:22 +01:00
thebsdbox
ad43fa3202 Adds documentation for KIND 2021-07-06 17:16:30 +01:00
Daniel Finneran
d7078a89e2 Create CODEOWNERS 2021-07-06 15:44:07 +01:00
Daniel Finneran
1ede20f457 Merge pull request #227 from thebsdbox/annotations_bug
Fixes the hang on BGP password
2021-07-06 14:31:58 +01:00
Daniel Finneran
478e0d6ac9 Merge pull request #231 from thebsdbox/docs_rewrite
Big docs re-org
2021-07-06 14:31:47 +01:00
thebsdbox
f682535990 Final re-arrange of lb docs 2021-07-06 13:53:35 +01:00
thebsdbox
090182bcc8 BGP router_ID 2021-07-06 13:44:32 +01:00
thebsdbox
f19deede30 Big docs re-org 2021-07-06 13:12:48 +01:00
thebsdbox
9273a7d9e4 Fixes the hang on BGP password 2021-07-05 13:38:40 +01:00
Daniel Finneran
bba0906293 Merge pull request #222 from rawkode/fix/bgp-broadcast-error 2021-06-24 19:53:22 +03:00
David McKay
b24723ea7a fix: propagate errors when broadcasting BGP address fails 2021-06-24 16:28:25 +01:00
Daniel Finneran
2a6faaa37b Merge pull request #219 from thebsdbox/Makefile
Fixes manifest generation
2021-06-18 14:23:09 +01:00
thebsdbox
6e2495b9a1 Fixes manifest generation 2021-06-18 14:13:29 +01:00
Daniel Finneran
edfec80d03 Merge pull request #218 from sammcgeown/main
Update CCM docs and manifest
2021-06-17 20:09:08 +01:00
Sam McGeown
98803b4d74 Update kube-vip services docs with latest kube-vip details 2021-06-17 15:17:52 +01:00
Sam McGeown
aa39904040 Update CCM controller manifest to match kube-vip-cloud-controller repository 2021-06-17 14:15:38 +01:00
Daniel Finneran
deb2276e3e Merge pull request #212 from onedr0p/patch-1 2021-05-28 13:04:43 +01:00
ᗪєνιη ᗷυнʟ
a9286fd8c3 feat: push images to ghcr 2021-05-28 07:59:22 -04:00
Daniel Finneran
a0b5e7720a Merge pull request #208 from tahaozket/patch-1
Update kube-vip.go
2021-05-18 16:51:46 +01:00
Taha Ozket
2f0e1eec47 Update kube-vip.go
typo fixed metalrojectID -> metalProjectID
2021-05-15 19:29:26 +03:00
Daniel Finneran
94e8984ed1 Create CONTRIBUTING.md 2021-05-14 14:07:37 +01:00
Daniel Finneran
79f0fb9283 Create CODE_OF_CONDUCT.md 2021-05-14 12:55:21 +01:00
Daniel Finneran
318eaca208 Merge pull request #206 from kube-vip/Roadmap
Create ROADMAP.md
2021-05-14 12:41:31 +01:00
Daniel Finneran
1efc24d712 Create ROADMAP.md 2021-05-14 09:39:45 +01:00
Daniel Finneran
2cedaff8be Merge pull request #205 from thebsdbox/ddns
Fixes DDNS
2021-05-13 17:11:39 +01:00
thebsdbox
5545471391 Fixes DDNS 2021-05-13 17:10:44 +01:00
Daniel Finneran
874a0bb6d1 Merge pull request #203 from thebsdbox/dhcp_swap
Swap DHCP to a pkg with better licenses
2021-05-13 16:43:27 +01:00
thebsdbox
f69d0b77f6 Complete re-write of dhcp 2021-05-13 14:02:38 +01:00
thebsdbox
927ddf74fb Swap DHCP to a pkg with better licenses 2021-05-07 15:55:25 +01:00
Daniel Finneran
cb8cf78234 Merge pull request #200 from franciosi/patch-2
Small Typo Improves in README.md
2021-04-27 10:17:46 +01:00
Franciosi
eaebadd668 Small Typo Improves in README.md
Small typo improvements
2021-04-26 15:54:46 -03:00
Daniel Finneran
f234a6b7fe Merge pull request #199 from thebsdbox/error_fix
Error fixes
2021-04-21 19:32:38 +01:00
thebsdbox
49b77ab303 Error fixes 2021-04-21 19:31:40 +01:00
Daniel Finneran
49c5821508 Merge pull request #198 from thebsdbox/interface_fix
Fixes interface on networking restart
2021-04-21 08:40:41 +01:00
thebsdbox
239ff56dfa Fixes interface on networking restart 2021-04-20 15:25:32 +01:00
Daniel Finneran
00572acbc1 Update README.md 2021-04-20 11:04:52 +01:00
Daniel Finneran
afffb41d5d Merge pull request #197 from rosenhouse/e2e-action
run e2e tests in CI
2021-04-20 09:05:06 +01:00
Daniel Finneran
2af456b66f Merge pull request #196 from thebsdbox/BGP_PASSWORD
Bgp password support from annotations.
2021-04-20 09:04:51 +01:00
Gabe Rosenhouse
9fdf8026dd run e2e tests in CI 2021-04-19 21:58:58 +00:00
thebsdbox
e1d3ee24ea base64 decoding 2021-04-19 13:55:38 +01:00
thebsdbox
f1553b2bcd Adds Password support 2021-04-19 13:51:38 +01:00
Daniel Finneran
30f1c44223 Merge pull request #195 from anagno/actions
Adding the release actions
2021-04-19 09:39:58 +01:00
Vasileios Anagnostopoulos
e304614f35 Adding the release actions 2021-04-17 00:43:22 +02:00
227 changed files with 25136 additions and 10765 deletions

4
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
# Enable GitHub funding
github: [kube-vip]

14
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
- package-ecosystem: gomod
directory: /
schedule:
interval: weekly
- package-ecosystem: docker
directory: /
schedule:
interval: weekly

31
.github/workflows/anchore-syft.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow checks out code, builds an image, performs a container image
# scan with Anchore's Syft tool, and uploads the results to the GitHub Dependency
# submission API.
# For more information on the Anchore sbom-action usage
# and parameters, see https://github.com/anchore/sbom-action. For more
# information about the Anchore SBOM tool, Syft, see
# https://github.com/anchore/syft
name: Anchore Syft SBOM scan
on:
release:
types: [published]
jobs:
sbom:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ github.ref_name }}
- name: Anchore SBOM Action
uses: anchore/sbom-action@v0.20.10
with:
format: cyclonedx-json

71
.github/workflows/ci-pull-request.yaml vendored Normal file
View File

@@ -0,0 +1,71 @@
name: For each PR
on:
pull_request:
jobs:
e2e-tests:
runs-on: ubuntu-latest
name: E2E tests
strategy:
matrix:
mode: ["arp", "rt", "bgp"]
fail-fast: true
steps:
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%d-%H-%M')"
- name: Ensure fs wont cause issues
run: sudo sysctl fs.inotify.max_user_instances=8192 && sudo sysctl fs.inotify.max_user_watches=524288
- name: Checkout code
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Build image locally
run: make dockerx86Local
- name: Run Manifest generation tests
run: make manifest-test
- name: Run ARP mode tests v1.29.0 onwards
run: E2E_KEEP_LOGS=true make e2e-tests129-arp
if: matrix.mode== 'arp'
- name: Run RT mode tests v1.29.0 onwards
run: E2E_KEEP_LOGS=true make e2e-tests129-rt
if: matrix.mode== 'rt'
- name: Get GoBGP binaries
run: make get-gobgp
if: matrix.mode== 'bgp'
- name: Run BGP mode tests v1.29.0 onwards
run: sudo -E PATH=$PATH DOCKER_API_VERSION=1.48 E2E_KEEP_LOGS=true make e2e-tests129-bgp
if: matrix.mode== 'bgp'
- name: Change log directory permissions
run: sudo chmod -R 755 /tmp/kube-vip-test-${{ matrix.mode }}*
if: matrix.mode== 'bgp' && always()
- name: Save logs
uses: actions/upload-artifact@v5
with:
name: e2e-test-logs-${{ matrix.mode }}-${{ steps.date.outputs.date }}
path: /tmp/kube-vip-test-${{ matrix.mode }}*
if: always()
service-e2e-tests:
runs-on: ubuntu-latest
name: E2E service tests
steps:
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%d-%H-%M')"
- name: Checkout code
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Build image with iptables
run: make dockerx86ActionIPTables
- name: Run tests
run: DOCKERTAG=action E2E_KEEP_LOGS=true make service-tests
- name: Save logs
uses: actions/upload-artifact@v5
with:
name: services-test-logs-${{ steps.date.outputs.date }}
path: /tmp/kube-vip-service-tests*
if: always()

View File

@@ -1,25 +1,62 @@
name: For each commit and PR
name: For each commit
on:
push:
pull_request:
jobs:
validation:
runs-on: ubuntu-latest
env:
CGO_ENABLED: 0
name: Checks and linters
steps:
- name: Init
run: sudo apt-get update && sudo apt-get install -y build-essential golint
- name: Checkout code
uses: actions/checkout@v2
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: '1.15'
- name: checks
run: make check
- name: test docker build
run: make dockerx86Action
- name: Manifest generate
run: ./testing/testing.sh
- name: Init
run: sudo apt-get update && sudo apt-get install -y build-essential && sudo sysctl fs.inotify.max_user_instances=8192 && sudo sysctl fs.inotify.max_user_watches=524288
- name: Install golangci-lint
run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.8
- name: Checkout code
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: All checks
run: make check
unit-tests:
runs-on: ubuntu-latest
name: Unit tests
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Run tests
run: make unit-tests
integration-tests:
name: Integration tests
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
- name: Run tests
run: make integration-tests
image-vul-check:
runs-on: ubuntu-latest
name: Image vulnerability scan
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Build image with iptables
run: make dockerx86ActionIPTables
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: "plndr/kube-vip:action"
format: "table"
exit-code: "1"
ignore-unfixed: true
vuln-type: "os,library"
severity: "CRITICAL,HIGH"

75
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,75 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '17 10 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v4
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4

52
.github/workflows/main.yaml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Build and publish main image regularly
on:
schedule:
- cron: '25 0 * * *'
workflow_dispatch:
jobs:
nightly_build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to Github Packages
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build standard version
id: docker_build
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
push: ${{ github.event_name != 'pull_request' }}
tags: >-
plndr/kube-vip:${{ github.ref_name }},
ghcr.io/kube-vip/kube-vip:${{ github.ref_name }}
- name: Build iptables version
id: docker_build_iptables
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile_iptables
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
push: ${{ github.event_name != 'pull_request' }}
tags: >-
plndr/kube-vip-iptables:${{ github.ref_name }},
ghcr.io/kube-vip/kube-vip-iptables:${{ github.ref_name }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

64
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,64 @@
name: Publish Releases to Docker Hub and GitHub Container Registry
on:
push:
tags:
- '*'
workflow_dispatch:
jobs:
docker:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to Github Packages
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate Metadata
uses: docker/metadata-action@v5.9.0
id: metadata
with:
labels: |
org.opencontainers.image.documentation=https://kube-vip.io/docs/
- name: Build and push main branch
id: docker_build
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
push: ${{ github.event_name != 'pull_request' }}
labels: ${{ steps.metadata.outputs.labels }}
tags: >-
plndr/kube-vip:${{ github.ref_name }},
plndr/kube-vip:latest,
ghcr.io/kube-vip/kube-vip:${{ github.ref_name }},
ghcr.io/kube-vip/kube-vip:latest
- name: Build iptables version and push main branch
id: docker_build_iptables
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile_iptables
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
push: ${{ github.event_name != 'pull_request' }}
labels: ${{ steps.metadata.outputs.labels }}
tags: >-
plndr/kube-vip-iptables:${{ github.ref_name }},
plndr/kube-vip-iptables:latest,
ghcr.io/kube-vip/kube-vip-iptables:${{ github.ref_name }},
ghcr.io/kube-vip/kube-vip-iptables:latest
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
.idea
kube-vip
.vscode
bin
testing/e2e/etcd/certs
pkg/etcd/etcd.pid
pkg/etcd/etcd-data

13
.golangci.yml Normal file
View File

@@ -0,0 +1,13 @@
run:
timeout: 10m
linters:
enable:
- bodyclose
- gofmt
- goimports
- revive
- gosec
- misspell
- unconvert
- unparam

33
CHANGELOG.md Normal file
View File

@@ -0,0 +1,33 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- SIGUSR1 signal handler for runtime configuration dumps (#1301)
- Send SIGUSR1 to kube-vip process to dump current configuration to stdout
- Configuration dump includes:
- Basic configuration (VIP, interface, port, namespace settings)
- BGP configuration (enabled status, AS number, router ID, peers)
- ARP/NDP configuration (enabled status, broadcast rate)
- Services configuration (enabled status, load balancer settings)
- Network interfaces status
- Leader election configuration (type, lease details)
- Runtime statistics (load balancer, Prometheus, health check settings)
- Output format: Human-readable plaintext via fmt.Printf()
- Thread-safe implementation using mutex protection
- Non-disruptive: Process continues running after configuration dump
- Added comprehensive unit tests for all dump methods
- Added E2E tests for signal handling
### Changed
- Updated signal handlers in manager_arp.go, manager_bgp.go, manager_wireguard.go, and manager_table.go to use switch statement pattern for handling multiple signals (SIGUSR1, SIGINT, SIGTERM)
## [v1.0.1] - Previous Release
### Previous changes
- See git history for changes prior to CHANGELOG.md introduction

10
CODEOWNERS Normal file
View File

@@ -0,0 +1,10 @@
# For more information on the syntax of the CODEOWNERS file, see:
# https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners
# The Kube-Vip maintainers team
* @thebsdbox @yastij
# Emeritus Maintainers
#
# N/A

128
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
conduct@kube-vip.io.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

289
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,289 @@
# Developer Guide
Thank you for taking the time out to contribute to the **kube-vip** project!
This guide will walk you through the process of making your first commit and how
to effectively get it merged upstream.
<!-- toc -->
- [Getting Started](#getting-started)
- [Contribute](#contribute)
- [GitHub Workflow](#github-workflow)
- [Getting reviewers](#getting-reviewers)
- [Inclusive Naming](#inclusive-naming)
- [Building and testing your change](#building-and-testing-your-change)
- [Reverting a commit](#reverting-a-commit)
- [Sign-off Your Work](#sign-off-your-work)
- [Issue and PR Management](#issue-and-pr-management)
- [Filing An Issue](#filing-an-issue)
- [Issue Triage](#issue-triage)
<!-- /toc -->
## Getting Started
To get started, let's ensure you have completed the following prerequisites for
contributing to project **kube-vip**:
1. Read and observe the [code of conduct](CODE_OF_CONDUCT.md).
2. Check out the [Architecture documentation](https://kube-vip.io) for the **kube-vip**
architecture and design.
3. Set up your [development environment](docs/contributors/manual-installation.md)
Now that you're setup, skip ahead to learn how to [contribute](#contribute).
**Also**, A GitHub account will be required in order to submit code changes and
interact with the project. For committing any changes in **Github** it is required for
you to have a [github account](https://github.com/join).
## Contribute
There are multiple ways in which you can contribute, either by contributing
code in the form of new features or bug-fixes or non-code contributions like
helping with code reviews, triaging of bugs, documentation updates, filing
[new issues](#filing-an-issue) or writing blogs/manuals etc.
### GitHub Workflow
Developers work in their own forked copy of the repository and when ready,
submit pull requests to have their changes considered and merged into the
project's repository.
1. Fork your own copy of the repository to your GitHub account by clicking on
`Fork` button on [kube-vip's GitHub repository](https://github.com/kube-vip/kube-vip).
2. Clone the forked repository on your local setup.
```bash
git clone https://github.com/$user/kube-vip
```
Add a remote upstream to track upstream kube-vip repository.
```bash
git remote add upstream https://github.com/kube-vip/kube-vip
```
Never push to upstream remote
```bash
git remote set-url --push upstream no_push
```
3. Create a topic branch.
```bash
git checkout -b branchName
```
4. Make changes and commit it locally. Make sure that your commit is
[signed](#sign-off-your-work).
```bash
git add <modifiedFile>
git commit -s
```
5. Update the "Unreleased" section of the [CHANGELOG](CHANGELOG.md) for any
significant change that impacts users.
6. Keeping branch in sync with upstream.
```bash
git checkout branchName
git fetch upstream
git rebase upstream/main
```
7. Push local branch to your forked repository.
```bash
git push -f $remoteBranchName branchName
```
8. Create a Pull request on GitHub.
Visit your fork at `https://github.com/kube-vip/kube-vip` and click
`Compare & Pull Request` button next to your `remoteBranchName` branch.
### Getting reviewers
Once you have opened a Pull Request (PR), reviewers will be assigned to your
PR and they may provide review comments which you need to address.
Commit changes made in response to review comments to the same branch on your
fork. Once a PR is ready to merge, squash any *fix review feedback, typo*
and *merged* sorts of commits.
To make it easier for reviewers to review your PR, consider the following:
1. Follow the golang [coding conventions](https://github.com/golang/go/wiki/CodeReviewComments).
2. Format your code with `make golangci-fix`; if the [linters](ci/README.md) flag an issue that
cannot be fixed automatically, an error message will be displayed so you can address the issue.
3. Follow [git commit](https://chris.beams.io/posts/git-commit/) guidelines.
4. Follow [logging](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md) guidelines.
If your PR fixes a bug or implements a new feature, add the appropriate test
cases to our [automated test suite](ci/README.md) to guarantee enough
coverage. A PR that makes significant code changes without contributing new test
cases will be flagged by reviewers and will not be accepted.
### Inclusive Naming
For symbol names and documentation, do not introduce new usage of harmful
language such as 'master / slave' (or 'slave' independent of 'master') and
'blacklist / whitelist'. For more information about what constitutes harmful
language and for a reference word replacement list, please refer to the
[Inclusive Naming Initiative](https://inclusivenaming.org/).
We are committed to removing all harmful language from the project. If you
detect existing usage of harmful language in code or documentation, please
report the issue to us or open a Pull Request to address it directly. Thanks!
### Building and testing your change
To build the **kube-vip** Docker image together with all **kube-vip** bits, you can simply
do:
1. Checkout your feature branch and `cd` into it.
2. Run `make dockerx86`
The second step will compile the **kube-vip** code in a `golang` container, and build
a `Ubuntu 20.04` Docker image that includes all the generated binaries. [`Docker`](https://docs.docker.com/install)
must be installed on your local machine in advance.
Alternatively, you can build the **kube-vip** code in your local Go environment. The
**kube-vip** project uses the [Go modules support](https://github.com/golang/go/wiki/Modules) which was introduced in Go 1.11. It
facilitates dependency tracking and no longer requires projects to live inside
the `$GOPATH`.
To develop locally, you can follow these steps:
1. [Install Go 1.19](https://golang.org/doc/install)
2. Checkout your feature branch and `cd` into it.
3. To build all Go files and install them under `bin`, run `make bin`
4. To run all Go unit tests, run `make test-unit`
5. To build the **kube-vip** Ubuntu Docker image separately with the binaries generated in step 2, run `make ubuntu`
### CI testing
For more information about the tests we run as part of CI, please refer to
[ci/README.md](ci/README.md).
### Reverting a commit
1. Create a branch in your forked repo
```bash
git checkout -b revertName
```
2. Sync the branch with upstream
```bash
git fetch upstream
git rebase upstream/main
```
3. Create a revert based on the SHA of the commit. The commit needs to be
[signed](#sign-off-your-work).
```bash
git revert -s SHA
```
4. Push this new commit.
```bash
git push $remoteRevertName revertName
```
5. Create a Pull Request on GitHub.
Visit your fork at `https://github.com/kube-vip/kube-vip` and click
`Compare & Pull Request` button next to your `remoteRevertName` branch.
### Sign-off Your Work
It is recommended to sign your work when contributing to the **kube-vip**
repository.
Git provides the `-s` command-line option to append the required line
automatically to the commit message:
```bash
git commit -s -m 'This is my commit message'
```
For an existing commit, you can also use this option with `--amend`:
```bash
git commit -s --amend
```
If more than one person works on something it's possible for more than one
person to sign-off on it. For example:
```bash
Signed-off-by: Some Developer somedev@example.com
Signed-off-by: Another Developer anotherdev@example.com
```
We use the [DCO Github App](https://github.com/apps/dco) to enforce that all
commits in a Pull Request include the required `Signed-off-by` line. If this is
not the case, the app will report a failed status for the Pull Request and it
will be blocked from being merged.
Compared to our earlier CLA, DCO tends to make the experience simpler for new
contributors. If you are contributing as an employee, there is no need for your
employer to sign anything; the DCO assumes you are authorized to submit
contributions (it's your responsibility to check with your employer).
## Issue and PR Management
We use labels and workflows (some manual, some automated with GitHub Actions) to
help us manage triage, prioritize, and track issue progress. For a detailed
discussion, see [docs/issue-management.md](docs/contributors/issue-management.md).
### Filing An Issue
Help is always appreciated. If you find something that needs fixing, please file
an issue [here](https://github.com/kube-vip/kube-vip/issues). Please ensure
that the issue is self explanatory and has enough information for an assignee to
get started.
Before picking up a task, go through the existing
[issues](https://github.com/kube-vip/kube-vip/issues) and make sure that your
change is not already being worked on. If it does not exist, please create a new
issue and discuss it with other members.
For simple contributions to **kube-vip**, please ensure that this minimum set of
labels are included on your issue:
* **kind** -- common ones are `kind/feature`, `kind/support`, `kind/bug`,
`kind/documentation`, or `kind/design`. For an overview of the different types
of issues that can be submitted, see [Issue and PR
Kinds](#issue-and-pr-kinds).
The kind of issue will determine the issue workflow.
* **area** (optional) -- if you know the area the issue belongs in, you can assign it.
Otherwise, another community member will label the issue during triage. The
area label will identify the area of interest an issue or PR belongs in and
will ensure the appropriate reviewers shepherd the issue or PR through to its
closure. For an overview of areas, see the
[`docs/github-labels.md`](docs/contributors/github-labels.md).
* **size** (optional) -- if you have an idea of the size (lines of code, complexity,
effort) of the issue, you can label it using a [size label](#size). The size
can be updated during backlog grooming by contributors. This estimate is used
to guide the number of features selected for a milestone.
All other labels will be assigned during issue triage.
### Issue Triage
Once an issue has been submitted, the CI (GitHub actions) or a human will
automatically review the submitted issue or PR to ensure that it has all relevant
information. If information is lacking or there is another problem with the
submitted issue, an appropriate `triage/<?>` label will be applied.
After an issue has been triaged, the maintainers can prioritize the issue with
an appropriate `priority/<?>` label.
Once an issue has been submitted, categorized, triaged, and prioritized it
is marked as `ready-to-work`. A ready-to-work issue should have labels
indicating assigned areas, prioritization, and should not have any remaining
triage labels.

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:experimental
FROM golang:1.15-alpine as dev
FROM golang:1.25.4-alpine3.22 as dev
RUN apk add --no-cache git ca-certificates make
RUN adduser -D appuser
COPY . /src/
@@ -16,4 +16,4 @@ FROM scratch
COPY --from=dev /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
# Add kube-vip binary
COPY --from=dev /src/kube-vip /
ENTRYPOINT ["/kube-vip"]
ENTRYPOINT ["/kube-vip"]

21
Dockerfile_iptables Normal file
View File

@@ -0,0 +1,21 @@
# syntax=docker/dockerfile:experimental
FROM golang:1.25.4-alpine3.22 as dev
RUN apk add --no-cache git make
RUN adduser -D appuser
COPY . /src/
WORKDIR /src
ENV GO111MODULE=on
RUN --mount=type=cache,sharing=locked,id=gomod,target=/go/pkg/mod/cache \
--mount=type=cache,sharing=locked,id=goroot,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=linux make build
FROM alpine:3.22.2
# Update pkgs and add iptables
RUN apk upgrade && \
apk add --no-cache iptables iptables-legacy
# Add kube-vip binary
COPY --from=dev /src/kube-vip /
ENTRYPOINT ["/kube-vip"]

118
Makefile
View File

@@ -2,10 +2,11 @@ SHELL := /bin/sh
# The name of the executable (default is current directory name)
TARGET := kube-vip
.DEFAULT_GOAL: $(TARGET)
.DEFAULT_GOAL := $(TARGET)
# These will be provided to the target
VERSION := 0.3.3
VERSION := v1.0.2
BUILD := `git rev-parse HEAD`
# Operating System Default (LINUX)
@@ -14,9 +15,9 @@ TARGETOS=linux
# Use linker flags to provide version/build settings to the target
LDFLAGS=-ldflags "-s -w -X=main.Version=$(VERSION) -X=main.Build=$(BUILD) -extldflags -static"
DOCKERTAG ?= $(VERSION)
REPOSITORY = plndr
REPOSITORY ?= docker.io/plndr
.PHONY: all build clean install uninstall fmt simplify check run e2e-tests
.PHONY: all build clean install uninstall simplify check run e2e-tests
all: check install
@@ -36,17 +37,30 @@ install:
uninstall: clean
@rm -f $$(which ${TARGET})
fmt:
@gofmt -l -w ./...
demo:
@cd demo
@docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --push -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x --push -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@echo New Multi Architecture Docker image created
@cd ..
## Remote (push of images)
# This build a local docker image (x86 only) for quick testing
dockerx86Dev:
@-rm ./kube-vip
@docker buildx build --platform linux/amd64 --push -t $(REPOSITORY)/$(TARGET):dev .
@echo New single x86 Architecture Docker image created
dockerx86Iptables:
@-rm ./kube-vip
@docker buildx build --platform linux/amd64 -f ./Dockerfile_iptables --push -t $(REPOSITORY)/$(TARGET):dev .
@echo New single x86 Architecture Docker image created
dockerx86IptablesLocal:
@-rm ./kube-vip
@docker buildx build --platform linux/amd64 -f ./Dockerfile_iptables -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@echo New single x86 Architecture Docker image created
dockerx86:
@-rm ./kube-vip
@docker buildx build --platform linux/amd64 --push -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@@ -54,7 +68,7 @@ dockerx86:
docker:
@-rm ./kube-vip
@docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --push -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x --push -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@echo New Multi Architecture Docker image created
## Local (docker load of images)
@@ -69,33 +83,97 @@ dockerx86Action:
@docker buildx build --platform linux/amd64 --load -t $(REPOSITORY)/$(TARGET):action .
@echo New Multi Architecture Docker image created
dockerx86ActionIPTables:
@-rm ./kube-vip
@docker buildx build --platform linux/amd64 -f ./Dockerfile_iptables --load -t $(REPOSITORY)/$(TARGET):action .
@echo New Multi Architecture Docker image created
dockerLocal:
@-rm ./kube-vip
@docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --load -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x --load -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@echo New Multi Architecture Docker image created
simplify:
@gofmt -s -l -w ./...
@gofmt -s -l -w *.go pkg cmd
check:
go mod tidy
test -z "$(git status --porcelain)"
test -z $(shell gofmt -l main.go | tee /dev/stderr) || echo "[WARN] Fix formatting issues with 'make fmt'"
golint ./...
test -z $(shell gofmt -l *.go pkg cmd) || echo "[WARN] Fix formatting issues with 'make simplify'"
golangci-lint run
go vet ./...
run: install
@$(TARGET)
manifests:
@make build
@mkdir -p ./docs/manifests/$(VERSION)/
@./kube-vip manifest pod --interface eth0 --vip 192.168.0.1 --arp --leaderElection --controlplane --services > ./docs/manifests/$(VERSION)/kube-vip-arp.yaml
@./kube-vip manifest pod --interface eth0 --vip 192.168.0.1 --bgp --controlplane --services > ./docs/manifests/$(VERSION)/kube-vip-bgp.yaml
@./kube-vip manifest daemonset --interface eth0 --vip 192.168.0.1 --arp --leaderElection --controlplane --services --inCluster > ./docs/manifests/$(VERSION)/kube-vip-arp-ds.yaml
@./kube-vip manifest daemonset --interface eth0 --vip 192.168.0.1 --bgp --leaderElection --controlplane --services --inCluster > ./docs/manifests/$(VERSION)/kube-vip-bgp-ds.yaml
@./kube-vip manifest daemonset --interface eth0 --vip 192.168.0.1 --bgp --leaderElection --controlplane --services --inCluster --provider-config /etc/cloud-sa/cloud-sa.json > ./docs/manifests/$(VERSION)/kube-vip-bgp-em-ds.yaml
@./kube-vip manifest pod --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --arp --leaderElection --controlplane --services > ./docs/manifests/$(VERSION)/kube-vip-arp.yaml
@./kube-vip manifest pod --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --arp --leaderElection --controlplane --services --enableLoadBalancer > ./docs/manifests/$(VERSION)/kube-vip-arp-lb.yaml
@./kube-vip manifest pod --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --bgp --controlplane --services > ./docs/manifests/$(VERSION)/kube-vip-bgp.yaml
@./kube-vip manifest daemonset --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --arp --leaderElection --controlplane --services --inCluster > ./docs/manifests/$(VERSION)/kube-vip-arp-ds.yaml
@./kube-vip manifest daemonset --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --arp --leaderElection --controlplane --services --inCluster --enableLoadBalancer > ./docs/manifests/$(VERSION)/kube-vip-arp-ds-lb.yaml
@./kube-vip manifest daemonset --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --bgp --leaderElection --controlplane --services --inCluster > ./docs/manifests/$(VERSION)/kube-vip-bgp-ds.yaml
@./kube-vip manifest daemonset --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --bgp --leaderElection --controlplane --services --inCluster > ./docs/manifests/$(VERSION)/kube-vip-bgp-em-ds.yaml
@-rm ./kube-vip
manifest-test:
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest pod --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --arp --leaderElection --controlplane --services
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest pod --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --arp --leaderElection --controlplane --services --enableLoadBalancer
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest pod --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --bgp --controlplane --services
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest daemonset --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --arp --leaderElection --controlplane --services --inCluster
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest daemonset --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --arp --leaderElection --controlplane --services --inCluster --enableLoadBalancer
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest daemonset --interface eth0 --vip 192.168.0.1 --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --bgp --leaderElection --controlplane --services --inCluster
unit-tests:
go test ./...
integration-tests:
go test -tags=integration,e2e -v ./pkg/etcd
e2e-tests:
E2E_IMAGE_PATH=$(REPOSITORY)/$(TARGET):$(DOCKERTAG) go run github.com/onsi/ginkgo/ginkgo -v -p testing/e2e
GOMAXPROCS=4 E2E_IMAGE_PATH=$(REPOSITORY)/$(TARGET):$(DOCKERTAG) go run github.com/onsi/ginkgo/v2/ginkgo --tags=e2e -v -p ./testing/e2e ./testing/e2e/etcd
e2e-tests129-arp:
GOMAXPROCS=4 TEST_MODE=arp V129=true K8S_IMAGE_PATH=kindest/node:v1.29.0 E2E_IMAGE_PATH=$(REPOSITORY)/$(TARGET):$(DOCKERTAG) go run github.com/onsi/ginkgo/v2/ginkgo --tags=e2e -v -p ./testing/e2e
e2e-tests129-rt:
GOMAXPROCS=4 TEST_MODE=rt V129=true K8S_IMAGE_PATH=kindest/node:v1.29.0 E2E_IMAGE_PATH=$(REPOSITORY)/$(TARGET):$(DOCKERTAG) go run github.com/onsi/ginkgo/v2/ginkgo --tags=e2e -v -p ./testing/e2e
e2e-tests129-bgp:
GOMAXPROCS=4 TEST_MODE=bgp V129=true K8S_IMAGE_PATH=kindest/node:v1.29.0 E2E_IMAGE_PATH=$(REPOSITORY)/$(TARGET):$(DOCKERTAG) go run github.com/onsi/ginkgo/v2/ginkgo --tags=e2e -v -p ./testing/e2e
e2e-tests129: e2e-tests129-arp e2e-tests129-rt e2e-tests129-bgp
service-tests:
E2E_IMAGE_PATH=$(REPOSITORY)/$(TARGET):$(DOCKERTAG) go run ./testing/services -Services -simple -deployments -leaderActive -leaderFailover -localDeploy -egress -egressIPv6 -dualStack
trivy: dockerx86ActionIPTables
docker run -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy:0.47.0 \
image \
--format table \
--exit-code 1 \
--ignore-unfixed \
--vuln-type 'os,library' \
--severity 'CRITICAL,HIGH' \
$(REPOSITORY)/$(TARGET):action
kind-quick:
echo "Standing up your cluster"
kind create cluster --config ./testing/kind/kind.yaml --name kube-vip
kubectl apply -f https://kube-vip.io/manifests/rbac.yaml
kubectl create configmap --namespace kube-system kubevip --from-literal range-global=172.18.100.10-172.18.100.30
kubectl apply -f https://raw.githubusercontent.com/kube-vip/kube-vip-cloud-provider/main/manifest/kube-vip-cloud-controller.yaml
kind load docker-image --name kube-vip $(REPOSITORY)/$(TARGET):$(DOCKERTAG)
docker run --network host --rm $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest daemonset --services --inCluster --image "$(REPOSITORY)/$(TARGET):$(DOCKERTAG)" --arp --servicesElection --interface eth0 | kubectl apply -f -
kind-reload:
kind load docker-image $(REPOSITORY)/$(TARGET):$(DOCKERTAG) --name services
kubectl rollout restart -n kube-system daemonset/kube-vip-ds
get-gobgp:
mkdir -p bin
wget -nc --directory-prefix=bin https://github.com/osrg/gobgp/releases/download/v3.37.0/gobgp_3.37.0_linux_amd64.tar.gz
tar -xvzf bin/gobgp_3.37.0_linux_amd64.tar.gz -C bin

View File

@@ -1,8 +1,10 @@
# kube-vip
High Availability and Load-Balancing
High Availability and Load-Balancing
![](https://kube-vip.io/kube-vip.png)
![](https://github.com/kube-vip/kube-vip/raw/main/kube-vip.png)
[![Build and publish main image regularly](https://github.com/kube-vip/kube-vip/actions/workflows/main.yaml/badge.svg)](https://github.com/kube-vip/kube-vip/actions/workflows/main.yaml) [![LFX Health Score](https://img.shields.io/static/v1?label=Health%20Score&message=Healthy&color=A7F3D0&logo=linuxfoundation&logoColor=white&style=flat)](https://insights.linuxfoundation.org/project/kube-vip) [![LFX Active Contributors](https://img.shields.io/static/v1?label=Active%20contributors%20(1Y)&message=212&color=0094FF&logo=linuxfoundation&logoColor=white&style=flat)](https://insights.linuxfoundation.org/project/kube-vip)
## Overview
Kubernetes Virtual IP and Load-Balancer for both control plane and Kubernetes services
@@ -14,12 +16,13 @@ The idea behind `kube-vip` is a small self-contained Highly-Available option for
- Virtualisation
- Pretty much anywhere else :)
**NOTE** All documentation of both usage and architecture are now available at [https://kube-vip.io](https://kube-vip.io)
**NOTE:** All documentation of both usage and architecture are now available at [https://kube-vip.io](https://kube-vip.io).
## Features
Kube-Vip was originally created to provide a HA solution for the Kubernetes control plane, over time it has evolved to incorporate that same functionality into Kubernetes service type [load-balancers](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer).
- VIP addresses can be both IPv4 or IPv6
- Control Plane with ARP (Layer 2) or BGP (Layer 3)
- Control Plane using either [leader election](https://godoc.org/k8s.io/client-go/tools/leaderelection) or [raft](https://en.wikipedia.org/wiki/Raft_(computer_science))
- Control Plane HA with kubeadm (static Pods)
@@ -29,7 +32,8 @@ Kube-Vip was originally created to provide a HA solution for the Kubernetes cont
- Service LoadBalancer address pools per namespace or global
- Service LoadBalancer address via (existing network DHCP)
- Service LoadBalancer address exposure to gateway via UPNP
- ... manifest generation, vendor API integrations and many nore...
- Egress! Kube-vip will utilise a service loadbalancer as both the ingress and **egress** for a pod.
- ... manifest generation, vendor API integrations and many more...
## Why?
@@ -41,7 +45,7 @@ The purpose of `kube-vip` is to simplify the building of HA Kubernetes clusters,
**VIP**:
- [Keepalived](https://www.keepalived.org/)
- [Ucarp](https://ucarp.wordpress.com/)
- [UCARP](https://ucarp.wordpress.com/)
- Hardware Load-balancer (functionality differs per vendor)
@@ -54,4 +58,14 @@ All of these would require a separate level of configuration and in some infrast
## Troubleshooting and Feedback
Please raise issues on the GitHub repository and as mentioned check the documentation at [https://kube-vip.io](https://kube-vip.io/)
Please raise issues on the GitHub repository and as mentioned check the documentation at [https://kube-vip.io](https://kube-vip.io/).
## Contributing
Thanks for taking the time to join our community and start contributing! We welcome pull requests. Feel free to dig through the [issues](https://github.com/kube-vip/kube-vip/issues) and jump in.
:warning: This project has issue compiling on MacOS, please compile it on linux distribution
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=kube-vip/kube-vip&type=Date)](https://star-history.com/#kube-vip/kube-vip&Date)

35
ROADMAP.md Normal file
View File

@@ -0,0 +1,35 @@
# Kube-Vip Roadmap
This document outlines the roadmap for the **kube-vip** project and only covers the technologies within this particular project, other projects that augment or provide additional functionality (such as cloud-providers) may have their own roadmaps in future. The functionality for **kube-vip** has grown either been developed organically or through real-world needs, and this is the first attempt to put into words a plan for the future of **kube-vip** and will additional evolve over time. This means that items listed or detailed here are not necessarily set in stone and the roadmap can grow/shrink as the project matures. We definitely welcome suggestions and ideas from everyone about the roadmap and **kube-vip** features. Reach us through Issues, Slack or email <catch-all>@kube-vip.io.
## Release methodology
The **kube-vip** project attempts to follow a tick-tock release cycle, this typically means that one release will come **packed** with new features where the following release will come with fixes, code sanitation and performance enhancements.
## Roadmap
The **kube-vip** project offers two main areas of functionality:
- HA Kubernetes clusters through a control-plane VIP
- Kubernetes `service type:LoadBalancer`
Whilst both of these functions share underlying technologies and code they will have slightly differing roadmaps.
### HA Kubernetes Control Plane
- **Re-implement LoadBalancing** - due to a previous request the HTTP loadbalancing was removed leaving just HA for the control plane. This functionality will be re-implemented either through the original round-robin HTTP requests or utilising IPVS.
- **Utilise the Kubernetes API to determine additional Control Plane members** - Once a single node cluster is running **kube-vip** could use the API to determine the additional members, at this time a Cluster-API provider needs to drop a static manifest per CP node.
- **Re-evaluate raft** - **kube-vip** is mainly designed to run within a Kubernetes cluster, however it's original design was a raft cluster external to Kubernetes. Unfortunately given some of the upgrade paths identified in things like CAPV moving to leaderElection within Kubernetes became a better idea.
## Kubernetes `service type:LoadBalancer`
- **`ARP` LeaderElection per loadBalancer** - Currently only one pod that is elected leader will field all traffic for a VIP.. extending this to generate a leaderElection token per service would allow services to proliferate across all pods across the cluster
- **Aligning of `service` and `manager`** - The move to allow hybrid (be both HA control plane and offer load-balancer services at the same time) introduced a duplicate code path.. these need to converge as it's currently confusing for contributors.
## Global **Kube-Vip** items
- **Improved metrics** - At this time the scaffolding for monitoring exists, however this needs drastically extending to provide greater observability to what is happening within **kube-vip**
- **Windows support** - The Go SDK didn't support the capability for low-levels sockets for ARP originally, this should be revisited.
- **Additional BGP features** :
- Communities
- BFD

View File

@@ -1,146 +0,0 @@
package cmd
import (
"fmt"
"github.com/ghodss/yaml"
"github.com/plunder-app/kube-vip/pkg/kubevip"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
appv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// [sample configuration] - flags
var cliConfig kubevip.Config
var cliConfigLB kubevip.LoadBalancer
var cliLocalPeer string
var cliRemotePeers, cliBackends []string
func init() {
kubeVipSampleConfig.Flags().StringVar(&cliConfig.Interface, "interface", "eth0", "Name of the interface to bind to")
kubeVipSampleConfig.Flags().StringVar(&cliConfig.VIP, "vip", "192.168.0.1", "The Virtual IP address")
kubeVipSampleConfig.Flags().BoolVar(&cliConfig.SingleNode, "singleNode", false, "Start this instance as a single node")
kubeVipSampleConfig.Flags().BoolVar(&cliConfig.StartAsLeader, "startAsLeader", false, "Start this instance as the cluster leader")
kubeVipSampleConfig.Flags().BoolVar(&cliConfig.EnableARP, "arp", true, "Use ARP broadcasts to improve VIP re-allocations")
kubeVipSampleConfig.Flags().StringVar(&cliLocalPeer, "localPeer", "server1:192.168.0.1:10000", "Settings for this peer, format: id:address:port")
kubeVipSampleConfig.Flags().StringSliceVar(&cliRemotePeers, "remotePeers", []string{"server2:192.168.0.2:10000", "server3:192.168.0.3:10000"}, "Comma seperated remotePeers, format: id:address:port")
// Load Balancer flags
kubeVipSampleConfig.Flags().BoolVar(&cliConfigLB.BindToVip, "lbBindToVip", false, "Bind example load balancer to VIP")
kubeVipSampleConfig.Flags().StringVar(&cliConfigLB.Type, "lbType", "tcp", "Type of load balancer instance (TCP/HTTP)")
kubeVipSampleConfig.Flags().StringVar(&cliConfigLB.Name, "lbName", "Example Load Balancer", "The name of a load balancer instance")
kubeVipSampleConfig.Flags().IntVar(&cliConfigLB.Port, "lbPort", 8080, "Port that load balancer will expose on")
kubeVipSampleConfig.Flags().StringSliceVar(&cliBackends, "lbBackends", []string{"192.168.0.1:8080", "192.168.0.2:8080"}, "Comma seperated backends, format: address:port")
}
var kubeVipSampleConfig = &cobra.Command{
Use: "config",
Short: "Generate a Sample configuration",
Run: func(cmd *cobra.Command, args []string) {
// // Parse localPeer
// p, err := kubevip.ParsePeerConfig(cliLocalPeer)
// if err != nil {
// cmd.Help()
// log.Fatalln(err)
// }
// cliConfig.LocalPeer = *p
// // Parse remotePeers
// //Iterate backends
// for i := range cliRemotePeers {
// p, err := kubevip.ParsePeerConfig(cliRemotePeers[i])
// if err != nil {
// cmd.Help()
// log.Fatalln(err)
// }
// cliConfig.RemotePeers = append(cliConfig.RemotePeers, *p)
// }
// //Iterate backends
// for i := range cliBackends {
// b, err := kubevip.ParseBackendConfig(cliBackends[i])
// if err != nil {
// cmd.Help()
// log.Fatalln(err)
// }
// cliConfigLB.Backends = append(cliConfigLB.Backends, *b)
// }
// Add the basic Load-Balancer to the configuration
cliConfig.LoadBalancers = append(cliConfig.LoadBalancers, cliConfigLB)
err := cliConfig.ParseFlags(cliLocalPeer, cliRemotePeers, cliBackends)
if err != nil {
cmd.Help()
log.Fatalln(err)
}
err = kubevip.ParseEnvironment(&cliConfig)
if err != nil {
cmd.Help()
log.Fatalln(err)
}
cliConfig.PrintConfig()
},
}
var kubeVipSampleManifest = &cobra.Command{
Use: "manifest",
Short: "Generate a Sample kubernetes manifest",
Run: func(cmd *cobra.Command, args []string) {
// Generate the sample manifest specification
p := &appv1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kube-vip",
Namespace: "kube-system",
},
Spec: appv1.PodSpec{
Containers: []appv1.Container{
{
Name: "kube-vip",
Image: fmt.Sprintf("docker.io/plndr/kube-vip:%s", Release.Version),
SecurityContext: &appv1.SecurityContext{
Capabilities: &appv1.Capabilities{
Add: []appv1.Capability{
"NET_ADMIN",
"SYS_TIME",
},
},
},
Args: []string{
"start",
"-c",
"/etc/kube-vip/config.yaml",
},
VolumeMounts: []appv1.VolumeMount{
{
Name: "config",
MountPath: "/etc/kube-vip/",
},
},
},
},
Volumes: []appv1.Volume{
{
Name: "config",
VolumeSource: appv1.VolumeSource{
HostPath: &appv1.HostPathVolumeSource{
Path: "/etc/kube-vip/",
},
},
},
},
HostNetwork: true,
},
}
b, _ := yaml.Marshal(p)
fmt.Printf(string(b))
},
}

View File

@@ -1,18 +1,13 @@
package cmd
import (
"context"
"fmt"
"net"
"os"
"github.com/plunder-app/kube-vip/pkg/kubevip"
log "github.com/sirupsen/logrus"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
// kubeadm adds two subcommands for managing a vip during a kubeadm init/join
@@ -28,8 +23,8 @@ func init() {
var kubeKubeadm = &cobra.Command{
Use: "kubeadm",
Short: "Kubeadm functions",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
_ = cmd.Help()
// TODO - A load of text detailing what's actually happening
},
}
@@ -38,124 +33,84 @@ var kubeKubeadmInit = &cobra.Command{
Use: "init",
Short: "kube-vip init",
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) {
// Set the logging level for all subsequent functions
log.SetLevel(log.Level(logLevel))
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
// TODO - A load of text detailing what's actually happening
kubevip.ParseEnvironment(&initConfig)
err := kubevip.ParseEnvironment(&initConfig)
if err != nil {
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")
_ = cmd.Help()
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")
_ = cmd.Help()
log.Error("No address is specified for kube-vip to expose services on")
return
}
cfg := kubevip.GeneratePodManifestFromConfig(&initConfig, Release.Version, inCluster)
fmt.Println(cfg)
// Ensure there is an address to generate the CIDR from
if initConfig.VIPSubnet == "" && initConfig.Address != "" {
initConfig.VIPSubnet, err = GenerateCidrRange(initConfig.Address, initConfig.DNSMode)
if err != nil {
log.Error("generating VIPSubnet", "err", err)
return
}
}
cfg := kubevip.GeneratePodManifestFromConfig(&initConfig, image, Release.Version, inCluster)
fmt.Println(cfg) // output manifest to stdout
},
}
var kubeKubeadmJoin = &cobra.Command{
Use: "join",
Short: "kube-vip join",
Run: func(cmd *cobra.Command, args []string) {
// Set the logging level for all subsequent functions
log.SetLevel(log.Level(logLevel))
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
// TODO - A load of text detailing what's actually happening
kubevip.ParseEnvironment(&initConfig)
err := kubevip.ParseEnvironment(&initConfig)
if err != nil {
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")
_ = cmd.Help()
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")
_ = cmd.Help()
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
}
// We will use kubeconfig in order to find all the master nodes
// use the current context in kubeconfig
config, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath)
if err != nil {
log.Fatal(err.Error())
}
// create the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
log.Fatal(err.Error())
}
opts := metav1.ListOptions{}
opts.LabelSelector = "node-role.kubernetes.io/master"
nodes, err := clientset.CoreV1().Nodes().List(context.TODO(), opts)
// Iterate over all nodes that are masters and find the details to build a peer list
for x := range nodes.Items {
// Get hostname and address
var nodeAddress, nodeHostname string
for y := range nodes.Items[x].Status.Addresses {
switch nodes.Items[x].Status.Addresses[y].Type {
case corev1.NodeHostName:
nodeHostname = nodes.Items[x].Status.Addresses[y].Address
case corev1.NodeInternalIP:
nodeAddress = nodes.Items[x].Status.Addresses[y].Address
}
}
newPeer, err := kubevip.ParsePeerConfig(fmt.Sprintf("%s:%s:%d", nodeHostname, nodeAddress, 10000))
// Ensure there is an address to generate the CIDR from
if initConfig.VIPSubnet == "" && initConfig.Address != "" {
initConfig.VIPSubnet, err = GenerateCidrRange(initConfig.Address, initConfig.DNSMode)
if err != nil {
panic(err.Error())
log.Error("generating VIPSubnet", "err", err)
return
}
initConfig.RemotePeers = append(initConfig.RemotePeers, *newPeer)
}
// Generate manifest and print
cfg := kubevip.GeneratePodManifestFromConfig(&initConfig, Release.Version, inCluster)
fmt.Println(cfg)
cfg := kubevip.GeneratePodManifestFromConfig(&initConfig, image, Release.Version, inCluster)
fmt.Println(cfg) // output manifest to stdout
},
}
func autoGenLocalPeer() (*kubevip.RaftPeer, error) {
// hostname // address // defaultport
h, err := os.Hostname()
if err != nil {
return nil, err
}
var a string
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
for _, address := range addrs {
// check the address type and if it is not a loopback the display it
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To16() != nil {
a = ipnet.IP.String()
break
}
}
}
if a == "" {
return nil, fmt.Errorf("Unable to find local address")
}
return &kubevip.RaftPeer{
ID: h,
Address: a,
Port: 10000,
}, nil
}

View File

@@ -3,8 +3,9 @@ package cmd
import (
"fmt"
"github.com/plunder-app/kube-vip/pkg/kubevip"
log "github.com/sirupsen/logrus"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/spf13/cobra"
)
@@ -12,23 +13,27 @@ import (
// manifests will be used to generate:
// - Pod spec manifest, mainly used for a static pod (kubeadm)
// - Daemonset manifest, mainly used to run kube-vip as a deamonset within Kubernetes (k3s/rke)
// - RBAC manifest, used to generate the RBAC permissions for kube-vip
//var inCluster bool
var taint bool
var taint, role, rolebinding bool
func init() {
kubeManifest.PersistentFlags().BoolVar(&inCluster, "inCluster", false, "Use the incluster token to authenticate to Kubernetes")
kubeManifest.PersistentFlags().StringVar(&image, "image", "ghcr.io/kube-vip/kube-vip", "Define a hardcoded image with or without tag for the manifest")
kubeManifestDaemon.PersistentFlags().BoolVar(&taint, "taint", false, "Taint the manifest for only running on control planes")
kubeManifestRbac.PersistentFlags().BoolVar(&role, "role", false, "Generate only a Role inside the serviceNamespace access")
kubeManifestRbac.PersistentFlags().BoolVar(&rolebinding, "rolebinding", false, "Generate only a RoleBinding for namespaced access")
kubeManifest.AddCommand(kubeManifestPod)
kubeManifest.AddCommand(kubeManifestDaemon)
kubeManifest.AddCommand(kubeManifestRbac)
}
var kubeManifest = &cobra.Command{
Use: "manifest",
Short: "Manifest functions",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
_ = cmd.Help()
// TODO - A load of text detailing what's actually happening
},
}
@@ -36,51 +41,111 @@ var kubeManifest = &cobra.Command{
var kubeManifestPod = &cobra.Command{
Use: "pod",
Short: "Generate a Pod Manifest",
Run: func(cmd *cobra.Command, args []string) {
// Set the logging level for all subsequent functions
log.SetLevel(log.Level(logLevel))
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
var err error
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
// TODO - A load of text detailing what's actually happening
kubevip.ParseEnvironment(&initConfig)
// TODO - check for certain things VIP/interfaces
if initConfig.Interface == "" {
cmd.Help()
log.Fatalln("No interface is specified for kube-vip to bind to")
if err := kubevip.ParseEnvironment(&initConfig); err != nil {
log.Error("parsing environment", "err", err)
return
}
// The control plane has a requirement for a VIP being specified
if initConfig.EnableControlPane && (initConfig.VIP == "" && initConfig.Address == "") {
cmd.Help()
log.Fatalln("No address is specified for kube-vip to expose services on")
if initConfig.EnableControlPlane && (initConfig.VIP == "" && initConfig.Address == "" && !initConfig.DDNS) {
_ = cmd.Help()
log.Error("No address is specified for kube-vip to expose services on")
return
}
cfg := kubevip.GeneratePodManifestFromConfig(&initConfig, Release.Version, inCluster)
fmt.Println(cfg)
// Ensure there is an address to generate the CIDR from
if initConfig.VIPSubnet == "" && initConfig.Address != "" {
initConfig.VIPSubnet, err = GenerateCidrRange(initConfig.Address, initConfig.DNSMode)
if err != nil {
log.Error("config parse", "err", err)
return
}
}
cfg := kubevip.GeneratePodManifestFromConfig(&initConfig, image, Release.Version, inCluster)
fmt.Println(cfg) // output manifest to stdout
},
}
var kubeManifestDaemon = &cobra.Command{
Use: "daemonset",
Short: "Generate a Daemonset Manifest",
Run: func(cmd *cobra.Command, args []string) {
// Set the logging level for all subsequent functions
log.SetLevel(log.Level(logLevel))
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
var err error
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
// TODO - A load of text detailing what's actually happening
kubevip.ParseEnvironment(&initConfig)
// TODO - check for certain things VIP/interfaces
if initConfig.Interface == "" {
cmd.Help()
log.Fatalln("No interface is specified for kube-vip to bind to")
if err := kubevip.ParseEnvironment(&initConfig); err != nil {
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.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.VIPSubnet == "" && initConfig.Address != "" {
initConfig.VIPSubnet, err = GenerateCidrRange(initConfig.Address, initConfig.DNSMode)
if err != nil {
log.Error("config parse", "err", err)
return
}
}
cfg := kubevip.GenerateDaemonsetManifestFromConfig(&initConfig, image, Release.Version, inCluster, taint)
fmt.Println(cfg) // output manifest to stdout
},
}
var kubeManifestRbac = &cobra.Command{
Use: "rbac",
Short: "Generate an RBAC Manifest",
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
var err error
initConfig.LoadBalancers = append(initConfig.LoadBalancers, initLoadBalancer)
// TODO - A load of text detailing what's actually happening
if err := kubevip.ParseEnvironment(&initConfig); err != nil {
log.Error("parsing environment", "err", err)
return
}
// The control plane has a requirement for a VIP being specified
if initConfig.EnableControlPane && (initConfig.VIP == "" && initConfig.Address == "") {
cmd.Help()
log.Fatalln("No address is specified for kube-vip to expose services on")
if initConfig.EnableControlPlane && (initConfig.VIP == "" && initConfig.Address == "" && !initConfig.DDNS) {
_ = cmd.Help()
log.Error("No address is specified for kube-vip to expose services on")
return
}
cfg := kubevip.GenerateDeamonsetManifestFromConfig(&initConfig, Release.Version, inCluster, taint)
fmt.Println(cfg)
// Ensure there is an address to generate the CIDR from
if initConfig.VIPSubnet == "" && initConfig.Address != "" {
initConfig.VIPSubnet, err = GenerateCidrRange(initConfig.Address, initConfig.DNSMode)
if err != nil {
log.Error("generating VIPSubnet", "err", err)
return
}
}
saCfg := kubevip.GenerateSA(&initConfig)
roleCfg := kubevip.GenerateRole(&initConfig, role)
if role {
rolebinding = true
}
roleBindingCfg := kubevip.GenerateRoleBinding(rolebinding, saCfg, roleCfg)
// Output the YAML manifests to stdout
fmt.Println("---") // Separator for YAML documents
fmt.Println(kubevip.TransformApplyObjectToManifest(saCfg))
fmt.Println("---") // Separator for YAML documents
fmt.Println(kubevip.TransformApplyObjectToManifest(roleCfg))
fmt.Println("---") // Separator for YAML documents
fmt.Println(kubevip.TransformApplyObjectToManifest(roleBindingCfg))
},
}

View File

@@ -1,136 +0,0 @@
package cmd
import (
"os"
"os/signal"
"github.com/plunder-app/kube-vip/pkg/bgp"
"github.com/plunder-app/kube-vip/pkg/cluster"
"github.com/plunder-app/kube-vip/pkg/kubevip"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
// Start as a single node (no cluster), start as a leader in the cluster
var startConfig kubevip.Config
var startConfigLB kubevip.LoadBalancer
var startLocalPeer, startKubeConfigPath string
var startRemotePeers, startBackends []string
var inCluster bool
func init() {
// Get the configuration file
kubeVipStart.Flags().StringVarP(&configPath, "config", "c", "", "Path to a kube-vip configuration")
kubeVipStart.Flags().BoolVarP(&disableVIP, "disableVIP", "d", false, "Disable the VIP functionality")
// Pointers so we can see if they're nil (and not called)
kubeVipStart.Flags().StringVar(&startConfig.Interface, "interface", "eth0", "Name of the interface to bind to")
kubeVipStart.Flags().StringVar(&startConfig.VIP, "vip", "192.168.0.1", "The Virtual IP address")
kubeVipStart.Flags().StringVar(&startConfig.Address, "address", "", "an address (IP or DNS name) to use as a VIP")
kubeVipStart.Flags().IntVar(&startConfig.Port, "port", 6443, "listen port for the VIP")
kubeVipStart.Flags().BoolVar(&startConfig.DDNS, "ddns", false, "use Dynamic DNS + DHCP to allocate VIP for address")
kubeVipStart.Flags().BoolVar(&startConfig.SingleNode, "singleNode", false, "Start this instance as a single node")
kubeVipStart.Flags().BoolVar(&startConfig.StartAsLeader, "startAsLeader", false, "Start this instance as the cluster leader")
kubeVipStart.Flags().BoolVar(&startConfig.EnableARP, "arp", false, "Use ARP broadcasts to improve VIP re-allocations")
kubeVipStart.Flags().StringVar(&startLocalPeer, "localPeer", "server1:192.168.0.1:10000", "Settings for this peer, format: id:address:port")
kubeVipStart.Flags().StringSliceVar(&startRemotePeers, "remotePeers", []string{"server2:192.168.0.2:10000", "server3:192.168.0.3:10000"}, "Comma seperated remotePeers, format: id:address:port")
// Load Balancer flags
kubeVipStart.Flags().BoolVar(&startConfigLB.BindToVip, "lbBindToVip", false, "Bind example load balancer to VIP")
kubeVipStart.Flags().StringVar(&startConfigLB.Type, "lbType", "tcp", "Type of load balancer instance (TCP/HTTP)")
kubeVipStart.Flags().StringVar(&startConfigLB.Name, "lbName", "Example Load Balancer", "The name of a load balancer instance")
kubeVipStart.Flags().IntVar(&startConfigLB.Port, "lbPort", 8080, "Port that load balancer will expose on")
kubeVipStart.Flags().IntVar(&startConfigLB.BackendPort, "lbBackEndPort", 6443, "A port that all backends may be using (optional)")
kubeVipStart.Flags().StringSliceVar(&startBackends, "lbBackends", []string{"192.168.0.1:8080", "192.168.0.2:8080"}, "Comma seperated backends, format: address:port")
// Cluster configuration
kubeVipStart.Flags().StringVar(&startKubeConfigPath, "kubeConfig", "/etc/kubernetes/admin.conf", "The path of a kubernetes configuration file")
kubeVipStart.Flags().BoolVar(&inCluster, "inCluster", false, "Use the incluster token to authenticate to Kubernetes")
kubeVipStart.Flags().BoolVar(&startConfig.EnableLeaderElection, "leaderElection", false, "Use the Kubernetes leader election mechanism for clustering")
// This sets the namespace that the lock should exist in
kubeVipStart.Flags().StringVarP(&startConfig.Namespace, "namespace", "n", "kube-system", "The configuration map defined within the cluster")
}
var kubeVipStart = &cobra.Command{
Use: "start",
Short: "Start the Virtual IP / Load balancer",
Run: func(cmd *cobra.Command, args []string) {
// Set the logging level for all subsequent functions
log.SetLevel(log.Level(logLevel))
var err error
// If a configuration file is loaded, then it will overwrite flags
if configPath != "" {
c, err := kubevip.OpenConfig(configPath)
if err != nil {
log.Fatalf("%v", err)
}
startConfig = *c
}
// parse environment variables, these will overwrite anything loaded or flags
err = kubevip.ParseEnvironment(&startConfig)
if err != nil {
log.Fatalln(err)
}
newCluster, err := cluster.InitCluster(&startConfig, disableVIP)
if err != nil {
log.Fatalf("%v", err)
}
var bgpServer *bgp.Server
if startConfig.SingleNode {
// If the Virtual IP isn't disabled then create the netlink configuration
// Start a single node cluster
newCluster.StartSingleNode(&startConfig, disableVIP)
} else {
if disableVIP {
log.Fatalln("Cluster mode requires the Virtual IP to be enabled, use single node with no VIP")
}
if startConfig.EnableLeaderElection {
cm, err := cluster.NewManager(startKubeConfigPath, inCluster, startConfig.Port)
if err != nil {
log.Fatalf("%v", err)
}
if startConfig.EnableBGP {
log.Info("Starting the BGP server to adverise VIP routes to VGP peers")
bgpServer, err = bgp.NewBGPServer(&startConfig.BGPConfig)
if err != nil {
log.Fatalf("%v", err)
}
// Defer a function to check if the bgpServer has been created and if so attempt to close it
defer func() {
if bgpServer != nil {
bgpServer.Close()
}
}()
}
// Leader Cluster will block
err = newCluster.StartLeaderCluster(&startConfig, cm, bgpServer)
if err != nil {
log.Fatalf("%v", err)
}
} else {
// // Start a multi-node (raft) cluster, this doesn't block so will wait on signal
err = newCluster.StartRaftCluster(&startConfig)
if err != nil {
log.Fatalf("%v", err)
}
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt)
<-signalChan
newCluster.Stop()
}
}
},
}

View File

@@ -3,42 +3,38 @@ package cmd
import (
"context"
"fmt"
"net"
"net/http"
"os"
"slices"
"strings"
"time"
"github.com/plunder-app/kube-vip/pkg/kubevip"
"github.com/plunder-app/kube-vip/pkg/manager"
"github.com/plunder-app/kube-vip/pkg/packet"
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"
"golang.org/x/sys/unix"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/manager"
"github.com/kube-vip/kube-vip/pkg/utils"
"github.com/kube-vip/kube-vip/pkg/vip"
)
// Path to the configuration file
var configPath string
// Is an option to set the image
var image string
// Path to the configuration file
var namespace string
// Disable the Virtual IP (bind to the existing network stack)
var disableVIP bool
// Disable the Virtual IP (bind to the existing network stack)
var controlPlane bool
// Run as a load balancer service (within a pod / kubernetes)
var serviceArp bool
// Is kube-vip running within cluster
var inCluster bool
// ConfigMap name within a Kubernetes cluster
var configMap string
// Configure the level of loggin
var logLevel uint32
// Provider Config
var providerConfig string
// Points to a kubernetes configuration file
var kubeConfigPath string
// Release - this struct contains the release information populated when building kube-vip
var Release struct {
@@ -47,11 +43,10 @@ var Release struct {
}
// Structs used via the various subcommands
var initConfig kubevip.Config
var initLoadBalancer kubevip.LoadBalancer
// Points to a kubernetes configuration file
var kubeConfigPath string
var (
initConfig kubevip.Config
initLoadBalancer kubevip.LoadBalancer
)
var kubeVipCmd = &cobra.Command{
Use: "kube-vip",
@@ -59,83 +54,114 @@ var kubeVipCmd = &cobra.Command{
}
func init() {
localpeer, err := autoGenLocalPeer()
if err != nil {
log.Fatalln(err)
}
initConfig.LocalPeer = *localpeer
//initConfig.Peers = append(initConfig.Peers, *localpeer)
// Basic flags
kubeVipCmd.PersistentFlags().StringVar(&initConfig.Interface, "interface", "", "Name of the interface to bind to")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.ServicesInterface, "serviceInterface", "", "Name of the interface to bind to (for services)")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.VIP, "vip", "", "The Virtual IP address")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.VIPSubnet, "vipSubnet", "", "The Virtual IP address subnet e.g. /32 /24 /8 etc.. (Default to 32 for IPv4 and 128 for IPv6)")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.NodeName, "nodeName", "", "Name to be used for lease holder. Must be unique for each node/instance")
// VIP flags
kubeVipCmd.PersistentFlags().StringVar(&initConfig.Address, "address", "", "an address (IP or DNS name) to use as a VIP")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.Port, "port", 6443, "listen port for the VIP")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.VIPCIDR, "cidr", "32", "The CIDR range for the virtual IP address")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableARP, "arp", false, "Enable Arp for Vip changes")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.Annotations, "annotations", "", "Set Node annotations prefix for parsing")
kubeVipCmd.PersistentFlags().Uint16Var(&initConfig.Port, "port", 6443, "Port for the VIP")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableARP, "arp", false, "Enable Arp for VIP changes")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableWireguard, "wireguard", false, "Enable Wireguard for services VIPs")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableRoutingTable, "table", false, "Enable Routing Table for services VIPs")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.PreserveVIPOnLeadershipLoss, "preserveVipOnLeadershipLoss", false, "Preserve ARP VIP addresses on interface when leadership is lost (default: false for backward compatibility)")
// LoadBalancer flags
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableLoadBalancer, "enableLoadBalancer", false, "enable loadbalancing on the VIP with IPVS")
kubeVipCmd.PersistentFlags().Uint16Var(&initConfig.LoadBalancerPort, "lbPort", 6443, "loadbalancer port for the VIP")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.LoadBalancerForwardingMethod, "lbForwardingMethod", "local", "loadbalancer forwarding method")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.DDNS, "ddns", false, "use Dynamic DNS + DHCP to allocate VIP for address")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.MirrorDestInterface, "mirrorDestInterface", "", "network interface where all traffic that traverses the service interface will be mirrored to. Source interface will use default interface is servicesInterface is not set.")
// Clustering type (leaderElection)
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableLeaderElection, "leaderElection", false, "Use the Kubernetes leader election mechanism for clustering")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.LeaseDuration, "leaseDuration", 5, "Length of time a Kubernetes leader lease can be held for")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.RenewDeadline, "leaseRenewDuration", 3, "Length of time a Kubernetes leader can attempt to renew its lease")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.RetryPeriod, "leaseRetry", 1, "Number of times the host will retry to hold a lease")
// Clustering type (raft)
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.StartAsLeader, "startAsLeader", false, "Start this instance as the cluster leader")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.AddPeersAsBackends, "addPeersToLB", true, "Add raft peers to the load-balancer")
// Packet flags
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableMetal, "metal", false, "This will use the Equinix Metal API (requires the token ENV) to update the EIP <-> VIP")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.MetalAPIKey, "metalKey", "", "The API token for authenticating with the Equinix Metal API")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.MetalProject, "metalProject", "", "The name of project already created within Equinix Metal")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.MetalProjectID, "metalrojectID", "", "The ID of project already created within Equinix Metal")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.ProviderConfig, "provider-config", "", "The path to a provider configuration")
// Load Balancer flags
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableLoadBalancer, "lbEnable", false, "Enable a load-balancer on the VIP")
kubeVipCmd.PersistentFlags().BoolVar(&initLoadBalancer.BindToVip, "lbBindToVip", true, "Bind example load balancer to VIP")
kubeVipCmd.PersistentFlags().StringVar(&initLoadBalancer.Type, "lbType", "tcp", "Type of load balancer instance (TCP/HTTP)")
kubeVipCmd.PersistentFlags().StringVar(&initLoadBalancer.Name, "lbName", "Kubeadm Load Balancer", "The name of a load balancer instance")
kubeVipCmd.PersistentFlags().IntVar(&initLoadBalancer.Port, "lbPort", 6443, "Port that load balancer will expose on")
kubeVipCmd.PersistentFlags().IntVar(&initLoadBalancer.BackendPort, "lbBackEndPort", 6444, "A port that all backends may be using (optional)")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.LeaderElectionType, "leaderElectionType", "kubernetes", "Defines the backend to run the leader election: kubernetes or etcd. Defaults to kubernetes.")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.LeaseName, "leaseName", "plndr-cp-lock", "Name of the lease that is used for leader election")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.LeaseDuration, "leaseDuration", 5, "Length of time (in seconds) a Kubernetes leader lease can be held for")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.RenewDeadline, "leaseRenewDuration", 3, "Length of time (in seconds) a Kubernetes leader can attempt to renew its lease")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.RetryPeriod, "leaseRetry", 1, "Length of time (in seconds) the LeaderElector clients should wait between tries of actions")
// BGP flags
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableBGP, "bgp", false, "This will enable BGP support within kube-vip")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.BGPConfig.RouterID, "bgpRouterID", "", "The routerID for the bgp server")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.BGPConfig.SourceIF, "sourceIF", "", "The source interface for bgp peering (not to be used with sourceIP)")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.BGPConfig.SourceIP, "sourceIP", "", "The source address for bgp peering (not to be used with sourceIF)")
kubeVipCmd.PersistentFlags().Uint32Var(&initConfig.BGPConfig.AS, "localAS", 65000, "The local AS number for the bgp server")
kubeVipCmd.PersistentFlags().Uint64Var(&initConfig.BGPConfig.HoldTime, "bgpHoldTimer", 30, "The hold timer for all bgp peers (it defines the time a session is held)")
kubeVipCmd.PersistentFlags().Uint64Var(&initConfig.BGPConfig.KeepaliveInterval, "bgpKeepAliveInterval", 10, "The keepalive interval for all bgp peers (it defines the heartbeat of keepalive messages)")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.BGPPeerConfig.Address, "peerAddress", "", "The address of a BGP peer")
kubeVipCmd.PersistentFlags().Uint32Var(&initConfig.BGPPeerConfig.AS, "peerAS", 65000, "The AS number for a BGP peer")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.BGPPeerConfig.Password, "peerPass", "", "The md5 password for a BGP peer")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.BGPPeerConfig.MultiHop, "multihop", false, "This will enable BGP multihop support")
kubeVipCmd.PersistentFlags().StringSliceVar(&initConfig.BGPPeers, "bgppeers", []string{}, "Comma seperated BGP Peer, format: address:as:password:multihop")
kubeVipCmd.PersistentFlags().StringSliceVar(&initConfig.BGPPeers, "bgppeers", []string{}, "Comma separated BGP Peer, format: address:as:password:multihop")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.Annotations, "annotations", "", "Set Node annotations prefix for parsing")
// Control plane specific flags
kubeVipCmd.PersistentFlags().StringVarP(&initConfig.Namespace, "namespace", "n", "kube-system", "The configuration map defined within the cluster")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.BGPConfig.Zebra.Enabled, "zebra", false, "This will enable Zebra support within kube-vip")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.BGPConfig.Zebra.URL, "zebraUrl", "unix:/var/run/frr/zserv.api", "Path to the unix domain socket for connecting to Zebra daemon")
kubeVipCmd.PersistentFlags().Uint32Var(&initConfig.BGPConfig.Zebra.Version, "zebraVersion", 6, "Zebra API Version")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.BGPConfig.Zebra.SoftwareName, "zebraSoftwareName", "frr8.3", "Software Name for Zebra")
// Namespace for kube-vip
kubeVipCmd.PersistentFlags().StringVarP(&initConfig.Namespace, "namespace", "n", "kube-system", "The namespace for the configmap defined within the cluster")
// Manage logging
kubeVipCmd.PersistentFlags().Uint32Var(&logLevel, "log", 4, "Set the level of logging")
kubeVipCmd.PersistentFlags().Int32Var(&initConfig.Logging, "log", 0, "Set the level of logging")
// Service flags
kubeVipService.Flags().StringVarP(&configMap, "configMap", "c", "plndr", "The configuration map defined within the cluster")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableControlPane, "controlplane", false, "Enable HA for control plane, hybrid mode")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableServices, "services", false, "Enable Kubernetes services, hybrid mode")
// Routing Table flags
kubeVipCmd.PersistentFlags().IntVar(&initConfig.RoutingTableID, "tableID", 198, "The routing table used for all table entries")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.RoutingTableType, "tableType", unix.RTN_UNICAST, "The type of route that will be added to the routing table")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.RoutingProtocol, "routingProtocol", 248, "The routing protocol value used to create routes")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.CleanRoutingTable, "cleanRoutingTable", false, "Clean routing table of redundant routes on start")
// Behaviour flags
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableControlPlane, "controlplane", false, "Enable HA for control plane")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.DetectControlPlane, "autodetectcp", false, "Determine working address for control plane (from loopback)")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableServices, "services", false, "Enable Kubernetes services")
// Extended behaviour flags
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableServicesElection, "servicesElection", false, "Enable leader election per kubernetes service")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.LoadBalancerClassOnly, "lbClassOnly", false, fmt.Sprintf("Enable load balancing only for services with LoadBalancerClass %q", kubevip.LBClassName))
kubeVipCmd.PersistentFlags().StringVar(&initConfig.LoadBalancerClassName, "lbClassName", kubevip.LBClassName, fmt.Sprintf("Name of load balancer class for kube-VIP, defaults to %q", kubevip.LBClassName))
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.LoadBalancerClassLegacyHandling, "lbClassNameLegacyHandling", true, "Use legacy LoadBalancer class name handling (e.g. accepting services both with empty and non-empty class)")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableServiceSecurity, "onlyAllowTrafficServicePorts", false, "Only allow traffic to service ports, others will be dropped, defaults to false")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableNodeLabeling, "enableNodeLabeling", false, fmt.Sprintf("Enable leader node labeling with %q, defaults to false", kubevip.HasIP))
kubeVipCmd.PersistentFlags().StringVar(&initConfig.ServicesLeaseName, "servicesLeaseName", "plndr-svcs-lock", "Name of the lease that is used for leader election for services (in arp mode)")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.DNSMode, "dnsMode", "first", "Name of the mode that DNS lookup will be performed (first, ipv4, ipv6, dual)")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.DisableServiceUpdates, "disableServiceUpdates", false, "If true, kube-vip will process services as usual, but will not update service's Status.LoadBalancer.Ingress slice")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableEndpoints, "enableEndpoints", false, "If enabled, kube-vip will only advertise services, but will use the (deprecated since v1.33) endpoints for IP addresses")
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.LoInterfaceGlobalScope, "loInterfaceGlobalScope", false, "If true, kube-vip will set global scope when using the lo interface, otherwise a host scope will be used by default")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.HealthCheckPort, "healthCheckPort", 0, "If set to non-zero (> 1024), then this is the port that the healthcheck will listen on")
// Prometheus HTTP Server
kubeVipCmd.PersistentFlags().StringVar(&initConfig.PrometheusHTTPServer, "promethuesHTTPServer", ":2112", "Host and port used to expose Promethues metrics via an HTTP server")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.PrometheusHTTPServer, "prometheusHTTPServer", ":2112", "Host and port used to expose Prometheus metrics via an HTTP server")
// Etcd
kubeVipCmd.PersistentFlags().StringVar(&initConfig.Etcd.CAFile, "etcdCACert", "", "Verify certificates of TLS-enabled secure servers using this CA bundle file")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.Etcd.ClientCertFile, "etcdCert", "", "Identify secure client using this TLS certificate file")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.Etcd.ClientKeyFile, "etcdKey", "", "Identify secure client using this TLS key file")
kubeVipCmd.PersistentFlags().StringSliceVar(&initConfig.Etcd.Endpoints, "etcdEndpoints", nil, "Etcd member endpoints")
// Kubernetes client specific flags
kubeVipCmd.PersistentFlags().StringVar(&initConfig.K8sConfigFile, "k8sConfigPath", "/etc/kubernetes/admin.conf", "Path to the configuration file used with the Kubernetes client")
// Configuration file flag
kubeVipCmd.PersistentFlags().StringVar(&initConfig.ConfigFile, "config-file", "", "Path to a JSON/YAML configuration file to load settings from")
kubeVipCmd.AddCommand(kubeKubeadm)
kubeVipCmd.AddCommand(kubeManifest)
kubeVipCmd.AddCommand(kubeVipManager)
kubeVipCmd.AddCommand(kubeVipSample)
kubeVipCmd.AddCommand(kubeVipService)
kubeVipCmd.AddCommand(kubeVipStart)
kubeVipCmd.AddCommand(kubeVipVersion)
// Sample commands
kubeVipSample.AddCommand(kubeVipSampleConfig)
kubeVipSample.AddCommand(kubeVipSampleManifest)
// Set the logging level for all subsequent functions
log.SetLogLoggerLevel(log.Level(initConfig.Logging))
}
// Execute - starts the command parsing process
@@ -149,7 +175,7 @@ func Execute() {
var kubeVipVersion = &cobra.Command{
Use: "version",
Short: "Version and Release information about the Kubernetes Virtual IP Server",
Run: func(cmd *cobra.Command, args []string) {
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
fmt.Printf("Kube-VIP Release Information\n")
fmt.Printf("Version: %s\n", Release.Version)
fmt.Printf("Build: %s\n", Release.Build)
@@ -159,22 +185,43 @@ var kubeVipVersion = &cobra.Command{
var kubeVipSample = &cobra.Command{
Use: "sample",
Short: "Generate a Sample configuration",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
_ = cmd.Help()
},
}
var kubeVipService = &cobra.Command{
Use: "service",
Short: "Start the Virtual IP / Load balancer as a service within a Kubernetes cluster",
Run: func(cmd *cobra.Command, args []string) {
// Set the logging level for all subsequent functions
log.SetLevel(log.Level(logLevel))
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
// parse environment variables, these will overwrite anything loaded or flags
// Load configuration from file if specified (lowest priority)
if initConfig.ConfigFile != "" {
err := kubevip.MergeConfigFromFile(&initConfig, initConfig.ConfigFile)
if err != nil {
log.Error("loading config file", "err", err)
return
}
}
// parse environment variables, these will overwrite anything loaded from config file
err := kubevip.ParseEnvironment(&initConfig)
if err != nil {
log.Fatalln(err)
log.Error("parsing env", "err", err)
return
}
// Change RTN_UNSPEC to default type
if initConfig.RoutingProtocol == unix.RTN_UNSPEC {
initConfig.RoutingProtocol = unix.RTN_UNICAST
}
// Set the logging level for all subsequent functions
log.SetLogLoggerLevel(log.Level(initConfig.Logging))
if err := initConfig.CheckInterface(); err != nil {
log.Error("checking interface", "err", err)
return
}
// User Environment variables as an option to make manifest clearer
@@ -183,16 +230,27 @@ var kubeVipService = &cobra.Command{
configMap = envConfigMap
}
// Ensure there is an address to generate the CIDR from
if initConfig.VIPSubnet == "" && initConfig.Address != "" {
initConfig.VIPSubnet, err = GenerateCidrRange(initConfig.Address, initConfig.DNSMode)
if err != nil {
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
}
},
}
@@ -200,18 +258,143 @@ var kubeVipService = &cobra.Command{
var kubeVipManager = &cobra.Command{
Use: "manager",
Short: "Start the kube-vip manager",
Run: func(cmd *cobra.Command, args []string) {
// Set the logging level for all subsequent functions
log.SetLevel(log.Level(logLevel))
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
// Load configuration from file if specified (lowest priority)
if initConfig.ConfigFile != "" {
err := kubevip.MergeConfigFromFile(&initConfig, initConfig.ConfigFile)
if err != nil {
log.Error("loading config file", "err", err)
return
}
}
go servePrometheusHTTPServer(cmd.Context(), PrometheusHTTPServerConfig{
Addr: initConfig.PrometheusHTTPServer,
})
// parse environment variables, these will overwrite anything loaded or flags
// parse environment variables, these will overwrite anything loaded from config file
err := kubevip.ParseEnvironment(&initConfig)
if err != nil {
log.Fatalln(err)
log.Error("parsing environment", "err", err)
return
}
// Change RTN_UNSPEC to default type
if initConfig.RoutingProtocol == unix.RTN_UNSPEC {
initConfig.RoutingProtocol = unix.RTN_UNICAST
}
// Set the logging level for all subsequent functions
log.SetLogLoggerLevel(log.Level(initConfig.Logging))
// Ensure there is an address to generate the CIDR from
if initConfig.VIPSubnet == "" && initConfig.Address != "" {
initConfig.VIPSubnet, err = GenerateCidrRange(initConfig.Address, initConfig.DNSMode)
if err != nil {
log.Error("No interface is specified for kube-vip to bind to")
return
}
}
// Welome messages
log.Info("kube-vip.io", "version", Release.Version, "build", Release.Build)
// start prometheus server
if initConfig.PrometheusHTTPServer != "" {
go servePrometheusHTTPServer(cmd.Context(), PrometheusHTTPServerConfig{
Addr: initConfig.PrometheusHTTPServer,
})
}
// Determine the kube-vip mode
var mode string
if initConfig.EnableARP {
mode = "ARP"
}
if initConfig.EnableBGP {
mode = "BGP"
}
if initConfig.EnableWireguard {
mode = "Wireguard"
}
if initConfig.EnableRoutingTable {
mode = "Routing Table"
}
// Provide configuration to output/logging
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.Error("no features are enabled")
return
}
if !initConfig.EnableARP && strings.Contains(initConfig.VIPSubnet, kubevip.Auto) {
log.Error("auto subnet discovery cannot be used outside ARP mode")
return
}
if strings.Contains(initConfig.VIPSubnet, kubevip.Auto) && initConfig.Address != "" {
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
if initConfig.EnableWireguard {
if initConfig.Interface == "" {
// Set the vip interface to the wireguard interface
initConfig.Interface = "wg0"
}
log.Info("configuring Wireguard networking")
l, err := netlink.LinkByName(initConfig.Interface)
if err != nil {
if strings.Contains(err.Error(), "Link not found") {
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.Error("adding link", "err", err)
return
}
l, err = netlink.LinkByName(initConfig.Interface)
if err != nil {
log.Error("finding link", "err", err)
return
}
}
}
err = netlink.LinkSetUp(l)
if err != nil {
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.Info("No interface is specified for VIP in config, auto-detecting default Interface")
defaultIF, err := vip.GetDefaultGatewayInterface()
if err != nil {
_ = cmd.Help()
log.Error("detecting interface", "err", err)
return
}
initConfig.Interface = defaultIF.Name
log.Info("kube-vip bind", "interface", initConfig.Interface)
go func() {
if err := vip.MonitorDefaultInterface(context.TODO(), defaultIF); err != nil {
log.Error("interface monitor", "err", err)
return
}
}()
}
}
// Perform a check on the state of the interface
if err := initConfig.CheckInterface(); err != nil {
log.Error("checking interface", "err", err)
return
}
// User Environment variables as an option to make manifest clearer
@@ -220,34 +403,25 @@ var kubeVipManager = &cobra.Command{
configMap = envConfigMap
}
// If Packet is enabled and there is a provider configuration passed
if initConfig.EnableMetal {
if providerConfig != "" {
providerAPI, providerProject, err := packet.GetPacketConfig(providerConfig)
if err != nil {
log.Fatalf("%v", err)
}
initConfig.MetalAPIKey = providerAPI
initConfig.MetalProject = providerProject
}
}
// 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
}
prometheus.MustRegister(mgr.PromethesCollector()...)
prometheus.MustRegister(mgr.PrometheusCollector()...)
// 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("start manager", "err", err)
return
}
},
}
// PrometheusHTTPServerConfig defines the Prometheus server configuration.
type PrometheusHTTPServerConfig struct {
// Addr sets the http server address used to expose the metric endpoint
Addr string
@@ -257,23 +431,34 @@ func servePrometheusHTTPServer(ctx context.Context, config PrometheusHTTPServerC
var err error
mux := http.NewServeMux()
mux.Handle("/metrics", promhttp.Handler())
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { //nolint TODO
_, _ = w.Write([]byte(`<html>
<head><title>kube-vip</title></head>
<body>
<h1>kube-vip Metrics</h1>
<p><a href="` + "/metrics" + `">Metrics</a></p>
</body>
</html>`))
})
srv := &http.Server{
Addr: config.Addr,
Handler: mux,
Addr: config.Addr,
Handler: mux,
ReadHeaderTimeout: 2 * time.Second,
}
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("server started")
log.Info("prometheus HTTP server started")
<-ctx.Done()
log.Printf("server stopped")
log.Info("prometheus HTTP server stopped")
ctxShutDown, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer func() {
@@ -281,11 +466,46 @@ 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 {
err = nil
}
}
func GenerateCidrRange(address string, dnsMode string) (string, error) {
var cidrs []string
addresses := strings.Split(address, ",")
for _, a := range addresses {
ip := net.ParseIP(a)
if ip == nil {
// we probably are a DNS name
ips, err := utils.LookupHost(a, dnsMode)
if len(ips) == 0 || err != nil {
return "", fmt.Errorf("invalid IP address: %s from [%s], %v", a, address, err)
}
for _, addr := range ips {
ip = net.ParseIP(addr)
if ip.To4() != nil {
cidrs = append(cidrs, "32")
} else {
cidrs = append(cidrs, "128")
}
}
} else {
if ip.To4() != nil {
cidrs = append(cidrs, "32")
} else {
cidrs = append(cidrs, "128")
}
}
}
// compact as DNS could have a lot of addresses
slices.Sort(cidrs)
cidrs = slices.Compact(cidrs)
slices.Reverse(cidrs)
return strings.Join(cidrs, ","), nil
}

46
demo/README.md Normal file
View File

@@ -0,0 +1,46 @@
# Demo client-server
This contains some example code to determine how long "failovers" are taking within kube-vip, the server component should live within the cluster and the client should be externally.
## Deploy the server
Simply apply the manifest to a working cluster that has kube-vip deployed:
```
kubectl apply -f ./demo/server/deploy.yaml
```
Retrieve the loadBalancer IP that is fronting the service:
```
kubectl get svc demo-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
demo-service LoadBalancer 10.104.18.147 192.168.0.217 10002:32529/UDP 117m
```
## Connect the client
From elsewhere, clone the kube-vip repository and connect the client to the server endpoint (loadBalancer IP) with the following command:
```
go run ./demo/client/main.go -address=<vip>
```
You will only see output when the client has reconcilled the connection to a pod beneath the service, where it will print the timestamp to reconnection along with the time in milliseconds it took:
```
15:58:35.916952 3008
15:58:45.947506 2005
15:58:57.983151 3007
15:59:08.013450 2005
15:59:20.046491 3008
15:59:30.076341 2507
15:59:42.110747 3008
```
## Kill some pods to test
On a machine or control plane that has `kubectl` and has the credentials to speak to the cluster we will run a command to find the demo pod and kill it every 10 seconds:
`while true ; do kubectl delete pod $(kubectl get pods | grep -v NAME | grep vip| awk '{ print $1 }'); sleep 10; done`

71
demo/client/main.go Normal file
View File

@@ -0,0 +1,71 @@
package main
import (
"bufio"
"flag"
"fmt"
"net"
"time"
)
const udpdata = "a3ViZS12aXAK=kube-vip"
func main() {
address := flag.String("address", "127.0.0.1", "The address of the server")
port := flag.Int("port", 10002, "the port of the server")
interval := flag.Float64("interval", 1000, "Interval in milliseconds")
flag.Parse()
var errorTime time.Time
var errorOccurred bool
for {
p := make([]byte, 2048)
conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", *address, *port))
if err != nil {
if !errorOccurred {
errorTime = time.Now()
errorOccurred = true
}
continue
}
err = conn.SetDeadline(time.Now().Add(time.Duration(*interval) * time.Millisecond))
if err != nil {
//fmt.Printf("Connectivity error [%v]", err)
if !errorOccurred {
errorTime = time.Now()
errorOccurred = true
}
if err = conn.Close(); err != nil {
fmt.Printf("Error closing connection [%v]", err)
}
continue
}
_, err = fmt.Fprint(conn, udpdata)
if err != nil {
fmt.Printf("Error writing data [%v]", err)
}
_, err = bufio.NewReader(conn).Read(p)
if err != nil {
//fmt.Printf("read error %v\n", err)
if !errorOccurred {
errorTime = time.Now()
errorOccurred = true
}
if err = conn.Close(); err != nil {
fmt.Printf("Error closing connection [%v]", err)
}
continue
}
time.Sleep(time.Duration(*interval) * time.Millisecond)
if errorOccurred {
finishTime := time.Since(errorTime)
//fmt.Printf("connectivity reconciled in %dms\n", finishTime.Milliseconds())
//t :=time.Now().Format("15:04:05.000000")
fmt.Printf("%s %d\n", time.Now().Format("15:04:05.000000"), finishTime.Milliseconds())
errorOccurred = false
}
}
}

View File

@@ -1,3 +0,0 @@
module github.com/plunder-app/kube-vip/demo
go 1.13

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:experimental
FROM golang:1.13-alpine as dev
FROM golang:1.19-alpine as dev
RUN apk add --no-cache git ca-certificates
RUN adduser -D appuser
COPY main.go /src/
@@ -13,4 +13,4 @@ RUN --mount=type=cache,sharing=locked,id=gomod,target=/go/pkg/mod/cache \
FROM scratch
COPY --from=dev /src/demo /
CMD ["/demo"]
CMD ["/demo"]

View File

@@ -45,7 +45,7 @@ fmt:
@gofmt -l -w $(SRC)
docker:
@docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 --push -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7,linux/ppc64le,linux/s390x --push -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@echo New Multi Architecture Docker image created
simplify:

View File

@@ -6,7 +6,7 @@ metadata:
app: kube-vip-demo
name: kube-vip-demo
spec:
replicas: 3
replicas: 1
selector:
matchLabels:
app: kube-vip-demo
@@ -30,4 +30,25 @@ spec:
ports:
- containerPort: 10001
- containerPort: 10002
status: {}
status: {}
---
apiVersion: v1
kind: Service
metadata:
name: demo-service
namespace: default
labels:
app: demo-service
annotations:
kube-vip.io/egress: "true"
spec:
type: LoadBalancer
# "Local" preserves the client source IP and avoids a second hop for
# LoadBalancer and NodePort
externalTrafficPolicy: Local
ports:
- name: demo-udp
port: 10002
protocol: UDP
selector:
app: kube-vip-demo

3
demo/server/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module github.com/kube-vip/kube-vip/demo
go 1.13

View File

@@ -32,7 +32,7 @@ func main() {
}
}
if serverType == strings.ToLower("udp") {
if serverType == "udp" {
// Start the UDP echo server
ServerAddr, err := net.ResolveUDPAddr("udp", ":10002")

View File

@@ -1,135 +0,0 @@
# **kube-vip** architecture
This section covers two parts of the architecture:
1. The technical capabilities of `kube-vip`
2. The components to build a load-balancing service within [Kubernetes](https://kubernetes.io)
The `kube-vip` project is designed to provide both a highly available networking endpoint and load-balancing functionality for underlying networking services. The project was originally designed for the purpose of providing a resilient control-plane for Kubernetes, it has since expanded to provide the same functionality for applications within a Kubernetes cluster.
Additionally `kube-vip` is designed to be lightweight and **multi-architecture**, all of the components are built for Linux but are also built for both `x86` and `armv7`,`armhvf`. This means that `kube-vip` will run fine in **bare-metal**, **virtual** and **edge** (raspberry pi or small arm SoC devices).
## Technologies
There are a number of technologies or functional design choices that provide high-availability or networking functions as part of a VIP/Load-balancing solution.
### Cluster
The `kube-vip` service builds a multi-node or multi-pod cluster to provide High-Availability. In ARP mode a leader is elected, this node will inherit the Virtual IP and become the leader of the load-balancing within the cluster, whereas with BGP all nodes will advertise the VIP address.
When using ARP or layer2 it will use [leader election](https://godoc.org/k8s.io/client-go/tools/leaderelection)
It is also possible to use [raft](https://en.wikipedia.org/wiki/Raft_(computer_science) clustering technology, but this approach has largely been superseded by leader election especially when running in cluster.
### Virtual IP
The leader within the cluster will assume the **vip** and will have it bound to the selected interface that is declared within the configuration. When the leader changes it will evacuate the **vip** first or in failure scenarios the **vip** will be directly assumed by the next elected leader.
When the **vip** moves from one host to another any host that has been using the **vip** will retain the previous `vip <-> MAC address` mapping until the ARP (Address resolution protocol) expires the old entry (typically 30 seconds) and retrieves a new `vip <-> MAC` mapping. This can be improved using Gratuitous ARP broadcasts (when enabled), this is detailed below.
### ARP
(Optional) The `kube-vip` can be configured to broadcast a [gratuitous arp](https://wiki.wireshark.org/Gratuitous_ARP) that will typically immediately notify all local hosts that the `vip <-> MAC` has changed.
**Below** we can see that the failover is typically done within a few seconds as the ARP broadcast is recieved.
```
64 bytes from 192.168.0.75: icmp_seq=146 ttl=64 time=0.258 ms
64 bytes from 192.168.0.75: icmp_seq=147 ttl=64 time=0.240 ms
92 bytes from 192.168.0.70: Redirect Host(New addr: 192.168.0.75)
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 0054 bc98 0 0000 3f 01 3d16 192.168.0.95 192.168.0.75
Request timeout for icmp_seq 148
92 bytes from 192.168.0.70: Redirect Host(New addr: 192.168.0.75)
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 0054 75ff 0 0000 3f 01 83af 192.168.0.95 192.168.0.75
Request timeout for icmp_seq 149
92 bytes from 192.168.0.70: Redirect Host(New addr: 192.168.0.75)
Vr HL TOS Len ID Flg off TTL Pro cks Src Dst
4 5 00 0054 2890 0 0000 3f 01 d11e 192.168.0.95 192.168.0.75
Request timeout for icmp_seq 150
64 bytes from 192.168.0.75: icmp_seq=151 ttl=64 time=0.245 ms
```
### Load Balancing
Within a Kubernetes cluster, the load-balancing is managed by the `plndr-cloud-provider` which watches all service that are created, and for those of `type=LoadBalancer` will create the configuration for `kube-vip` to consume.
#### Load Balancing (Inside a cluster)
When using `type=LoadBalancer` within a Kubernetes cluster `kube-vip` will assign the VIP to the leader (when using ARP) or to all running Pods (when using BGP). When traffic is directed to a node with the VIP then the rules configured by `kube-proxy` will redirect the traffic to one of the pods running in the service.
#### Load Balancing (Outside a cluster)
Within the configuration of `kube-vip` multiple load-balancers can be created, below is the example load-balancer for a Kubernetes Control-plane:
```
loadBalancers:
- name: Kubernetes Control Plane
type: tcp
port: 6443
bindToVip: true
backends:
- port: 6444
address: 192.168.0.70
- port: 6444
address: 192.168.0.71
- port: 6444
address: 192.168.0.72
```
The above load balancer will create an instance that listens on port `6443` and will forward traffic to the array of backend addresses. If the load-balancer type is `tcp` then the backends will be IP addresses, however if the backend is set to `http` then the backends should be URLs:
```
type: http
port: 6443
bindToVip: true
backends:
- port: 6444
address: https://192.168.0.70
```
Additionally the load-balancing within `kibe-vip` has two modes of operation:
`bindToVip: false` - will result in every node in the cluster binding all load-balancer port(s) to all interfaces on the host itself
`bindToVip: true` - The load-balancer will only **bind** to the VIP address.
## Components within a Kubernetes Cluster
The `kube-vip` kubernetes load-balancer requires a number of components in order to function:
- The Plunder Cloud Provider -> [https://github.com/plunder-app/plndr-cloud-provider](https://github.com/plunder-app/plndr-cloud-provider)
- The Kube-Vip Deployment -> [https://github.com/plunder-app/kube-vip](https://github.com/plunder-app/kube-vip)
### Architecture overview
![kubernetes-vip-architecture.png](kubernetes-vip-architecture.png)
### Plunder Cloud Provider
The cloud provider works like all Kubernetes cloud providers and is built using the Kubernetes cloud-provider SDK. It's role is to provide the same cloud "like" services one would expect from services such as AWS / Azure / GCP etc.. in that when a user requests functionality then the cloud provider can speak natively to the underlying vendor and provision the required service
e.g. _In AWS when requesting a Kubernetes LoadBalancer, the cloud provider will provision an **ELB**_
The `Plunder cloud Provider` is *currently* only designed to intercept the creation of LoadBalancers and translate that into a `kube-vip` load balancer.
It is configured by a `configMap` within the `kube-system` namespace that contains the ranges of addresses that the other `kube-vip` load-balancers can use, it will also manage the allocation of addresses and then build the configMap configurations in these namespaces for consumption by `kube-vip`. The IP addresses for each namespace should be in the structure `cidr-<namespace>` followed by the cidr range for the address pool.
**Example `ConfigMap`**
```
apiVersion: v1
kind: ConfigMap
metadata:
name: plndr
namespace: kube-system
data:
cidr-default: 192.168.0.200/29
cidr-plunder: 192.168.0.210/29
cidr-testing: 192.168.0.220/29
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

View File

@@ -1,147 +0,0 @@
# Load Balancing a Kubernetes Cluster (Control-Plane) (pre 0.1.5)
This document covers all of the details for using `kube-vip` to build a HA Kubernetes cluster
`tl;dr version`
- Generate/modify first node `kube-vip` config/manifest
- `init` first node
- `join` remaining nodes
- Add remaining config/manifests
## Infrastructure architecture
The infrastructure for our example HA Kubernetes cluster is as follows:
| Node | Address |
|----------------|------------|
| VIP | 10.0.0.75 |
| controlPlane01 | 10.0.0.70 |
| controlPlane02 | 10.0.0.71 |
| controlPlane03 | 10.0.0.72 |
All nodes are running Ubuntu 18.04, Docker CE and will use Kubernetes 1.17.0.
### Generate the `kube-vip` configuration
Make sure that the config directory exists: `sudo mkdir -p /etc/kube-vip/`, this directory can be any directory however the `hostPath` in the manifest will need modifying to point to the correct path.
```
sudo docker run -it --rm plndr/kube-vip:0.1 /kube-vip sample config | sudo tee /etc/kube-vip/config.yaml
```
### Modify the configuration
**Cluster Configuration**
Modify the `remotePeers` to point to the correct addresses of the other two nodes, ensure that their `id` is unique otherwise this will confuse the raft algorithm. The `localPeer` should be the configuration of the current node (`controlPlane01`), which is where this instance of the cluster will run.
As this node will be the first node, it will need to elect itself leader as until this occurs the VIP wont be activated!
`startAsLeader: true`
**VIP Config**
We will need to set our VIP address to `192.168.0.75` and to ensure all hosts are updated when the VIP moves we will enable ARP broadcasts `gratuitousARP: true`
**Load Balancer**
We will configure the load balancer to sit on the standard API-Server port `6443` and we will configure the backends to point to the API-servers that will be configured to run on port `6444`. Also for the Kubernetes Control Plane we will configure the load balancer to be of `type: tcp`.
We can also use `6443` for both the VIP and the API-Servers, in order to do this we need to specify that the api-server is bound to it's local IP. To do this we use the `--apiserver-advertise-address` flag as part of the `init`, this means that we can then bind the same port to the VIP and we wont have a port conflict.
**config.yaml**
`user@controlPlane01:/etc/kube-vip$ cat config.yaml`
...
```
remotePeers:
- id: server2
address: 192.168.0.71
port: 10000
- id: server3
address: 192.168.0.72
port: 10000
localPeer:
id: server1
address: 192.168.0.70
port: 10000
vip: 192.168.0.75
gratuitousARP: true
singleNode: false
startAsLeader: true
interface: ens192
loadBalancers:
- name: Kubernetes Control Plane
type: tcp
port: 6443
bindToVip: true
backends:
- port: 6444
address: 192.168.0.70
- port: 6444
address: 192.168.0.71
- port: 6444
address: 192.168.0.72
```
### First Node
To generate the basic Kubernetes static pod `yaml` configuration:
Make sure that the manifest directory exists: `sudo mkdir -p /etc/kubernetes/manifests/`
```
sudo docker run -it --rm plndr/kube-vip:0.1 /kube-vip sample manifest | sudo tee /etc/kubernetes/manifests/kube-vip.yaml
```
Ensure that `image: plndr/kube-vip:<x>` is modified to point to a specific version (`0.1` at the time of writing), refer to [docker hub](https://hub.docker.com/r/plndr/kube-vip/tags) for details. Also ensure that the `hostPath` points to the correct `kube-vip` configuration, if it isnt the above path.
The **vip** is set to `192.168.0.75` and this first node will elect itself as leader, and as part of the `kubeadm init` it will use the VIP in order to speak back to the initialising api-server.
`sudo kubeadm init --control-plane-endpoint “192.168.0.75:6443” --apiserver-bind-port 6444 --upload-certs --kubernetes-version “v1.17.0”`
Once this node is up and running we will be able to see the control-plane pods, including the `kube-vip` pod:
```
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
<...>
kube-system kube-vip-controlplane01 1/1 Running 0 10m
```
### Remaining Nodes
We first will need to create the `kube-vip` configuration that resides in `/etc/kube-vip/config.yaml` or we can regenerate it from scratch using the above example. Ensure that the configuration is almost identical with the `localPeer` and `remotePeers` sections are updated for each node. Finally, ensure that the remaining nodes will behave as standard cluster nodes by setting `startAsLeader: false`.
At this point **DONT** generate the manifests, this is due to some bizarre `kubeadm/kubelet` behaviour.
```
kubeadm join 192.168.0.75:6443 --token <tkn> \
--discovery-token-ca-cert-hash sha256:<hash> \
--control-plane --certificate-key <key>
```
**After** this node has been added to the cluster, we can add the manifest to also add this node as a `kube-vip` member. (Adding the manifest afterwards doesnt interfere with `kubeadm`).
```
sudo docker run -it --rm plndr/kube-vip:0.1 /kube-vip sample manifest | sudo tee /etc/kubernetes/manifests/kube-vip.yaml
```
Once this node is added we will be able to see that the `kube-vip` pod is up and running as expected:
```
user@controlPlane01:~$ kubectl get pods -A | grep vip
kube-system kube-vip-controlplane01 1/1 Running 1 16m
kube-system kube-vip-controlplane02 1/1 Running 0 18m
kube-system kube-vip-controlplane03 1/1 Running 0 20m
```
If we look at the logs, we can see that the VIP is running on the second node and were waiting for our third node to join the cluster:
```
$ kubectl logs kube-vip-controlplane02 -n kube-system
time=“2020-02-12T15:33:09Z” level=info msg=“The Node [192.168.0.70:10000] is leading”
time=“2020-02-12T15:33:09Z” level=info msg=“The Node [192.168.0.70:10000] is leading”
```

View File

@@ -1,195 +0,0 @@
# Load Balancing a Kubernetes Cluster (Control-Plane)
This document covers the newer (post `0.1.5`) method for using `kube-vip` to provide HA for a Kubernetes Cluster. The documentation for older releases can be found [here](./0.1.4/)
This document covers all of the details for using `kube-vip` to build a HA Kubernetes cluster
`tl;dr version`
- Generate/modify first node `kube-vip` config/manifest
- `init` first node
- `join` remaining nodes
- Add remaining config/manifests
Below are examples of the steps required:
```
# First Node
sudo docker run --network host --rm plndr/kube-vip:0.1.5 kubeadm init --interface ens192 --vip 192.168.0.81 --startAsLeader=true | sudo tee /etc/kubernetes/manifests/vip.yaml
sudo kubeadm init --kubernetes-version 1.17.0 --control-plane-endpoint 192.168.0.81 --upload-certs
# Additional Node(s)
sudo kubeadm join 192.168.0.81:6443 --token w5atsr.blahblahblah --control-plane --certificate-key abc123
sudo docker run -v /etc/kubernetes/admin.conf:/etc/kubernetes/admin.conf --network host --rm plndr/kube-vip:0.1.5 kubeadm join --interface ens192 --vip 192.168.0.81 --startAsLeader=false | sudo tee /etc/kubernetes/manifests/vip.yaml
```
## Infrastructure architecture
The infrastructure for our example HA Kubernetes cluster is as follows:
| Node | Address |
|----------------|------------|
| VIP | 10.0.0.75 |
| controlPlane01 | 10.0.0.70 |
| controlPlane02 | 10.0.0.71 |
| controlPlane03 | 10.0.0.72 |
All nodes are running Ubuntu 18.04, Docker CE and will use Kubernetes 1.17.0.
### Generate the `kube-vip` configuration
Kube-Vip no longer requires storing it's configuration in a seperate directory and will now store its configuration in the actual manifest that defines the static pods.
```
sudo docker run --network host \
--rm plndr/kube-vip:0.1.5 \
kubeadm init \
--interface ens192 \
--vip 192.168.0.75 \
--startAsLeader=true | sudo tee /etc/kubernetes/manifests/vip.yaml
```
The above command will "initialise" the manifest within the `/etc/kubernetes/manifests` directory, that will be started when we actually initialise our Kubernetes cluster with `kubeadm init`
### Modify the configuration
**Cluster Configuration**
As this node will be the first node, it will need to elect itself leader as until this occurs the VIP wont be activated!
`--startAsLeader=true`
**VIP Config**
We will need to set our VIP address to `192.168.0.75` with `--vip 192.168.0.75` and to ensure all hosts are updated when the VIP moves we will enable ARP broadcasts `--arp` (defaults to `true`)
**Load Balancer**
We will configure the load balancer to sit on the standard API-Server port `6443` and we will configure the backends to point to the API-servers that will be configured to run on port `6444`. Also for the Kubernetes Control Plane we will configure the load balancer to be of `type: tcp`.
We can also use `6443` for both the VIP and the API-Servers, in order to do this we need to specify that the api-server is bound to it's local IP. To do this we use the `--apiserver-advertise-address` flag as part of the `init`, this means that we can then bind the same port to the VIP and we wont have a port conflict.
**vip.yaml** Static-pod Manifest
`$ sudo cat /etc/kubernetes/manifests/vip.yaml`
```
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- start
env:
- name: vip_arp
value: "true"
- name: vip_interface
value: ens192
- name: vip_address
value: 192.168.0.81
- name: vip_startleader
value: "true"
- name: vip_addpeerstolb
value: "true"
- name: vip_localpeer
value: controlPlane01:192.168.0.70:10000
- name: lb_backendport
value: "6443"
- name: lb_name
value: Kubeadm Load Balancer
- name: lb_type
value: tcp
- name: lb_bindtovip
value: "true"
image: plndr/kube-vip:0.1.5
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- SYS_TIME
hostNetwork: true
status: {}
```
### First Node
To generate the basic Kubernetes static pod `yaml` configuration:
Make sure that the manifest directory exists: `sudo mkdir -p /etc/kubernetes/manifests/`
```
sudo docker run --network host \
--rm plndr/kube-vip:0.1.5 \
kubeadm init \
--interface ens192 \
--vip 192.168.0.75 \
--startAsLeader=true | sudo tee /etc/kubernetes/manifests/vip.yaml
```
Ensure that `image: plndr/kube-vip:<x>` is modified to point to a specific version (`0.1.5` at the time of writing), refer to [docker hub](https://hub.docker.com/r/plndr/kube-vip/tags) for details.
The **vip** is set to `192.168.0.75` and this first node will elect itself as leader, and as part of the `kubeadm init` it will use the VIP in order to speak back to the initialising api-server.
`sudo kubeadm init --control-plane-endpoint “192.168.0.75:6443” --apiserver-bind-port 6444 --upload-certs --kubernetes-version “v1.17.0”`
Once this node is up and running we will be able to see the control-plane pods, including the `kube-vip` pod:
```
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
<...>
kube-system kube-vip-controlplane01 1/1 Running 0 10m
```
### Remaining Nodes
At this point **DONT** generate the manifests, this is due to some bizarre `kubeadm/kubelet` behaviour.
```
kubeadm join 192.168.0.75:6443 --token <tkn> \
--discovery-token-ca-cert-hash sha256:<hash> \
--control-plane --certificate-key <key>
```
**After** this node has been added to the cluster, we can add the manifest to also add this node as a `kube-vip` member. (Adding the manifest afterwards doesnt interfere with `kubeadm`).
```
sudo docker run \
-v /etc/kubernetes/admin.conf:/etc/kubernetes/admin.conf \
--network host \
--rm plndr/kube-vip:0.1.5 \
kubeadm join \
--interface ens192 \
--vip 192.168.0.81 \
--startAsLeader=false | sudo tee /etc/kubernetes/manifests/vip.yaml
```
Once this node is added we will be able to see that the `kube-vip` pod is up and running as expected:
```
user@controlPlane01:~$ kubectl get pods -A | grep vip
kube-system kube-vip-controlplane01 1/1 Running 1 16m
kube-system kube-vip-controlplane02 1/1 Running 0 18m
kube-system kube-vip-controlplane03 1/1 Running 0 20m
```
If we look at the logs, we can see that the VIP is running on the second node and were waiting for our third node to join the cluster:
```
$ kubectl logs kube-vip-controlplane02 -n kube-system
time=“2020-02-12T15:33:09Z” level=info msg=“The Node [192.168.0.70:10000] is leading”
time=“2020-02-12T15:33:09Z” level=info msg=“The Node [192.168.0.70:10000] is leading”
```

View File

@@ -1,421 +0,0 @@
# Load Balancing a Kubernetes Cluster (Control-Plane)
**Note**: The most common deployment currently for HA Kubernetes clusters w/`kube-vip` involved `kubeadm`, however recently we've worked to bring a method of bringing `kube-vip` to other types of Kubernetes cluster. Typically this deployment method makes use of a daemonset that is usually brought up during the cluster instantiation.. So for those wanting to deploy [k3s](https://k3s.io), we now have installation steps available [here](https://kube-vip.io/control-plane/#k3s),
This document covers the newer (post `0.1.6`) method for using `kube-vip` to provide HA for a Kubernetes Cluster. The documentation for older releases can be found [here](./0.1.5/)
From version `0.1.6` we've moved `kube-vip` from raft to leaderElection within the Kubernetes cluster. After a lot of testing it became clear that the leaderElection gave quicker reconciliation when removing nodes etc.. during upgrades and failures.
For **more** configuration around LeaderElection click [here](https://kube-vip.io/control-plane/#leaderelection-configuration).
This document covers all of the details for using `kube-vip` to build a HA Kubernetes cluster
`tl;dr version`
- Generate/modify first node `kube-vip` config/manifest
- `init` first node
- `join` remaining nodes
- Add remaining config/manifests
Below are examples of the steps required:
```
# First Node
sudo docker run --network host --rm plndr/kube-vip:0.2.1 manifest pod \
--interface ens192 \
--vip 192.168.0.75 \
--arp \
--leaderElection | sudo tee /etc/kubernetes/manifests/vip.yaml
sudo kubeadm init --kubernetes-version 1.17.0 --control-plane-endpoint 192.168.0.75 --upload-certs
# Additional Node(s)
sudo kubeadm join 192.168.0.75:6443 --token w5atsr.blahblahblah --control-plane --certificate-key abc123
sudo docker run --network host --rm plndr/kube-vip:0.2.1 manifest pod \
--interface ens192 \
--vip 192.168.0.75 \
--arp \
--leaderElection | sudo tee /etc/kubernetes/manifests/vip.yaml
```
## Infrastructure architecture
The infrastructure for our example HA Kubernetes cluster is as follows:
| Node | Address |
|----------------|------------|
| VIP | 10.0.0.75 |
| controlPlane01 | 10.0.0.70 |
| controlPlane02 | 10.0.0.71 |
| controlPlane03 | 10.0.0.72 |
All nodes are running Ubuntu 18.04, Docker CE and will use Kubernetes 1.17.0.
### Generate the `kube-vip` configuration
`kube-vip` no longer requires storing its configuration in a separate directory and will now store its configuration in the actual manifest that defines the static pods.
```
sudo docker run --network host \
--rm plndr/kube-vip:0.2.1 \
manifest pod \
--interface ens192 \
--vip 192.168.0.75 \
--arp \
--leaderElection | sudo tee /etc/kubernetes/manifests/vip.yaml
```
The above command will "initialise" the manifest within the `/etc/kubernetes/manifests` directory, that will be started when we actually initialise our Kubernetes cluster with `kubeadm init`
### Modify the configuration
**Cluster Configuration**
To enable Kubernetes leader Election passing the `--leaderElection` flag will enable `kube-vip` to use the Kubernetes leaderElection functionality to work out which member is the leader.
**VIP Config**
We will need to set our VIP address to `192.168.0.75` with `--vip 192.168.0.75` and to ensure all hosts are updated when the VIP moves we will enable ARP broadcasts `--arp` (defaults to `true`)
**vip.yaml** Static-pod Manifest
`$ sudo cat /etc/kubernetes/manifests/vip.yaml`
```
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- start
env:
- name: vip_arp
value: "true"
- name: vip_interface
value: ens160
- name: vip_leaderelection
value: "true"
- name: vip_leaseduration
value: "5"
- name: vip_renewdeadline
value: "3"
- name: vip_retryperiod
value: "1"
- name: vip_address
value: 192.168.0.75
image: plndr/kube-vip:0.2.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- SYS_TIME
hostNetwork: true
status: {}
```
### First Node
To generate the basic Kubernetes static pod `yaml` configuration:
Make sure that the manifest directory exists: `sudo mkdir -p /etc/kubernetes/manifests/`
```
sudo docker run --network host \
--rm plndr/kube-vip:0.2.1 \
manifest pod \
--interface ens192 \
--vip 192.168.0.75 \
--arp \
--leaderElection | sudo tee /etc/kubernetes/manifests/vip.yaml
```
Ensure that `image: plndr/kube-vip:<x>` is modified to point to a specific version (`0.1.8` at the time of writing), refer to [docker hub](https://hub.docker.com/r/plndr/kube-vip/tags) for details.
The **vip** is set to `192.168.0.75` and this first node will elect itself as leader, and as part of the `kubeadm init` it will use the VIP in order to speak back to the initialising api-server.
`sudo kubeadm init --control-plane-endpoint “192.168.0.75:6443” --upload-certs --kubernetes-version “v1.17.0”`
Once this node is up and running we will be able to see the control-plane pods, including the `kube-vip` pod:
```
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
<...>
kube-system kube-vip-controlplane01 1/1 Running 0 10m
```
### Remaining Nodes
At this point **DONT** generate the manifests, this is due to some bizarre `kubeadm/kubelet` behaviour.
```
kubeadm join 192.168.0.75:6443 --token <tkn> \
--discovery-token-ca-cert-hash sha256:<hash> \
--control-plane --certificate-key <key>
```
**After** this node has been added to the cluster, we can add the manifest to also add this node as a `kube-vip` member. (Adding the manifest afterwards doesnt interfere with `kubeadm`).
```
sudo docker run --network host \
--rm plndr/kube-vip:0.2.1 \
manifest pod \
--interface ens192 \
--vip 192.168.0.75 \
--arp \
--leaderElection | sudo tee /etc/kubernetes/manifests/vip.yaml
```
Once this node is added we will be able to see that the `kube-vip` pod is up and running as expected:
```
user@controlPlane01:~$ kubectl get pods -A | grep vip
kube-system kube-vip-controlplane01 1/1 Running 1 16m
kube-system kube-vip-controlplane02 1/1 Running 0 18m
kube-system kube-vip-controlplane03 1/1 Running 0 20m
```
## DNS Support
### Static DNS Support (added in 0.2.0)
A new flag `--address` is introduced to support using a DNS record as the control plane endpoint. `kube-vip` will do a dns lookup to retrieve the IP for the DNS record, and use that IP as the VIP. An `dnsUpdater` periodically checks and updates the system if IP changes for the DNS record.
### Dynamic DNS Support (added in 0.2.1)
`kube-vip` was also updated to support DHCP + [Dynamic DNS](https://en.wikipedia.org/wiki/Dynamic_DNS), for the use case where it's not able to reserve a static IP for the control plane endpoint.
A new flag `--ddns` is introduced. Once enabled, `kube-vip` expects the input `--address` will be a FQDN without binding to an IP. Then `kube-vip` will start a dhcp client to allocate an IP for the hostname of FQDN, and maintain the lease for it.
Once DHCP returns an IP for the FQDN, the same `dnsUpdater` runs to periodically checks and updates if IP got changed.
## BGP Support (added in 0.1.8)
In version `0.1.8`+ `kube-vip` was updated to support [BGP](https://en.wikipedia.org/wiki/Border_Gateway_Protocol) as a VIP failover mechanism. When a node is elected as a leader then it will update it's peers so that they are aware to route traffic to that node in order to access the VIP.
The following new flags are used:
- `--bgp` This will enable BGP support within kube-vip
- `--localAS` The local AS number
- `--bgpRouterID` The local router address
- `--peerAS` The AS number for a BGP peer
- `--peerAddress` The address of a BGP peer
### BGP Packet support
If the `--bgp` flag is passed alone with the Packet flags `packet, packetKey and packetProject`, then the Packet API will be used in order to determine the BGP configuration for the nodes being used in the cluster. This automates a lot of the process and makes using BGP within Packet much simpler.
## Packet Support (added in 0.1.7)
Recently in version `0.1.7` of `kube-vip` we added the functionality to use a Packet Elastic IP as the virtual IP fronting the Kubernetes Control plane cluster. In order to first get out virtual IP we will need to use our Packet account and create a EIP (either public (eek) or private). We will only need a single address so a `/32` will suffice, once this is created as part of a Packet project we can now apply this address to the servers that live in the same project.
In this example we've logged into the UI can created a new EIP of `147.75.1.2`, and we've deployed three small server instances with Ubuntu.
The following new flags are used:
- `--packet` which enables the use of the Packet API
- `--packetKey` which is our API key
- `--packetProject`which is the name of our Packet project where our servers and EIP are located.
*Also* the `--arp` flag should NOT be used as it wont work within the Packet network.
### Variables
```
export EIP=1.1.1.1
export PACKET_AUTH_TOKEN=XYZ
```
### First node
```
# Generate the manifest
sudo docker run --network host --rm plndr/kube-vip:0.2.1 manifest pod \
--arp=false \
--interface lo \
--vip $EIP \
--leaderElection \
--packet \
--packetKey $PACKET_AUTH_TOKEN \
--packetProject vipTest | sudo tee /etc/kubernetes/manifests/vip.yaml\
# Init Kubernetes
sudo kubeadm init --kubernetes-version 1.18.5 --control-plane-endpoint $EIP --upload-certs
```
### Other nodes
```
# Join
kubeadm join $EIP:6443 --token BLAH --control-plane --certificate-key BLAH --discovery-token-ca-cert-hash sha:blah
# Generate Manifest
sudo docker run --network host --rm plndr/kube-vip:0.2.1 manifest pod \
--arp=false \
--interface lo \
--vip $EIP \
--leaderElection \
--packet \
--packetKey $PACKET_AUTH_TOKEN \
--packetProject vipTest | sudo tee /etc/kubernetes/manifests/vip.yaml\
```
The Elastic IP failover takes some time (30+ seconds) to move from a failed host to a new leader, so in this release it is mainly for testing.
## Upgrades
From above we have a 3 node cluster and the controlPlane01 is leader:
```
$ kubectl logs -n kube-system kube-vip-controlplane01 -f
time="2020-07-04T15:12:52Z" level=info msg="Beginning cluster membership, namespace [kube-system], lock name [plunder-lock], id [controlPlane01]"
I0704 15:12:52.290420 1 leaderelection.go:242] attempting to acquire leader lease kube-system/plunder-lock...
I0704 15:12:56.373113 1 leaderelection.go:252] successfully acquired lease kube-system/plunder-lock
time="2020-07-04T15:12:56Z" level=info msg="This node is assuming leadership of the cluster"
time="2020-07-04T15:12:56Z" level=error msg="This node is leader and is adopting the virtual IP"
time="2020-07-04T15:12:56Z" level=info msg="Starting TCP Load Balancer for service [192.168.0.81:0]"
time="2020-07-04T15:12:56Z" level=info msg="Load Balancer [Kubeadm Load Balancer] started"
time="2020-07-04T15:12:56Z" level=info msg="Broadcasting ARP update for 192.168.0.81 (00:50:56:a5:69:a1) via ens192"
time="2020-07-04T15:12:56Z" level=info msg="Starting TCP Load Balancer for service [192.168.0.81:0]"
time="2020-07-04T15:12:56Z" level=info msg="Load Balancer [Kubeadm Load Balancer] started"
time="2020-07-04T15:12:56Z" level=info msg="Broadcasting ARP update for 192.168.0.81 (00:50:56:a5:69:a1) via ens192"
time="2020-07-04T15:12:56Z" level=info msg="new leader elected: controlPlane01"
```
We will kill this node and watch `kube-vip` logs from another node:
#### Pinging VIP
```
64 bytes from 192.168.0.81: icmp_seq=667 ttl=64 time=0.387 ms
Request timeout for icmp_seq 668
Request timeout for icmp_seq 669
Request timeout for icmp_seq 670
Request timeout for icmp_seq 671
Request timeout for icmp_seq 672
64 bytes from 192.168.0.81: icmp_seq=673 ttl=64 time=0.453 ms
```
#### Logs
```
$ kubectl logs -n kube-system kube-vip-controlplane03 -f
time="2020-07-04T15:17:53Z" level=info msg="Beginning cluster membership, namespace [kube-system], lock name [plunder-lock], id [controlPlane03]"
I0704 15:17:53.484698 1 leaderelection.go:242] attempting to acquire leader lease kube-system/plunder-lock...
time="2020-07-04T15:17:53Z" level=info msg="new leader elected: controlPlane01"
E0704 15:20:18.864141 1 leaderelection.go:331] error retrieving resource lock kube-system/plunder-lock: etcdserver: request timed out
time="2020-07-04T15:20:20Z" level=info msg="new leader elected: controlPlane02"
```
#### Adding `controlPlane04`
A kubeadm join will fail as the `controlPlane01` still exists as an endpoint, so we have two options (manual steps and configmap edit to remove all mention of this node, or we can bring this node up and `kubeadm reset` the node (which we will do)).
```
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
controlplane01 NotReady master 14m v1.17.0
controlplane02 Ready master 13m v1.17.2
controlplane03 Ready master 13m v1.17.0
controlplane04 NotReady master 9s v1.17.0
```
After this we can add this node into `kube-vip` with the same manifest created by `docker run`.
## LeaderElection configuration
The Kubernetes LeaderElection that is used to manage the election of a new leader now supports having it's settings managed through flags.
- `--leaseDuration` Length of time a Kubernetes leader lease can be held for
- `--leaseRenewDuration` Length of time a Kubernetes leader can attempt to renew its lease
- `--leaseRetry` Number of times the host will retry to hold a lease
For larger clusters the `--leaseDuration` and `--leaseRenewDuration` may need extending due to slower `etcd` performance. (Tested with 2000 nodes)
## k3s
This section details the steps required to deploye `k3s` in a Highly available manner, using kube-vip deployed within k3s as a daemonset on the control plane nodes. As of `k3s` v1 the persistent datastore is back to etcd, however this guide will also include the steps for using `mysql`.
### Example MySQL deployment (optional)
To quickly validate this we can use docker on a host to quickly spin up a mysql database to store the persistent Kubernetes data.
#### Create local directory for BD storage
`mkdir mysql`
#### Start Docker MySQL container
`sudo docker run --cap-add SYS_NICE -p 3306:3306 --name k3s-mysql -v /home/dan/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=k3s-password -d mysql:8`
### Create `kube-vip` manifest
The `kube-vip` manifest contains all the configuration for starting up `kube-vip` within the `k3s` cluster, it runs as a daemonset with affinity/taints for the control-plane nodes. As `k3s` starts it will parse all manifests in the manifests folder and start the highly available VIP across all control plane nodes in the cluster.
#### Create the `k3` manifests directory
Create the manifests directory, this directory is used by `k3s` for all of it's other deployments once it's up and running.
`sudo mkdir -p /var/lib/rancher/k3s/server/manifests/`
#### Generate the manifest
Modify the `vipAddress` and `vipInterface` to match the floating IP address you'd like to use and the interface it should bind to.
`curl -sL kube-vip.io/k3s | vipAddress=192.168.0.10 vipInterface=ens192 sh | sudo tee /var/lib/rancher/k3s/server/manifests/vip.yaml`
### Start `k3s`
Set the VIP **first**
`export VIP=192.168.0.10`
From online `-->`
```
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--write-kubeconfig-mode 644 \
-t agent-secret --tls-san $VIP" sh -
```
From local `-->`
```
sudo ./k3s server --tls-san $VIP
```
#### With MySQL
From online `-->`
```
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--write-kubeconfig-mode 644 \
--datastore-endpoint mysql://root:k3s-password@tcp(192.168.0.43:3306)/kubernetes \
-t agent-secret --tls-san $VIP" sh -
```
From local `-->`
```
sudo ./k3s server --tls-san $VIP \
--datastore-endpoint="mysql://root:k3s-password@tcp(192.168.0.43:3306)/kubernetes"
```
### Get a `kubeconfig` that uses the vip
````
mkdir -p $HOME/.kube
sudo cat /etc/rancher/k3s/k3s.yaml | sed 's/127.0.0.1/'$VIP'/g' > $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
```

View File

@@ -1,226 +0,0 @@
# Kube-Vip as a daemonset
In Hybrid mode `kube-vip` will manage a virtual IP address that is passed through it's configuration for a Highly Available Kubernetes cluster, it will also "watch" services of `type:LoadBalancer` and once their `spec.LoadBalancerIP` is updated (typically by a cloud controller) it will advertise this address using BGP/ARP.
**Note about Daemonsets**
The "hybrid" mode is now the default mode in `kube-vip` from `0.2.3` onwards, and allows both modes to be enabled at the same time.
If the Kubernetes installer allows for adding a Virtual IP as an additional [SAN](https://en.wikipedia.org/wiki/Subject_Alternative_Name) to the API server certificate then we can apply `kube-vip` to the cluster once the first node has been brought up.
Unlike generating the static manifest there are a few more things that may need configuring, this page will cover most scenarios.
## Create the RBAC settings
As a daemonSet runs within the Kubernetes cluster it needs the correct access to be able to watch Kubernetes services and other objects. In order to do this we create a User, Role, and a binding.. we can apply this with the command:
```
kubectl apply -f https://kube-vip.io/manifests/rbac.yaml
```
## Generating a Manifest
This section only covers generating a simple *BGP* configuration, as the main focus is will be on additional changes to the manifest. For more examples we can look at [here](/hybrid/static/).
**Note:** Pay attention if using the "static" examples, as the `manifest` subcommand should use `daemonset` and NOT `pod`.
### Set configuration details
`export VIP=192.168.0.40`
`export INTERFACE=<interface>`
### Configure to use a container runtime
The easiest method to generate a manifest is using the container itself, below will create an alias for different container runtimes.
#### containerd
`alias kube-vip="ctr run --rm --net-host docker.io/plndr/kube-vip:0.3.1 vip"`
#### Docker
`alias kube-vip="docker run --network host --rm plndr/kube-vip:0.3.1"`
### BGP Example
This configuration will create a manifest that will start `kube-vip` providing **controlplane** and **services** management. **Unlike** ARP, all nodes in the BGP configuration will advertise virtual IP addresses.
**Note** we bind the address to `lo` as we don't want multiple devices that have the same address on public interfaces. We can specify all the peers in a comma seperate list in the format of `address:AS:password:multihop`.
**Note 2** we pass the `--inCluster` flag as this is running as a daemonSet within the Kubernetes cluster and therefore will have access to the token inside the running pod.
**Note 2** we pass the `--taint` flag as we're deploying `kube-vip` as both a daemonset and as advertising controlplane, we want to taint this daemonset to only run on the worker nodes.
`export INTERFACE=lo`
```
kube-vip manifest daemonset \
--interface $INTERFACE \
--vip $VIP \
--controlplane \
--services \
--inCluster \
--taint \
--bgp \
--bgppeers 192.168.0.10:65000::false,192.168.0.11:65000::false
```
### Generated Manifest
```
apiVersion: apps/v1
kind: DaemonSet
metadata:
creationTimestamp: null
name: kube-vip-ds
namespace: kube-system
spec:
selector:
matchLabels:
name: kube-vip-ds
template:
metadata:
creationTimestamp: null
labels:
name: kube-vip-ds
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "false"
- name: vip_interface
value: lo
- name: port
value: "6443"
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: svc_enable
value: "true"
- name: bgp_enable
value: "true"
- name: bgp_peers
value: "192.168.0.10:65000::false,192.168.0.11:65000::false"
- name: vip_address
value: 192.168.0.40
image: plndr/kube-vip:0.2.3
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- SYS_TIME
hostNetwork: true
serviceAccountName: kube-vip
nodeSelector:
node-role.kubernetes.io/master: "true"
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
updateStrategy: {}
```
### Manifest Overview
- `nodeSelector` - Ensures that this particular daemonset only runs on control plane nodes
- `serviceAccountName: kube-vip` - this specifies the user in the `rbac` that will give us the permissions to get/update services.
- `hostNetwork: true` - This pod will need to modify interfaces (for VIPs)
- `env {...}` - We pass the configuration into the kube-vip pod through environment variables.
## Equinix Metal Overview (using the [Equinix Metal CCM](https://github.com/packethost/packet-ccm))
The below example is for running `type:LoadBalancer` services on worker nodes only and will create a daemonset that will run `kube-vip`.
**NOTE** This use-case requires the [Equinix Metal CCM](https://github.com/packethost/packet-ccm) to be installed and that the cluster/kubelet is configured to use an "external" cloud provider.
This is important as the CCM will apply the BGP configuration to the [node annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) making it easy for `kube-vip` to find the networking configuration it needs to expose load balancer addresses. The `--annotations metal.equinix.com` will cause kube-vip to "watch" the annotations of the worker node that it is running on, once all of the configuarion has been applied by the CCM then the `kube-vip` pod is ready to advertise BGP addresses for the service.
```
kube-vip manifest daemonset \
--interface $INTERFACE \
--services \
--bgp \
--annotations metal.equinix.com \
--inCluster | k apply -f -
```
### Troubleshooting
If `kube-vip` has been sat waiting for a long time then you may need to investigate that the annotations have been applied correctly by doing running the `describe` on the node:
```
kubectl describe node k8s.bgp02
...
Annotations: kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
metal.equinix.com/node-asn: 65000
metal.equinix.com/peer-asn: 65530
metal.equinix.com/peer-ip: x.x.x.x
metal.equinix.com/src-ip: x.x.x.x
```
If there are errors regarding `169.254.255.1` or `169.254.255.2` in the `kube-vip` logs then the routes to the ToR switches that provide BGP peering may by missing from the nodes. They can be replaced with the below command:
```
GATEWAY_IP=$(curl https://metadata.platformequinix.com/metadata | jq -r ".network.addresses[] | select(.public == false) | .gateway")
ip route add 169.254.255.1 via $GATEWAY_IP
ip route add 169.254.255.2 via $GATEWAY_IP
```
Additionally examining the logs of the Packet CCM may reveal why the node is not yet ready.
## K3s overview (on Equinix Metal)
### Step 1: TIDY (best if something was running before)
`rm -rf /var/lib/rancher /etc/rancher ~/.kube/*; ip addr flush dev lo; ip addr add 127.0.0.1/8 dev lo; mkdir -p /var/lib/rancher/k3s/server/manifests/`
### Step 2: Get rbac
`curl https://kube-vip.io/manifests/rbac.yaml > /var/lib/rancher/k3s/server/manifests/rbac.yaml`
### Step 3: Generate kube-vip (get EIP from CLI or UI)
```
export EIP=x.x.x.x
export INTERFACE=lo
```
```
kube-vip manifest daemonset \
--interface $INTERFACE \
--vip $EIP \
--controlplane \
--services \
--inCluster \
--taint \
--bgp \
--metal \
--provider-config /etc/cloud-sa/cloud-sa.json | tee /var/lib/rancher/k3s/server/manifests/vip.yaml
```
NOTE: the `—provider-config` actually comes from the secret we apply in step 5 (this will leave kube-vip waiting to start)
### Step 4: Up Cluster
`K3S_TOKEN=SECRET k3s server --cluster-init --tls-san $EIP --no-deploy servicelb --disable-cloud-controller`
### Step 5: Add CCM
`alias k="k3s kubectl"`
`k apply -f ./secret.yaml`
(^ https://github.com/packethost/packet-ccm/blob/master/deploy/template/secret.yaml)
`k apply -f https://gist.githubusercontent.com/thebsdbox/c86dd970549638105af8d96439175a59/raw/4abf90fb7929ded3f7a201818efbb6164b7081f0/ccm.yaml`
### Step 6: Demo !
`k apply -f https://k8s.io/examples/application/deployment.yaml`
`k expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx`
### Step 7 watch and test:
`k get svc --watch`

View File

@@ -1,141 +0,0 @@
# Using `kube-vip` in Hybrid Mode
We can deploy kube-vip in two different methods, which completely depends on your use-case and method for installing Kubernetes:
- Static Pods (hybrid)
- Daemonset (hybrid, requires taint)
## **Prerequisites**
In order for `kube-vip` to be able to speak with the Kubernetes API server, we need to be able to resolve the hostname within the pod. In order to ensure this will work as expected the `/etc/hosts` file should have the `hostname` of the server within it. The `/etc/hosts` file is passed into the running container and will ensure that the pod isn't "confused" by any Kubernetes networking.
## Kubernetes Services (`type:LoadBalancer`)
To learn more about how `kube-vip` in hybrid works with the LoadBalancer services within a kubernetes cluster the documentation is [here](./services/). To get `kube-vip` deployed read on !
## Static Pods
Static pods are a Kubernetes pod that is ran by the `kubelet` on a single node, and is **not** managed by the Kubernetes cluster itself. This means that whilst the pod can appear within Kubernetes it can't make use of a variety of kubernetes functionality (such as the kubernetes token or `configMaps`). The static pod approach is primarily required for [kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/), this is due to the sequence of actions performed by `kubeadm`. Ideally we want `kube-vip` to be part of the kubernetes cluster, for various bits of functionality we also need `kube-vip` to provide a HA virtual IP as part of the installation.
The sequence of events for this to work follows:
1. Generate a `kube-vip` manifest in the static pods manifest folder
2. Run `kubeadm init`, this generates the manifests for the control plane and wait to connect to the VIP
3. The `kubelet` will parse and execute all manifest, including the `kube-vip` manifest
4. `kube-vip` starts and advertises our VIP
5. The `kubeadm init` finishes succesfully.
## Daemonset
Other Kubernetes distributions can bring up a Kubernetes cluster, without depending on a VIP (BUT they are configured to support one). A prime example of this would be k3s, that can be configured to start and also sign the certificates to allow incoming traffic to a virtual IP. Given we don't need the VIP to exist **before** the cluster, we can bring up the k3s node(s) and then add `kube-vip` as a daemonset for all control plane nodes.
# Deploying `kube-vip`
The simplest method for generating the Kubernetes manifests is with `kube-vip` itself.. The subcommand `manifest pod|daemonset` can be used to generate specific types of Kubernetes manifests for use in a cluster. These subcommands can be configured with additional flags to enable/disable BGP/ARP/LeaderElection and a host of other options.
Both Examples will use the same Architecture:
#### Infrastructure architecture
The infrastructure for our example HA Kubernetes cluster is as follows:
| Node | Address |
|----------------|------------|
| VIP | 10.0.0.40 |
| controlPlane01 | 10.0.0.41 |
| controlPlane02 | 10.0.0.42 |
| controlPlane03 | 10.0.0.43 |
| worker01 | 10.0.0.44 |
All nodes are running Ubuntu 18.04, Docker CE and will use Kubernetes 1.19.0, we only have one worker as we're going to use our controlPlanes in "hybrid" mode.
## As a static Pod (for kubeadm)
The details for creating a static pod are available [here](./static/)
## As a daemonset
When using `kube-vip` as a daemonset the details are available [here](./daemonset/)
# Kube-Vip flag reference
| Category | Flag | Usage | Notes |
|--------------|------|-------|-------|
|**Mode** ||||
| |`--controlPlane`|Enables `kube-vip` control-plane functionality||
| |`--services`|Enables `kube-vip` to watch services of type:LoadBalancer||
|**Vip Config** ||||
| |`--arp`|Enables ARP brodcasts from Leader||
| |`--bgp`|Enables BGP peering from `kube-vip`||
| |`--vip`|`<IP Address>`|(deprecated)|
| |`--address`|`<IP Address>` or `<DNS name>`||
| |`--interface`|`<linux interface>`||
| |`--leaderElection`|Enables Kubernetes LeaderElection|Used by ARP, as only the leader can broadcast|
|**Services**||||
| |`--cidr`|Defaults "32"|Used when advertising BGP addresses (typically as `x.x.x.x/32`)|
|**Kubernetes**||||
| |`--inCluster`|Defaults to looking inside the Pod for the token||
| |`--taint`|Enables a taint, stopping control plane daemonset being on workers||
|**LeaderElection**||||
| |`--leaseDuration`|default 5|Seconds a lease is held for|
| |`--leaseRenewDuration`|default 3|Seconds a leader can attempt to renew the lease|
| |`--leaseRetry`|default 1|Number of times the leader will hold the lease for|
| |`--namespace`|"kube-vip"|The namespace where the lease will reside|
|**BGP**||||
| |`--bgpRouterID`|`<IP Address>`|Typically the address of the local node|
| |`--localAS`|default 65000|The AS we peer from|
| |`--bgppeers`|`<address:AS:password:mutlihop>`|Comma seperate list of BGP peers|
| |`--peerAddress`|`<IP Address>`|Address of a single BGP Peer|
| |`--peerAS`|default 65000|AS of a single BGP Peer|
| |`--peerPass`|""| Password to work with a single BGP Peer|
| |`--multiHop`|Enables eBGP MultiHop| Enable multiHop with a single BGP Peer|
| |`--annotaions`|`<provider string>`|Startup will be paused until the node annotaions contain the BGP configuration|
|**Equinix Metal**|||(May be deprecated)|
| |`--metal`|Enables Equinix Metal API calls||
| |`--metalKey`|Equinix Metal API token||
| |`--metalProject`|Equinix Metal Project (Name)||
| |`--metalProjectID`|Equinix Metal Project (UUID)||
| |`--provider-config`|Path to the Equinix Metal provider configuration|Requires the Equinix Metal CCM|
## Changelog
### Static DNS Support (added in 0.2.0)
A new flag `--address` is introduced to support using a DNS record as the control plane endpoint. `kube-vip` will do a dns lookup to retrieve the IP for the DNS record, and use that IP as the VIP. An `dnsUpdater` periodically checks and updates the system if IP changes for the DNS record.
### Dynamic DNS Support (added in 0.2.1)
`kube-vip` was also updated to support DHCP + [Dynamic DNS](https://en.wikipedia.org/wiki/Dynamic_DNS), for the use case where it's not able to reserve a static IP for the control plane endpoint.
A new flag `--ddns` is introduced. Once enabled, `kube-vip` expects the input `--address` will be a FQDN without binding to an IP. Then `kube-vip` will start a dhcp client to allocate an IP for the hostname of FQDN, and maintain the lease for it.
Once DHCP returns an IP for the FQDN, the same `dnsUpdater` runs to periodically checks and updates if IP got changed.
## BGP Support (added in 0.1.8)
In version `0.1.8` `kube-vip` was updated to support [BGP](https://en.wikipedia.org/wiki/Border_Gateway_Protocol) as a VIP failover mechanism. When a node is elected as a leader then it will update it's peers so that they are aware to route traffic to that node in order to access the VIP.
The following new flags are used:
- `--bgp` This will enable BGP support within kube-vip
- `--localAS` The local AS number
- `--bgpRouterID` The local router address
- `--peerAS` The AS number for a BGP peer
- `--peerAddress` The address of a BGP peer
### Equinix Metal BGP support
If the `--bgp` flag is passed along with the Equinix Metal flags `metal, metalKey and metalProject`, then Equinix Metal API will be used in order to determine the BGP configuration for the nodes being used in the cluster. This automates a lot of the process and makes using BGP within Equinix Metal much simpler.
## Equinix Metal Control Plane Support (added in 0.1.8)
Recently in version `0.1.7` of `kube-vip` we added the functionality to use a Equinix Metal Elastic IP as the virtual IP fronting the Kubernetes Control plane cluster. In order to first get out virtual IP we will need to use our Equinix Metal account and create a EIP (either public or private). We will only need a single address so a `/32` will suffice, once this is created as part of a Equinix Metal project we can now apply this address to the servers that live in the same project.
In this example we've logged into the UI can created a new EIP of `147.75.1.2`, and we've deployed three small server instances with Ubuntu.
The following new flags are used:
- `--metal` which enables the use of the Equinix Metal API
- `--metalKey` which is our API key
- `--metalProject`which is the name of our Equinix Metal project where our servers and EIP are located.
*Also* the `--arp` flag should NOT be used as it wont work within the Equinix Metal network.

View File

@@ -1,214 +0,0 @@
# Kube-vip services
We've designed `kube-vip` to be as de-coupled or agnostic from other components that may exist within a Kubernetes cluster as possible. This has lead to `kube-vip` having a very simplistic but robust approach to advertising Kubernetes services to the outside world and marking these services as ready to use.
## Flow
This section details the flow of events in order for `kube-vip` to advertise a Kubernetes service:
1. An end user exposes a application through Kubernetes as a LoadBalancer => `kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx`
2. Within the Kubernetes cluster a service object is created with the `svc.Spec.Type = ServiceTypeLoadBalancer`
3. A controller (typically a Cloud Controller) has a loop that "watches" for services of the type `LoadBalancer`.
4. The controller now has the responsibility of providing an IP address for this service along with doing anything that is network specific for the environment where the cluster is running.
5. Once the controller has an IP address it will update the service `svc.Spec.LoadBalancerIP` with it's new IP address.
6. The `kube-vip` pods also implement a "watcher" for services that have a `svc.Spec.LoadBalancerIP` address attached.
7. When a new service appears `kube-vip` will start advertising this address to the wider network (through BGP/ARP) which will allow traffic to come into the cluster and hit the service network.
8. Finally `kube-vip` will update the service status so that the API reflects that this LoadBalancer is ready. This is done by updating the `svc.Status.LoadBalancer.Ingress` with the VIP address.
## CCM
We can see from the [flow](#Flow) above that `kube-vip` isn't coupled to anything other than the Kubernetes API, and will only act upon an existing Kubernetes primative (in this case the object of type `Service`). This makes it easy for exist CCMs to simply apply their logic to services of type LoadBalancer and leave `kube-vip` to take the next steps to advertise these load-balancers to the outside world.
The below instructions *should just work* on Kubernetes regardless of architecture, Linux as the Operating System is the only requirement.
## Using the Plunder Cloud Provider (CCM)
If you just want things to "work", then you can quickly install the "latest" components:
**Install the `plndr-cloud-provider`
```
kubectl apply -f https://kube-vip.io/manifests/controller.yaml
```
**Create the `cidr` for the `global` namespace**
```
kubectl create configmap --namespace kube-system plndr --from-literal cidr-global=192.168.0.200/29
```
Creating services of `type: LoadBalancer` in the default namespace will now take addresses from the **global** cidr defined in the `configmap`.
**Additional namespaces**
Edit the `configmap` and add in the cidr ranges for those namespaces, the key in the cidr should be `cidr-<namespace>`, then ensure that `kube-vip` is deployed into that namespac
e with the above `apply` command with the `-n namespace` flag.
## The Detailed guide
### Deploy the `plndr-cloud-provider`
To deploy the [latest] then `kubectl apply -f https://kube-vip.io/manifests/controller.yaml`, specific versions should be found in the repository as detailed below:
From the GitHub repository [https://github.com/plunder-app/plndr-cloud-provider/tree/master/example/pod](https://github.com/plunder-app/plndr-cloud-provider/tree/master/example/p
od), find the version of the plunder cloud provider manifest (although typically the highest version number will provider more functionality/stability). The [raw] option in Githu
b will provide the url that can be applied directly with a `kubectl apply -f <url>`.
The following output should appear when the manifest is applied:
```
serviceaccount/plunder-cloud-controller created
clusterrole.rbac.authorization.k8s.io/system:plunder-cloud-controller-role created
clusterrolebinding.rbac.authorization.k8s.io/system:plunder-cloud-controller-binding created
pod/plndr-cloud-provider created
```
We can validate the cloud-provider by examining the pods:
`kubectl logs -n kube-system plndr-cloud-provider-0 -f`
#### The `plndr-cloud-provider` `configmap`
The `configmap` details a CIDR range *per* namespace, however as of (`kube-vip 0.2.1` and `plnder-cloud-provider 0.1.4`), there is now the option of having a **global** CIDR rang
e (`cidr-global)`.
To manage the ranges for the load-balancer instances, the `plndr-cloud-provider` has a `configmap` held in the `kube-system` namespace. The structure for the key/values within th
e `configmap` should be that the key is in the format `cidr-<namespace>` and the value should be the cidr range.
Example Configmap:
```
apiVersion: v1
kind: ConfigMap
metadata:
name: plndr
namespace: kube-system
data:
cidr-default: 192.168.0.200/29
cidr-global: 192.168.0.210/29
```
### Expose a service
We can now expose a service and once the cloud provider has provided an address `kube-vip` will start to advertise that address to the outside world as shown below!
```
kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx
```
We can also expose a specific address by specifying it on the command line:
```
kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx --load-balancer-ip=1.1.1.1
```
### Using DHCP for Load Balancers (experimental)
With the latest release of `kube-vip` > 0.2.1, it is possible to use the local network DHCP server to provide `kube-vip` with a load-balancer address that can be used to access a
Kubernetes service on the network.
In order to do this we need to signify to `kube-vip` and the cloud-provider that we don't need one of their managed addresses. We do this by explicitly exposing a service on the
address `0.0.0.0`. When `kube-vip` sees a service on this address it will create a `macvlan` interface on the host and request a DHCP address, once this address is provided it wi
ll assign it as the VIP and update the Kubernetes service!
```
$ k expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx-dhcp --load-balancer-ip=0.0.0.0; k get svc
service/nginx-dhcp exposed
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17m
nginx-dhcp LoadBalancer 10.97.150.208 0.0.0.0 80:31184/TCP 0s
{ ... a second or so later ... }
$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17m
nginx-dhcp LoadBalancer 10.97.150.208 192.168.0.155 80:31184/TCP 3s
```
### Using UPNP to expose a service to the outside world
With the latest release of `kube-vip` > 0.2.1, it is possible to expose a load-balancer on a specific port and using UPNP (on a supported gateway) expose this service to the inte
rnet.
Most simple networks look something like the following:
`<----- <internal network 192.168.0.0/24> <Gateway / router> <external network address> ----> Internet`
Using UPNP we can create a matching port on the `<external network address>` allowing your service to be exposed to the internet.
#### Enable UPNP
Add the following to the `kube-vip` `env:` section, and the rest should be completely automated.
**Note** some environments may require (Unifi) will require `Secure mode` being `disabled` (this allows a host with a different address to register a port)
```
- name: enableUPNP
value: "true"
```
#### Exposing a service
To expose a port successfully we'll need to change the command slightly:
`--target-port=80` the port of the application in the pods (HTT/NGINX)
`--port=32380` the port the service will be exposed on (and what you should connect to in order to receive traffic from the service)
`kubectl expose deployment plunder-nginx --port=32380 --target-port=80 --type=LoadBalancer --namespace plunder`
The above example should expose a port on your external (internet facing address), that can be tested externally with:
```
$ curl externalIP:32380
<!DOCTYPE html>
<html>
...
```
### Expose with Equinix Metal (using the `plndr-cloud-provider`)
Either through the CLI or through the UI, create a public IPv4 EIP address.. and this is the address you can expose through BGP!
```
# packet ip request -p xxx-bbb-ccc -f ams1 -q 1 -t public_ipv4
+-------+---------------+--------+----------------------+
| ID | ADDRESS | PUBLIC | CREATED |
+-------+---------------+--------+----------------------+
| xxxxx | 1.1.1.1 | true | 2020-11-10T15:57:39Z |
+-------+---------------+--------+----------------------+
kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx --load-balancer-ip=1.1.1.1
```
## Equinix Metal Overview (using the [Equinix Metal CCM](https://github.com/packethost/packet-ccm))
Below are two examples for running `type:LoadBalancer` services on worker nodes only and will create a daemonset that will run `kube-vip`.
**NOTE** This use-case requires the [Equinix Metal CCM](https://github.com/packethost/packet-ccm) to be installed and that the cluster/kubelet is configured to use an "external" cloud provider.
### Using Annotations
This is important as the CCM will apply the BGP configuration to the [node annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/) making it easy for `kube-vip` to find the networking configuration it needs to expose load balancer addresses. The `--annotations metal.equinix.com` will cause kube-vip to "watch" the annotations of the worker node that it is running on, once all of the configuarion has been applied by the CCM then the `kube-vip` pod is ready to advertise BGP addresses for the service.
```
kube-vip manifest daemonset \
--interface $INTERFACE \
--services \
--bgp \
--annotations metal.equinix.com \
--inCluster | k apply -f -
```
### Using the existing CCM secret
Alternatively it is possible to create a daemonset that will use the existing CCM secret to do an API lookup, this will allow for discovering the networking configuration needed to advertise loadbalancer addresses through BGP.
```
kube-vip manifest daemonset --interface $INTERFACE \
--services \
--inCluster \
--bgp \
--metal \
--provider-config /etc/cloud-sa/cloud-sa.json | kubectl apply -f -
```

View File

@@ -1,129 +0,0 @@
# Kube-vip as a Static Pod
In Hybrid mode `kube-vip` will manage a virtual IP address that is passed through it's configuration for a Highly Available Kubernetes cluster, it will also "watch" services of `type:LoadBalancer` and once their `spec.LoadBalancerIP` is updated (typically by a cloud controller) it will advertise this address using BGP/ARP.
The "hybrid" mode is now the default mode in `kube-vip` from `0.2.3` onwards, and allows both modes to be enabled at the same time.
## Generating a Manifest
This section details creating a number of manifests for various use cases
### Set configuration details
`export VIP=192.168.0.40`
`export INTERFACE=<interface>`
### Configure to use a container runtime
The easiest method to generate a manifest is using the container itself, below will create an alias for different container runtimes.
#### containerd
`alias kube-vip="ctr run --rm --net-host docker.io/plndr/kube-vip:0.3.1 vip /kube-vip"`
#### Docker
`alias kube-vip="docker run --network host --rm plndr/kube-vip:0.3.1"`
### ARP
This configuration will create a manifest that starts `kube-vip` providing **controlplane** and **services** management, using **leaderElection**. When this instance is elected as the leader it will bind the `vip` to the specified `interface`, this is also the same for services of `type:LoadBalancer`.
`export INTERFACE=eth0`
```
kube-vip manifest pod \
--interface $INTERFACE \
--vip $VIP \
--controlplane \
--services \
--arp \
--leaderElection | tee /etc/kubernetes/manifests/kube-vip.yaml
```
### BGP
This configuration will create a manifest that will start `kube-vip` providing **controlplane** and **services** management. **Unlike** ARP, all nodes in the BGP configuration will advertise virtual IP addresses.
**Note** we bind the address to `lo` as we don't want multiple devices that have the same address on public interfaces. We can specify all the peers in a comma seperate list in the format of `address:AS:password:multihop`.
`export INTERFACE=lo`
```
kube-vip manifest pod \
--interface $INTERFACE \
--vip $VIP \
--controlplane \
--services \
--bgp \
--localAS 65000 \
--bgpRouterID 192.168.0.2 \
--bgppeers 192.168.0.10:65000::false,192.168.0.11:65000::false | tee /etc/kubernetes/manifests/kube-vip.yaml
```
### BGP with Equinix Metal
When deploying Kubernetes with Equinix Metal with the `--controlplane` functionality we need to pre-populate the BGP configuration in order for the control plane to be advertised and work in a HA scenario. Luckily Equinix Metal provides the capability to "look up" the configuration details (for BGP) that we need in order to advertise our virtual IP for HA functionality. We can either make use of the [Equinix Metal API](https://metal.equinix.com/developers/api/) or we can parse the [Equinix Metal Metadata service](https://metal.equinix.com/developers/docs/servers/metadata/).
**Note** If this cluster will be making use of Equinix Metal for `type:LoadBalancer` (by using the [Equinix Metal CCM](https://github.com/packethost/packet-ccm)) then we will need to ensure that nodes are set to use an external cloud-provider. Before doing a `kubeadm init|join` ensure the kubelet has the correct flags by using the following command `echo KUBELET_EXTRA_ARGS=\"--cloud-provider=external\" > /etc/default/kubelet`.
#### Creating a manifest using the API
We can enable `kube-vip` with the capability to discover the required configuration for BGP by passing the `--metal` flag and the API Key and our project ID.
```
kube-vip manifest pod \
--interface $INTERFACE\
--vip $VIP \
--controlplane \
--services \
--bgp \
--metal \
--metalKey xxxxxxx \
--metalProjectID xxxxx | tee /etc/kubernetes/manifests/kube-vip.yaml
```
#### Creating a manifest using the metadata
We can parse the metadata, *however* it requires that the tools `curl` and `jq` are installed.
```
kube-vip manifest pod \
--interface $INTERFACE\
--vip $VIP \
--controlplane \
--services \
--bgp \
--peerAS $(curl https://metadata.platformequinix.com/metadata | jq '.bgp_neighbors[0].peer_as') \
--peerAddress $(curl https://metadata.platformequinix.com/metadata | jq -r '.bgp_neighbors[0].peer_ips[0]') \
--localAS $(curl https://metadata.platformequinix.com/metadata | jq '.bgp_neighbors[0].customer_as') \
--bgpRouterID $(curl https://metadata.platformequinix.com/metadata | jq -r '.bgp_neighbors[0].customer_ip') | sudo tee /etc/kubernetes/manifests/vip.yaml
```
## Deploy your Kubernetes Cluster
### First node
```
sudo kubeadm init \
--kubernetes-version 1.19.0 \
--control-plane-endpoint $VIP \
--upload-certs
```
### Additional Node(s)
Due to an oddity with `kubeadm` we can't have our `kube-vip` manifest present **before** joining our additional nodes. So on these control plane nodes we will add them first to the cluster.
```
sudo kubeadm join $VIP:6443 \
--token w5atsr.blahblahblah
--control-plane \
--certificate-key abc123
```
**Once**, joined these nodes can have the same command that we ran on the first node to populate the `/etc/kubernetes/manifests/` folder with the `kube-vip` manifest.
## Services
At this point your `kube-vip` static pods will be up and running and where used with the `--services` flag will also be watching for Kubernetes services that they can advertise. In order for `kube-vip` to advertise a service it needs a CCM or other controller to apply an IP address to the `spec.LoadBalancerIP`, which marks the loadbalancer as defined.

View File

@@ -1,27 +0,0 @@
# Kube-vip
The **kube-vip** project provides High-Availability and load-balancing for both **inside** and **outside** a Kubernetes cluster
![kube-vip.png](kube-vip.png)
## Architecture
The architecture for `kube-vip` (and associated kubernetes components) is covered in detail [here](/architecture/)
## (New) Hybrid Control-plane HA and Kubernetes service `type=LoadBalancer`
With the newest release of `kube-vip` the internal "manager" can handle the lifecycle of VIPs for both HA and for Kubernetes Load-Balancing. The main driver for this is being most effective for large nodes that can run control-plane components and run applications. The details for hybrid mode are [here](/hybrid/)
## (Legacy) Control-plane load balancer
The details are [here](/control-plane/)
## (Legacy) Kubernetes service `"type: LoadBalancer"`
The details are [here](/kubernetes/)
## GitHub Repositories
- The Plunder Cloud Provider -> [https://github.com/plunder-app/plndr-cloud-provider](https://github.com/plunder-app/plndr-cloud-provider)
- The Kube-Vip Deployment -> [https://github.com/plunder-app/kube-vip](https://github.com/plunder-app/kube-vip)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

View File

@@ -1,181 +0,0 @@
# Kube-vip (Layer 2 / ARP)
**BEFORE** we begin we should ensure that ipvs has `strict` ARP enabled:
```
$ kubectl describe configmap -n kube-system kube-proxy | grep ARP
strictARP: false
```
If this is false we can enable it with the command:
```
$ kubectl get configmap kube-proxy -n kube-system -o yaml | \
sed -e "s/strictARP: false/strictARP: true/" | \
kubectl apply -f - -n kube-system
```
and confirm with:
```
$ kubectl describe configmap -n kube-system kube-proxy | grep ARP
strictARP: true
```
## Deploy `kube-vip`
To deploy the [latest] then `kubectl apply -f https://kube-vip.io/manifests/kube-vip.yaml`, specific versions should be found in the repository as detailed below:
From the GitHub repository [https://github.com/plunder-app/kube-vip/tree/master/example/deploy](https://github.com/plunder-app/kube-vip/tree/master/example/deploy) find the version of the `kube-vip` to deploy (although typically the highest version number will provider more functionality/stability). The [raw] option in Github will provide the url that can be applied directly with a `kubectl apply -f <url>`.
The following output should appear when the manifest is applied:
```
serviceaccount/vip created
role.rbac.authorization.k8s.io/vip-role created
rolebinding.rbac.authorization.k8s.io/vip-role-bind created
deployment.apps/kube-vip-cluster created
```
*NOTE* The manifest for the `kube-vip` deployment has rules to ensure affinity (pods are always distributed to different nodes for HA). By default the replicas are set to `3` in the event you have less than `3` worker nodes then those replicas will sit as `pending`. This in itself isn't an issue, it means when new workers are added then they will be scheduled. *However*, tooling such as `kapps` will inspect the manifest before it's applied an error because of issues such as this.
### Editing `kube-vip` configuration
Either download and edit the manifest locally or apply as above and edit the deployment with `kubectl edit deploy/kube-vip-cluster` (change namespace where appropriate `-n`)
```
- name: vip_interface
value: ens192
- name: vip_configmap
value: plndr
- name: vip_arp
value: "true"
- name: vip_loglevel
value: "5"
```
- `vip_interface` - defines the interface that the VIP will bind to
- `vip_configmap` - defines the `configmap` that `kube-vip` will watch for service configuration
- `vip_arp` - determines if ARP broadcasts are enabled
- `vip_loglevel` - determines the verbosity of logging
## Using other namespaces
In this example we'll deploy and load-balance within the namespace `plunder`
### Create the namespace
`kubectl create namespace plunder`
### Add a network range/cidr for this namespace
`kubectl edit -n kube-system configmap/plndr`
We will add the range 192.168.0.210/29 for the namespace plunder underneath the existing range for the namespace default:
```
apiVersion: v1
data:
cidr-default: 192.168.0.200/29
cidr-global: 192.168.0.210/29
cidr-plunder: 192.168.0.220/29
<...>
```
### Deploy `kube-vip` in the namespace **plunder**
In the same way we deployed `kube-vip` into the default namespace we can deploy the same manifest into a different namespace using `-n namespace` e.g.
**Note** change the version of manifest when actually deploying!
```
kubectl apply -f https://kube-vip.io/manifests/kube-vip.yaml -n plunder
```
## Usage
This example will deploy into the namespace `plunder` as mention in the [Using other namespaces](Using other namespaces) example. Remove the `-n plunder` to deploy within the `default` namespace.
### Deploy nginx
```
kubectl create deployment --image nginx plunder-nginx --namespace plunder
```
### Create a load balancer
```
kubectl expose deployment plunder-nginx --port=80 --type=LoadBalancer --namespace plunder
```
## Using DHCP for Load Balancers (experimental)
With the latest release of `kube-vip` > 0.2.1, it is possible to use the local network DHCP server to provide `kube-vip` with a load-balancer address that can be used to access a Kubernetes service on the network.
In order to do this we need to signify to `kube-vip` and the cloud-provider that we don't need one of their managed addresses. We do this by explicitly exposing a service on the address `0.0.0.0`. When `kube-vip` sees a service on this address it will create a `macvlan` interface on the host and request a DHCP address, once this address is provided it will assign it as the VIP and update the Kubernetes service!
```
$ k expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx-dhcp --load-balancer-ip=0.0.0.0; k get svc
service/nginx-dhcp exposed
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17m
nginx-dhcp LoadBalancer 10.97.150.208 0.0.0.0 80:31184/TCP 0s
{ ... a second or so later ... }
$ k get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 17m
nginx-dhcp LoadBalancer 10.97.150.208 192.168.0.155 80:31184/TCP 3s
```
## Using UPNP to expose a service to the outside world
With the latest release of `kube-vip` > 0.2.1, it is possible to expose a load-balancer on a specific port and using UPNP (on a supported gateway) expose this service to the internet.
Most simple networks look something like the following:
`<----- <internal network 192.168.0.0/24> <Gateway / router> <external network address> ----> Internet`
Using UPNP we can create a matching port on the `<external network address>` allowing your service to be exposed to the internet.
### Enable UPNP
Add the following to the `kube-vip` `env:` section, and the rest should be completely automated.
**Note** some environments may require (Unifi) will require `Secure mode` being `disabled` (this allows a host with a different address to register a port)
```
- name: enableUPNP
value: "true"
```
### Exposing a service
To expose a port successfully we'll need to change the command slightly:
`--target-port=80` the port of the application in the pods (HTT/NGINX)
`--port=32380` the port the service will be exposed on (and what you should connect to in order to receive traffic from the service)
`kubectl expose deployment plunder-nginx --port=32380 --target-port=80 --type=LoadBalancer --namespace plunder`
The above example should expose a port on your external (internet facing address), that can be tested externally with:
```
$ curl externalIP:32380
<!DOCTYPE html>
<html>
...
```
## Troubleshooting
Typically the logs from the `kube-vip` controller will reveal the most clues as to where a problem may lie.
The `ClusterRoleBinding` is missing will result in the following:
```
E0229 17:36:38.014351 1 retrywatcher.go:129] Watch failed: unknown (get endpoints)
E0229 17:36:38.014352 1 retrywatcher.go:129] Watch failed: unknown (get endpoints)
```
Additionally ensure that the vip_interface matches the correct interface from `ip addr`

View File

@@ -1,87 +0,0 @@
# Kube-vip (Layer 3 / BGP)
## Deploy `kube-vip`
To deploy the [latest] then `kubectl apply -f https://kube-vip.io/manifests/kube-vip.yaml`, specific versions should be found in the repository as detailed below:
From the GitHub repository [https://github.com/plunder-app/kube-vip/tree/master/example/deploy](https://github.com/plunder-app/kube-vip/tree/master/example/deploy) find the version of the `kube-vip` to deploy (although typically the highest version number will provider more functionality/stability). The [raw] option in Github will provide the url that can be applied directly with a `kubectl apply -f <url>`.
The following output should appear when the manifest is applied:
```
serviceaccount/vip created
role.rbac.authorization.k8s.io/vip-role created
rolebinding.rbac.authorization.k8s.io/vip-role-bind created
deployment.apps/kube-vip-cluster created
```
*NOTE* The manifest for the `kube-vip` deployment has rules to ensure affinity (pods are always distributed to different nodes for HA). By default the replicas are set to `3` in the event you have less than `3` worker nodes then those replicas will sit as `pending`. This in itself isn't an issue, it means when new workers are added then they will be scheduled. *However*, tooling such as `kapps` will inspect the manifest before it's applied an error because of issues such as this.
### Editing `kube-vip` configuration
Either download and edit the manifest locally or apply as above and edit the deployment with `kubectl edit deploy/kube-vip-cluster` (change namespace where appropriate `-n`)
Ensure the `vip_arp` isn't enabled as ARP and BGP can't be used at the same time (today), also that the `vip_interface` is set to localhost (`lo`).
```
- name: vip_interface
value: "lo"
- name: vip_configmap
value: "plndr"
- name: bgp_enable
value: "true"
- name: vip_loglevel
value: "5"
```
### BGP Specific configuration
Additionally for BGP we'll need some configuration details, your local friendly network admin should be able to help here:
```
- name: bgp_routerid
value: "192.168.0.45"
- name: bgp_as
value: "65000"
- name: bgp_peeraddress
value: "10.0.0.1"
- name: bgp_peeras
value: "65522"
```
### BGP on Packet
If you're lucky enough to be running services on Packet then The above BGP information can be found from the API, instead of specifying the above we need to use the following:
```
- name: vip_packet
value: "true"
- name: vip_packetproject
value: "My Project"
- name: PACKET_AUTH_TOKEN
value: "XXYZZYVVY"
```
With the above configuration in place, all `kube-vip` pods will start in active mode and when a service is exposed then all nodes will advertise the VIP to the routers.
## Expose a service
Given that `kube-vip` doesn't know your network (at this point) ask your local friendly network OPs for an address you can advertise. That is the address you can expose to the outside world as shown below!
```
kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx --load-balancer-ip=1.1.1.1
```
## Expose with packet
Either through the CLI or through the UI, create a public IPv4 EIP address.. and this is the address you can expose through BGP!
```
# packet ip request -p xxx-bbb-ccc -f ams1 -q 1 -t public_ipv4
+-------+---------------+--------+----------------------+
| ID | ADDRESS | PUBLIC | CREATED |
+-------+---------------+--------+----------------------+
| xxxxx | 1.1.1.1 | true | 2020-11-10T15:57:39Z |
+-------+---------------+--------+----------------------+
kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx --load-balancer-ip=1.1.1.1
```

View File

@@ -1,75 +0,0 @@
# Usage
The below instructions *should just work* on Kubernetes regardless of architecture, Linux as the Operating System is the only requirement.
## The `tl;dr` guide
If you just want things to "work", then you can quickly install the "latest" components:
**NOTE** the `kube-vip.yaml` may need customising to set ARP/BGP OR to configure which interface to bind VIPs too.
**Install the `plndr-cloud-provider`, and `kube-vip`**
```
kubectl apply -f https://kube-vip.io/manifests/controller.yaml
kubectl apply -f https://kube-vip.io/manifests/kube-vip.yaml
```
**Create the `cidr` for the `global` namespace**
```
kubectl create configmap --namespace kube-system plndr --from-literal cidr-global=192.168.0.200/29
```
Creating services of `type: LoadBalancer` in the default namespace will now take addresses from the **global** cidr defined in the `configmap`.
**Additional namespaces**
Edit the `configmap` and add in the cidr ranges for those namespaces, the key in the cidr should be `cidr-<namespace>`, then ensure that `kube-vip` is deployed into that namespace with the above `apply` command with the `-n namespace` flag.
## The Detailed guide
### Deploy the `plndr-cloud-provider`
To deploy the [latest] then `kubectl apply -f https://kube-vip.io/manifests/controller.yaml`, specific versions should be found in the repository as detailed below:
From the GitHub repository [https://github.com/plunder-app/plndr-cloud-provider/tree/master/example/pod](https://github.com/plunder-app/plndr-cloud-provider/tree/master/example/pod), find the version of the plunder cloud provider manifest (although typically the highest version number will provider more functionality/stability). The [raw] option in Github will provide the url that can be applied directly with a `kubectl apply -f <url>`.
The following output should appear when the manifest is applied:
```
serviceaccount/plunder-cloud-controller created
clusterrole.rbac.authorization.k8s.io/system:plunder-cloud-controller-role created
clusterrolebinding.rbac.authorization.k8s.io/system:plunder-cloud-controller-binding created
pod/plndr-cloud-provider created
```
We can validate the cloud-provider by examining the pods:
`kubectl logs -n kube-system plndr-cloud-provider-0 -f`
#### The `plndr-cloud-provider` `configmap`
The `configmap` details a CIDR range *per* namespace, however as of (`kube-vip 0.2.1` and `plnder-cloud-provider 0.1.4`), there is now the option of having a **global** CIDR range (`cidr-global)`.
To manage the ranges for the load-balancer instances, the `plndr-cloud-provider` has a `configmap` held in the `kube-system` namespace. The structure for the key/values within the `configmap` should be that the key is in the format `cidr-<namespace>` and the value should be the cidr range.
Example Configmap:
```
apiVersion: v1
kind: ConfigMap
metadata:
name: plndr
namespace: kube-system
data:
cidr-default: 192.168.0.200/29
cidr-global: 192.168.0.210/29
```
### Deploying `kube-vip`
To use `kube-vip` in Layer2/ARP the follow this [guide](/kubernetes/arp/)
To use `kube-vip` in Layer3/BGP the follow this [guide](/kubernetes/bgp/)

View File

@@ -1,72 +0,0 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
creationTimestamp: null
name: kube-vip-ds
namespace: kube-system
spec:
selector:
matchLabels:
name: kube-vip-ds
template:
metadata:
creationTimestamp: null
labels:
name: kube-vip-ds
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "false"
- name: vip_interface
value: eth0
- name: port
value: "6443"
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: svc_enable
value: "true"
- name: vip_leaderelection
value: "true"
- name: vip_leaseduration
value: "5"
- name: vip_renewdeadline
value: "3"
- name: vip_retryperiod
value: "1"
- name: bgp_enable
value: "true"
- name: bgp_routerid
- name: bgp_as
value: "65000"
- name: bgp_peeraddress
- name: bgp_peerpass
- name: bgp_peeras
value: "65000"
- name: vip_address
value: 192.168.0.1
image: plndr/kube-vip:0.3.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
hostNetwork: true
serviceAccountName: kube-vip
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0

View File

@@ -1,82 +0,0 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
creationTimestamp: null
name: kube-vip-ds
namespace: kube-system
spec:
selector:
matchLabels:
name: kube-vip-ds
template:
metadata:
creationTimestamp: null
labels:
name: kube-vip-ds
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "false"
- name: vip_interface
value: lo
- name: port
value: "6443"
- name: vip_cidr
value: "32"
- name: cp_enable
value: "false"
- name: cp_namespace
value: kube-system
- name: svc_enable
value: "true"
- name: vip_leaderelection
value: "true"
- name: vip_leaseduration
value: "5"
- name: vip_renewdeadline
value: "3"
- name: vip_retryperiod
value: "1"
- name: provider_config
value: /etc/cloud-sa/cloud-sa.json
- name: bgp_enable
value: "true"
- name: bgp_routerid
- name: bgp_as
value: "65000"
- name: bgp_peeraddress
- name: bgp_peerpass
- name: bgp_peeras
value: "65000"
- name: vip_address
value: 192.168.0.1
image: plndr/kube-vip:0.3.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
volumeMounts:
- mountPath: /etc/cloud-sa
name: cloud-sa-volume
readOnly: true
hostNetwork: true
serviceAccountName: kube-vip
volumes:
- name: cloud-sa-volume
secret:
secretName: packet-cloud-config
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0

View File

@@ -1,62 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "false"
- name: vip_interface
value: eth0
- name: port
value: "6443"
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: svc_enable
value: "true"
- name: vip_startleader
value: "false"
- name: vip_addpeerstolb
value: "true"
- name: vip_localpeer
value: code:192.168.0.22:10000
- name: bgp_enable
value: "true"
- name: bgp_routerid
- name: bgp_as
value: "65000"
- name: bgp_peeraddress
- name: bgp_peerpass
- name: bgp_peeras
value: "65000"
- name: vip_address
value: 192.168.0.1
image: plndr/kube-vip:0.3.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}

View File

@@ -1,67 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: plunder-cloud-controller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
name: system:plunder-cloud-controller-role
rules:
- apiGroups: [""]
resources: ["configmaps", "endpoints","events","services/status"]
verbs: ["*"]
- apiGroups: [""]
resources: ["nodes", "services"]
verbs: ["list","get","watch","update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system:plunder-cloud-controller-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:plunder-cloud-controller-role
subjects:
- kind: ServiceAccount
name: plunder-cloud-controller
namespace: kube-system
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: plndr-cloud-provider
namespace: kube-system
spec:
serviceName: plndr-cloud-provider
podManagementPolicy: OrderedReady
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: kube-vip
component: plndr-cloud-provider
template:
metadata:
labels:
app: kube-vip
component: plndr-cloud-provider
spec:
containers:
- command:
- /plndr-cloud-provider
- --leader-elect-resource-name=plndr-cloud-controller
image: plndr/plndr-cloud-provider:0.1.5
name: plndr-cloud-provider
imagePullPolicy: Always
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
serviceAccountName: plunder-cloud-controller

View File

@@ -1,85 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-vip
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
name: system:kube-vip-role
rules:
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "create", "update", "list", "put"]
- apiGroups: [""]
resources: ["services"]
verbs: ["list","get","watch", "update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system:kube-vip-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-vip-role
subjects:
- kind: ServiceAccount
name: kube-vip
namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: kube-vip-workers
name: kube-vip-workers
namespace: kube-system
spec:
replicas: 3
selector:
matchLabels:
app: kube-vip-workers
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: kube-vip-workers
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- kube-vip-workers
topologyKey: "kubernetes.io/hostname"
containers:
- image: plndr/kube-vip:0.2.2
imagePullPolicy: Always
name: kube-vip
command:
- /kube-vip
- service
env:
- name: vip_interface
value: "ens160"
- name: vip_arp
value: "true"
- name: vip_loglevel
value: "5"
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
hostNetwork: true
serviceAccountName: kube-vip
status: {}

View File

@@ -1,90 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-vip
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
name: system:kube-vip-role
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["list","get","watch", "update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system:kube-vip-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-vip-role
subjects:
- kind: ServiceAccount
name: kube-vip
namespace: kube-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: kube-vip-workers
name: kube-vip-workers
namespace: kube-system
spec:
replicas: 3
selector:
matchLabels:
app: kube-vip-workers
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: kube-vip-workers
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- kube-vip-workers
topologyKey: "kubernetes.io/hostname"
containers:
- image: plndr/kube-vip:0.2.2
imagePullPolicy: Always
name: kube-vip
command:
- /kube-vip
- service
env:
- name: vip_interface
value: "lo"
- name: bgp_enable
value: "true"
- name: vip_loglevel
value: "5"
- name: bgp_routerinterface
value: "ens160"
- name: bgp_as
value: "64512"
- name: bgp_peeraddress
value: "192.168.0.1"
- name: bgp_peeras
value: "64512"
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
hostNetwork: true
serviceAccountName: kube-vip
status: {}

View File

@@ -1,91 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-vip
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
name: system:kube-vip-role
rules:
- apiGroups: [""]
resources: ["services", "services/status"]
verbs: ["list","get","watch", "update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system:kube-vip-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-vip-role
subjects:
- kind: ServiceAccount
name: kube-vip
namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
creationTimestamp: null
name: kube-vip-ds
namespace: kube-system
spec:
selector:
matchLabels:
name: kube-vip-ds
template:
metadata:
creationTimestamp: null
labels:
name: kube-vip-ds
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "false"
- name: vip_interface
value: lo
- name: port
value: "6443"
- name: vip_cidr
value: "32"
- name: svc_enable
value: "true"
- name: provider_config
value: /etc/cloud-sa/cloud-sa.json
- name: vip_packet
value: "true"
- name: bgp_enable
value: "true"
image: plndr/kube-vip:0.2.3
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- SYS_TIME
volumeMounts:
- mountPath: /etc/cloud-sa
name: cloud-sa-volume
readOnly: true
hostNetwork: true
serviceAccountName: kube-vip
volumes:
- name: cloud-sa-volume
secret:
secretName: packet-cloud-config
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0

View File

@@ -1,83 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: vip
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: vip-role
rules:
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "create", "update", "list", "put"]
- apiGroups: [""]
resources: ["configmaps", "endpoints"]
verbs: ["watch", "get"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: vip-role-bind
subjects:
- kind: ServiceAccount
name: vip
apiGroup: ""
roleRef:
kind: Role
name: vip-role
apiGroup: ""
---
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: kube-vip-cluster
name: kube-vip-cluster
spec:
replicas: 3
selector:
matchLabels:
app: kube-vip-cluster
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: kube-vip-cluster
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: "app"
operator: In
values:
- kube-vip-cluster
topologyKey: "kubernetes.io/hostname"
containers:
- image: plndr/kube-vip:0.1.3
imagePullPolicy: Always
name: kube-vip
command:
- /kube-vip
- service
env:
- name: vip_interface
value: "ens192"
- name: vip_configmap
value: "plndr"
- name: vip_arp
value: "true"
- name: vip_loglevel
value: "5"
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
hostNetwork: true
serviceAccountName: vip
status: {}

View File

@@ -1,32 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-vip
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
name: system:kube-vip-role
rules:
- apiGroups: [""]
resources: ["services", "services/status", "nodes"]
verbs: ["list","get","watch", "update"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["list", "get", "watch", "update", "create"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system:kube-vip-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-vip-role
subjects:
- kind: ServiceAccount
name: kube-vip
namespace: kube-system

View File

@@ -1,10 +0,0 @@
#!/bin/bash
echo Deploying updated documentation
generate-md --layout github --input ./index/ --output /var/www/kube-vip/
generate-md --layout github --input ./architecture/ --output /var/www/kube-vip/architecture/
generate-md --layout github --input ./control-plane/ --output /var/www/kube-vip/control-plane/
generate-md --layout github --input ./hybrid/ --output /var/www/kube-vip/hybrid/
generate-md --layout github --input ./kubernetes/ --output /var/www/kube-vip/kubernetes/
generate-md --layout github --input ./manifests/ --output /var/www/kube-vip/manifests/

View File

@@ -28,7 +28,7 @@ spec:
- kube-vip-cluster
topologyKey: "kubernetes.io/hostname"
containers:
- image: plndr/kube-vip:0.1.2
- image: ghcr.io/kube-vip/kube-vip:0.3.7
imagePullPolicy: Always
name: kube-vip
command:

View File

@@ -58,7 +58,7 @@ spec:
- kube-vip-cluster
topologyKey: "kubernetes.io/hostname"
containers:
- image: plndr/kube-vip:0.1.3
- image: ghcr.io/kube-vip/kube-vip:0.3.7
imagePullPolicy: Always
name: kube-vip
command:

View File

@@ -26,23 +26,16 @@ spec:
value: "6443"
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: svc_enable
value: "true"
- name: vip_leaderelection
- name: vip_startleader
value: "false"
- name: vip_addpeerstolb
value: "true"
- name: vip_leaseduration
value: "5"
- name: vip_renewdeadline
value: "3"
- name: vip_retryperiod
value: "1"
- name: vip_localpeer
value: ip-172-20-40-207:172.20.40.207:10000
- name: vip_address
value: 192.168.0.1
image: plndr/kube-vip:0.3.1
image: plndr/kube-vip:v0.3.5
imagePullPolicy: Always
name: kube-vip
resources: {}
@@ -60,4 +53,3 @@ status:
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0

19
example/deployment.yaml Normal file
View File

@@ -0,0 +1,19 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: nginx-interface-ens192-service
annotations:
kube-vip.io/serviceInterface: ens192
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP

13
example/service.yaml Normal file
View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP

218
go.mod
View File

@@ -1,65 +1,165 @@
module github.com/plunder-app/kube-vip
module github.com/kube-vip/kube-vip
go 1.14
go 1.24.4
require (
github.com/armon/go-metrics v0.3.4 // indirect
github.com/davecgh/go-spew v1.1.1
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect
github.com/digineo/go-dhclient v1.0.2
github.com/eapache/queue v1.1.0 // indirect
github.com/fatih/color v1.9.0 // indirect
github.com/ghodss/yaml v1.0.0
github.com/go-logr/logr v0.2.1 // indirect
github.com/golang/protobuf v1.4.2
github.com/google/go-cmp v0.5.2 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/gopacket v1.1.18
github.com/google/uuid v1.1.2 // indirect
github.com/googleapis/gnostic v0.5.1 // indirect
github.com/hashicorp/go-hclog v0.14.1 // indirect
github.com/hashicorp/go-immutable-radix v1.2.0 // indirect
github.com/hashicorp/go-msgpack v1.1.5 // indirect
github.com/hashicorp/go-retryablehttp v0.6.7 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/raft v1.1.2
github.com/imdario/mergo v0.3.11 // indirect
github.com/k-sone/critbitgo v1.4.0 // indirect
github.com/kamhlos/upnp v0.0.0-20171112074648-2713e75d9aef
github.com/magiconair/properties v1.8.3 // indirect
github.com/mattn/go-colorable v0.1.7 // indirect
github.com/mdlayher/ndp v0.0.0-20200602162440-17ab9e3e5567
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 // indirect
github.com/mitchellh/mapstructure v1.3.3 // indirect
github.com/onsi/ginkgo v1.11.0
github.com/onsi/gomega v1.7.0
github.com/osrg/gobgp v2.0.0+incompatible
github.com/packethost/packngo v0.5.1
github.com/cloudflare/ipvs v0.11.0
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/docker/docker v28.5.2+incompatible
github.com/florianl/go-conntrack v0.4.0
github.com/google/go-cmp v0.7.0
github.com/google/go-containerregistry v0.20.6
github.com/google/nftables v0.3.0
github.com/gookit/slog v0.6.0
github.com/huin/goupnp v1.3.0
github.com/insomniacslk/dhcp v0.0.0-20241224095048-b56fa0d5f25d
github.com/jpillora/backoff v1.0.0
github.com/mdlayher/ndp v1.1.0
github.com/onsi/ginkgo/v2 v2.27.2
github.com/onsi/gomega v1.38.2
github.com/osrg/gobgp/v3 v3.37.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.4.0
github.com/sirupsen/logrus v1.6.0
github.com/spf13/afero v1.4.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/cobra v1.0.0
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/viper v1.7.1 // indirect
github.com/vishvananda/netlink v1.1.0
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae // indirect
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a // indirect
golang.org/x/net v0.0.0-20201021035429-f5854403a974
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
google.golang.org/genproto v0.0.0-20200917134801-bb4cff56e0d0 // indirect
google.golang.org/grpc v1.32.0 // indirect
gopkg.in/ini.v1 v1.61.0 // indirect
k8s.io/api v0.19.2
k8s.io/apimachinery v0.19.2
k8s.io/client-go v0.19.0
k8s.io/klog v1.0.0
k8s.io/klog/v2 v2.3.0
k8s.io/utils v0.0.0-20200912215256-4140de9c8800 // indirect
sigs.k8s.io/kind v0.10.0
github.com/prometheus/client_golang v1.23.2
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.10.1
github.com/stretchr/testify v1.11.1
github.com/vishvananda/netlink v1.3.1
go.etcd.io/etcd/api/v3 v3.6.6
go.etcd.io/etcd/client/pkg/v3 v3.6.6
go.etcd.io/etcd/client/v3 v3.6.6
go.uber.org/zap v1.27.1
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329
golang.org/x/sync v0.18.0
golang.org/x/sys v0.38.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
google.golang.org/grpc v1.77.0
google.golang.org/protobuf v1.36.10
k8s.io/api v0.34.2
k8s.io/apimachinery v0.34.2
k8s.io/client-go v0.34.1
k8s.io/klog/v2 v2.130.1
sigs.k8s.io/kind v0.30.0
sigs.k8s.io/yaml v1.6.0
)
replace github.com/osrg/gobgp v2.0.0+incompatible => github.com/osrg/gobgp v0.0.0-20191101114856-a42a1a5f6bf0
require (
al.essio.dev/pkg/shellescape v1.5.1 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/dgryski/go-farm v0.0.0-20240924180020-3414d57e47da // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/dlclark/regexp2 v1.11.4 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/eapache/channels v1.1.0 // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.7.0 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gookit/color v1.6.0 // indirect
github.com/gookit/goutil v0.7.1 // indirect
github.com/gookit/gsr v0.1.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/k-sone/critbitgo v1.4.0 // indirect
github.com/magiconair/properties v1.8.9 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mdlayher/genetlink v1.3.2 // indirect
github.com/mdlayher/netlink v1.7.3-0.20250113171957-fbb4dce95f42 // indirect
github.com/mdlayher/packet v1.1.2 // indirect
github.com/mdlayher/socket v0.5.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pierrec/lz4/v4 v4.1.22 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.66.1 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sagikazarmark/locafero v0.6.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.9 // indirect
github.com/spf13/viper v1.19.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tj/go-spin v1.1.0 // indirect
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/vishvananda/netns v0.0.5 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xlab/c-for-go v1.3.0 // indirect
github.com/xlab/pkgconfig v0.0.0-20170226114623-cea12a0fd245 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect
go.opentelemetry.io/otel/metric v1.38.0 // indirect
go.opentelemetry.io/otel/trace v1.38.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
go.yaml.in/yaml/v3 v3.0.4 // indirect
golang.org/x/crypto v0.45.0 // indirect
golang.org/x/mod v0.29.0 // indirect
golang.org/x/net v0.47.0 // indirect
golang.org/x/oauth2 v0.32.0 // indirect
golang.org/x/term v0.37.0 // indirect
golang.org/x/text v0.31.0 // indirect
golang.org/x/time v0.9.0 // indirect
golang.org/x/tools v0.38.0 // indirect
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
modernc.org/cc/v4 v4.24.4 // indirect
modernc.org/mathutil v1.7.1 // indirect
modernc.org/opt v0.1.4 // indirect
modernc.org/sortutil v1.2.1 // indirect
modernc.org/strutil v1.2.1 // indirect
modernc.org/token v1.1.0 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
)

1248
go.sum

File diff suppressed because it is too large Load Diff

BIN
kube-vip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

@@ -1,147 +0,0 @@
# Load Balancing a Kubernetes Cluster (Control-Plane)
This document covers all of the details for using `kube-vip` to build a HA Kubernetes cluster
`tl;dr version`
- Generate/modify first node `kube-vip` config/manifest
- `init` first node
- `join` remaining nodes
- Add remaining config/manifests
## Infrastructure architecture
The infrastructure for our example HA Kubernetes cluster is as follows:
| Node | Address |
|----------------|------------|
| VIP | 10.0.0.75 |
| controlPlane01 | 10.0.0.70 |
| controlPlane02 | 10.0.0.71 |
| controlPlane03 | 10.0.0.72 |
All nodes are running Ubuntu 18.04, Docker CE and will use Kubernetes 1.17.0.
### Generate the `kube-vip` configuration
Make sure that the config directory exists: `sudo mkdir -p /etc/kube-vip/`, this directory can be any directory however the `hostPath` in the manifest will need modifying to point to the correct path.
```
sudo docker run -it --rm plndr/kube-vip:0.1.5 sample config | sudo tee /etc/kube-vip/config.yaml
```
### Modify the configuration
**Cluster Configuration**
Modify the `remotePeers` to point to the correct addresses of the other two nodes, ensure that their `id` is unique otherwise this will confuse the raft algorithm. The `localPeer` should be the configuration of the current node (`controlPlane01`), which is where this instance of the cluster will run.
As this node will be the first node, it will need to elect itself leader as until this occurs the VIP wont be activated!
`startAsLeader: true`
**VIP Config**
We will need to set our VIP address to `192.168.0.75` and to ensure all hosts are updated when the VIP moves we will enable ARP broadcasts `gratuitousARP: true`
**Load Balancer**
We will configure the load balancer to sit on the standard API-Server port `6443` and we will configure the backends to point to the API-servers that will be configured to run on port `6444`. Also for the Kubernetes Control Plane we will configure the load balancer to be of `type: tcp`.
We can also use `6443` for both the VIP and the API-Servers, in order to do this we need to specify that the api-server is bound to it's local IP. To do this we use the `--apiserver-advertise-address` flag as part of the `init`, this means that we can then bind the same port to the VIP and we wont have a port conflict.
**config.yaml**
`user@controlPlane01:/etc/kube-vip$ cat config.yaml`
...
```
remotePeers:
- id: server2
address: 192.168.0.71
port: 10000
- id: server3
address: 192.168.0.72
port: 10000
localPeer:
id: server1
address: 192.168.0.70
port: 10000
vip: 192.168.0.75
gratuitousARP: true
singleNode: false
startAsLeader: true
interface: ens192
loadBalancers:
- name: Kubernetes Control Plane
type: tcp
port: 6443
bindToVip: true
backends:
- port: 6444
address: 192.168.0.70
- port: 6444
address: 192.168.0.71
- port: 6444
address: 192.168.0.72
```
### First Node
To generate the basic Kubernetes static pod `yaml` configuration:
Make sure that the manifest directory exists: `sudo mkdir -p /etc/kubernetes/manifests/`
```
sudo docker run -it --rm plndr/kube-vip:0.1.5 sample manifest | sudo tee /etc/kubernetes/manifests/kube-vip.yaml
```
Ensure that `image: plndr/kube-vip:<x>` is modified to point to a specific version (`0.1.5` at the time of writing), refer to [docker hub](https://hub.docker.com/r/plndr/kube-vip/tags) for details. Also ensure that the `hostPath` points to the correct `kube-vip` configuration, if it isnt the above path.
The **vip** is set to `192.168.0.75` and this first node will elect itself as leader, and as part of the `kubeadm init` it will use the VIP in order to speak back to the initialising api-server.
`sudo kubeadm init --control-plane-endpoint “192.168.0.75:6443” --apiserver-bind-port 6444 --upload-certs --kubernetes-version “v1.17.0”`
Once this node is up and running we will be able to see the control-plane pods, including the `kube-vip` pod:
```
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
<...>
kube-system kube-vip-controlplane01 1/1 Running 0 10m
```
### Remaining Nodes
We first will need to create the `kube-vip` configuration that resides in `/etc/kube-vip/config.yaml` or we can regenerate it from scratch using the above example. Ensure that the configuration is almost identical with the `localPeer` and `remotePeers` sections are updated for each node. Finally, ensure that the remaining nodes will behave as standard cluster nodes by setting `startAsLeader: false`.
At this point **DONT** generate the manifests, this is due to some bizarre `kubeadm/kubelet` behaviour.
```
kubeadm join 192.168.0.75:6443 --token <tkn> \
--discovery-token-ca-cert-hash sha256:<hash> \
--control-plane --certificate-key <key>
```
**After** this node has been added to the cluster, we can add the manifest to also add this node as a `kube-vip` member. (Adding the manifest afterwards doesnt interfere with `kubeadm`).
```
sudo docker run -it --rm plndr/kube-vip:0.1.5 sample manifest | sudo tee /etc/kubernetes/manifests/kube-vip.yaml
```
Once this node is added we will be able to see that the `kube-vip` pod is up and running as expected:
```
user@controlPlane01:~$ kubectl get pods -A | grep vip
kube-system kube-vip-controlplane01 1/1 Running 1 16m
kube-system kube-vip-controlplane02 1/1 Running 0 18m
kube-system kube-vip-controlplane03 1/1 Running 0 20m
```
If we look at the logs, we can see that the VIP is running on the second node and were waiting for our third node to join the cluster:
```
$ kubectl logs kube-vip-controlplane02 -n kube-system
time=“2020-02-12T15:33:09Z” level=info msg=“The Node [192.168.0.70:10000] is leading”
time=“2020-02-12T15:33:09Z” level=info msg=“The Node [192.168.0.70:10000] is leading”
```

View File

@@ -1,6 +1,8 @@
package main
import "github.com/plunder-app/kube-vip/cmd"
import (
"github.com/kube-vip/kube-vip/cmd"
)
// Version is populated from the Makefile and is tied to the release TAG
var Version string
@@ -9,6 +11,7 @@ var Version string
var Build string
func main() {
cmd.Release.Version = Version
cmd.Release.Build = Build
cmd.Execute()

207
pkg/arp/arp.go Normal file
View File

@@ -0,0 +1,207 @@
package arp
import (
"context"
"fmt"
log "log/slog"
"sync"
"time"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/utils"
"github.com/kube-vip/kube-vip/pkg/vip"
)
type Manager struct {
instances sync.Map
config *kubevip.Config
}
type Instance struct {
network vip.Network
ndp *vip.NdpResponder
mu sync.Mutex
counter int
}
func NewManager(config *kubevip.Config) *Manager {
return &Manager{
config: config,
}
}
func NewInstance(network vip.Network, ndp *vip.NdpResponder) *Instance {
return &Instance{
ndp: ndp,
network: network,
counter: 1,
}
}
func (i *Instance) Name() string {
return i.network.ARPName()
}
func (m *Manager) Insert(instance *Instance) {
i, err := m.get(instance.Name())
if err != nil {
log.Error("[ARP manager] unable to insert instance", "err", err)
return
}
if i == nil {
log.Info("[ARP manager] inserting ARP/NDP instance", "name", instance.Name())
m.instances.Store(instance.Name(), instance)
} else {
i.mu.Lock()
defer i.mu.Unlock()
i.counter++
}
}
func (m *Manager) Remove(instance *Instance) {
m.RemoveWithIPDelete(instance, true)
}
// RemoveOnLeadershipLoss removes an ARP instance when leadership is lost
func (m *Manager) RemoveOnLeadershipLoss(instance *Instance) {
// Use the inverse of PreserveVIPOnLeadershipLoss to decide whether to delete the IP
// If preserve is true, don't delete IP (deleteIP = false)
// If preserve is false, delete IP (deleteIP = true), This is the legacy behavior
deleteIP := !m.config.PreserveVIPOnLeadershipLoss
m.RemoveWithIPDelete(instance, deleteIP)
}
func (m *Manager) RemoveWithIPDelete(instance *Instance, deleteIP bool) {
i, err := m.get(instance.Name())
if err != nil {
log.Error("[ARP manager] unable to remove the instance", "err", err)
return
}
if i != nil {
i.mu.Lock()
defer i.mu.Unlock()
if i.counter > 1 {
i.counter--
} else {
log.Info("[ARP manager] removing ARP/NDP instance", "name", instance.Name())
if deleteIP {
if _, err := instance.network.DeleteIP(); err != nil {
log.Error("failed to delete IP", "address", instance.network.IP(), "err", err)
}
}
m.instances.Delete(instance.Name())
}
} else {
log.Warn("[ARP manager] unable to remove the instance - instance not found", "name", instance.Name())
}
}
func (m *Manager) Count(name string) int {
i, err := m.get(name)
if err != nil {
log.Error("[ARP manager] unable to count instance", "err", err)
return -1
}
if i != nil {
i.mu.Lock()
defer i.mu.Unlock()
return i.counter
}
return 0
}
func (m *Manager) StartAdvertisement(ctx context.Context) {
log.Info("[ARP manager] starting ARP/NDP advertisement")
for {
select {
case <-ctx.Done(): // if cancel() execute
return
default:
m.instances.Range(func(_ any, instance any) bool {
if i, ok := instance.(*Instance); ok {
if i.counter > 0 {
ensureIPAndSendGratuitous(i)
} else {
// this instance should not be advertised - delete the IP just in case...
if _, err := i.network.DeleteIP(); err != nil {
log.Error("[ARP manager] failed to delete IP", "address", i.network.IP(), "err", err)
}
}
}
return true
})
}
if m.config.ArpBroadcastRate < 500 {
log.Warn("[ARP manager] arp broadcast rate is too low", "rate (ms)", m.config.ArpBroadcastRate, "setting to (ms)", "3000")
m.config.ArpBroadcastRate = 3000
}
time.Sleep(time.Duration(m.config.ArpBroadcastRate) * time.Millisecond)
}
}
func (m *Manager) get(name string) (*Instance, error) {
i, exists := m.instances.Load(name)
if !exists {
return nil, nil
}
inst, ok := i.(*Instance)
if !ok {
return nil, fmt.Errorf("value for name %q is not of Instance pointer type", name)
}
return inst, nil
}
// ensureIPAndSendGratuitous - adds IP to the interface if missing, and send
// either a gratuitous ARP or gratuitous NDP. Re-adds the interface if it is IPv6
// and in a dadfailed state.
func ensureIPAndSendGratuitous(instance *Instance) {
iface := instance.network.Interface()
ipString := instance.network.IP()
// Check if IP is dadfailed
if instance.network.IsDADFAIL() {
log.Warn("IP address is in dadfailed state, removing config", "ip", ipString, "interface", iface)
deleted, err := instance.network.DeleteIP()
if err != nil {
log.Warn(err.Error())
}
if deleted {
log.Info("deleted and recreating address with NODAD flag to skip DAD", "IP", ipString, "interface", iface)
// Re-add immediately without DAD check since we're recovering from DADFAILED
// The AddIP function will set IFA_F_NODAD flag for IPv6 addresses when skipDAD=true
if _, err := instance.network.AddIP(false, true); err != nil {
log.Error("failed to recreate address after DADFAILED", "IP", ipString, "interface", iface, "err", err)
} else {
log.Info("successfully recreated address after DADFAILED recovery", "IP", ipString, "interface", iface)
}
}
// Return early after DADFAILED recovery to avoid double IP addition
return
}
// Normal case: add IP with precheck and normal DAD process
if added, err := instance.network.AddIP(true, false); err != nil {
log.Warn(err.Error())
} else if added {
log.Warn("Re-applied the VIP configuration", "ip", ipString, "interface", iface)
}
if utils.IsIPv6(ipString) {
// Gratuitous NDP, will broadcast new MAC <-> IPv6 address
if instance.ndp == nil {
log.Error("NDP responder was not created")
} else {
err := instance.ndp.SendGratuitous(ipString)
if err != nil {
log.Warn(err.Error())
}
}
} else {
// Gratuitous ARP, will broadcast to new MAC <-> IPv4 address
err := vip.ARPSendGratuitous(ipString, iface)
if err != nil {
log.Warn(err.Error())
}
}
}

87
pkg/backend/backend.go Normal file
View File

@@ -0,0 +1,87 @@
package backend
import (
"fmt"
"time"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/k8s"
"github.com/kube-vip/kube-vip/pkg/utils"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
type Entry struct {
Addr string
Port uint16
IsLocal bool
}
type Map map[Entry]bool
func (e *Entry) Check() bool {
var client *kubernetes.Clientset
var err error
var config *rest.Config
adminConfigPath := "/etc/kubernetes/admin.conf"
// TODO: add one more switch case of homeConfigPath if there is such scenario in future
// homeConfigPath := filepath.Join(os.Getenv("HOME"), ".kube", "config")
var k8sAddr string
if utils.IsIPv4(e.Addr) {
k8sAddr = fmt.Sprintf("%s:%v", e.Addr, e.Port)
} else {
k8sAddr = fmt.Sprintf("[%s]:%v", e.Addr, e.Port)
}
switch {
case utils.FileExists(adminConfigPath):
config, err = k8s.NewRestConfig(adminConfigPath, false, k8sAddr)
if err != nil {
log.Error("create k8s REST config", "path", adminConfigPath, "err", err)
return false
}
default:
config, err = k8s.NewRestConfig("", true, k8sAddr)
if err != nil {
log.Error("create k8s REST config", "err", err)
return false
}
}
client, err = k8s.NewClientset(config)
if err != nil {
log.Error("create k8s client", "err", err)
return false
}
_, err = client.DiscoveryClient.ServerVersion()
if err != nil {
log.Error("discover k8s version", "err", err)
return false
}
return true
}
func Watch(tickAction func(), interval int, stop chan struct{}) {
if interval <= 0 {
interval = 5
}
ticker := time.NewTicker(time.Second * time.Duration(interval))
defer ticker.Stop()
for {
select {
case <-stop:
ticker.Stop()
return
case <-ticker.C:
ticker.Stop()
tickAction()
ticker.Reset(time.Second * time.Duration(interval))
}
}
}

View File

@@ -2,9 +2,10 @@ package bgp
import (
"context"
"fmt"
"net"
api "github.com/osrg/gobgp/api"
api "github.com/osrg/gobgp/v3/api"
)
// AddHost will update peers of a host
@@ -13,15 +14,20 @@ func (b *Server) AddHost(addr string) (err error) {
if err != nil {
return err
}
p := b.getPath(ip)
if p == nil {
return err
return fmt.Errorf("failed to get path for %v", ip)
}
_, err = b.s.AddPath(context.Background(), &api.AddPathRequest{
Path: p,
})
if err != nil {
return err
}
return
}

View File

@@ -4,36 +4,31 @@ import (
"context"
"fmt"
"net"
"strconv"
"strings"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/any"
api "github.com/osrg/gobgp/api"
//nolint
"github.com/kube-vip/kube-vip/pkg/kubevip"
api "github.com/osrg/gobgp/v3/api"
"github.com/kube-vip/kube-vip/pkg/utils"
"github.com/osrg/gobgp/v3/pkg/server"
"google.golang.org/protobuf/types/known/anypb"
)
//AddPeer will add peers to the BGP configuration
func (b *Server) AddPeer(peer Peer) (err error) {
port := 179
if t := strings.SplitN(peer.Address, ":", 2); len(t) == 2 {
peer.Address = t[0]
if port, err = strconv.Atoi(t[1]); err != nil {
return fmt.Errorf("Unable to parse port '%s' as int: %s", t[1], err)
}
}
// AddPeer will add peers to the BGP configuration
func (b *Server) AddPeer(peer kubevip.BGPPeer) (err error) {
p := &api.Peer{
Conf: &api.PeerConf{
NeighborAddress: peer.Address,
PeerAs: peer.AS,
PeerAsn: peer.AS,
AuthPassword: peer.Password,
},
Timers: &api.Timers{
Config: &api.TimersConfig{
ConnectRetry: 10,
ConnectRetry: 10,
HoldTime: b.c.HoldTime,
KeepaliveInterval: b.c.KeepaliveInterval,
},
},
@@ -46,95 +41,204 @@ func (b *Server) AddPeer(peer Peer) (err error) {
Transport: &api.Transport{
MtuDiscovery: true,
RemoteAddress: peer.Address,
RemotePort: uint32(port),
RemotePort: uint32(179),
},
}
// if b.c.SourceIP != "" {
// p.Transport.LocalAddress = b.c.SourceIP
// }
// if b.c.SourceIF != "" {
// p.Transport.BindInterface = b.c.SourceIF
// }
return b.s.AddPeer(context.Background(), &api.AddPeerRequest{
Peer: p,
})
}
func (b *Server) getPath(ip net.IP) *api.Path {
var pfxLen uint32 = 32
if ip.To4() == nil {
if !b.c.IPv6 {
return nil
if b.c.MpbgpNexthop != "" {
p.AfiSafis = []*api.AfiSafi{
{
Config: &api.AfiSafiConfig{
Family: &api.Family{
Afi: api.Family_AFI_IP,
Safi: api.Family_SAFI_UNICAST,
},
Enabled: true,
},
},
{
Config: &api.AfiSafiConfig{
Family: &api.Family{
Afi: api.Family_AFI_IP6,
Safi: api.Family_SAFI_UNICAST,
},
Enabled: true,
},
},
}
pfxLen = 128
peer.SetMpbgpOptions(b.c)
ipv4Address, ipv6Address, err := peer.FindMpbgpAddresses(p, b.c)
if err != nil {
return fmt.Errorf("failed to get MP-BGP addresses: %w", err)
}
mask := "128"
address := ipv4Address
family := api.Family_AFI_IP
if utils.IsIPv4(p.Conf.NeighborAddress) {
mask = "32"
address = ipv6Address
family = api.Family_AFI_IP6
}
err = b.s.AddDefinedSet(context.Background(), &api.AddDefinedSetRequest{
DefinedSet: &api.DefinedSet{
DefinedType: api.DefinedType_NEIGHBOR,
Name: fmt.Sprintf("peer-%s", p.Conf.NeighborAddress),
List: []string{fmt.Sprintf("%s/%s", p.Conf.NeighborAddress, mask)},
},
})
if err != nil {
return fmt.Errorf("failed to add defined set: %v", err)
}
if address != "" {
if err := insertPolicy(b.s, address, p, family); err != nil {
return fmt.Errorf("failed to add policy: %w", err)
}
}
} else {
if b.c.SourceIP != "" {
p.Transport.LocalAddress = b.c.SourceIP
}
if b.c.SourceIF != "" {
p.Transport.BindInterface = b.c.SourceIF
}
}
nlri, _ := ptypes.MarshalAny(&api.IPAddressPrefix{
Prefix: ip.String(),
PrefixLen: pfxLen,
})
if err := b.s.AddPeer(context.Background(), &api.AddPeerRequest{Peer: p}); err != nil {
return fmt.Errorf("failed to add peer: %v", err)
}
a1, _ := ptypes.MarshalAny(&api.OriginAttribute{
return nil
}
func (b *Server) getPath(ip net.IP) (path *api.Path) {
isV6 := ip.To4() == nil
//nolint
originAttr, _ := anypb.New(&api.OriginAttribute{
Origin: 0,
})
var nh string
if b.c.NextHop != "" {
nh = b.c.NextHop
} else if b.c.SourceIP != "" {
nh = b.c.SourceIP
if !isV6 {
//nolint
nlri, _ := anypb.New(&api.IPAddressPrefix{
Prefix: ip.String(),
PrefixLen: 32,
})
//nolint
nhAttr, _ := anypb.New(&api.NextHopAttribute{
NextHop: "0.0.0.0", // gobgp will fill this
})
path = &api.Path{
Family: &api.Family{
Afi: api.Family_AFI_IP,
Safi: api.Family_SAFI_UNICAST,
},
Nlri: nlri,
Pattrs: []*anypb.Any{originAttr, nhAttr},
}
} else {
nh = b.c.RouterID
}
//nolint
nlri, _ := anypb.New(&api.IPAddressPrefix{
Prefix: ip.String(),
PrefixLen: 128,
})
a2, _ := ptypes.MarshalAny(&api.NextHopAttribute{
NextHop: nh,
})
return &api.Path{
Family: &api.Family{
Afi: api.Family_AFI_IP,
v6Family := &api.Family{
Afi: api.Family_AFI_IP6,
Safi: api.Family_SAFI_UNICAST,
},
Nlri: nlri,
Pattrs: []*any.Any{a1, a2},
}
}
// ParseBGPPeerConfig - take a string and parses it into an array of peers
func ParseBGPPeerConfig(config string) (bgpPeers []Peer, err error) {
peers := strings.Split(config, ",")
if len(peers) == 0 {
return nil, fmt.Errorf("No BGP Peer configurations found")
}
for x := range peers {
peer := strings.Split(peers[x], ":")
if len(peer) != 4 {
return nil, fmt.Errorf("BGP Peer configuration format error <host>:<AS>:<password>:<multihop>")
}
ASNumber, err := strconv.Atoi(peer[1])
if err != nil {
return nil, fmt.Errorf("BGP Peer AS format error [%s]", peer[1])
}
multiHop, err := strconv.ParseBool(peer[3])
if err != nil {
return nil, fmt.Errorf("BGP MultiHop format error (true/false) [%s]", peer[1])
}
peerConfig := Peer{
Address: peer[0],
AS: uint32(ASNumber),
Password: peer[2],
MultiHop: multiHop,
}
//nolint
mpAttr, _ := anypb.New(&api.MpReachNLRIAttribute{
Family: v6Family,
NextHops: []string{"::"}, // gobgp will fill this
Nlris: []*anypb.Any{nlri},
})
bgpPeers = append(bgpPeers, peerConfig)
path = &api.Path{
Family: v6Family,
Nlri: nlri,
Pattrs: []*anypb.Any{originAttr, mpAttr},
}
}
return
}
func insertPolicy(s *server.BgpServer, address string, p *api.Peer, family api.Family_Afi) error {
familyType := "v4"
if family == api.Family_AFI_IP6 {
familyType = "v6"
}
setName := fmt.Sprintf("peer-%s", p.Conf.NeighborAddress)
policyName := fmt.Sprintf("%s-%s", setName, familyType)
policy := &api.Policy{
Name: policyName,
Statements: []*api.Statement{
{
Conditions: &api.Conditions{
AfiSafiIn: []*api.Family{
{
Afi: family,
Safi: api.Family_SAFI_UNICAST,
},
},
NeighborSet: &api.MatchSet{
Type: api.MatchSet_ANY,
Name: setName,
},
},
Actions: &api.Actions{
RouteAction: api.RouteAction_ACCEPT,
Nexthop: &api.NexthopAction{
Address: address,
},
},
},
{
Conditions: &api.Conditions{
NeighborSet: &api.MatchSet{
Type: api.MatchSet_ANY,
Name: setName,
},
},
Actions: &api.Actions{
RouteAction: api.RouteAction_ACCEPT,
},
},
},
}
err := s.AddPolicy(context.Background(), &api.AddPolicyRequest{
Policy: policy,
})
if err != nil {
return fmt.Errorf("failed to add policy: %w", err)
}
err = s.AddPolicyAssignment(context.Background(), &api.AddPolicyAssignmentRequest{
Assignment: &api.PolicyAssignment{
Name: "global",
Direction: api.PolicyDirection_EXPORT,
Policies: []*api.Policy{
{
Name: policy.Name,
},
},
},
})
if err != nil {
return fmt.Errorf("failed to add policy assignment: %v", err)
}
return nil
}

56
pkg/bgp/peers_test.go Normal file
View File

@@ -0,0 +1,56 @@
package bgp
import (
"reflect"
"testing"
"github.com/kube-vip/kube-vip/pkg/kubevip"
)
func TestParseBGPPeerConfig(t *testing.T) {
type args struct {
config string
}
tests := []struct {
name string
args args
wantBgpPeers []kubevip.BGPPeer
wantErr bool
}{
{
name: "IPv4, default port",
args: args{config: "192.168.0.10:65000::false,192.168.0.11:65000::false"},
wantBgpPeers: []kubevip.BGPPeer{
{Address: "192.168.0.10", Port: 179, AS: 65000, MultiHop: false},
{Address: "192.168.0.11", Port: 179, AS: 65000, MultiHop: false},
},
},
{
name: "IPv4, different port",
args: args{config: "192.168.0.10:65000::false:180,192.168.0.11:65000::false:190"},
wantBgpPeers: []kubevip.BGPPeer{
{Address: "192.168.0.10", Port: 180, AS: 65000, MultiHop: false},
{Address: "192.168.0.11", Port: 190, AS: 65000, MultiHop: false},
},
},
{
name: "IPv6, multi-protocol",
args: args{config: "[fd00:1111:2222:3333:c7d9:7235:6bf7:5d52]:65501::false/mpbgp_nexthop=auto_sourceif"},
wantBgpPeers: []kubevip.BGPPeer{
{Address: "fd00:1111:2222:3333:c7d9:7235:6bf7:5d52", Port: 179, AS: 65501, MultiHop: false, MpbgpNexthop: "auto_sourceif"},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotBgpPeers, err := kubevip.ParseBGPPeerConfig(tt.args.config)
if (err != nil) != tt.wantErr {
t.Errorf("ParseBGPPeerConfig() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(gotBgpPeers, tt.wantBgpPeers) {
t.Errorf("ParseBGPPeerConfig() = %v, want %v", gotBgpPeers, tt.wantBgpPeers)
}
})
}
}

View File

@@ -3,53 +3,96 @@ package bgp
import (
"context"
"fmt"
"log"
"time"
api "github.com/osrg/gobgp/api"
gobgp "github.com/osrg/gobgp/pkg/server"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/kubevip"
api "github.com/osrg/gobgp/v3/api"
gobgp "github.com/osrg/gobgp/v3/pkg/server"
"github.com/prometheus/client_golang/prometheus"
)
// Server manages a server object
type Server struct {
s *gobgp.BgpServer
c *kubevip.BGPConfig
// This is a prometheus gauge indicating the state of the sessions.
// 1 means "ESTABLISHED", 0 means "NOT ESTABLISHED"
BGPSessionInfoGauge *prometheus.GaugeVec
}
// NewBGPServer takes a configuration and returns a running BGP server instance
func NewBGPServer(c *Config) (b *Server, err error) {
func NewBGPServer(c kubevip.BGPConfig) (b *Server, err error) {
if c.AS == 0 {
return nil, fmt.Errorf("You need to provide AS")
return nil, fmt.Errorf("you need to provide AS")
}
// if c.SourceIP != "" && c.SourceIF != "" {
// return nil, fmt.Errorf("SourceIP and SourceIF are mutually exclusive")
// }
if c.SourceIP != "" && c.SourceIF != "" {
return nil, fmt.Errorf("sourceIP and SourceIF are mutually exclusive")
}
if len(c.Peers) == 0 {
return nil, fmt.Errorf("You need to provide at least one peer")
return nil, fmt.Errorf("you need to provide at least one peer")
}
b = &Server{
s: gobgp.NewBgpServer(),
c: c,
c: &c,
BGPSessionInfoGauge: prometheus.NewGaugeVec(prometheus.GaugeOpts{
Namespace: "kube_vip",
Subsystem: "manager",
Name: "bgp_session_info",
Help: "Display state of session by setting metric for label value with current state to 1",
}, []string{"state", "peer"}),
}
return
}
// Start starts the BGP server
func (b *Server) Start(peerStateChangeCallback func(*api.WatchEventResponse_PeerEvent)) (err error) {
go b.s.Serve()
if err = b.s.StartBgp(context.Background(), &api.StartBgpRequest{
Global: &api.Global{
As: c.AS,
RouterId: c.RouterID,
Asn: b.c.AS,
RouterId: b.c.RouterID,
ListenPort: -1,
},
}); err != nil {
return
}
if err = b.s.MonitorPeer(context.Background(), &api.MonitorPeerRequest{}, func(p *api.Peer) { log.Println(p) }); err != nil {
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.Info("[BGP]", "peer", p.String())
if peerStateChangeCallback != nil {
peerStateChangeCallback(p)
}
}
}); err != nil {
return
}
for _, p := range c.Peers {
for _, p := range b.c.Peers {
if err = b.AddPeer(p); err != nil {
return
}
}
if b.c.Zebra.Enabled {
if err = b.s.EnableZebra(context.Background(), &api.EnableZebraRequest{
Url: b.c.Zebra.URL,
Version: b.c.Zebra.Version,
SoftwareName: b.c.Zebra.SoftwareName,
}); err != nil {
log.Error(err.Error())
return
}
}
return
}

View File

@@ -1,29 +0,0 @@
package bgp
import gobgp "github.com/osrg/gobgp/pkg/server"
// Peer defines a BGP Peer
type Peer struct {
Address string
AS uint32
Password string
MultiHop bool
}
// Config defines the BGP server configuration
type Config struct {
AS uint32
RouterID string
NextHop string
SourceIP string
SourceIF string
Peers []Peer
IPv6 bool
}
// Server manages a server object
type Server struct {
s *gobgp.BgpServer
c *Config
}

View File

@@ -1,52 +1,80 @@
package cluster
import (
"github.com/plunder-app/kube-vip/pkg/kubevip"
"github.com/plunder-app/kube-vip/pkg/vip"
)
"sync"
const leaderLogcount = 5
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/arp"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/networkinterface"
"github.com/kube-vip/kube-vip/pkg/vip"
)
// Cluster - The Cluster object manages the state of the cluster for a particular node
type Cluster struct {
stateMachine FSM
stop chan bool
completed chan bool
Network vip.Network
stop chan bool
completed chan bool
once sync.Once
Network []vip.Network
arpMgr *arp.Manager
}
// InitCluster - Will attempt to initialise all of the required settings for the cluster
func InitCluster(c *kubevip.Config, disableVIP bool) (*Cluster, error) {
// TODO - Check for root (needed to netlink)
var network vip.Network
func InitCluster(c *kubevip.Config, disableVIP bool, intfMgr *networkinterface.Manager, arpMgr *arp.Manager) (*Cluster, error) {
var networks []vip.Network
var err error
if !disableVIP {
// Start the Virtual IP Networking configuration
network, err = startNetworking(c)
networks, err = startNetworking(c, intfMgr)
if err != nil {
return nil, err
}
}
// Initialise the Cluster structure
newCluster := &Cluster{
Network: network,
Network: networks,
arpMgr: arpMgr,
}
log.Debug("service security", "enabled", c.EnableServiceSecurity)
return newCluster, nil
}
func startNetworking(c *kubevip.Config) (vip.Network, error) {
func startNetworking(c *kubevip.Config, intfMgr *networkinterface.Manager) ([]vip.Network, error) {
address := c.VIP
if c.Address != "" {
address = c.Address
}
network, err := vip.NewConfig(address, c.Interface, c.DDNS)
if err != nil {
return nil, err
addresses := vip.Split(address)
networks := []vip.Network{}
for _, addr := range addresses {
network, err := vip.NewConfig(addr, c.Interface, c.LoInterfaceGlobalScope, c.VIPSubnet, c.DDNS, c.RoutingTableID,
c.RoutingTableType, c.RoutingProtocol, c.DNSMode, c.LoadBalancerForwardingMethod, c.IptablesBackend,
c.EnableLoadBalancer, c.EnableServiceSecurity, intfMgr)
if err != nil {
return nil, err
}
networks = append(networks, network...)
}
return network, nil
return networks, nil
}
// Stop - Will stop the Cluster and release VIP if needed
func (cluster *Cluster) Stop() {
// Close the stop channel, which will shut down the VIP (if needed)
if cluster.stop != nil {
cluster.once.Do(func() { // Ensure that the close channel can only ever be called once
close(cluster.stop)
})
}
// Wait until the completed channel is closed, signallign all shutdown tasks completed
<-cluster.completed
}

View File

@@ -2,7 +2,8 @@ package cluster
import (
"context"
"github.com/plunder-app/kube-vip/pkg/vip"
"github.com/kube-vip/kube-vip/pkg/vip"
)
// StartDDNS should start go routine for dhclient to hold the lease for the IP
@@ -11,14 +12,13 @@ import (
// during runtime if IP changes, startDDNS don't have to do reconfigure because
// dnsUpdater already have the functionality to keep trying resolve the IP
// and update the VIP configuration if it changes
func (cluster *Cluster) StartDDNS(ctx context.Context) error {
ddnsMgr := vip.NewDDNSManager(ctx, cluster.Network)
func (cluster *Cluster) StartDDNS(ctx context.Context, network vip.Network) error {
ddnsMgr := vip.NewDDNSManager(ctx, network)
ip, err := ddnsMgr.Start()
if err != nil {
return err
}
if err = cluster.Network.SetIP(ip); err != nil {
if err = network.SetIP(ip); err != nil {
return err
}

View File

@@ -1,456 +0,0 @@
package cluster
import (
"context"
"fmt"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"github.com/plunder-app/kube-vip/pkg/bgp"
"github.com/plunder-app/kube-vip/pkg/kubevip"
leaderelection "github.com/plunder-app/kube-vip/pkg/leaderElection"
"github.com/plunder-app/kube-vip/pkg/loadbalancer"
"github.com/plunder-app/kube-vip/pkg/packet"
"github.com/plunder-app/kube-vip/pkg/vip"
"github.com/packethost/packngo"
log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/leaderelection/resourcelock"
)
const plunderLock = "plndr-cp-lock"
// Manager degines the manager of the load-balancing services
type Manager struct {
KubernetesClient *kubernetes.Clientset
}
// NewManager will create a new managing object
func NewManager(path string, inCluster bool, port int) (*Manager, error) {
var clientset *kubernetes.Clientset
if inCluster {
// This will attempt to load the configuration when running within a POD
cfg, err := rest.InClusterConfig()
if err != nil {
return nil, fmt.Errorf("error creating kubernetes client config: %s", err.Error())
}
clientset, err = kubernetes.NewForConfig(cfg)
if err != nil {
return nil, fmt.Errorf("error creating kubernetes client: %s", err.Error())
}
// use the current context in kubeconfig
} else {
if path == "" {
path = filepath.Join(os.Getenv("HOME"), ".kube", "config")
}
config, err := clientcmd.BuildConfigFromFlags("", path)
if err != nil {
panic(err.Error())
}
// We modify the config so that we can always speak to the correct host
id, err := os.Hostname()
if err != nil {
return nil, err
}
config.Host = fmt.Sprintf("%s:%v", id, port)
clientset, err = kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("error creating kubernetes client: %s", err.Error())
}
}
return &Manager{
KubernetesClient: clientset,
}, nil
}
// StartLeaderCluster - Begins a running instance of the Raft cluster
func (cluster *Cluster) StartLeaderCluster(c *kubevip.Config, sm *Manager, bgpServer *bgp.Server) error {
id, err := os.Hostname()
if err != nil {
return err
}
log.Infof("Beginning cluster membership, namespace [%s], lock name [%s], id [%s]", c.Namespace, plunderLock, 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{
LeaseMeta: metav1.ObjectMeta{
Name: plunderLock,
Namespace: c.Namespace,
},
Client: sm.KubernetesClient.CoordinationV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: id,
},
}
// use a Go context so we can tell the leaderelection code when we
// want to step down
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// use a Go context so we can tell the arp loop code when we
// want to step down
ctxArp, cancelArp := context.WithCancel(context.Background())
defer cancelArp()
// use a Go context so we can tell the dns loop code when we
// want to step down
ctxDNS, cancelDNS := context.WithCancel(context.Background())
defer cancelDNS()
// listen for interrupts or the Linux SIGTERM signal and cancel
// our context, which the leader election code will observe and
// step down
signalChan := make(chan os.Signal, 1)
// Add Notification for Userland interrupt
signal.Notify(signalChan, syscall.SIGINT)
// Add Notification for SIGTERM (sent from Kubernetes)
signal.Notify(signalChan, syscall.SIGTERM)
// Add Notification for SIGKILL (sent from Kubernetes)
signal.Notify(signalChan, syscall.SIGKILL)
go func() {
<-signalChan
log.Info("Received termination, signaling shutdown")
// Cancel the context, which will in turn cancel the leadership
cancel()
// Cancel the arp context, which will in turn stop any broadcasts
}()
// (attempt to) Remove the virtual IP, incase it already exists
cluster.Network.DeleteIP()
// Managers for Vip load balancers and none-vip loadbalancers
nonVipLB := loadbalancer.LBManager{}
VipLB := loadbalancer.LBManager{}
// Defer a function to check if the bgpServer has been created and if so attempt to close it
defer func() {
if bgpServer != nil {
bgpServer.Close()
}
}()
// If Packet is enabled then we can begin our preperation work
var packetClient *packngo.Client
if c.EnableMetal {
packetClient, err = packngo.NewClient()
if err != nil {
log.Error(err)
}
// We're using Packet with BGP, popuplate the Peer information from the API
if c.EnableBGP {
log.Infoln("Looking up the BGP configuration from packet")
err = packet.BGPLookup(packetClient, c)
if err != nil {
log.Error(err)
}
}
}
if c.EnableBGP {
// Lets start BGP
log.Info("Starting the BGP server to adverise VIP routes to VGP peers")
bgpServer, err = bgp.NewBGPServer(&c.BGPConfig)
if err != nil {
log.Error(err)
}
}
if c.EnableLoadBalancer {
// Iterate through all Configurations
if len(c.LoadBalancers) != 0 {
for x := range c.LoadBalancers {
// If the load balancer doesn't bind to the VIP
if c.LoadBalancers[x].BindToVip == false {
err = nonVipLB.Add("", &c.LoadBalancers[x])
if err != nil {
log.Warnf("Error creating loadbalancer [%s] type [%s] -> error [%s]", c.LoadBalancers[x].Name, c.LoadBalancers[x].Type, err)
}
}
}
}
}
// start the leader election code loop
leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{
Lock: lock,
// IMPORTANT: you MUST ensure that any code you have that
// is protected by the lease must terminate **before**
// you call cancel. Otherwise, you could have a background
// loop still running and another process could
// get elected before your background loop finished, violating
// the stated goal of the lease.
ReleaseOnCancel: true,
LeaseDuration: time.Duration(c.LeaseDuration) * time.Second,
RenewDeadline: time.Duration(c.RenewDeadline) * time.Second,
RetryPeriod: time.Duration(c.RetryPeriod) * time.Second,
Callbacks: leaderelection.LeaderCallbacks{
OnStartedLeading: func(ctx context.Context) {
// we're notified when we start
log.Info("This node is starting with leadership of the cluster")
// setup ddns first
// for first time, need to wait until IP is allocated from DHCP
if cluster.Network.IsDDNS() {
if err := cluster.StartDDNS(ctxDNS); err != nil {
log.Error(err)
}
}
// start the dns updater if address is dns
if cluster.Network.IsDNS() {
log.Infof("starting the DNS updater for the address %s", cluster.Network.DNSName())
ipUpdater := vip.NewIPUpdater(cluster.Network)
ipUpdater.Run(ctxDNS)
}
err = cluster.Network.AddIP()
if err != nil {
log.Warnf("%v", err)
}
if c.EnableMetal {
// We're not using Packet with BGP
if !c.EnableBGP {
// Attempt to attach the EIP in the standard manner
log.Debugf("Attaching the Packet EIP through the API to this host")
err = packet.AttachEIP(packetClient, c, id)
if err != nil {
log.Error(err)
}
}
}
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.IP(), c.VIPCIDR)
log.Debugf("Attempting to advertise the address [%s] over BGP", cidrVip)
err = bgpServer.AddHost(cidrVip)
if err != nil {
log.Error(err)
}
}
if c.EnableLoadBalancer {
// Once we have the VIP running, start the load balancer(s) that bind to the VIP
for x := range c.LoadBalancers {
if c.LoadBalancers[x].BindToVip == true {
err = VipLB.Add(cluster.Network.IP(), &c.LoadBalancers[x])
if err != nil {
log.Warnf("Error creating loadbalancer [%s] type [%s] -> error [%s]", c.LoadBalancers[x].Name, c.LoadBalancers[x].Type, err)
// Stop all load balancers associated with the VIP
err = VipLB.StopAll()
if err != nil {
log.Warnf("%v", err)
}
err = cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
}
}
}
}
}
if c.EnableARP == true {
ctxArp, cancelArp = context.WithCancel(context.Background())
ipString := cluster.Network.IP()
var ndp *vip.NdpResponder
if vip.IsIPv6(ipString) {
ndp, err = vip.NewNDPResponder(c.Interface)
if err != nil {
log.Fatalf("failed to create new NDP Responder")
}
}
go func(ctx context.Context) {
if ndp != nil {
defer ndp.Close()
}
for {
select {
case <-ctx.Done(): // if cancel() execute
return
default:
if vip.IsIPv4(ipString) {
// Gratuitous ARP, will broadcast to new MAC <-> IP
err := vip.ARPSendGratuitous(ipString, c.Interface)
if err != nil {
log.Warnf("%v", err)
}
} else {
// Gratuitous NDP, will broadcast new MAC <-> IPv6 address
err := ndp.SendGratuitous(ipString)
if err != nil {
log.Warnf("%v", err)
}
}
}
time.Sleep(3 * time.Second)
}
}(ctxArp)
}
},
OnStoppedLeading: func() {
// we can do cleanup here
log.Info("This node is becoming a follower within the cluster")
// Stop the dns context
cancelDNS()
// Stop the Arp context if it is running
cancelArp()
// Stop the BGP server
if bgpServer != nil {
err = bgpServer.Close()
if err != nil {
log.Warnf("%v", err)
}
}
// Stop all load balancers associated with the VIP
err = VipLB.StopAll()
if err != nil {
log.Warnf("%v", err)
}
err = cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
}
log.Fatal("lost leadership, restarting kube-vip")
},
OnNewLeader: func(identity string) {
// we're notified when new leader elected
log.Infof("Node [%s] is assuming leadership of the cluster", identity)
if identity == id {
// We have the lock
}
},
},
})
return nil
}
// TODO - refactor an active machine func(), this will replace the singleNode code and have a single code block
// func (cluster *Cluster) active(c *kubevip.Config) error {
// // we're notified when we start
// log.Info("This node is starting with leadership of the cluster")
// // setup ddns first
// // for first time, need to wait until IP is allocated from DHCP
// if cluster.Network.IsDDNS() {
// if err := cluster.StartDDNS(ctxDns); err != nil {
// log.Error(err)
// }
// }
// // start the dns updater if address is dns
// if cluster.Network.IsDNS() {
// log.Infof("starting the DNS updater for the address %s", cluster.Network.DNSName())
// ipUpdater := vip.NewIPUpdater(cluster.Network)
// ipUpdater.Run(ctxDns)
// }
// err := cluster.Network.AddIP()
// if err != nil {
// log.Warnf("%v", err)
// }
// if c.EnablePacket {
// // We're not using Packet with BGP
// if !c.EnableBGP {
// // Attempt to attach the EIP in the standard manner
// log.Debugf("Attaching the Packet EIP through the API to this host")
// err = packet.AttachEIP(packetClient, c, id)
// if err != nil {
// log.Error(err)
// }
// }
// }
// 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.IP(), c.VIPCIDR)
// log.Debugf("Attempting to advertise the address [%s] over BGP", cidrVip)
// err = bgpServer.AddHost(cidrVip)
// if err != nil {
// log.Error(err)
// }
// }
// if c.EnableLoadBalancer {
// // Once we have the VIP running, start the load balancer(s) that bind to the VIP
// for x := range c.LoadBalancers {
// if c.LoadBalancers[x].BindToVip == true {
// err = VipLB.Add(cluster.Network.IP(), &c.LoadBalancers[x])
// if err != nil {
// log.Warnf("Error creating loadbalancer [%s] type [%s] -> error [%s]", c.LoadBalancers[x].Name, c.LoadBalancers[x].Type, err)
// // Stop all load balancers associated with the VIP
// err = VipLB.StopAll()
// if err != nil {
// log.Warnf("%v", err)
// }
// err = cluster.Network.DeleteIP()
// if err != nil {
// log.Warnf("%v", err)
// }
// }
// }
// }
// }
// if c.EnableARP == true {
// ctxArp, cancelArp = context.WithCancel(context.Background())
// go func(ctx context.Context) {
// for {
// select {
// case <-ctx.Done(): // if cancel() execute
// return
// default:
// // Gratuitous ARP, will broadcast to new MAC <-> IP
// err = vip.ARPSendGratuitous(cluster.Network.IP(), c.Interface)
// if err != nil {
// log.Warnf("%v", err)
// }
// }
// time.Sleep(3 * time.Second)
// }
// }(ctxArp)
// }
// }

View File

@@ -0,0 +1,451 @@
package cluster
import (
"context"
"fmt"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"github.com/davecgh/go-spew/spew"
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/etcd"
"github.com/kube-vip/kube-vip/pkg/k8s"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/loadbalancer"
"github.com/kube-vip/kube-vip/pkg/utils"
log "log/slog"
clientv3 "go.etcd.io/etcd/client/v3"
v1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/leaderelection"
"k8s.io/client-go/tools/leaderelection/resourcelock"
watchtools "k8s.io/client-go/tools/watch"
)
// Manager degines the manager of the load-balancing services
type Manager struct {
KubernetesClient *kubernetes.Clientset
RetryWatcherClient *kubernetes.Clientset
// This channel is used to signal a shutdown
SignalChan chan os.Signal
EtcdClient *clientv3.Client
}
// NewManager will create a new managing object
func NewManager(path string, inCluster bool, port int) (*Manager, error) {
var hostname string
// If inCluster is set then it will likely have started as a static pod or won't have the
// VIP up before trying to connect to the API server, we set the API endpoint to this machine to
// ensure connectivity. Else if the path passed is empty and not running in the cluster,
// attempt to look for a kubeconfig in the default HOME dir.
hostname = fmt.Sprintf("kubernetes:%v", port)
if len(path) == 0 && !inCluster {
path = filepath.Join(os.Getenv("HOME"), ".kube", "config")
// We modify the config so that we can always speak to the correct host
id, err := os.Hostname()
if err != nil {
return nil, err
}
hostname = fmt.Sprintf("%s:%v", id, port)
}
config, err := k8s.NewRestConfig(path, inCluster, hostname)
if err != nil {
return nil, fmt.Errorf("failed to create k8s REST config: %w", err)
}
clientset, err := k8s.NewClientset(config)
if err != nil {
return nil, fmt.Errorf("error creating a new k8s clientset: %v", err)
}
rwConfig, err := k8s.NewRestConfig(path, inCluster, hostname)
if err != nil {
return nil, fmt.Errorf("failed to create k8s REST config for retryClientSet: %w", err)
}
rwConfig.Timeout = 0 // empty value to disable the timeout
rwClientSet, err := k8s.NewClientset(rwConfig)
if err != nil {
return nil, fmt.Errorf("failed to create k8s client for retry watcher: %w", err)
}
return &Manager{
KubernetesClient: clientset,
RetryWatcherClient: rwClientSet,
}, nil
}
// StartCluster - Begins a running instance of the Leader Election cluster
func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *bgp.Server) error {
var err error
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
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// use a Go context so we can tell the arp loop code when we
// want to step down
ctxArp, cancelArp := context.WithCancel(context.Background())
defer cancelArp()
// use a Go context so we can tell the dns loop code when we
// want to step down
ctxDNS, cancelDNS := context.WithCancel(context.Background())
defer cancelDNS()
// listen for interrupts or the Linux SIGTERM signal and cancel
// our context, which the leader election code will observe and
// step down
signalChan := make(chan os.Signal, 1)
// Add Notification for Userland interrupt
signal.Notify(signalChan, syscall.SIGINT)
// Add Notification for SIGTERM (sent from Kubernetes)
signal.Notify(signalChan, syscall.SIGTERM)
go func() {
<-signalChan
log.Info("Received termination, signaling cluster shutdown")
// Cancel the context, which will in turn cancel the leadership
cancel()
// Cancel the arp context, which will in turn stop any broadcasts
}()
// (attempt to) Remove the virtual IP, in case it already exists
for i := range cluster.Network {
deleted, err := cluster.Network[i].DeleteIP()
if err != nil {
log.Error("could not delete virtualIP", "err", err)
}
if deleted {
log.Info("deleted address", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
}
// Defer a function to check if the bgpServer has been created and if so attempt to close it
defer func() {
if bgpServer != nil {
bgpServer.Close()
}
}()
if c.EnableBGP && bgpServer == nil {
// Lets start BGP
log.Info("Starting the BGP server to advertise VIP routes to VGP peers")
bgpServer, err = bgp.NewBGPServer(c.BGPConfig)
if err != nil {
log.Error("new BGP server", "err", err)
}
if err := bgpServer.Start(nil); err != nil {
log.Error("starting BGP server", "err", err)
}
}
run := &runConfig{
config: c,
leaseID: c.NodeName,
sm: sm,
onStartedLeading: func(ctx context.Context) { //nolint TODO: potential clean code
// When we become leader, ensure we can take over VIPs even if they're preserved on other nodes
if c.PreserveVIPOnLeadershipLoss {
log.Info("Becoming leader with VIP preservation enabled - ensuring VIP takeover")
// Force add the VIPs (this will work even if they exist due to the precheck logic)
for i := range cluster.Network {
added, err := cluster.Network[i].AddIP(true, false)
if err != nil {
log.Error("failed to ensure VIP on leader takeover", "vip", cluster.Network[i].IP(), "err", err)
} else if added {
log.Info("took over VIP as new leader", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
} else {
log.Info("VIP already configured on interface", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
}
}
// Start ARP advertisements now that we have leadership
log.Info("Start ARP/NDP advertisement")
go cluster.arpMgr.StartAdvertisement(ctxArp)
// As we're leading lets start the vip service
err := cluster.vipService(ctxArp, ctxDNS, c, sm, bgpServer, cancel)
if err != nil {
log.Error("starting VIP service on leader", "err", err)
}
},
onStoppedLeading: func() {
// we can do cleanup here
log.Info("This node is becoming a follower within the cluster")
// Stop the dns context
cancelDNS()
// Stop the Arp context if it is running
cancelArp()
// Stop the BGP server
if bgpServer != nil {
err := bgpServer.Close()
if err != nil {
log.Warn("close BGP server", "err", err)
}
}
// Handle VIP cleanup based on configuration
if c.PreserveVIPOnLeadershipLoss {
// For IPv6, we must remove VIPs immediately to avoid DAD failures on the new leader
// IPv6 Duplicate Address Detection will fail if the new leader tries to add an IP that is still present on this node's interface
// We need to check each VIP individually and only remove IPv6 VIPs
for i := range cluster.Network {
if utils.IsIPv6(cluster.Network[i].IP()) {
log.Info("Removing IPv6 VIP immediately (required to prevent DAD failures on new leader)", "ip", cluster.Network[i].IP())
deleted, err := cluster.Network[i].DeleteIP()
if err != nil {
log.Warn("delete VIP", "err", err)
}
if deleted {
log.Info("deleted address", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
} else {
log.Info("Preserving IPv4 VIP address on interface, only stopped ARP broadcasting", "ip", cluster.Network[i].IP())
}
}
} else {
// Legacy behavior: delete VIP addresses on leadership loss
log.Info("Deleting VIP addresses on leadership loss (legacy behavior)")
for i := range cluster.Network {
deleted, err := cluster.Network[i].DeleteIP()
if err != nil {
log.Warn("delete VIP", "err", err)
}
if deleted {
log.Info("deleted address", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
}
}
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.Info("New leader", "leader", identity)
// If we're not the new leader and we have VIPs preserved from previous leadership,
// we need to clean them up to avoid conflicts.
if identity != c.NodeName && c.PreserveVIPOnLeadershipLoss {
log.Info("Cleaning up preserved VIPs as another node became leader", "new_leader", identity)
for i := range cluster.Network {
deleted, err := cluster.Network[i].DeleteIP()
if err != nil {
log.Warn("failed to cleanup preserved VIP", "vip", cluster.Network[i].IP(), "err", err)
}
if deleted {
log.Info("cleaned up preserved VIP to avoid conflict", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface(), "new_leader", identity)
} else {
log.Debug("VIP was not present on this node", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
}
}
},
}
switch c.LeaderElectionType {
case "kubernetes", "":
cluster.runKubernetesLeaderElectionOrDie(ctx, run)
case "etcd":
cluster.runEtcdLeaderElectionOrDie(ctx, run)
default:
log.Info(fmt.Sprintf("LeaderElectionMode %s not supported, exiting", c.LeaderElectionType))
}
return nil
}
type runConfig struct {
config *kubevip.Config
leaseID string
sm *Manager
// onStartedLeading is called when this member starts leading.
onStartedLeading func(context.Context)
// onStoppedLeading is called when this member stops leading.
onStoppedLeading func()
// onNewLeader is called when the client observes a leader that is
// not the previously observed leader. This includes the first observed
// leader when the client starts.
onNewLeader func(identity string)
}
func (cluster *Cluster) runKubernetesLeaderElectionOrDie(ctx context.Context, run *runConfig) {
// 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{
LeaseMeta: metav1.ObjectMeta{
Name: run.config.LeaseName,
Namespace: run.config.Namespace,
Annotations: run.config.LeaseAnnotations,
},
Client: run.sm.KubernetesClient.CoordinationV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: run.leaseID,
},
}
// start the leader election code loop
leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{
Lock: lock,
// IMPORTANT: you MUST ensure that any code you have that
// is protected by the lease must terminate **before**
// you call cancel. Otherwise, you could have a background
// loop still running and another process could
// get elected before your background loop finished, violating
// the stated goal of the lease.
ReleaseOnCancel: true,
LeaseDuration: time.Duration(run.config.LeaseDuration) * time.Second,
RenewDeadline: time.Duration(run.config.RenewDeadline) * time.Second,
RetryPeriod: time.Duration(run.config.RetryPeriod) * time.Second,
Callbacks: leaderelection.LeaderCallbacks{
OnStartedLeading: run.onStartedLeading,
OnStoppedLeading: run.onStoppedLeading,
OnNewLeader: run.onNewLeader,
},
})
}
func (cluster *Cluster) runEtcdLeaderElectionOrDie(ctx context.Context, run *runConfig) {
etcd.RunElectionOrDie(ctx, &etcd.LeaderElectionConfig{
EtcdConfig: etcd.ClientConfig{Client: run.sm.EtcdClient},
Name: run.config.LeaseName,
MemberID: run.leaseID,
LeaseDurationSeconds: int64(run.config.LeaseDuration),
Callbacks: etcd.LeaderCallbacks{
OnStartedLeading: run.onStartedLeading,
OnStoppedLeading: run.onStoppedLeading,
OnNewLeader: run.onNewLeader,
},
})
}
func (sm *Manager) NodeWatcher(ctxArp context.Context, lb *loadbalancer.IPVSLoadBalancer, port uint16) error {
// Use a restartable watcher, as this should help in the event of etcd or timeout issues
log.Info("Kube-Vip is watching nodes for control-plane labels")
listOptions := metav1.ListOptions{
LabelSelector: "node-role.kubernetes.io/control-plane",
}
rw, err := watchtools.NewRetryWatcherWithContext(ctxArp, "1", &cache.ListWatch{
WatchFunc: func(_ metav1.ListOptions) (watch.Interface, error) {
return sm.RetryWatcherClient.CoreV1().Nodes().Watch(context.Background(), listOptions)
},
})
if err != nil {
return fmt.Errorf("error creating label watcher: %s", err.Error())
}
go func() {
<-sm.SignalChan
log.Info("Received termination, signaling shutdown")
// Cancel the context
rw.Stop()
}()
ch := rw.ResultChan()
// defer rw.Stop()
for event := range ch {
// We need to inspect the event and get ResourceVersion out of it
switch event.Type {
case watch.Added, watch.Modified:
node, ok := event.Object.(*v1.Node)
if !ok {
return fmt.Errorf("unable to parse Kubernetes Node from Annotation watcher")
}
// Find the node IP address (this isn't foolproof)
for x := range node.Status.Addresses {
if node.Status.Addresses[x].Type == v1.NodeInternalIP {
if checkIfNodeIsReady(node) {
err = lb.AddBackend(node.Status.Addresses[x].Address, port)
if err != nil {
log.Error("add IPVS backend", "err", err)
}
} else {
err = lb.RemoveBackend(node.Status.Addresses[x].Address, port)
if err != nil {
log.Error("remove IPVS backend", "err", err)
}
}
}
}
case watch.Deleted:
node, ok := event.Object.(*v1.Node)
if !ok {
return fmt.Errorf("unable to parse Kubernetes Node from Annotation watcher")
}
// Find the node IP address (this isn't foolproof)
for x := range node.Status.Addresses {
if node.Status.Addresses[x].Type == v1.NodeInternalIP {
err = lb.RemoveBackend(node.Status.Addresses[x].Address, port)
if err != nil {
log.Error("Del IPVS backend", "err", err)
}
}
}
log.Info("Node deleted", "name", node.Name)
case watch.Bookmark:
// Un-used
case watch.Error:
log.Error("Error attempting to watch Kubernetes Nodes")
// This round trip allows us to handle unstructured status
errObject := apierrors.FromObject(event.Object)
statusErr, ok := errObject.(*apierrors.StatusError)
if !ok {
log.Error(spew.Sprintf("Received an error which is not *metav1.Status but %#+v", event.Object))
}
status := statusErr.ErrStatus
log.Error("watcher", "status", status)
default:
}
}
log.Info("Exiting Node watcher")
return nil
}
func checkIfNodeIsReady(node *v1.Node) bool {
if node == nil {
return false
}
for _, condition := range node.Status.Conditions {
if condition.Type == v1.NodeReady {
if condition.Status == v1.ConditionTrue {
return true
}
}
}
return false
}

View File

@@ -1,296 +0,0 @@
package cluster
import (
"fmt"
"net"
"time"
"github.com/hashicorp/raft"
"github.com/plunder-app/kube-vip/pkg/kubevip"
"github.com/plunder-app/kube-vip/pkg/loadbalancer"
"github.com/plunder-app/kube-vip/pkg/vip"
log "github.com/sirupsen/logrus"
)
// StartRaftCluster - Begins a running instance of the Raft cluster
func (cluster *Cluster) StartRaftCluster(c *kubevip.Config) error {
// Create local configuration address
localAddress := fmt.Sprintf("%s:%d", c.LocalPeer.Address, c.LocalPeer.Port)
// Begin the Raft configuration
config := raft.DefaultConfig()
config.LocalID = raft.ServerID(c.LocalPeer.ID)
logger := log.StandardLogger().Writer()
config.LogOutput = logger
// Initialize communication
address, err := net.ResolveTCPAddr("tcp", localAddress)
if err != nil {
return err
}
// Create transport
transport, err := raft.NewTCPTransport(localAddress, address, 3, 10*time.Second, logger)
if err != nil {
return err
}
// Create Raft structures
snapshots := raft.NewInmemSnapshotStore()
logStore := raft.NewInmemStore()
stableStore := raft.NewInmemStore()
// Cluster configuration
configuration := raft.Configuration{}
// Add Local Peer
configuration.Servers = append(configuration.Servers, raft.Server{
ID: raft.ServerID(c.LocalPeer.ID),
Address: raft.ServerAddress(fmt.Sprintf("%s:%d", c.LocalPeer.Address, c.LocalPeer.Port))})
// If we want to start a node as leader then we will not add any remote peers, this will leave this as a cluster of one
// The remotePeers will add themselves to the cluster as they're added
if c.StartAsLeader != true {
for x := range c.RemotePeers {
// Make sure that we don't add in this server twice
if c.LocalPeer.Address != c.RemotePeers[x].Address {
// Build the address from the peer configuration
peerAddress := fmt.Sprintf("%s:%d", c.RemotePeers[x].Address, c.RemotePeers[x].Port)
// Set this peer into the raft configuration
configuration.Servers = append(configuration.Servers, raft.Server{
ID: raft.ServerID(c.RemotePeers[x].ID),
Address: raft.ServerAddress(peerAddress)})
}
}
log.Info("This node will attempt to start as Follower")
} else {
log.Info("This node will attempt to start as Leader")
}
// Bootstrap cluster
if err := raft.BootstrapCluster(config, logStore, stableStore, snapshots, transport, configuration); err != nil {
return err
}
// Create RAFT instance
raftServer, err := raft.NewRaft(config, cluster.stateMachine, logStore, stableStore, snapshots, transport)
if err != nil {
return err
}
cluster.stop = make(chan bool, 1)
cluster.completed = make(chan bool, 1)
ticker := time.NewTicker(time.Second)
isLeader := c.StartAsLeader
// (attempt to) Remove the virtual IP, incase it already exists
cluster.Network.DeleteIP()
// leader log broadcast - this counter is used to stop flooding STDOUT with leader log entries
var leaderbroadcast int
// Managers for Vip load balancers and none-vip loadbalancers
nonVipLB := loadbalancer.LBManager{}
VipLB := loadbalancer.LBManager{}
// Iterate through all Configurations
for x := range c.LoadBalancers {
// If the load balancer doesn't bind to the VIP
if c.LoadBalancers[x].BindToVip == false {
err = nonVipLB.Add("", &c.LoadBalancers[x])
if err != nil {
log.Warnf("Error creating loadbalancer [%s] type [%s] -> error [%s]", c.LoadBalancers[x].Name, c.LoadBalancers[x].Type, err)
}
}
}
// On a cold start the node will sleep for 5 seconds to ensure that leader elections are complete
log.Infoln("This instance will wait approximately 5 seconds, from cold start to ensure cluster elections are complete")
time.Sleep(time.Second * 5)
go func() {
for {
if c.AddPeersAsBackends == true {
// Get addresses and change backends
// c.LoadBalancers[0].Backends
// for x := range raftServer.GetConfiguration().Configuration().Servers {
// raftServer.GetConfiguration().Configuration().Servers[x].Address
// }
}
// Broadcast the current leader on this node if it's the correct time (every leaderLogcount * time.Second)
if leaderbroadcast == leaderLogcount {
log.Infof("The Node [%s] is leading", raftServer.Leader())
// Reset the timer
leaderbroadcast = 0
// ensure that if this node is the leader, it is set as the leader
if localAddress == string(raftServer.Leader()) {
// Re-broadcast arp to ensure network stays up to date
if c.EnableARP == true {
// Gratuitous ARP, will broadcast to new MAC <-> IP
err = vip.ARPSendGratuitous(cluster.Network.IP(), c.Interface)
if err != nil {
log.Warnf("%v", err)
}
}
if !isLeader {
log.Infoln("This node is leading, but isnt the leader (correcting)")
isLeader = true
}
} else {
// (attempt to) Remove the virtual IP, incase it already exists to keep nodes clean
cluster.Network.DeleteIP()
isLeader = false
}
}
leaderbroadcast++
select {
case leader := <-raftServer.LeaderCh():
log.Infoln("New Election event")
if leader {
isLeader = true
log.Info("This node is assuming leadership of the cluster")
err = cluster.Network.AddIP()
if err != nil {
log.Warnf("%v", err)
}
// Once we have the VIP running, start the load balancer(s) that bind to the VIP
for x := range c.LoadBalancers {
if c.LoadBalancers[x].BindToVip == true {
err = VipLB.Add(cluster.Network.IP(), &c.LoadBalancers[x])
if err != nil {
log.Warnf("Error creating loadbalancer [%s] type [%s] -> error [%s]", c.LoadBalancers[x].Name, c.LoadBalancers[x].Type, err)
log.Errorf("Dropping Leadership to another node in the cluster")
raftServer.LeadershipTransfer()
// Stop all load balancers associated with the VIP
err = VipLB.StopAll()
if err != nil {
log.Warnf("%v", err)
}
err = cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
}
}
}
}
if c.EnableARP == true {
// Gratuitous ARP, will broadcast to new MAC <-> IP
err = vip.ARPSendGratuitous(cluster.Network.IP(), c.Interface)
if err != nil {
log.Warnf("%v", err)
}
}
} else {
isLeader = false
log.Info("This node is becoming a follower within the cluster")
// Stop all load balancers associated with the VIP
err = VipLB.StopAll()
if err != nil {
log.Warnf("%v", err)
}
err = cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
}
}
case <-ticker.C:
if isLeader {
result, err := cluster.Network.IsSet()
if err != nil {
log.WithFields(log.Fields{"error": err, "ip": cluster.Network.IP(), "interface": cluster.Network.Interface()}).Error("Could not check ip")
}
if result == false {
log.Error("This node is leader and is adopting the virtual IP")
err = cluster.Network.AddIP()
if err != nil {
log.Warnf("%v", err)
}
// Once we have the VIP running, start the load balancer(s) that bind to the VIP
for x := range c.LoadBalancers {
if c.LoadBalancers[x].BindToVip == true {
err = VipLB.Add(cluster.Network.IP(), &c.LoadBalancers[x])
if err != nil {
log.Warnf("Error creating loadbalancer [%s] type [%s] -> error [%s]", c.LoadBalancers[x].Name, c.LoadBalancers[x].Type, err)
}
}
}
if c.EnableARP == true {
// Gratuitous ARP, will broadcast to new MAC <-> IP
err = vip.ARPSendGratuitous(cluster.Network.IP(), c.Interface)
if err != nil {
log.Warnf("%v", err)
}
}
}
}
case <-cluster.stop:
log.Info("[RAFT] Stopping this node")
log.Info("[LOADBALANCER] Stopping load balancers")
// Stop all load balancers associated with the VIP
err = VipLB.StopAll()
if err != nil {
log.Warnf("%v", err)
}
// Stop all load balancers associated with the Host
err = nonVipLB.StopAll()
if err != nil {
log.Warnf("%v", err)
}
if isLeader {
log.Info("[VIP] Releasing the Virtual IP")
err = cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
}
}
close(cluster.completed)
return
}
}
}()
log.Info("Started")
return nil
}
// Stop - Will stop the Cluster and release VIP if needed
func (cluster *Cluster) Stop() {
// Close the stop chanel, which will shut down the VIP (if needed)
close(cluster.stop)
// Wait until the completed channel is closed, signallign all shutdown tasks completed
<-cluster.completed
log.Info("Stopped")
}

418
pkg/cluster/service.go Normal file
View File

@@ -0,0 +1,418 @@
package cluster
import (
"context"
"errors"
"fmt"
"io/fs"
"net"
"os"
"os/signal"
"sync"
"syscall"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/arp"
"github.com/kube-vip/kube-vip/pkg/backend"
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/loadbalancer"
"github.com/kube-vip/kube-vip/pkg/utils"
"github.com/kube-vip/kube-vip/pkg/vip"
"github.com/vishvananda/netlink"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Config, sm *Manager, bgpServer *bgp.Server, cancelLeaderElection context.CancelFunc) error {
var err error
// listen for interrupts or the Linux SIGTERM signal and cancel
// our context, which the leader election code will observe and
// step down
signalChan := make(chan os.Signal, 1)
// Add Notification for Userland interrupt
signal.Notify(signalChan, syscall.SIGINT)
// Add Notification for SIGTERM (sent from Kubernetes)
signal.Notify(signalChan, syscall.SIGTERM)
loadbalancers := []*loadbalancer.IPVSLoadBalancer{}
var arpWG sync.WaitGroup
for i := range cluster.Network {
network := cluster.Network[i]
if network.IsDDNS() {
if err := cluster.StartDDNS(ctxDNS, cluster.Network[i]); err != nil {
log.Error("failed to start DDNS", "err", err)
}
}
if err := network.SetMask(c.VIPSubnet); err != nil {
log.Error("failed to set mask", "subnet", c.VIPSubnet, "err", err)
panic("")
}
// start the dns updater if address is dns
if network.IsDNS() {
log.Info("starting the DNS updater", "address", network.DNSName())
ipUpdater := vip.NewIPUpdater(network)
ipUpdater.Run(ctxDNS)
}
if !c.EnableRoutingTable {
// Normal VIP addition, use skipDAD=false for normal DAD process
if _, err = network.AddIP(false, false); err != nil {
log.Error(err.Error())
}
}
if c.EnableBGP {
// Lets advertise the VIP over BGP, the host needs to be passed using CIDR notation
log.Debug("Attempting to advertise over BGP", "address", network.CIDR())
err = bgpServer.AddHost(network.CIDR())
if err != nil {
log.Error(err.Error())
}
}
if c.EnableLoadBalancer {
lb, err := loadbalancer.NewIPVSLB(network.IP(), c.LoadBalancerPort, c.LoadBalancerForwardingMethod, c.BackendHealthCheckInterval, c.Interface, cancelLeaderElection, signalChan)
if err != nil {
log.Error("Error creating IPVS LoadBalancer", "err", err)
}
go func() {
err = sm.NodeWatcher(ctxArp, lb, c.Port) //TODO: We're using the ctxARP as the context this will change when rkatz finishes his change
if err != nil {
log.Error("Error watching node labels", "err", err)
}
}()
loadbalancers = append(loadbalancers, lb)
}
if c.EnableARP {
arpWG.Add(1)
go cluster.layer2Update(ctxArp, network, c, &arpWG)
}
}
if c.EnableLoadBalancer {
// Shutdown function that will wait on this signal, unless we call it ourselves
<-signalChan
for _, lb := range loadbalancers {
err = lb.RemoveIPVSLB()
if err != nil {
log.Error("Error stopping IPVS LoadBalancer", "err", err)
}
}
}
if c.EnableRoutingTable {
backendMapV4 := backend.Map{}
backendMapV6 := backend.Map{}
// only check localhost
nodename := ""
if c.NodeName != "" {
nodename = c.NodeName
} else {
nodename = os.Getenv("HOSTNAME")
}
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 nod", "err", err)
}
}
if len(ips) == 0 {
isV6, err := isV6(cluster.Network[0].IP())
if err != nil {
return fmt.Errorf("failed to parse IP '%s'", cluster.Network[0].IP())
}
if !isV6 {
ips = append(ips, "127.0.0.1")
} else {
ips = append(ips, "::1")
}
log.Info("no IP address found for node - will fallback to use localhost address", "addresses", ips)
}
for _, ip := range ips {
entry := backend.Entry{Addr: ip, Port: c.Port}
ipv6, err := isV6(ip)
if err != nil {
log.Error("failed to check IP type", "IP", ip, "error", err)
}
if !ipv6 {
backendMapV4[entry] = false
} else {
backendMapV6[entry] = false
}
}
stop := make(chan struct{})
// will wait for system interrupt and will send stop signal to backend watch
go func() {
<-signalChan
stop <- struct{}{}
}()
backend.Watch(func() {
for i := range cluster.Network {
network := cluster.Network[i]
networkIP := network.IP()
isNetworkV6, err := isV6(networkIP)
if err != nil {
log.Error("failed to check IP type", "IP", networkIP, "error", err)
continue
}
log.Debug("current ip to process", "ip", networkIP)
backendMap := &backendMapV4
if isNetworkV6 {
backendMap = &backendMapV6
}
for entry := range *backendMap {
log.Debug("entry.Check() for entry", "entry", entry)
if entry.Check() {
log.Debug("entry.Check() true")
// Normal VIP addition with precheck, use skipDAD=false for normal DAD process
_, err = network.AddIP(true, false)
if err != nil {
log.Error("error adding address", "err", err)
}
if !(*backendMap)[entry] {
log.Info("added backend", "ip", network.IP())
}
err = network.AddRoute(true)
if err != nil && !errors.Is(err, fs.ErrExist) && !errors.Is(err, syscall.ESRCH) {
log.Warn(err.Error())
} else if err == nil && !(*backendMap)[entry] {
log.Info("added route", "route", network.PrepareRoute().String())
}
(*backendMap)[entry] = true
break
}
(*backendMap)[entry] = false
}
deleteAddress := true
for entry := range *backendMap {
if (*backendMap)[entry] {
deleteAddress = false
break
}
}
if deleteAddress {
err = network.DeleteRoute()
if err != nil && !errors.Is(err, fs.ErrNotExist) && !errors.Is(err, syscall.ESRCH) {
log.Warn("deleting route", "err", err)
} else if err == nil {
log.Info("deleted route", "route", network.PrepareRoute().String())
}
deleted, err := network.DeleteIP()
if err != nil {
log.Error("error deleting IP", "err", err)
panic("")
}
if deleted {
log.Info("deleted address", "IP", network.IP(), "interface", network.Interface())
}
}
}
}, c.BackendHealthCheckInterval, stop)
}
return nil
}
func isV6(ip string) (bool, error) {
ipaddr := net.ParseIP(ip)
if ipaddr == nil {
return false, fmt.Errorf("failed to parse IP '%s'", ip)
}
return ipaddr.To4() == nil, nil
}
func getNodeIPs(ctx context.Context, nodename string, client *kubernetes.Clientset) ([]string, error) {
node, err := client.CoreV1().Nodes().Get(ctx, nodename, metav1.GetOptions{})
if err != nil && !apierrors.IsNotFound(err) {
return []string{}, fmt.Errorf("failed to get data about '%s' node: %w", nodename, err)
}
ips := []string{}
for _, addr := range node.Status.Addresses {
if addr.Type == corev1.NodeInternalIP {
ips = append(ips, addr.Address)
}
}
return ips, nil
}
// StartLoadBalancerService will start a VIP instance and leave it for kube-proxy to handle
func (cluster *Cluster) StartLoadBalancerService(ctx context.Context, c *kubevip.Config, bgp *bgp.Server, name string, CountRouteReferences func(*netlink.Route) int) {
// use a Go context so we can tell the arp loop code when we
// want to step down
//nolint
ctxArp, cancelArp := context.WithCancel(ctx)
cluster.stop = make(chan bool, 1)
cluster.completed = make(chan bool, 1)
var arpWG sync.WaitGroup
log.Debug("StartLoadBalancerService")
for i := range cluster.Network {
network := cluster.Network[i]
log.Debug("current ip to process", "ip", network.IP(), "mask", c.VIPSubnet)
if err := network.SetMask(c.VIPSubnet); err != nil {
log.Error("failed to set mask", "subnet", c.VIPSubnet, "err", err)
panic("")
}
_, err := network.DeleteIP()
if err != nil {
log.Warn("attempted to clean existing VIP", "err", err)
}
log.Debug("config flags", "enable_routing_table", c.EnableRoutingTable, "enable_leader_election", c.EnableLeaderElection, "enable_services_election", c.EnableServicesElection)
if c.EnableRoutingTable && (c.EnableLeaderElection || c.EnableServicesElection) {
err = network.AddRoute(false)
if err != nil {
log.Warn(err.Error())
} else {
log.Info("successful add Route")
}
}
// Normal VIP addition, use skipDAD=false for normal DAD process
if _, err = network.AddIP(false, false); err != nil {
log.Warn(err.Error())
} else {
log.Info("successful add IP")
}
if c.EnableARP {
arpWG.Add(1)
go cluster.layer2Update(ctxArp, network, c, &arpWG)
}
if c.EnableBGP && (c.EnableLeaderElection || c.EnableServicesElection) {
// Lets advertise the VIP over BGP, the host needs to be passed using CIDR notation
log.Debug("(svcs) attempting to advertise over BGP", "address", network.CIDR())
err = bgp.AddHost(network.CIDR())
if err != nil {
log.Error(err.Error())
}
}
}
go func() {
<-cluster.stop
// Stop the Arp context if it is running
cancelArp()
arpWG.Wait() // wait for all cluster ARP/NDP to be finished
log.Info("[LOADBALANCER] Stopping load balancers", "name", name)
if c.EnableRoutingTable {
for i := range cluster.Network {
// chek if route is not referenced by another service
r := cluster.Network[i].PrepareRoute()
if CountRouteReferences(r) < 1 {
log.Info("[VIP] Deleting Route for VIP", "IP", cluster.Network[i].IP())
if err := cluster.Network[i].DeleteRoute(); err != nil {
log.Warn(err.Error())
}
}
}
close(cluster.completed)
return
}
for i := range cluster.Network {
if c.EnableARP && cluster.arpMgr.Count(cluster.Network[i].ARPName()) > 1 {
continue
}
// Handle VIP cleanup based on configuration
if c.PreserveVIPOnLeadershipLoss {
// For IPv6, we must remove VIPs immediately to avoid DAD failures on the new leader
// IPv6 Duplicate Address Detection will fail if the new leader tries to add an IP
// that is still present on this node's interface
if utils.IsIPv6(cluster.Network[i].IP()) {
log.Info("[VIP] Removing IPv6 VIP immediately (required to prevent DAD failures on new leader)", "ip", cluster.Network[i].IP())
deleted, err := cluster.Network[i].DeleteIP()
if err != nil {
log.Warn(err.Error())
}
if deleted {
log.Info("deleted address", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
} else {
log.Info("[VIP] Preserving IPv4 VIP address on interface, only stopped ARP broadcasting", "ip", cluster.Network[i].IP())
}
} else {
// Legacy behavior: delete VIP addresses on leadership loss
log.Info("[VIP] Deleting VIP", "ip", cluster.Network[i].IP())
deleted, err := cluster.Network[i].DeleteIP()
if err != nil {
log.Warn(err.Error())
}
if deleted {
log.Info("deleted address", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
}
}
close(cluster.completed)
}()
}
// Layer2Update, handles the creation of the
func (cluster *Cluster) layer2Update(ctx context.Context, network vip.Network, c *kubevip.Config, arpWG *sync.WaitGroup) {
defer arpWG.Done()
log.Info("layer 2 broadcaster starting")
var ndp *vip.NdpResponder
var err error
ipString := network.IP()
if utils.IsIPv6(ipString) {
if network.IPisLinkLocal() {
log.Error("layer2 is link-local can't use NDP", "address", ipString)
} else {
ndp, err = vip.NewNDPResponder(network.Interface())
if err != nil {
log.Error("failed to create new NDP Responder", "error", err)
} else {
if ndp != nil {
defer ndp.Close()
}
}
}
}
log.Debug("layer 2 update", "ip", ipString, "interface", network.Interface(), "ms", c.ArpBroadcastRate)
arpInstance := arp.NewInstance(network, ndp)
cluster.arpMgr.Insert(arpInstance)
<-ctx.Done() // if cancel() execute
log.Debug("ending layer 2 update", "ip", ipString, "interface", network.Interface(), "ms", c.ArpBroadcastRate)
cluster.arpMgr.RemoveOnLeadershipLoss(arpInstance)
}

View File

@@ -1,161 +1,85 @@
package cluster
import (
"fmt"
"context"
log "github.com/sirupsen/logrus"
log "log/slog"
"github.com/plunder-app/kube-vip/pkg/bgp"
"github.com/plunder-app/kube-vip/pkg/kubevip"
"github.com/plunder-app/kube-vip/pkg/loadbalancer"
"github.com/plunder-app/kube-vip/pkg/vip"
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/vip"
)
// StartSingleNode will start a single node cluster
func (cluster *Cluster) StartSingleNode(c *kubevip.Config, disableVIP bool) error {
// Start kube-vip as a single node server
// TODO - Split all this code out as a seperate function
log.Infoln("Starting kube-vip as a single node cluster")
// TODO - Split all this code out as a separate function
log.Info("Starting kube-vip as a single node cluster")
log.Info("This node is assuming leadership of the cluster")
cluster.stop = make(chan bool, 1)
cluster.completed = make(chan bool, 1)
// Managers for Vip load balancers and none-vip loadbalancers
nonVipLB := loadbalancer.LBManager{}
VipLB := loadbalancer.LBManager{}
// Iterate through all Configurations
for x := range c.LoadBalancers {
// If the load balancer doesn't bind to the VIP
if c.LoadBalancers[x].BindToVip == false {
err := nonVipLB.Add("", &c.LoadBalancers[x])
for i := range cluster.Network {
if !disableVIP {
deleted, err := cluster.Network[i].DeleteIP()
if err != nil {
log.Warnf("Error creating loadbalancer [%s] type [%s] -> error [%s]", c.LoadBalancers[x].Name, c.LoadBalancers[x].Type, err)
log.Warn("Attempted to clean existing VIP", "err", err)
}
if deleted {
log.Info("deleted address", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
// Normal VIP addition for single node, use skipDAD=false for normal DAD process
_, err = cluster.Network[i].AddIP(false, false)
if err != nil {
log.Warn(err.Error())
}
}
}
if !disableVIP {
err := cluster.Network.DeleteIP()
if err != nil {
log.Warnf("Attempted to clean existing VIP => %v", err)
}
err = cluster.Network.AddIP()
if err != nil {
log.Warnf("%v", err)
}
// Once we have the VIP running, start the load balancer(s) that bind to the VIP
for x := range c.LoadBalancers {
if c.LoadBalancers[x].BindToVip == true {
err = VipLB.Add(cluster.Network.IP(), &c.LoadBalancers[x])
if err != nil {
log.Warnf("Error creating loadbalancer [%s] type [%s] -> error [%s]", c.LoadBalancers[x].Name, c.LoadBalancers[x].Type, err)
}
if c.EnableARP {
// Gratuitous ARP, will broadcast to new MAC <-> IP
err := vip.ARPSendGratuitous(cluster.Network[i].IP(), c.Interface)
if err != nil {
log.Warn(err.Error())
}
}
}
if c.EnableARP == true {
// Gratuitous ARP, will broadcast to new MAC <-> IP
err := vip.ARPSendGratuitous(cluster.Network.IP(), c.Interface)
if err != nil {
log.Warnf("%v", err)
}
}
go func() {
for {
select {
case <-cluster.stop:
log.Info("[LOADBALANCER] Stopping load balancers")
<-cluster.stop
// Stop all load balancers associated with the VIP
err := VipLB.StopAll()
if !disableVIP {
for i := range cluster.Network {
log.Info("[VIP] Releasing the VIP", "address", cluster.Network[i].IP())
deleted, err := cluster.Network[i].DeleteIP()
if err != nil {
log.Warnf("%v", err)
log.Warn(err.Error())
}
// Stop all load balancers associated with the Host
err = nonVipLB.StopAll()
if err != nil {
log.Warnf("%v", err)
if deleted {
log.Info("deleted address", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
if !disableVIP {
log.Info("[VIP] Releasing the Virtual IP")
err = cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
}
}
close(cluster.completed)
return
}
}
close(cluster.completed)
}()
log.Infoln("Started Load Balancer and Virtual IP")
log.Info("Started Load Balancer and Virtual IP")
return nil
}
// StartLoadBalancerService will start a VIP instance and leave it for kube-proxy to handle
func (cluster *Cluster) StartLoadBalancerService(c *kubevip.Config, bgp *bgp.Server) error {
// Start a kube-vip loadbalancer service
log.Infof("Starting advertising address [%s] with kube-vip", c.VIP)
func (cluster *Cluster) StartVipService(c *kubevip.Config, sm *Manager, bgp *bgp.Server) error {
// use a Go context so we can tell the arp loop code when we
// want to step down
ctxArp, cancelArp := context.WithCancel(context.Background())
defer cancelArp()
cluster.stop = make(chan bool, 1)
cluster.completed = make(chan bool, 1)
// use a Go context so we can tell the dns loop code when we
// want to step down
ctxDNS, cancelDNS := context.WithCancel(context.Background())
defer cancelDNS()
err := cluster.Network.DeleteIP()
if err != nil {
log.Warnf("Attempted to clean existing VIP => %v", err)
}
err = cluster.Network.AddIP()
if err != nil {
log.Warnf("%v", err)
}
if c.EnableARP == true {
// Gratuitous ARP, will broadcast to new MAC <-> IP
err := vip.ARPSendGratuitous(cluster.Network.IP(), c.Interface)
if err != nil {
log.Warnf("%v", err)
}
}
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.IP(), c.VIPCIDR)
log.Debugf("Attempting to advertise the address [%s] over BGP", cidrVip)
err = bgp.AddHost(cidrVip)
if err != nil {
log.Error(err)
}
}
go func() {
for {
select {
case <-cluster.stop:
log.Info("[LOADBALANCER] Stopping load balancers")
log.Info("[VIP] Releasing the Virtual IP")
err = cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
}
close(cluster.completed)
return
}
}
}()
log.Infoln("Started Load Balancer and Virtual IP")
return nil
return cluster.vipService(ctxArp, ctxDNS, c, sm, bgp, nil)
}

View File

@@ -1,39 +0,0 @@
package cluster
import (
"io"
"github.com/hashicorp/raft"
)
// FSM - Finite State Machine for Raft
type FSM struct {
}
// Apply - TODO
func (fsm FSM) Apply(log *raft.Log) interface{} {
return nil
}
// Restore - TODO
func (fsm FSM) Restore(snap io.ReadCloser) error {
return nil
}
// Snapshot - TODO, returns an empty snapshot
func (fsm FSM) Snapshot() (raft.FSMSnapshot, error) {
return Snapshot{}, nil
}
// Snapshot -
type Snapshot struct {
}
// Persist -
func (snapshot Snapshot) Persist(sink raft.SnapshotSink) error {
return nil
}
// Release -
func (snapshot Snapshot) Release() {
}

100
pkg/egress/egress.go Normal file
View File

@@ -0,0 +1,100 @@
package egress
import (
"fmt"
"strings"
"github.com/kube-vip/kube-vip/pkg/iptables"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/nftables"
"github.com/kube-vip/kube-vip/pkg/utils"
"github.com/kube-vip/kube-vip/pkg/vip"
)
func Teardown(podIP, vipIP, namespace, serviceUUID string, annotations map[string]string, useNftables bool) error {
// Look up the destination ports from the annotations on the service
destinationPorts := annotations[kubevip.EgressDestinationPorts]
deniedNetworks := annotations[kubevip.EgressDeniedNetworks]
allowedNetworks := annotations[kubevip.EgressAllowedNetworks]
internalEgress := annotations[kubevip.EgressInternal]
protocol := iptables.ProtocolIPv4
IPv6 := false
if utils.IsIPv6(podIP) {
protocol = iptables.ProtocolIPv6
IPv6 = true
}
// Use the internal egress implementation
if internalEgress != "" {
return nftables.DeleteSNAT(IPv6, serviceUUID)
}
i, err := vip.CreateIptablesClient(useNftables, namespace, protocol)
if err != nil {
return fmt.Errorf("error Creating iptables client [%s]", err)
}
if deniedNetworks != "" {
networks := strings.Split(deniedNetworks, ",")
for x := range networks {
err = i.DeleteMangleReturnForNetwork(vip.MangleChainName, networks[x])
if err != nil {
return fmt.Errorf("error deleting rules in mangle chain [%s], error [%s]", vip.MangleChainName, err)
}
}
}
if allowedNetworks != "" {
networks := strings.Split(allowedNetworks, ",")
for x := range networks {
err = i.DeleteMangleMarkingForNetwork(podIP, vip.MangleChainName, networks[x])
if err != nil {
return fmt.Errorf("error deleting rules in mangle chain [%s], error [%s]", vip.MangleChainName, err)
}
}
} else {
// Remove the marking of egress packets
err = i.DeleteMangleMarking(podIP, vip.MangleChainName)
if err != nil {
return fmt.Errorf("error changing iptables rules for egress [%s]", err)
}
}
// Clear up SNAT rules
if destinationPorts != "" {
fixedPorts := strings.Split(destinationPorts, ",")
for _, fixedPort := range fixedPorts {
var proto, port string
data := strings.Split(fixedPort, ":")
if len(data) == 0 {
continue
} else if len(data) == 1 {
proto = "tcp"
port = data[0]
} else {
proto = data[0]
port = data[1]
}
err = i.DeleteSourceNatForDestinationPort(podIP, vipIP, port, proto)
if err != nil {
return fmt.Errorf("error changing iptables rules for egress [%s]", err)
}
}
} else {
err = i.DeleteSourceNat(podIP, vipIP)
if err != nil {
return fmt.Errorf("error changing iptables rules for egress [%s]", err)
}
}
err = vip.DeleteExistingSessions(podIP, false, destinationPorts, "")
if err != nil {
return fmt.Errorf("error changing iptables rules for egress [%s]", err)
}
return nil
}

165
pkg/endpoints/endpoints.go Normal file
View File

@@ -0,0 +1,165 @@
package endpoints
import (
"context"
"fmt"
"net"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/endpoints/providers"
"github.com/kube-vip/kube-vip/pkg/instance"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/servicecontext"
v1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
"k8s.io/apimachinery/pkg/watch"
)
type Processor struct {
config *kubevip.Config
provider providers.Provider
bgpServer *bgp.Server
worker endpointWorker
instances *[]*instance.Instance
}
func NewEndpointProcessor(config *kubevip.Config, provider providers.Provider, bgpServer *bgp.Server,
instances *[]*instance.Instance) *Processor {
return &Processor{
config: config,
provider: provider,
bgpServer: bgpServer,
instances: instances,
worker: newEndpointWorker(config, provider, bgpServer, instances),
}
}
func (p *Processor) AddOrModify(ctx *servicecontext.Context, event watch.Event,
lastKnownGoodEndpoint *string, service *v1.Service, id string, leaderElectionActive *bool,
serviceFunc func(context.Context, *v1.Service) error,
leaderCtx *context.Context, cancel *context.CancelFunc) (bool, error) {
var err error
if err = p.provider.LoadObject(event.Object, *cancel); err != nil {
return false, fmt.Errorf("[%s] error loading k8s object: %w", p.provider.GetLabel(), err)
}
endpoints, err := p.worker.getEndpoints(service, id)
if err != nil {
return false, err
}
if err := p.worker.setInstanceEndpointsStatus(service, endpoints); err != nil {
log.Error("updating instance", "err", err)
}
// Find out if we have any local endpoints
// if out endpoint is empty then populate it
// if not, go through the endpoints and see if ours still exists
// If we have a local endpoint then begin the leader Election, unless it's already running
//
// Check that we have local endpoints
if len(endpoints) != 0 {
// Ignore IPv4
if service.Annotations[kubevip.EgressIPv6] == "true" && net.ParseIP(endpoints[0]).To4() != nil {
return true, nil
}
p.updateLastKnownGoodEndpoint(lastKnownGoodEndpoint, endpoints, service, leaderElectionActive, *cancel)
// start leader election if it's enabled and not already started
if !*leaderElectionActive && p.config.EnableServicesElection {
go func() {
*leaderCtx, *cancel = context.WithCancel(ctx.Ctx)
startLeaderElection(*leaderCtx, leaderElectionActive, service, serviceFunc)
}()
}
// There are local endpoints available on the node
if !p.config.EnableServicesElection && !p.config.EnableLeaderElection {
if err := p.worker.processInstance(ctx, service, leaderElectionActive); err != nil {
return false, fmt.Errorf("failed to process non-empty instance: %w", err)
}
}
} else {
// There are no local endpoints
p.worker.clear(ctx, lastKnownGoodEndpoint, service, *cancel, leaderElectionActive)
}
// Set the service accordingly
p.updateAnnotations(service, lastKnownGoodEndpoint)
log.Debug("watcher", "provider",
p.provider.GetLabel(), "service name", service.Name, "namespace", service.Namespace, "endpoints", len(endpoints), "last endpoint", *lastKnownGoodEndpoint, "active leader election", *leaderElectionActive)
return false, nil
}
func (p *Processor) Delete(service *v1.Service, id string) error {
if err := p.worker.delete(service, id); err != nil {
return fmt.Errorf("[%s] error deleting service: %w", p.provider.GetLabel(), err)
}
return nil
}
func (p *Processor) updateLastKnownGoodEndpoint(lastKnownGoodEndpoint *string, endpoints []string, service *v1.Service, leaderElectionActive *bool, cancel context.CancelFunc) {
// if we haven't populated one, then do so
if *lastKnownGoodEndpoint == "" {
*lastKnownGoodEndpoint = endpoints[0]
return
}
// check out previous endpoint exists
stillExists := false
for x := range endpoints {
if endpoints[x] == *lastKnownGoodEndpoint {
stillExists = true
}
}
// If the last endpoint no longer exists, we cancel our leader Election, and set another endpoint as last known good
if !stillExists {
p.worker.removeEgress(service, lastKnownGoodEndpoint)
if *leaderElectionActive && (p.config.EnableServicesElection || p.config.EnableLeaderElection) {
log.Warn("existing endpoint has been removed, restarting leaderElection", "provider", p.provider.GetLabel(), "endpoint", *lastKnownGoodEndpoint)
// Stop the existing leaderElection
cancel()
// disable last leaderElection flag
*leaderElectionActive = false
}
// Set our active endpoint to an existing one
*lastKnownGoodEndpoint = endpoints[0]
}
}
func (p *Processor) updateAnnotations(service *v1.Service, lastKnownGoodEndpoint *string) {
// Set the service accordingly
if service.Annotations[kubevip.Egress] == "true" {
activeEndpointAnnotation := kubevip.ActiveEndpoint
if !p.config.EnableEndpoints && p.provider.GetProtocol() == string(discoveryv1.AddressTypeIPv6) {
activeEndpointAnnotation = kubevip.ActiveEndpointIPv6
}
service.Annotations[activeEndpointAnnotation] = *lastKnownGoodEndpoint
}
}
func startLeaderElection(ctx context.Context, leaderElectionActive *bool, service *v1.Service, serviceFunc func(context.Context, *v1.Service) error) {
// This is a blocking function, that will restart (in the event of failure)
for {
// if the context isn't cancelled restart
if ctx.Err() != context.Canceled {
*leaderElectionActive = true
err := serviceFunc(ctx, service)
if err != nil {
log.Error(err.Error())
}
*leaderElectionActive = false
} else {
*leaderElectionActive = false
break
}
}
}

View File

@@ -0,0 +1,129 @@
package endpoints
import (
"context"
"fmt"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/instance"
"github.com/kube-vip/kube-vip/pkg/servicecontext"
v1 "k8s.io/api/core/v1"
)
type BGP struct {
generic
bgpServer *bgp.Server
}
func newBGP(generic generic, bgpServer *bgp.Server) endpointWorker {
return &BGP{
generic: generic,
bgpServer: bgpServer,
}
}
func (b *BGP) processInstance(ctx *servicecontext.Context, service *v1.Service, leaderElectionActive *bool) error {
if instance := instance.FindServiceInstance(service, *b.instances); instance != nil {
for _, cluster := range instance.Clusters {
for i := range cluster.Network {
if !ctx.IsNetworkConfigured(cluster.Network[i].IP()) {
log.Debug("attempting to advertise BGP service", "provider", b.provider.GetLabel(), "ip", cluster.Network[i].IP())
err := b.bgpServer.AddHost(cluster.Network[i].CIDR())
if err != nil {
log.Error("error adding BGP host", "provider", b.provider.GetLabel(), "err", err)
} else {
log.Info("added BGP host", "provider",
b.provider.GetLabel(), "ip", cluster.Network[i].CIDR(), "service name", service.Name, "namespace", service.Namespace)
ctx.ConfiguredNetworks.Store(cluster.Network[i].IP(), true)
*leaderElectionActive = true
}
}
}
}
}
return nil
}
func (b *BGP) clear(ctx *servicecontext.Context, lastKnownGoodEndpoint *string, service *v1.Service, cancel context.CancelFunc, leaderElectionActive *bool) {
if !b.config.EnableServicesElection && !b.config.EnableLeaderElection {
// If BGP mode is enabled - routes should be deleted
if instance := instance.FindServiceInstance(service, *b.instances); instance != nil {
for _, cluster := range instance.Clusters {
for i := range cluster.Network {
err := b.bgpServer.DelHost(cluster.Network[i].CIDR())
if err != nil {
log.Error("deleting BGP host", "provider", b.provider.GetLabel(), "ip", cluster.Network[i].IP(), "err", err)
} else {
log.Info("deleted BGP host", "provider",
b.provider.GetLabel(), "ip", cluster.Network[i].IP(), "service name", service.Name, "namespace", service.Namespace)
ctx.ConfiguredNetworks.Delete(cluster.Network[i].IP())
*leaderElectionActive = false
}
}
}
}
}
b.clearEgress(lastKnownGoodEndpoint, service, cancel, leaderElectionActive)
}
func (b *BGP) getEndpoints(service *v1.Service, id string) ([]string, error) {
return b.getAllEndpoints(service, id)
}
func (b *BGP) delete(service *v1.Service, id string) error {
// When no-leader-elecition mode
if !b.config.EnableServicesElection && !b.config.EnableLeaderElection {
// find all existing local endpoints
endpoints, err := b.getEndpoints(service, id)
if err != nil {
return fmt.Errorf("[%s] error getting endpoints: %w", b.provider.GetLabel(), err)
}
// If there were local endpoints deleted
if len(endpoints) > 0 {
b.deleteAction(service)
}
}
return nil
}
func (b *BGP) deleteAction(service *v1.Service) {
b.clearBGPHosts(service)
}
func (b *BGP) clearBGPHosts(service *v1.Service) {
ClearBGPHosts(service, b.instances, b.bgpServer)
}
func (b *BGP) setInstanceEndpointsStatus(_ *v1.Service, _ []string) error {
return nil
}
func ClearBGPHosts(service *v1.Service, instances *[]*instance.Instance, bgpServer *bgp.Server) {
if instance := instance.FindServiceInstance(service, *instances); instance != nil {
ClearBGPHostsByInstance(instance, bgpServer)
}
}
func ClearBGPHostsByInstance(instance *instance.Instance, bgpServer *bgp.Server) {
if instance == nil {
log.Error("failed to clear BGP host for nil instance")
return
}
for _, cluster := range instance.Clusters {
for i := range cluster.Network {
network := cluster.Network[i]
err := bgpServer.DelHost(network.CIDR())
if err != nil {
log.Error("[endpoint] error deleting BGP host", "err", err)
} else {
log.Debug("[endpoint] deleted BGP host", "ip",
network.CIDR(), "service name", instance.ServiceSnapshot.Name, "namespace", instance.ServiceSnapshot.Namespace)
}
}
}
}

View File

@@ -0,0 +1,118 @@
package endpoints
import (
"context"
"fmt"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/egress"
"github.com/kube-vip/kube-vip/pkg/endpoints/providers"
"github.com/kube-vip/kube-vip/pkg/instance"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/servicecontext"
v1 "k8s.io/api/core/v1"
)
type endpointWorker interface {
processInstance(svcCtx *servicecontext.Context, service *v1.Service, leaderElectionActive *bool) error
clear(svcCtx *servicecontext.Context, lastKnownGoodEndpoint *string, service *v1.Service, cancel context.CancelFunc, leaderElectionActive *bool)
getEndpoints(service *v1.Service, id string) ([]string, error)
removeEgress(service *v1.Service, lastKnownGoodEndpoint *string)
delete(service *v1.Service, id string) error
setInstanceEndpointsStatus(service *v1.Service, endpoints []string) error
}
func newEndpointWorker(config *kubevip.Config, provider providers.Provider, bgpServer *bgp.Server, instances *[]*instance.Instance) endpointWorker {
generic := newGeneric(config, provider, instances)
if config.EnableRoutingTable {
return newRoutingTable(generic)
}
if config.EnableBGP {
return newBGP(generic, bgpServer)
}
return &generic
}
type generic struct {
config *kubevip.Config
provider providers.Provider
instances *[]*instance.Instance
}
func newGeneric(config *kubevip.Config, provider providers.Provider, instances *[]*instance.Instance) generic {
return generic{
config: config,
provider: provider,
instances: instances,
}
}
func (g *generic) processInstance(_ *servicecontext.Context, _ *v1.Service, _ *bool) error {
return nil
}
func (g *generic) clear(_ *servicecontext.Context, lastKnownGoodEndpoint *string, service *v1.Service, cancel context.CancelFunc, leaderElectionActive *bool) {
g.clearEgress(lastKnownGoodEndpoint, service, cancel, leaderElectionActive)
}
func (g *generic) clearEgress(lastKnownGoodEndpoint *string, service *v1.Service, cancel context.CancelFunc, leaderElectionActive *bool) {
if *lastKnownGoodEndpoint != "" {
log.Warn("existing endpoint has been removed, no remaining endpoints for leaderElection", "provider", g.provider.GetLabel(), "endpoint", lastKnownGoodEndpoint)
if err := egress.Teardown(*lastKnownGoodEndpoint, service.Spec.LoadBalancerIP, service.Namespace, string(service.UID), service.Annotations, g.config.EgressWithNftables); err != nil {
log.Error("error removing redundant egress rules", "err", err)
}
*lastKnownGoodEndpoint = "" // reset endpoint
if g.config.EnableServicesElection || g.config.EnableLeaderElection {
cancel() // stop services watcher
}
*leaderElectionActive = false
}
}
func (g *generic) getEndpoints(_ *v1.Service, id string) ([]string, error) {
return g.getLocalEndpoints(id)
}
func (g *generic) getLocalEndpoints(id string) ([]string, error) {
// Build endpoints
var endpoints []string
var err error
if endpoints, err = g.provider.GetLocalEndpoints(id, g.config); err != nil {
return nil, fmt.Errorf("[%s] error getting local endpoints: %w", g.provider.GetLabel(), err)
}
return endpoints, nil
}
func (g *generic) getAllEndpoints(service *v1.Service, id string) ([]string, error) {
// Build endpoints
var err error
var endpoints []string
if !g.config.EnableLeaderElection && !g.config.EnableServicesElection &&
service.Spec.ExternalTrafficPolicy == v1.ServiceExternalTrafficPolicyTypeCluster {
if endpoints, err = g.provider.GetAllEndpoints(); err != nil {
return nil, fmt.Errorf("[%s] error getting all endpoints: %w", g.provider.GetLabel(), err)
}
} else {
if endpoints, err = g.provider.GetLocalEndpoints(id, g.config); err != nil {
return nil, fmt.Errorf("[%s] error getting local endpoints: %w", g.provider.GetLabel(), err)
}
}
return endpoints, nil
}
func (g *generic) removeEgress(_ *v1.Service, _ *string) {
}
func (g *generic) delete(_ *v1.Service, _ string) error {
return nil
}
func (g *generic) setInstanceEndpointsStatus(_ *v1.Service, _ []string) error {
return nil
}

View File

@@ -0,0 +1,189 @@
package endpoints
import (
"context"
"errors"
"fmt"
"net"
"syscall"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/egress"
"github.com/kube-vip/kube-vip/pkg/instance"
"github.com/kube-vip/kube-vip/pkg/servicecontext"
"github.com/vishvananda/netlink"
v1 "k8s.io/api/core/v1"
)
type RoutingTable struct {
generic
}
func newRoutingTable(generic generic) endpointWorker {
return &RoutingTable{
generic: generic,
}
}
func (rt *RoutingTable) processInstance(ctx *servicecontext.Context, service *v1.Service, leaderElectionActive *bool) error {
instance := instance.FindServiceInstance(service, *rt.instances)
if instance != nil {
for _, cluster := range instance.Clusters {
for i := range cluster.Network {
if !ctx.IsNetworkConfigured(cluster.Network[i].IP()) && cluster.Network[i].HasEndpoints() {
err := cluster.Network[i].AddRoute(false)
if err != nil {
if errors.Is(err, syscall.EEXIST) {
// If route exists, but protocol is not set (e.g. the route was created by the older version
// of kube-vip) try to update it if necessary
isUpdated, err := cluster.Network[i].UpdateRoutes()
if err != nil {
return fmt.Errorf("[%s] error updating existing routes: %w", rt.provider.GetLabel(), err)
}
if isUpdated {
log.Info("updated route", "provider",
rt.provider.GetLabel(), "ip", cluster.Network[i].IP(), "service name", service.Name, "namespace",
service.Namespace, "interface", cluster.Network[i].Interface(), "tableID", rt.config.RoutingTableID)
} else {
log.Info("route already present", "provider",
rt.provider.GetLabel(), "ip", cluster.Network[i].IP(), "service name", service.Name, "namespace",
service.Namespace, "interface", cluster.Network[i].Interface(), "tableID", rt.config.RoutingTableID)
}
} else {
// If other error occurs, return error
return fmt.Errorf("[%s] error adding route: %s", rt.provider.GetLabel(), err.Error())
}
} else {
log.Info("added route", "provider",
rt.provider.GetLabel(), "ip", cluster.Network[i].IP(), "service name", service.Name, "namespace",
service.Namespace, "interface", cluster.Network[i].Interface(), "tableID", rt.config.RoutingTableID)
ctx.ConfiguredNetworks.Store(cluster.Network[i].IP(), true)
*leaderElectionActive = true
}
}
}
}
}
return nil
}
func (rt *RoutingTable) clear(svcCtx *servicecontext.Context, lastKnownGoodEndpoint *string, service *v1.Service, cancel context.CancelFunc, leaderElectionActive *bool) {
if !rt.config.EnableServicesElection && !rt.config.EnableLeaderElection {
if errs := ClearRoutes(service, rt.instances); len(errs) == 0 {
svcCtx.ConfiguredNetworks.Clear()
} else {
for _, err := range errs {
log.Error("error while clearing routes", "err", err)
}
}
}
rt.clearEgress(lastKnownGoodEndpoint, service, cancel, leaderElectionActive)
}
func (rt *RoutingTable) getEndpoints(service *v1.Service, id string) ([]string, error) {
return rt.getAllEndpoints(service, id)
}
func (rt *RoutingTable) removeEgress(service *v1.Service, lastKnownGoodEndpoint *string) {
if err := egress.Teardown(*lastKnownGoodEndpoint, service.Spec.LoadBalancerIP,
service.Namespace, string(service.UID), service.Annotations, rt.config.EgressWithNftables); err != nil {
log.Warn("removing redundant egress rules", "err", err)
}
}
func (rt *RoutingTable) delete(service *v1.Service, id string) error {
// When no-leader-elecition mode
if !rt.config.EnableServicesElection && !rt.config.EnableLeaderElection {
// find all existing local endpoints
endpoints, err := rt.getEndpoints(service, id)
if err != nil {
return fmt.Errorf("[%s] error getting endpoints: %w", rt.provider.GetLabel(), err)
}
// If there were local endpoints deleted
if len(endpoints) > 0 {
rt.deleteAction(service)
}
}
return nil
}
func (rt *RoutingTable) deleteAction(service *v1.Service) {
ClearRoutes(service, rt.instances)
}
func (rt *RoutingTable) setInstanceEndpointsStatus(service *v1.Service, endpoints []string) error {
instance := instance.FindServiceInstanceWithTimeout(service, *rt.instances)
if instance == nil {
log.Error("failed to find the instance", "namespace", service.Namespace, "name", service.Name, "uid", service.UID, "provider", rt.provider.GetLabel())
} else {
for _, c := range instance.Clusters {
for n := range c.Network {
// if there are no endpoints set HasEndpoints false just in case
if len(endpoints) < 1 {
c.Network[n].SetHasEndpoints(false)
}
// check if endpoint are available and are of same IP family as service
if len(endpoints) > 0 && ((net.ParseIP(c.Network[n].IP()).To4() == nil) == (net.ParseIP(endpoints[0]).To4() == nil)) {
c.Network[n].SetHasEndpoints(true)
}
}
}
}
return nil
}
func ClearRoutes(service *v1.Service, instances *[]*instance.Instance) []error {
errs := []error{}
if svcInst := instance.FindServiceInstance(service, *instances); svcInst != nil {
clearErrs := ClearRoutesByInstance(service, svcInst, instances)
errs = append(errs, clearErrs...)
}
return errs
}
func ClearRoutesByInstance(service *v1.Service, svcInst *instance.Instance, instances *[]*instance.Instance) []error {
if svcInst == nil {
return []error{fmt.Errorf("failed to remove routes for nil instance of service %s/%s, uid: %s", service.Namespace, service.Name, service.UID)}
}
errs := []error{}
for _, cluster := range svcInst.Clusters {
for i := range cluster.Network {
route := cluster.Network[i].PrepareRoute()
// check if route we are about to delete is not referenced by more than one service
if CountRouteReferences(route, instances) <= 1 {
err := cluster.Network[i].DeleteRoute()
if err != nil && !errors.Is(err, syscall.ESRCH) {
log.Error("failed to delete route", "ip", cluster.Network[i].IP(), "err", err)
errs = append(errs, err)
}
log.Debug("deleted route", "ip",
cluster.Network[i].IP(), "service name", service.Name, "namespace", service.Namespace, "interface", cluster.Network[i].Interface())
}
}
}
return errs
}
func CountRouteReferences(route *netlink.Route, instances *[]*instance.Instance) int {
cnt := 0
for _, instance := range *instances {
for _, cluster := range instance.Clusters {
for n := range cluster.Network {
if cluster.Network[n].HasEndpoints() {
r := cluster.Network[n].PrepareRoute()
if r.Dst.String() == route.Dst.String() {
cnt++
}
}
}
}
}
return cnt
}

View File

@@ -0,0 +1,137 @@
package providers
import (
"context"
"fmt"
"strings"
"github.com/kube-vip/kube-vip/pkg/kubevip"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
watchtools "k8s.io/client-go/tools/watch"
"k8s.io/client-go/util/retry"
log "log/slog"
)
type Endpoints struct {
label string
//nolint:staticcheck // SA1019 endpoints are moving to an opt-in only
endpoints *v1.Endpoints
}
func NewEndpoints() Provider {
return &Endpoints{
label: "endpoints",
}
}
func (ep *Endpoints) CreateRetryWatcher(ctx context.Context, clientSet *kubernetes.Clientset,
service *v1.Service) (*watchtools.RetryWatcher, error) {
opts := metav1.ListOptions{
FieldSelector: fields.OneTermEqualSelector("metadata.name", service.Name).String(),
}
rw, err := watchtools.NewRetryWatcherWithContext(ctx, "1", &cache.ListWatch{
WatchFunc: func(_ metav1.ListOptions) (watch.Interface, error) {
return clientSet.CoreV1().Endpoints(service.Namespace).Watch(ctx, opts)
},
})
if err != nil {
return nil, fmt.Errorf("error creating endpoint watcher: %s", err.Error())
}
return rw, nil
}
func (ep *Endpoints) LoadObject(endpoints runtime.Object, cancel context.CancelFunc) error {
//nolint:staticcheck // SA1019 endpoints have to be explicitly requested now
eps, ok := endpoints.(*v1.Endpoints)
if !ok {
cancel()
return fmt.Errorf("[%s] unable to parse Kubernetes services from API watcher", ep.GetLabel())
}
ep.endpoints = eps
return nil
}
func (ep *Endpoints) GetAllEndpoints() ([]string, error) {
result := []string{}
for subset := range ep.endpoints.Subsets {
for address := range ep.endpoints.Subsets[subset].Addresses {
addr := strings.Split(ep.endpoints.Subsets[subset].Addresses[address].IP, "/")
result = append(result, addr[0])
}
}
return result, nil
}
func (ep *Endpoints) GetLocalEndpoints(id string, _ *kubevip.Config) ([]string, error) {
var localEndpoints []string
for _, subset := range ep.endpoints.Subsets {
for _, address := range subset.Addresses {
log.Debug("processing endpoint", "label", ep.label, "ip", address.IP)
// 1. Compare the Nodename
if address.NodeName != nil && id == *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.Debug("found local endpoint", "label", ep.label, "ip", address.IP, "hostname", address.Hostname)
localEndpoints = append(localEndpoints, address.IP)
continue
}
}
}
return localEndpoints, nil
}
func (ep *Endpoints) UpdateServiceAnnotation(endpoint string, _ string, service *v1.Service, clientSet *kubernetes.Clientset) error {
retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
// Retrieve the latest version of Deployment before attempting update
// RetryOnConflict uses exponential backoff to avoid exhausting the apiserver
currentService, err := clientSet.CoreV1().Services(service.Namespace).Get(context.TODO(), service.Name, metav1.GetOptions{})
if err != nil {
return err
}
currentServiceCopy := currentService.DeepCopy()
if currentServiceCopy.Annotations == nil {
currentServiceCopy.Annotations = make(map[string]string)
}
currentServiceCopy.Annotations[kubevip.ActiveEndpoint] = endpoint
_, err = clientSet.CoreV1().Services(currentService.Namespace).Update(context.TODO(), currentServiceCopy, metav1.UpdateOptions{})
if err != nil {
log.Error("error updating Service Spec", "label", ep.GetLabel(), "name", currentServiceCopy.Name, "err", err)
return err
}
return nil
})
if retryErr != nil {
log.Error("failed to set Services", "label", ep.GetLabel(), "err", retryErr)
return retryErr
}
return nil
}
func (ep *Endpoints) GetLabel() string {
return ep.label
}
func (ep *Endpoints) GetProtocol() string {
return ""
}

View File

@@ -0,0 +1,139 @@
package providers
import (
"context"
"fmt"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/kubevip"
v1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
watchtools "k8s.io/client-go/tools/watch"
"k8s.io/client-go/util/retry"
)
type Endpointslices struct {
label string
endpoints *discoveryv1.EndpointSlice
}
func NewEndpointslices() Provider {
return &Endpointslices{
label: "endpointslices",
}
}
func (ep *Endpointslices) CreateRetryWatcher(ctx context.Context, clientSet *kubernetes.Clientset,
service *v1.Service) (*watchtools.RetryWatcher, error) {
labelSelector := metav1.LabelSelector{MatchLabels: map[string]string{"kubernetes.io/service-name": service.Name}}
opts := metav1.ListOptions{
LabelSelector: labels.Set(labelSelector.MatchLabels).String(),
}
rw, err := watchtools.NewRetryWatcherWithContext(ctx, "1", &cache.ListWatch{
WatchFunc: func(_ metav1.ListOptions) (watch.Interface, error) {
return clientSet.DiscoveryV1().EndpointSlices(service.Namespace).Watch(ctx, opts)
},
})
if err != nil {
return nil, fmt.Errorf("[%s] error creating endpointslices watcher: %s", ep.label, err.Error())
}
return rw, nil
}
func (ep *Endpointslices) LoadObject(endpoints runtime.Object, cancel context.CancelFunc) error {
eps, ok := endpoints.(*discoveryv1.EndpointSlice)
if !ok {
cancel()
return fmt.Errorf("[%s] error casting endpoints to v1.Endpoints struct", ep.label)
}
ep.endpoints = eps
return nil
}
func (ep *Endpointslices) GetAllEndpoints() ([]string, error) {
result := []string{}
for _, ep := range ep.endpoints.Endpoints {
result = append(result, ep.Addresses...)
}
return result, nil
}
func (ep *Endpointslices) GetLocalEndpoints(id string, _ *kubevip.Config) ([]string, error) {
var localEndpoints []string
for _, endpoint := range ep.endpoints.Endpoints {
if endpoint.Conditions.Serving == nil || !*endpoint.Conditions.Serving {
continue
}
for _, address := range endpoint.Addresses {
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.Debug("found endpoint", "provider", ep.label, "ip", address, "hostname", *endpoint.Hostname, "nodename", *endpoint.NodeName)
} else {
log.Debug("found endpoint", "provider", ep.label, "ip", address, "nodename", *endpoint.NodeName)
}
localEndpoints = append(localEndpoints, address)
continue
}
// 2. Compare the Hostname (only useful if endpoint.NodeName is not available)
if endpoint.Hostname != nil && id == *endpoint.Hostname {
log.Debug("found endpoint", "provider", ep.label, "ip", address, "hostname", *endpoint.Hostname)
localEndpoints = append(localEndpoints, address)
}
}
}
return localEndpoints, nil
}
func (ep *Endpointslices) UpdateServiceAnnotation(endpoint, endpointIPv6 string, service *v1.Service, clientSet *kubernetes.Clientset) error {
retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
// Retrieve the latest version of Deployment before attempting update
// RetryOnConflict uses exponential backoff to avoid exhausting the apiserver
currentService, err := clientSet.CoreV1().Services(service.Namespace).Get(context.TODO(), service.Name, metav1.GetOptions{})
if err != nil {
return err
}
currentServiceCopy := currentService.DeepCopy()
if currentServiceCopy.Annotations == nil {
currentServiceCopy.Annotations = make(map[string]string)
}
currentServiceCopy.Annotations[kubevip.ActiveEndpoint] = endpoint
currentServiceCopy.Annotations[kubevip.ActiveEndpointIPv6] = endpointIPv6
_, err = clientSet.CoreV1().Services(currentService.Namespace).Update(context.TODO(), currentServiceCopy, metav1.UpdateOptions{})
if err != nil {
log.Error("error updating Service Spec", "provider", ep.label, "service name", currentServiceCopy.Name, "err", err)
return err
}
return nil
})
if retryErr != nil {
log.Error("failed to set Services", "provider", ep.label, "err", retryErr)
return retryErr
}
return nil
}
func (ep *Endpointslices) GetLabel() string {
return ep.label
}
func (ep *Endpointslices) GetProtocol() string {
return string(ep.endpoints.AddressType)
}

View File

@@ -0,0 +1,22 @@
package providers
import (
"context"
"github.com/kube-vip/kube-vip/pkg/kubevip"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes"
watchtools "k8s.io/client-go/tools/watch"
)
type Provider interface {
CreateRetryWatcher(context.Context, *kubernetes.Clientset,
*v1.Service) (*watchtools.RetryWatcher, error)
GetAllEndpoints() ([]string, error)
GetLocalEndpoints(string, *kubevip.Config) ([]string, error)
GetLabel() string
UpdateServiceAnnotation(string, string, *v1.Service, *kubernetes.Clientset) error
LoadObject(runtime.Object, context.CancelFunc) error
GetProtocol() string
}

26
pkg/etcd/client.go Normal file
View File

@@ -0,0 +1,26 @@
package etcd
import (
"go.etcd.io/etcd/client/pkg/v3/transport"
clientv3 "go.etcd.io/etcd/client/v3"
"github.com/kube-vip/kube-vip/pkg/kubevip"
)
func NewClient(c *kubevip.Config) (*clientv3.Client, error) {
tlsInfo := transport.TLSInfo{
TrustedCAFile: c.Etcd.CAFile,
CertFile: c.Etcd.ClientCertFile,
KeyFile: c.Etcd.ClientKeyFile,
}
clientTLS, err := tlsInfo.ClientConfig()
if err != nil {
return nil, err
}
return clientv3.New(clientv3.Config{
Endpoints: c.Etcd.Endpoints,
TLS: clientTLS,
})
}

227
pkg/etcd/election.go Normal file
View File

@@ -0,0 +1,227 @@
package etcd
import (
"context"
"hash/fnv"
"time"
log "log/slog"
"github.com/pkg/errors"
pb "go.etcd.io/etcd/api/v3/etcdserverpb"
clientv3 "go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/client/v3/concurrency"
)
// LeaderElectionConfig allows to configure the leader election params.
type LeaderElectionConfig struct {
// EtcdConfig contains the client to connect to the etcd cluster.
EtcdConfig ClientConfig
// Name uniquely identifies this leader election. All members of the same election
// should use the same value here.
Name string
// MemberID identifies uniquely this contestant from other in the leader election.
// It will be converted to an int64 using a hash, so theoretically collisions are possible
// when using a string. If you want to guarantee safety, us MemberUniqueID to specify a unique
// int64 directly.
// If two processes start a leader election using the same MemberID, one of them will
// fail.
MemberID string
// MemberUniqueID is the int equivalent to MemberID that allows to override the default conversion
// from string to int using hashing.
MemberUniqueID *uint64
// LeaseDurationSeconds is the duration that non-leader candidates will
// wait to force acquire leadership.
// This is just a request to the etcd server but it's not guaranteed, the server
// might decide to make the duration longer.
LeaseDurationSeconds int64
// Callbacks are callbacks that are triggered during certain lifecycle
// events of the LeaderElector
Callbacks LeaderCallbacks
}
// LeaderCallbacks are callbacks that are triggered during certain
// lifecycle events of the election.
type LeaderCallbacks struct {
// OnStartedLeading is called when this member starts leading.
OnStartedLeading func(context.Context)
// OnStoppedLeading is called when this member stops leading.
OnStoppedLeading func()
// OnNewLeader is called when the client observes a leader that is
// not the previously observed leader. This includes the first observed
// leader when the client starts.
OnNewLeader func(identity string)
}
// ClientConfig contains the client to connect to the etcd cluster.
type ClientConfig struct {
Client *clientv3.Client
}
// RunElectionOrDie behaves the same way as RunElection but panics if there is an error.
func RunElectionOrDie(ctx context.Context, config *LeaderElectionConfig) {
if err := RunElection(ctx, config); err != nil {
panic(err)
}
}
// RunElection starts a client with the provided config or panics.
// RunElection blocks until leader election loop is
// stopped by ctx or it has stopped holding the leader lease.
func RunElection(ctx context.Context, config *LeaderElectionConfig) error {
var memberID uint64
if config.MemberUniqueID != nil {
memberID = *config.MemberUniqueID
} else {
h := fnv.New64a()
if _, err := h.Write(append([]byte(config.Name), []byte(config.MemberID)...)); err != nil {
return err
}
memberID = h.Sum64()
}
ttl := config.LeaseDurationSeconds
r := &pb.LeaseGrantRequest{TTL: ttl, ID: int64(memberID)} //nolint
lease, err := clientv3.RetryLeaseClient(
config.EtcdConfig.Client,
).LeaseGrant(ctx, r)
if err != nil {
return errors.Wrap(err, "creating lease")
}
leaseID := clientv3.LeaseID(lease.ID)
s, err := concurrency.NewSession(
config.EtcdConfig.Client,
concurrency.WithTTL(int(lease.TTL)),
concurrency.WithLease(leaseID),
)
if err != nil {
return err
}
election := concurrency.NewElection(s, config.Name)
m := &member{
client: config.EtcdConfig.Client,
election: election,
callbacks: config.Callbacks,
memberID: config.MemberID,
weAreTheLeader: make(chan struct{}, 1),
leaseTTL: lease.TTL,
}
go m.tryToBeLeader(ctx)
m.watchLeaderChanges(ctx)
return nil
}
type member struct {
key string
client *clientv3.Client
election *concurrency.Election
isLeader bool
currentLeaderKey string
callbacks LeaderCallbacks
memberID string
weAreTheLeader chan struct{}
leaseTTL int64
}
func (m *member) watchLeaderChanges(ctx context.Context) {
observeCtx, observeCancel := context.WithCancel(ctx)
defer observeCancel()
changes := m.election.Observe(observeCtx)
watcher:
for {
select {
case <-ctx.Done():
break watcher
case <-m.weAreTheLeader:
m.isLeader = true
m.key = m.election.Key() // by this time, this should already be set, since Campaign has already returned
log.Debug("Marking self as leader with key", "id", m.memberID, "key", m.key)
case response := <-changes:
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
// just before the response channel is closed or the context is cancel
// In that case, just continue and let one of those two things happen
continue
}
newLeaderKey := response.Kvs[0].Key
if m.isLeader && m.key != string(newLeaderKey) {
// We stopped being leaders
// exit the loop, so we cancel the observe context so we stop watching
// for new leaders. That will close the channel and make this function exit,
// which also makes the routine to finish and RunElection returns
break watcher
}
if m.currentLeaderKey != string(newLeaderKey) {
// we observed a leader, this could be us or someone else
m.currentLeaderKey = string(newLeaderKey)
m.callbacks.OnNewLeader(string(response.Kvs[0].Value))
}
}
}
// If we are here, either we have stopped being leaders or we lost the watcher
// Make sure we call OnStoppedLeading if we were the leader.
if m.isLeader {
m.callbacks.OnStoppedLeading()
}
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.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.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?
// We probably want watchLeaderChanges to exit as well, since Run
// is expecting us to try to become the leader, but if we are here,
// we won't. So if we don't panic, we need to signal it somehow
}
// Inform the observer that we are the leader as soon as possible,
// so it can detect if we stop being it
m.weAreTheLeader <- struct{}{}
// Once we are the leader, start the routine to resign if context is canceled
go m.resignOnCancel(ctx)
// After becoming the leader, we wait for at least a lease TTL to wait for
// the previous leader to detect the new leadership (if there was one) and
// stop its processes
// TODO: is this too cautious?
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
m.callbacks.OnStartedLeading(ctx)
// Here the routine dies if OnStartedLeading doesn't block, there is nothing else to do
}
func (m *member) resignOnCancel(ctx context.Context) {
<-ctx.Done()
if err := m.election.Resign(m.client.Ctx()); err != nil && !errors.Is(err, context.Canceled) {
log.Error("Failed to resign after the context was canceled", "err", err)
}
}

171
pkg/etcd/election_test.go Normal file
View File

@@ -0,0 +1,171 @@
//go:build integration
// +build integration
package etcd_test
import (
"context"
"log"
"math/rand"
"sync"
"testing"
"time"
"github.com/kube-vip/kube-vip/pkg/etcd"
. "github.com/onsi/gomega"
clientv3 "go.etcd.io/etcd/client/v3"
"go.uber.org/zap"
)
func TestRunElectionWithMemberIDCollision(t *testing.T) {
t.Parallel()
g := NewWithT(t)
ctx := context.Background()
cli := client(g)
defer cli.Close()
electionName := randomElectionNameForTest("memberIDConflict")
log.Printf("Election name %s\n", electionName)
memberCtx, cancelMember1 := context.WithCancel(ctx)
config := &etcd.LeaderElectionConfig{
EtcdConfig: etcd.ClientConfig{
Client: cli,
},
Name: electionName,
MemberID: randomElectionNameForTest("my-host"),
LeaseDurationSeconds: 1,
Callbacks: etcd.LeaderCallbacks{
OnStartedLeading: func(ctx context.Context) {
log.Println("I'm the leader!!!!")
log.Println("Renouncing as leader by canceling context")
cancelMember1()
},
OnNewLeader: func(identity string) {
log.Printf("New leader: %s\n", identity)
},
OnStoppedLeading: func() {
log.Println("I'm not the leader anymore")
},
},
}
wg := &sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
g.Expect(etcd.RunElection(memberCtx, config)).To(Succeed())
}()
go func() {
defer wg.Done()
time.Sleep(time.Millisecond * 50) // make sure the first one becomes leader
g.Expect(etcd.RunElection(ctx, config)).Should(MatchError(ContainSubstring("creating lease")))
}()
wg.Wait()
}
func TestRunElectionWithTwoMembersAndReelection(t *testing.T) {
t.Parallel()
g := NewWithT(t)
ctx := context.Background()
cli := client(g)
defer cli.Close()
cliMember1 := client(g)
defer cliMember1.Close()
electionName := randomElectionNameForTest("steppingDown")
configBase := etcd.LeaderElectionConfig{
EtcdConfig: etcd.ClientConfig{
Client: cli,
},
Name: electionName,
LeaseDurationSeconds: 1,
}
member1Ctx, _ := context.WithCancel(ctx)
member2Ctx, cancelMember2 := context.WithCancel(ctx)
config1 := configBase
config1.EtcdConfig.Client = cliMember1
config1.MemberID = randomElectionNameForTest("my-host")
uniqueID := rand.Uint64()
config1.MemberUniqueID = &uniqueID
config1.Callbacks = baseCallbacksForName(config1.MemberID)
syncMembers := make(chan (any))
config1.Callbacks.OnStartedLeading = func(_ context.Context) {
log.Println("I'm my-host, the new leader!!!!")
close(syncMembers)
log.Println("Losing the leadership on purpose by stopping renewing the lease")
g.Expect(cliMember1.Lease.Close()).To(Succeed())
log.Println("Member1 leases closed")
}
config2 := configBase
config2.MemberID = randomElectionNameForTest("my-other-host")
config2.Callbacks = baseCallbacksForName(config2.MemberID)
config2.Callbacks.OnStartedLeading = func(_ context.Context) {
log.Println("I'm my-other-host, the new leader!!!!")
log.Println("Renouncing as leader by canceling context")
cancelMember2()
}
wg := &sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
g.Expect(etcd.RunElection(member1Ctx, &config1)).To(Succeed())
log.Printf("%s routine done\n", config1.MemberID)
}()
go func() {
defer wg.Done()
<-syncMembers
g.Expect(etcd.RunElection(member2Ctx, &config2)).To(Succeed())
log.Printf("%s routine done\n", config2.MemberID)
}()
wg.Wait()
}
func baseCallbacksForName(name string) etcd.LeaderCallbacks {
return etcd.LeaderCallbacks{
OnStartedLeading: func(ctx context.Context) {
log.Printf("[%s] I'm the new leader!!!!\n", name)
},
OnNewLeader: func(identity string) {
log.Printf("[%s] New leader: %s\n", name, identity)
},
OnStoppedLeading: func() {
log.Printf("[%s] I'm not the leader anymore\n", name)
},
}
}
func randomElectionNameForTest(name string) string {
return name + "-" + randomString(6)
}
const charSet = "0123456789abcdefghijklmnopqrstuvwxyz"
var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
func randomString(n int) string {
result := make([]byte, n)
for i := range result {
result[i] = charSet[rnd.Intn(len(charSet))]
}
return string(result)
}
func client(g Gomega) *clientv3.Client {
c, err := clientv3.New(clientv3.Config{
Endpoints: []string{"localhost:2379"},
Logger: zap.NewNop(),
})
g.Expect(err).NotTo(HaveOccurred())
return c
}

153
pkg/etcd/etcd_suite_test.go Normal file
View File

@@ -0,0 +1,153 @@
//go:build integration
// +build integration
package etcd_test
import (
"context"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strconv"
"testing"
"time"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
const (
etcdVersion = "v3.5.9"
etcdBinDir = "bin"
etcdBinPath = etcdBinDir + "/etcd"
downloadURL = "https://storage.googleapis.com/etcd"
tmpDownloadFile = "etcd.tar.gz"
pidFile = "etcd.pid"
)
func TestMain(m *testing.M) {
logrus.SetLevel(logrus.DebugLevel)
ctx := context.Background()
expectSuccess(startEtcd(ctx), "starting etcd")
os.Exit(runTestsWithCleanup(m, func() {
expectSuccess(stopEtcd(), "stopping etcd")
}))
}
func runTestsWithCleanup(m *testing.M, cleanup func()) int {
defer cleanup()
return m.Run()
}
func expectSuccess(err error, msg string) {
if err != nil {
log.Fatalf("%s: %s\n", msg, err)
}
}
func startEtcd(ctx context.Context) error {
if _, err := os.Stat(pidFile); err == nil {
log.Println("Etcd already running, reusing")
return nil
}
etcdPath, err := installEtcd(ctx)
if err != nil {
errors.Wrap(err, "installing etcd for tests")
}
etcdCmd := exec.Command(etcdPath, "--data-dir", "./etcd-data")
if os.Getenv("ETCD_SERVER_LOGS") == "true" {
log.Println("Enabling etcd server logs")
etcdCmd.Stdout = os.Stdout
etcdCmd.Stderr = os.Stderr
}
log.Println("Starting etcd")
if err := etcdCmd.Start(); err != nil {
errors.Wrap(err, "starting etcd for tests")
}
if err := os.WriteFile(pidFile, []byte(strconv.Itoa(etcdCmd.Process.Pid)), 0o600); err != nil {
return err
}
log.Println("Waiting for etcd to be up")
time.Sleep(time.Second)
return nil
}
func installEtcd(ctx context.Context) (string, error) {
projectRoot, err := filepath.Abs("../../")
if err != nil {
return "", err
}
binDir := filepath.Join(projectRoot, etcdBinDir)
etcdPath := filepath.Join(projectRoot, etcdBinPath)
if _, err := os.Stat(etcdPath); err == nil {
log.Println("Etcd already installed, skipping")
return etcdPath, nil
}
if err := os.MkdirAll(binDir, 0o755); err != nil {
return "", err
}
download := fmt.Sprintf("%s/%s/etcd-%s-linux-amd64.tar.gz", downloadURL, etcdVersion, etcdVersion)
// Hacky to run bash, but simplifies this code a lot
cmd := fmt.Sprintf("curl -sL %s | tar -xzvf - -C %s --strip-components=1", download, binDir)
out, err := exec.CommandContext(ctx, "bash", "-c", cmd).CombinedOutput()
if err != nil {
return "", errors.Wrapf(err, "downloading etcd: %s", string(out))
}
return etcdPath, nil
}
func stopEtcd() error {
if os.Getenv("REUSE_ETCD") == "true" {
log.Println("REUSE_ETCD=true, leaving etcd running")
return nil
}
if _, err := os.Stat(pidFile); os.IsNotExist(err) {
log.Println("Etcd pid file doesn't exit, skipping cleanup")
return nil
}
dat, err := os.ReadFile(pidFile)
if err != nil {
return err
}
pid, err := strconv.Atoi(string(dat))
if err != nil {
return err
}
etcdProcess, err := os.FindProcess(pid)
if err != nil {
return err
}
log.Println("Stopping etcd")
if err := etcdProcess.Kill(); err != nil {
return errors.Wrap(err, "Failed stopping etcd")
}
log.Println("Deleting etcd data")
if err := os.RemoveAll("./etcd-data"); err != nil {
return errors.Wrap(err, "deleting etcd data")
}
log.Println("Deleting etcd pid file")
if err := os.RemoveAll(pidFile); err != nil {
return errors.Wrap(err, "deleting pid file")
}
return nil
}

516
pkg/instance/instance.go Normal file
View File

@@ -0,0 +1,516 @@
package instance
import (
"fmt"
"net"
"strconv"
"strings"
"time"
"log/slog"
log "log/slog"
"github.com/vishvananda/netlink"
v1 "k8s.io/api/core/v1"
"github.com/kube-vip/kube-vip/pkg/arp"
"github.com/kube-vip/kube-vip/pkg/cluster"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/networkinterface"
"github.com/kube-vip/kube-vip/pkg/sysctl"
"github.com/kube-vip/kube-vip/pkg/utils"
"github.com/kube-vip/kube-vip/pkg/vip"
)
// Instance defines an instance of everything needed to manage vips
type Instance struct {
// Virtual IP / Load Balancer configuration
VIPConfigs []*kubevip.Config
// cluster instances
Clusters []*cluster.Cluster
// Service uses DHCP
IsDHCP bool
DHCPInterface string
DHCPInterfaceHwaddr string
DHCPInterfaceIP string
DHCPHostname string
DHCPClient *vip.DHCPClient
// External Gateway IP the service is forwarded from
UPNPGatewayIPs []string
// Kubernetes service mapping
ServiceSnapshot *v1.Service
}
type Port struct {
Port uint16
Type string
}
func NewInstance(svc *v1.Service, config *kubevip.Config, intfMgr *networkinterface.Manager, arpMgr *arp.Manager) (*Instance, error) {
instanceAddresses, _ := FetchServiceAddresses(svc)
var newVips []*kubevip.Config
var link netlink.Link
var err error
for _, address := range instanceAddresses {
// Detect if we're using a specific interface for services
var svcInterface string
svcInterface = svc.Annotations[kubevip.ServiceInterface] // If the service has a specific interface defined, then use it
if svcInterface == kubevip.Auto {
link, err = autoFindInterface(address)
if err != nil {
log.Error("automatically discover network interface for annotated IP", "address", address, "err", err)
} else {
if link == nil {
log.Error("automatically discover network interface for annotated IP address", "address", address)
}
}
if link == nil {
svcInterface = ""
} else {
svcInterface = getAutoInterfaceName(link, config.Interface)
}
}
// If it is still blank then use the
if svcInterface == "" {
switch config.ServicesInterface {
case kubevip.Auto:
link, err = autoFindInterface(address)
if err != nil {
log.Error("failed to automatically discover network interface for address", "ip", address, "err", err, "interface", config.Interface)
} else if link == nil {
log.Error("failed to automatically discover network interface for address", "ip", address, "defaulting to", config.Interface)
}
svcInterface = getAutoInterfaceName(link, config.Interface)
case "":
svcInterface = config.Interface
default:
svcInterface = config.ServicesInterface
}
}
if link == nil {
if link, err = netlink.LinkByName(svcInterface); err != nil {
return nil, fmt.Errorf("failed to get interface %s: %w", svcInterface, err)
}
if link == nil {
return nil, fmt.Errorf("failed to get interface %s", svcInterface)
}
}
cidrs := vip.Split(config.VIPSubnet)
ipv4AutoSubnet := false
ipv6AutoSubnet := false
if cidrs[0] == kubevip.Auto {
ipv4AutoSubnet = true
}
if len(cidrs) > 1 && cidrs[1] == kubevip.Auto {
ipv6AutoSubnet = true
}
if (config.Address != "" || config.VIP != "") && (ipv4AutoSubnet || ipv6AutoSubnet) {
return nil, fmt.Errorf("auto subnet discovery cannot be used if VIP address was provided")
}
subnet := ""
var err error
if utils.IsIPv4(address) {
if ipv4AutoSubnet {
subnet, err = autoFindSubnet(link, address)
if err != nil {
return nil, fmt.Errorf("failed to automatically find subnet for service %s/%s with IP address %s on interface %s: %w", svc.Namespace, svc.Name, address, svcInterface, err)
}
} else {
if cidrs[0] != "" && cidrs[0] != kubevip.Auto {
subnet = cidrs[0]
} else {
subnet = "32"
}
}
} else {
if ipv6AutoSubnet {
subnet, err = autoFindSubnet(link, address)
if err != nil {
return nil, fmt.Errorf("failed to automatically find subnet for service %s/%s with IP address %s on interface %s: %w", svc.Namespace, svc.Name, address, svcInterface, err)
}
} else {
if len(cidrs) > 1 && cidrs[1] != "" && cidrs[1] != kubevip.Auto {
subnet = cidrs[1]
} else {
subnet = "128"
}
}
}
// Generate new Virtual IP configuration
newVips = append(newVips, &kubevip.Config{
VIP: address,
Interface: svcInterface,
SingleNode: true,
EnableARP: config.EnableARP,
EnableBGP: config.EnableBGP,
VIPSubnet: subnet,
EnableRoutingTable: config.EnableRoutingTable,
RoutingTableID: config.RoutingTableID,
RoutingTableType: config.RoutingTableType,
RoutingProtocol: config.RoutingProtocol,
ArpBroadcastRate: config.ArpBroadcastRate,
EnableServiceSecurity: config.EnableServiceSecurity,
DNSMode: config.DNSMode,
DisableServiceUpdates: config.DisableServiceUpdates,
EnableServicesElection: config.EnableServicesElection,
PreserveVIPOnLeadershipLoss: config.PreserveVIPOnLeadershipLoss,
KubernetesLeaderElection: kubevip.KubernetesLeaderElection{
EnableLeaderElection: config.EnableLeaderElection,
},
})
}
// Create new service
instance := &Instance{
//UID: instanceUID,
//VIPs: instanceAddresses,
ServiceSnapshot: svc,
}
// for _, port := range svc.Spec.Ports {
// instance.ExternalPorts = append(instance.ExternalPorts, Port{
// Port: uint16(port.Port), //nolint
// Type: string(port.Protocol),
// })
// }
if svc.Annotations != nil {
instance.DHCPInterfaceHwaddr = svc.Annotations[kubevip.HwAddrKey]
instance.DHCPInterfaceIP = svc.Annotations[kubevip.RequestedIP]
instance.DHCPHostname = svc.Annotations[kubevip.LoadbalancerHostname]
}
configPorts := make([]kubevip.Port, 0)
for _, p := range svc.Spec.Ports {
configPorts = append(configPorts, kubevip.Port{
Type: string(p.Protocol),
Port: int(p.Port),
})
}
// Generate Load Balancer config
newLB := kubevip.LoadBalancer{
Name: fmt.Sprintf("%s-load-balancer", svc.Name),
Ports: configPorts,
BindToVip: true,
}
for _, vip := range newVips {
// Add Load Balancer Configuration
vip.LoadBalancers = append(vip.LoadBalancers, newLB)
}
// Create Add configuration to the new service
instance.VIPConfigs = newVips
// If this was purposely created with the address 0.0.0.0,
// we will create a macvlan on the main interface and a DHCP client
// TODO: Consider how best to handle DHCP with multiple addresses
if len(instanceAddresses) == 1 && instanceAddresses[0] == "0.0.0.0" {
err := instance.startDHCP()
if err != nil {
return nil, err
}
select {
case err := <-instance.DHCPClient.ErrorChannel():
return nil, fmt.Errorf("error starting DHCP for %s/%s: error: %s",
instance.ServiceSnapshot.Namespace, instance.ServiceSnapshot.Name, err)
case ip := <-instance.DHCPClient.IPChannel():
instance.VIPConfigs[0].Interface = instance.DHCPInterface
instance.VIPConfigs[0].VIP = ip
instance.DHCPInterfaceIP = ip
}
}
for _, vipConfig := range instance.VIPConfigs {
c, err := cluster.InitCluster(vipConfig, false, intfMgr, arpMgr)
if err != nil {
log.Error("Failed to add Service %s/%s", svc.Namespace, svc.Name)
return nil, err
}
for i := range c.Network {
c.Network[i].SetServicePorts(svc)
}
instance.Clusters = append(instance.Clusters, c)
log.Info("(svcs) adding VIP", "ip", vipConfig.VIP, "interface", vipConfig.Interface, "namespace", svc.Namespace, "name", svc.Name)
}
return instance, nil
}
func autoFindInterface(ip string) (netlink.Link, error) {
links, err := netlink.LinkList()
if err != nil {
return nil, fmt.Errorf("failed to list network interfaces: %w", err)
}
address := net.ParseIP(ip)
family := netlink.FAMILY_V4
if address.To4() == nil {
family = netlink.FAMILY_V6
}
for _, link := range links {
addr, err := netlink.AddrList(link, family)
if err != nil {
return nil, fmt.Errorf("failed to get IP addresses for interface %s: %w", link.Attrs().Name, err)
}
for _, a := range addr {
if a.IPNet.Contains(address) {
return link, nil
}
}
}
return nil, nil
}
func autoFindSubnet(link netlink.Link, ip string) (string, error) {
address := net.ParseIP(ip)
family := netlink.FAMILY_V4
if address.To4() == nil {
family = netlink.FAMILY_V6
}
addr, err := netlink.AddrList(link, family)
if err != nil {
return "", fmt.Errorf("failed to get IP addresses for interface %s: %w", link.Attrs().Name, err)
}
for _, a := range addr {
if a.IPNet.Contains(address) {
m, _ := a.IPNet.Mask.Size()
return strconv.Itoa(m), nil
}
}
return "", fmt.Errorf("failed to find suitable subnet for address %s", ip)
}
func getAutoInterfaceName(link netlink.Link, defaultInterface string) string {
if link == nil {
return defaultInterface
}
return link.Attrs().Name
}
func (i *Instance) startDHCP() error {
if len(i.VIPConfigs) != 1 {
return fmt.Errorf("DHCP requires exactly 1 VIP config, got: %v", len(i.VIPConfigs))
}
parent, err := netlink.LinkByName(i.VIPConfigs[0].Interface)
if err != nil {
return fmt.Errorf("error finding VIP Interface, for building DHCP Link : %v", err)
}
// Generate name from UID
interfaceName := fmt.Sprintf("vip-%s", i.ServiceSnapshot.UID[0:8])
// Check if the interface doesn't exist first
iface, err := net.InterfaceByName(interfaceName)
if err != nil {
log.Info("creating new macvlan interface for DHCP", "interface", interfaceName)
hwaddr, err := net.ParseMAC(i.DHCPInterfaceHwaddr)
if i.DHCPInterfaceHwaddr != "" && err != nil {
return err
} else if hwaddr == nil {
hwaddr, err = net.ParseMAC(vip.GenerateMac())
if err != nil {
return err
}
}
log.Info("new macvlan interface", "interface", interfaceName, "hardware address", hwaddr)
mac := &netlink.Macvlan{
LinkAttrs: netlink.LinkAttrs{
Name: interfaceName,
ParentIndex: parent.Attrs().Index,
HardwareAddr: hwaddr,
},
Mode: netlink.MACVLAN_MODE_DEFAULT,
}
err = netlink.LinkAdd(mac)
if err != nil {
return fmt.Errorf("could not add %s: %v", interfaceName, err)
}
err = netlink.LinkSetUp(mac)
if err != nil {
return fmt.Errorf("could not bring up interface [%s] : %v", interfaceName, err)
}
iface, err = net.InterfaceByName(interfaceName)
if err != nil {
return fmt.Errorf("error finding new DHCP interface by name [%v]", err)
}
} else {
log.Info("Using existing macvlan interface for DHCP", "interface", interfaceName)
}
// Default rp_filter setting (https://github.com/kube-vip/kube-vip/issues/1170)
rpfilterSetting := "0"
// Check if we need to set an override rp_filter value for the interface
if i.ServiceSnapshot.Annotations[kubevip.RPFilter] != "" {
// Check the rp_filter value
rpFilter, err := strconv.Atoi(i.ServiceSnapshot.Annotations[kubevip.RPFilter])
if err != nil {
slog.Error("[DHCP] unable to process rp_filter", "value", rpFilter)
} else {
if rpFilter >= 0 && rpFilter < 3 { // Ensure the value is 0,1,2
rpfilterSetting = i.ServiceSnapshot.Annotations[kubevip.RPFilter]
} else {
slog.Error("[DHCP] rp_filter value not within range 0-2", "value", rpFilter)
}
}
}
err = sysctl.WriteProcSys("/proc/sys/net/ipv4/conf/"+interfaceName+"/rp_filter", rpfilterSetting)
if err != nil {
slog.Error("[DHCP] unable to write rp_filter", "value", rpfilterSetting, "err", err)
}
var initRebootFlag bool
if i.DHCPInterfaceIP != "" {
initRebootFlag = true
}
client := vip.NewDHCPClient(iface, initRebootFlag, i.DHCPInterfaceIP)
// Add hostname to dhcp client if annotated
if i.DHCPHostname != "" {
log.Info("Hostname specified for dhcp lease", "interface", interfaceName, "hostname", i.DHCPHostname)
client.WithHostName(i.DHCPHostname)
}
go client.Start()
// Set that DHCP is enabled
i.IsDHCP = true
// Set the name of the interface so that it can be removed on Service deletion
i.DHCPInterface = interfaceName
i.DHCPInterfaceHwaddr = iface.HardwareAddr.String()
// Add the client so that we can call it to stop function
i.DHCPClient = client
return nil
}
// FetchLoadBalancerIngressAddresses tries to get the addresses from status.loadBalancerIP
func FetchLoadBalancerIngress(s *v1.Service) ([]string, []string) {
// If the service has no status, return empty
lbStatusAddresses := []string{}
lbStatusHostnames := []string{}
if len(s.Status.LoadBalancer.Ingress) == 0 {
return lbStatusAddresses, lbStatusHostnames
}
for _, ingress := range s.Status.LoadBalancer.Ingress {
if ingress.IP != "" {
lbStatusAddresses = append(lbStatusAddresses, ingress.IP)
}
if ingress.Hostname != "" {
lbStatusHostnames = append(lbStatusHostnames, ingress.Hostname)
}
}
return lbStatusAddresses, lbStatusHostnames
}
// FetchServiceAddresses tries to get the addresses from annotations
// kube-vip.io/loadbalancerIPs, then from spec.loadbalancerIP
func FetchServiceAddresses(s *v1.Service) ([]string, []string) {
annotationAvailable := false
if s.Annotations != nil {
if v, annotationAvailable := s.Annotations[kubevip.LoadbalancerIPAnnotation]; annotationAvailable {
ips := strings.Split(v, ",")
var trimmedIPs []string
var trimmedHostnames []string
for _, a := range ips {
a = strings.TrimSpace(a)
ip := net.ParseIP(a)
if ip == nil {
// this is probably a DNS name
trimmedHostnames = append(trimmedHostnames, a)
} else {
trimmedIPs = append(trimmedIPs, ip.String())
}
}
return trimmedIPs, trimmedHostnames
}
}
lbStatusAddresses := []string{}
lbStatusHostnames := []string{}
if !annotationAvailable {
lbStatusAddresses, lbStatusHostnames = FetchLoadBalancerIngress(s)
}
// Spec.LoadBalancerIP legacy handling
// if the loadBalancerIP is different from Status.LoadBalancer.Ingress IPs
// return the legacy LB as spec wins over status.
if lbIP := net.ParseIP(s.Spec.LoadBalancerIP); lbIP != nil && len(lbStatusAddresses) > 0 {
isLbIPv4 := utils.IsIPv4(s.Spec.LoadBalancerIP)
for _, a := range lbStatusAddresses {
if lbStatusIP := net.ParseIP(a); lbStatusIP != nil && utils.IsIPv4(a) == isLbIPv4 && !lbIP.Equal(lbStatusIP) {
return []string{s.Spec.LoadBalancerIP}, []string{}
}
}
}
if len(lbStatusAddresses) > 0 || len(lbStatusHostnames) > 0 {
return lbStatusAddresses, lbStatusHostnames
}
if s.Spec.LoadBalancerIP != "" {
return []string{s.Spec.LoadBalancerIP}, []string{}
}
return []string{}, []string{}
}
func FindServiceInstance(svc *v1.Service, instances []*Instance) *Instance {
log.Debug("finding service", "namespace", svc.Namespace, "name", svc.Name, "UID", svc.UID)
for i := range instances {
log.Debug("saved service", "instance", i, "UID", instances[i].ServiceSnapshot.UID)
if instances[i].ServiceSnapshot.UID == svc.UID {
return instances[i]
}
}
log.Debug("instance not found", "namespace", svc.Namespace, "name", svc.Name, "UID", svc.UID)
return nil
}
func FindServiceInstanceWithTimeout(svc *v1.Service, instances []*Instance) *Instance {
log.Debug("finding service with timeout", "namespace", svc.Namespace, "name", svc.Name, "UID", svc.UID)
ticker := time.NewTicker(time.Millisecond * 200)
defer ticker.Stop()
to := time.NewTimer(time.Second * 60)
defer to.Stop()
for {
select {
case <-to.C:
return nil
case <-ticker.C:
for i := range instances {
log.Debug("saved service", "instance", i, "UID", instances[i].ServiceSnapshot.UID)
if instances[i].ServiceSnapshot.UID == svc.UID {
return instances[i]
}
}
}
}
}

741
pkg/iptables/iptables.go Normal file
View File

@@ -0,0 +1,741 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package iptables
import (
"bytes"
"fmt"
"io"
"net"
"os/exec"
"regexp"
"strconv"
"strings"
"syscall"
)
// Adds the output of stderr to exec.ExitError
type Error struct {
exec.ExitError
cmd exec.Cmd
msg string
exitStatus *int //for overriding
}
func (e *Error) ExitStatus() int {
if e.exitStatus != nil {
return *e.exitStatus
}
return e.Sys().(syscall.WaitStatus).ExitStatus()
}
func (e *Error) Error() string {
return fmt.Sprintf("running %v: exit status %v: %v", e.cmd.Args, e.ExitStatus(), e.msg)
}
// IsNotExist returns true if the error is due to the chain or rule not existing
func (e *Error) IsNotExist() bool {
if e.ExitStatus() != 1 {
return false
}
msgNoRuleExist := "Bad rule (does a matching rule exist in that chain?).\n"
msgNoChainExist := "No chain/target/match by that name.\n"
return strings.Contains(e.msg, msgNoRuleExist) || strings.Contains(e.msg, msgNoChainExist)
}
// Protocol to differentiate between IPv4 and IPv6
type Protocol byte
const (
ProtocolIPv4 Protocol = iota
ProtocolIPv6
)
const (
TableFilter = "filter"
TableMangle = "mangle"
TableNat = "nat"
ChainInput = "INPUT"
ChainPREROUTING = "PREROUTING"
ChainPOSTROUTING = "POSTROUTING"
)
type IPTables struct {
path string
proto Protocol
hasCheck bool
hasWait bool
waitSupportSecond bool
hasRandomFully bool
v1 int
v2 int
v3 int
mode string // the underlying iptables operating mode, e.g. nf_tables
timeout int // time to wait for the iptables lock, default waits forever
nftables bool
}
// Stat represents a structured statistic entry.
type Stat struct {
Packets uint64 `json:"pkts"`
Bytes uint64 `json:"bytes"`
Target string `json:"target"`
Protocol string `json:"prot"`
Opt string `json:"opt"`
Input string `json:"in"`
Output string `json:"out"`
Source *net.IPNet `json:"source"`
Destination *net.IPNet `json:"destination"`
Options string `json:"options"`
}
type Option func(*IPTables)
func IPFamily(proto Protocol) Option {
return func(ipt *IPTables) {
ipt.proto = proto
}
}
func Timeout(timeout int) Option {
return func(ipt *IPTables) {
ipt.timeout = timeout
}
}
func EnableNFTables(enable bool) Option {
return func(ipt *IPTables) {
ipt.nftables = enable
}
}
// New creates a new IPTables configured with the options passed as parameter.
// For backwards compatibility, by default always uses IPv4 and timeout 0.
// i.e. you can create an IPv6 IPTables using a timeout of 5 seconds passing
// the IPFamily and Timeout options as follow:
//
// ip6t := New(IPFamily(ProtocolIPv6), Timeout(5))
func New(opts ...Option) (*IPTables, error) {
ipt := &IPTables{
proto: ProtocolIPv4,
timeout: 0,
}
for _, opt := range opts {
opt(ipt)
}
path, err := exec.LookPath(getIptablesCommand(ipt.proto, ipt.nftables))
if err != nil {
return nil, err
}
ipt.path = path
vstring, err := getIptablesVersionString(path)
if err != nil {
return nil, fmt.Errorf("could not get iptables version: %v", err)
}
v1, v2, v3, mode, err := extractIptablesVersion(vstring)
if err != nil {
return nil, fmt.Errorf("failed to extract iptables version from [%s]: %v", vstring, err)
}
ipt.v1 = v1
ipt.v2 = v2
ipt.v3 = v3
ipt.mode = mode
checkPresent, waitPresent, waitSupportSecond, randomFullyPresent := getIptablesCommandSupport(v1, v2, v3)
ipt.hasCheck = checkPresent
ipt.hasWait = waitPresent
ipt.waitSupportSecond = waitSupportSecond
ipt.hasRandomFully = randomFullyPresent
return ipt, nil
}
// New creates a new IPTables for the given proto.
// The proto will determine which command is used, either "iptables" or "ip6tables".
func NewWithProtocol(proto Protocol) (*IPTables, error) {
return New(IPFamily(proto), Timeout(0))
}
// Proto returns the protocol used by this IPTables.
func (ipt *IPTables) Proto() Protocol {
return ipt.proto
}
// Exists checks if given rulespec in specified table/chain exists
func (ipt *IPTables) Exists(table, chain string, rulespec ...string) (bool, error) {
if !ipt.hasCheck {
return ipt.existsForOldIptables(table, chain, rulespec)
}
cmd := append([]string{"-t", table, "-C", chain}, rulespec...)
err := ipt.run(cmd...)
eerr, eok := err.(*Error)
switch {
case err == nil:
return true, nil
case eok && eerr.ExitStatus() == 1:
return false, nil
default:
return false, err
}
}
// Insert inserts rulespec to specified table/chain (in specified pos)
func (ipt *IPTables) Insert(table, chain string, pos int, rulespec ...string) error {
cmd := append([]string{"-t", table, "-I", chain, strconv.Itoa(pos)}, rulespec...)
return ipt.run(cmd...)
}
// InsertUnique acts like Insert except that it won't insert a duplicate (no matter the position in the chain)
func (ipt *IPTables) InsertUnique(table, chain string, pos int, rulespec ...string) error {
exists, err := ipt.Exists(table, chain, rulespec...)
if err != nil {
return err
}
if !exists {
return ipt.Insert(table, chain, pos, rulespec...)
}
return nil
}
// Append appends rulespec to specified table/chain
func (ipt *IPTables) Append(table, chain string, rulespec ...string) error {
cmd := append([]string{"-t", table, "-A", chain}, rulespec...)
return ipt.run(cmd...)
}
// AppendUnique acts like Append except that it won't add a duplicate
func (ipt *IPTables) AppendUnique(table, chain string, rulespec ...string) error {
exists, err := ipt.Exists(table, chain, rulespec...)
if err != nil {
return err
}
if !exists {
return ipt.Append(table, chain, rulespec...)
}
return nil
}
// Delete removes rulespec in specified table/chain
func (ipt *IPTables) Delete(table, chain string, rulespec ...string) error {
cmd := append([]string{"-t", table, "-D", chain}, rulespec...)
return ipt.run(cmd...)
}
func (ipt *IPTables) DeleteIfExists(table, chain string, rulespec ...string) error {
exists, err := ipt.Exists(table, chain, rulespec...)
if err == nil && exists {
err = ipt.Delete(table, chain, rulespec...)
}
return err
}
// List rules in specified table/chain
func (ipt *IPTables) ListByID(table, chain string, id int) (string, error) {
args := []string{"-t", table, "-S", chain, strconv.Itoa(id)}
rule, err := ipt.executeList(args)
if err != nil {
return "", err
}
return rule[0], nil
}
// List rules in specified table/chain
func (ipt *IPTables) List(table, chain string) ([]string, error) {
args := []string{"-t", table, "-S", chain}
return ipt.executeList(args)
}
// List rules (with counters) in specified table/chain
func (ipt *IPTables) ListWithCounters(table, chain string) ([]string, error) {
args := []string{"-t", table, "-v", "-S", chain}
return ipt.executeList(args)
}
// ListChains returns a slice containing the name of each chain in the specified table.
func (ipt *IPTables) ListChains(table string) ([]string, error) {
args := []string{"-t", table, "-S"}
result, err := ipt.executeList(args)
if err != nil {
return nil, err
}
// Iterate over rules to find all default (-P) and user-specified (-N) chains.
// Chains definition always come before rules.
// Format is the following:
// -P OUTPUT ACCEPT
// -N Custom
var chains []string
for _, val := range result {
if strings.HasPrefix(val, "-P") || strings.HasPrefix(val, "-N") {
chains = append(chains, strings.Fields(val)[1])
} else {
break
}
}
return chains, nil
}
// '-S' is fine with non existing rule index as long as the chain exists
// therefore pass index 1 to reduce overhead for large chains
func (ipt *IPTables) ChainExists(table, chain string) (bool, error) {
err := ipt.run("-t", table, "-S", chain, "1")
eerr, eok := err.(*Error)
switch {
case err == nil:
return true, nil
case eok && eerr.ExitStatus() == 1:
return false, nil
default:
return false, err
}
}
// Stats lists rules including the byte and packet counts
func (ipt *IPTables) Stats(table, chain string) ([][]string, error) {
args := []string{"-t", table, "-L", chain, "-n", "-v", "-x"}
lines, err := ipt.executeList(args)
if err != nil {
return nil, err
}
appendSubnet := func(addr string) string {
if strings.IndexByte(addr, byte('/')) < 0 {
if strings.IndexByte(addr, '.') < 0 {
return addr + "/128"
}
return addr + "/32"
}
return addr
}
ipv6 := ipt.proto == ProtocolIPv6
rows := [][]string{}
for i, line := range lines {
// Skip over chain name and field header
if i < 2 {
continue
}
// Fields:
// 0=pkts 1=bytes 2=target 3=prot 4=opt 5=in 6=out 7=source 8=destination 9=options
line = strings.TrimSpace(line)
fields := strings.Fields(line)
// The ip6tables verbose output cannot be naively split due to the default "opt"
// field containing 2 single spaces.
if ipv6 {
// Check if field 6 is "opt" or "source" address
dest := fields[6]
ip, _, _ := net.ParseCIDR(dest)
if ip == nil {
ip = net.ParseIP(dest)
}
// If we detected a CIDR or IP, the "opt" field is empty.. insert it.
if ip != nil {
f := []string{}
f = append(f, fields[:4]...)
f = append(f, " ") // Empty "opt" field for ip6tables
f = append(f, fields[4:]...)
fields = f
}
}
// Adjust "source" and "destination" to include netmask, to match regular
// List output
fields[7] = appendSubnet(fields[7])
fields[8] = appendSubnet(fields[8])
// Combine "options" fields 9... into a single space-delimited field.
options := fields[9:]
fields = fields[:9]
fields = append(fields, strings.Join(options, " "))
rows = append(rows, fields)
}
return rows, nil
}
// ParseStat parses a single statistic row into a Stat struct. The input should
// be a string slice that is returned from calling the Stat method.
func (ipt *IPTables) ParseStat(stat []string) (parsed Stat, err error) {
// For forward-compatibility, expect at least 10 fields in the stat
if len(stat) < 10 {
return parsed, fmt.Errorf("stat contained fewer fields than expected")
}
// Convert the fields that are not plain strings
parsed.Packets, err = strconv.ParseUint(stat[0], 0, 64)
if err != nil {
return parsed, fmt.Errorf(err.Error(), "could not parse packets")
}
parsed.Bytes, err = strconv.ParseUint(stat[1], 0, 64)
if err != nil {
return parsed, fmt.Errorf(err.Error(), "could not parse bytes")
}
_, parsed.Source, err = net.ParseCIDR(stat[7])
if err != nil {
return parsed, fmt.Errorf(err.Error(), "could not parse source")
}
_, parsed.Destination, err = net.ParseCIDR(stat[8])
if err != nil {
return parsed, fmt.Errorf(err.Error(), "could not parse destination")
}
// Put the fields that are strings
parsed.Target = stat[2]
parsed.Protocol = stat[3]
parsed.Opt = stat[4]
parsed.Input = stat[5]
parsed.Output = stat[6]
parsed.Options = stat[9]
return parsed, nil
}
// StructuredStats returns statistics as structured data which may be further
// parsed and marshaled.
func (ipt *IPTables) StructuredStats(table, chain string) ([]Stat, error) {
rawStats, err := ipt.Stats(table, chain)
if err != nil {
return nil, err
}
structStats := []Stat{}
for _, rawStat := range rawStats {
stat, err := ipt.ParseStat(rawStat)
if err != nil {
return nil, err
}
structStats = append(structStats, stat)
}
return structStats, nil
}
func (ipt *IPTables) executeList(args []string) ([]string, error) {
var stdout bytes.Buffer
if err := ipt.runWithOutput(args, &stdout); err != nil {
return nil, err
}
rules := strings.Split(stdout.String(), "\n")
// strip trailing newline
if len(rules) > 0 && rules[len(rules)-1] == "" {
rules = rules[:len(rules)-1]
}
for i, rule := range rules {
rules[i] = filterRuleOutput(rule)
}
return rules, nil
}
// NewChain creates a new chain in the specified table.
// If the chain already exists, it will result in an error.
func (ipt *IPTables) NewChain(table, chain string) error {
return ipt.run("-t", table, "-N", chain)
}
const existsErr = 1
// ClearChain flushed (deletes all rules) in the specified table/chain.
// If the chain does not exist, a new one will be created
func (ipt *IPTables) ClearChain(table, chain string) error {
err := ipt.NewChain(table, chain)
eerr, eok := err.(*Error)
switch {
case err == nil:
return nil
case eok && eerr.ExitStatus() == existsErr:
// chain already exists. Flush (clear) it.
return ipt.run("-t", table, "-F", chain)
default:
return err
}
}
// RenameChain renames the old chain to the new one.
func (ipt *IPTables) RenameChain(table, oldChain, newChain string) error {
return ipt.run("-t", table, "-E", oldChain, newChain)
}
// DeleteChain deletes the chain in the specified table.
// The chain must be empty
func (ipt *IPTables) DeleteChain(table, chain string) error {
return ipt.run("-t", table, "-X", chain)
}
func (ipt *IPTables) ClearAndDeleteChain(table, chain string) error {
exists, err := ipt.ChainExists(table, chain)
if err != nil || !exists {
return err
}
err = ipt.run("-t", table, "-F", chain)
if err == nil {
err = ipt.run("-t", table, "-X", chain)
}
return err
}
func (ipt *IPTables) ClearAll() error {
return ipt.run("-F")
}
func (ipt *IPTables) DeleteAll() error {
return ipt.run("-X")
}
// ChangePolicy changes policy on chain to target
func (ipt *IPTables) ChangePolicy(table, chain, target string) error {
return ipt.run("-t", table, "-P", chain, target)
}
// Check if the underlying iptables command supports the --random-fully flag
func (ipt *IPTables) HasRandomFully() bool {
return ipt.hasRandomFully
}
// Return version components of the underlying iptables command
func (ipt *IPTables) GetIptablesVersion() (int, int, int) {
return ipt.v1, ipt.v2, ipt.v3
}
// run runs an iptables command with the given arguments, ignoring
// any stdout output
func (ipt *IPTables) run(args ...string) error {
return ipt.runWithOutput(args, nil)
}
// runWithOutput runs an iptables command with the given arguments,
// writing any stdout output to the given writer
func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error {
args = append([]string{ipt.path}, args...)
if ipt.hasWait {
args = append(args, "--wait")
if ipt.timeout != 0 && ipt.waitSupportSecond {
args = append(args, strconv.Itoa(ipt.timeout))
}
} else {
fmu, err := newXtablesFileLock()
if err != nil {
return err
}
ul, err := fmu.tryLock()
if err != nil {
syscall.Close(fmu.fd)
return err
}
defer func() {
_ = ul.Unlock()
}()
}
var stderr bytes.Buffer
cmd := exec.Cmd{
Path: ipt.path,
Args: args,
Stdout: stdout,
Stderr: &stderr,
}
if err := cmd.Run(); err != nil {
switch e := err.(type) {
case *exec.ExitError:
return &Error{*e, cmd, stderr.String(), nil}
default:
return err
}
}
return nil
}
// getIptablesCommand returns the correct command for the given protocol, either "iptables" or "ip6tables".
func getIptablesCommand(proto Protocol, nftables bool) string {
if proto == ProtocolIPv6 {
if nftables {
return "ip6tables-nft"
}
return "ip6tables-legacy"
}
if nftables {
return "iptables-nft"
}
return "iptables-legacy"
}
// Checks if iptables has the "-C" and "--wait" flag
func getIptablesCommandSupport(v1 int, v2 int, v3 int) (bool, bool, bool, bool) {
return iptablesHasCheckCommand(v1, v2, v3), iptablesHasWaitCommand(v1, v2, v3), iptablesWaitSupportSecond(v1, v2), iptablesHasRandomFully(v1, v2, v3)
}
// getIptablesVersion returns the first three components of the iptables version
// and the operating mode (e.g. nf_tables or legacy)
// e.g. "iptables v1.3.66" would return (1, 3, 66, legacy, nil)
func extractIptablesVersion(str string) (int, int, int, string, error) {
versionMatcher := regexp.MustCompile(`v([0-9]+)\.([0-9]+)\.([0-9]+)(?:\s+\((\w+))?`)
result := versionMatcher.FindStringSubmatch(str)
if result == nil {
return 0, 0, 0, "", fmt.Errorf("no iptables version found in string: %s", str)
}
v1, err := strconv.Atoi(result[1])
if err != nil {
return 0, 0, 0, "", err
}
v2, err := strconv.Atoi(result[2])
if err != nil {
return 0, 0, 0, "", err
}
v3, err := strconv.Atoi(result[3])
if err != nil {
return 0, 0, 0, "", err
}
mode := "legacy"
if result[4] != "" {
mode = result[4]
}
return v1, v2, v3, mode, nil
}
// Runs "iptables --version" to get the version string
func getIptablesVersionString(path string) (string, error) {
cmd := exec.Command(path, "--version")
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return "", err
}
return out.String(), nil
}
// Checks if an iptables version is after 1.4.11, when --check was added
func iptablesHasCheckCommand(v1 int, v2 int, v3 int) bool {
if v1 > 1 {
return true
}
if v1 == 1 && v2 > 4 {
return true
}
if v1 == 1 && v2 == 4 && v3 >= 11 {
return true
}
return false
}
// Checks if an iptables version is after 1.4.20, when --wait was added
func iptablesHasWaitCommand(v1 int, v2 int, v3 int) bool { //nolint
if v1 > 1 {
return true
}
if v1 == 1 && v2 > 4 {
return true
}
if v1 == 1 && v2 == 4 && v3 >= 20 {
return true
}
return false
}
// Checks if an iptablse version is after 1.6.0, when --wait support second
func iptablesWaitSupportSecond(v1 int, v2 int) bool {
if v1 > 1 {
return true
}
if v1 == 1 && v2 >= 6 {
return true
}
return false
}
// Checks if an iptables version is after 1.6.2, when --random-fully was added
func iptablesHasRandomFully(v1 int, v2 int, v3 int) bool {
if v1 > 1 {
return true
}
if v1 == 1 && v2 > 6 {
return true
}
if v1 == 1 && v2 == 6 && v3 >= 2 {
return true
}
return false
}
// Checks if a rule specification exists for a table
func (ipt *IPTables) existsForOldIptables(table, chain string, rulespec []string) (bool, error) {
rs := strings.Join(append([]string{"-A", chain}, rulespec...), " ")
args := []string{"-t", table, "-S"}
var stdout bytes.Buffer
err := ipt.runWithOutput(args, &stdout)
if err != nil {
return false, err
}
return strings.Contains(stdout.String(), rs), nil
}
// counterRegex is the regex used to detect nftables counter format
var counterRegex = regexp.MustCompile(`^\[([0-9]+):([0-9]+)\] `)
// filterRuleOutput works around some inconsistencies in output.
// For example, when iptables is in legacy vs. nftables mode, it produces
// different results.
func filterRuleOutput(rule string) string {
out := rule
// work around an output difference in nftables mode where counters
// are output in iptables-save format, rather than iptables -S format
// The string begins with "[0:0]"
//
// Fixes #49
if groups := counterRegex.FindStringSubmatch(out); groups != nil {
// drop the brackets
out = out[len(groups[0]):]
out = fmt.Sprintf("%s -c %s %s", out, groups[1], groups[2])
}
return out
}
func GetIPTablesRuleSpecification(rule, specification string) string {
parts := strings.Split(rule, " ")
for i, part := range parts {
if part == specification && i+1 < len(parts) {
return parts[i+1]
}
}
return ""
}

84
pkg/iptables/lock.go Normal file
View File

@@ -0,0 +1,84 @@
// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package iptables
import (
"os"
"sync"
"syscall"
)
const (
// In earlier versions of iptables, the xtables lock was implemented
// via a Unix socket, but now flock is used via this lockfile:
// http://git.netfilter.org/iptables/commit/?id=aa562a660d1555b13cffbac1e744033e91f82707
// Note the LSB-conforming "/run" directory does not exist on old
// distributions, so assume "/var" is symlinked
xtablesLockFilePath = "/var/run/xtables.lock"
defaultFilePerm = 0600
)
type Unlocker interface {
Unlock() error
}
type nopUnlocker struct{}
func (n nopUnlocker) Unlock() error { return nil }
type fileLock struct {
// mu is used to protect against concurrent invocations from within this process
mu sync.Mutex
fd int
}
// tryLock takes an exclusive lock on the xtables lock file without blocking.
// This is best-effort only: if the exclusive lock would block (i.e. because
// another process already holds it), no error is returned. Otherwise, any
// error encountered during the locking operation is returned.
// The returned Unlocker should be used to release the lock when the caller is
// done invoking iptables commands.
func (l *fileLock) tryLock() (Unlocker, error) {
l.mu.Lock()
err := syscall.Flock(l.fd, syscall.LOCK_EX|syscall.LOCK_NB)
switch err {
case syscall.EWOULDBLOCK:
l.mu.Unlock()
return nopUnlocker{}, nil
case nil:
return l, nil
default:
l.mu.Unlock()
return nil, err
}
}
// Unlock closes the underlying file, which implicitly unlocks it as well. It
// also unlocks the associated mutex.
func (l *fileLock) Unlock() error {
defer l.mu.Unlock()
return syscall.Close(l.fd)
}
// newXtablesFileLock opens a new lock on the xtables lockfile without
// acquiring the lock
func newXtablesFileLock() (*fileLock, error) {
fd, err := syscall.Open(xtablesLockFilePath, os.O_CREATE, defaultFilePerm)
if err != nil {
return nil, err
}
return &fileLock{fd: fd}, nil
}

91
pkg/iptables/version.go Normal file
View File

@@ -0,0 +1,91 @@
package iptables
import (
"fmt"
"os/exec"
"regexp"
"strconv"
"strings"
)
type Version struct {
Major int
Minor int
Patch int
BackendMode string
}
func (v Version) String() string {
return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
func (v Version) Compare(other Version) int {
if v.Major != other.Major {
return v.Major - other.Major
}
if v.Minor != other.Minor {
return v.Minor - other.Minor
}
return v.Patch - other.Patch
}
func ParseVersion(versionString string) (Version, error) {
re := regexp.MustCompile(`v([0-9]+)\.([0-9]+)\.([0-9]+)`)
match := re.FindStringSubmatch(versionString)
if len(match) != 4 {
return Version{}, fmt.Errorf("invalid version string: %s", versionString)
}
major, _ := strconv.Atoi(match[1])
minor, _ := strconv.Atoi(match[2])
patch, _ := strconv.Atoi(match[3])
return Version{Major: major, Minor: minor, Patch: patch}, nil
}
func GetVersion() (Version, error) {
ver := Version{}
cmd := exec.Command("iptables", "--version")
out, err := cmd.Output()
if err != nil {
return ver, fmt.Errorf("run cmd 'iptables --version' wtith error: %v", err)
}
ver, err = ParseVersion(string(out))
if err != nil {
return ver, err
}
nft4 := getOutput("iptables-nft-save")
legacy4 := getOutput("iptables-legacy-save")
nft6 := getOutput("ip6tables-nft-save")
legacy6 := getOutput("ip6tables-legacy-save")
if strings.Contains(nft4, "KUBE-IPTABLES") ||
strings.Contains(nft6, "KUBE-IPTABLES") ||
strings.Contains(nft4, "KUBE-KUBELET") ||
strings.Contains(nft6, "KUBE-KUBELET") {
ver.BackendMode = "nft"
} else if strings.Contains(legacy4, "KUBE-IPTABLES") ||
strings.Contains(legacy6, "KUBE-IPTABLES") ||
strings.Contains(legacy4, "KUBE-KUBELET") ||
strings.Contains(legacy6, "KUBE-KUBELET") {
ver.BackendMode = "legacy"
} else {
nftCount := strings.Count(nft4, "\n") + strings.Count(nft6, "\n")
legacyCount := strings.Count(legacy4, "\n") + strings.Count(legacy6, "\n")
if nftCount >= legacyCount {
ver.BackendMode = "nft"
} else {
ver.BackendMode = "legacy"
}
}
return ver, nil
}
func getOutput(name string) string {
cmd := exec.Command(name)
out, _ := cmd.Output()
return string(out)
}

123
pkg/k8s/client.go Normal file
View File

@@ -0,0 +1,123 @@
package k8s
import (
"crypto/tls"
"fmt"
"net"
"time"
log "log/slog"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
const (
defaultTimeout = 10 * time.Second
)
// NewClientset takes REST config and returns k8s clientest.
func NewClientset(config *rest.Config) (*kubernetes.Clientset, error) {
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("error creating kubernetes client: %s", err.Error())
}
return clientset, nil
}
// NewRestConfig takes an optional configPath and creates a new REST config for clientset.
// If the configPath is not specified, and inCluster is true, then an
// InClusterConfig is used.
// Also takes a hostname which allow for overriding the config's hostname.
func NewRestConfig(configPath string, inCluster bool, hostname string) (*rest.Config, error) {
config, err := restConfig(configPath, inCluster, defaultTimeout)
if err != nil {
return nil, fmt.Errorf("failed to create rest config: %w", err)
}
if len(hostname) > 0 {
config.Host = hostname
}
return config, nil
}
func restConfig(kubeconfig string, inCluster bool, timeout time.Duration) (*rest.Config, error) {
var cfg *rest.Config
var err error
if inCluster {
if cfg, err = rest.InClusterConfig(); err != nil {
return nil, fmt.Errorf("failed to get incluster config: %w", err)
}
} else if kubeconfig != "" {
if cfg, err = clientcmd.BuildConfigFromFlags("", kubeconfig); err != nil {
return nil, fmt.Errorf("failed to build config from file '%s': %w", kubeconfig, err)
}
} else {
return nil, fmt.Errorf("failed to build config from file: path to KubeConfig not specified")
}
// Override some of the defaults allowing a little bit more flexibility speaking with the API server
// these should hopefully be redundant, however issues will still be logged.
cfg.QPS = 100
cfg.Burst = 250
cfg.Timeout = timeout
return cfg, nil
}
func findAddressFromRemoteCert(address string) ([]net.IP, error) {
// TODO: should we care at this point, probably not as we just want the certificates
conf := &tls.Config{
MinVersion: tls.VersionTLS12,
InsecureSkipVerify: true, //nolint
}
d := &net.Dialer{
Timeout: time.Duration(3) * time.Second,
}
// Create the TCP connection
conn, err := tls.DialWithDialer(d, "tcp", address, conf)
if err != nil {
return nil, err
}
defer conn.Close()
// Grab the certificactes
certs := conn.ConnectionState().PeerCertificates
if len(certs) > 1 {
return nil, fmt.Errorf("[k8s client] not designed to recive multiple certs from API server")
}
return certs[0].IPAddresses, nil
}
func FindWorkingKubernetesAddress(configPath string, inCluster bool) (*rest.Config, error) {
// check with loopback, and retrieve its certificate
ips, err := findAddressFromRemoteCert("127.0.0.1:6443")
if err != nil {
return nil, err
}
for x := range ips {
log.Debug("[k8s client] testing", "address", ips[x].String())
c, err := NewRestConfig(configPath, inCluster, net.JoinHostPort(ips[x].String(), "6443"))
if err != nil {
log.Error("failed to create k8s REST config", "err", err)
}
c.Timeout = 2 * time.Second
k, err := NewClientset(c)
if err != nil {
log.Error("failed to create k8s clientset", "err", err)
}
_, err = k.DiscoveryClient.ServerVersion()
if err == nil {
log.Info("[k8s client] working", "address", ips[x].String())
c.Timeout = defaultTimeout
return c, nil
}
}
return nil, fmt.Errorf("unable to find a working address for the local API server [%v]", err)
}

70
pkg/k8s/client_test.go Normal file
View File

@@ -0,0 +1,70 @@
package k8s
//"192.168.0.174:6443"
// func Test_findAddressFromRemoteCert(t *testing.T) {
// type args struct {
// address string
// }
// tests := []struct {
// name string
// args args
// want []net.IP
// wantErr bool
// }{
// {
// name: "test server",
// args: args{address: "192.168.0.174:6443"},
// want: []net.IP{net.IPv4(10, 96, 0, 1), net.IPv4(192, 168, 0, 174)},
// wantErr: false,
// },
// }
// for _, tt := range tests {
// t.Run(tt.name, func(t *testing.T) {
// got, err := findAddressFromRemoteCert(tt.args.address)
// if (err != nil) != tt.wantErr {
// t.Errorf("findAddressFromRemoteCert() error = %v, wantErr %v", err, tt.wantErr)
// return
// }
// if !reflect.DeepEqual(got, tt.want) {
// t.Errorf("findAddressFromRemoteCert() = %v, want %v", got, tt.want)
// }
// })
// }
// }
// //findAddressFromRemoteCert() =
// //[10.96.0.1 192.168.0.174]
// //[10.96.0.1 192.168.0.174]
// func Test_findWorkingKubernetesAddress(t *testing.T) {
// type args struct {
// configPath string
// inCluster bool
// }
// tests := []struct {
// name string
// args args
// want *kubernetes.Clientset
// wantErr bool
// }{
// {
// name: "test",
// args: args{
// configPath: "/home/dan/super-admin.conf",
// inCluster: false,
// },
// wantErr: false,
// },
// }
// for _, tt := range tests {
// t.Run(tt.name, func(t *testing.T) {
// _, err := FindWorkingKubernetesAddress(tt.args.configPath, tt.args.inCluster)
// if (err != nil) != tt.wantErr {
// t.Errorf("findWorkingKubernetesAddress() error = %v, wantErr %v", err, tt.wantErr)
// return
// }
// })
// }
// }

Some files were not shown because too many files have changed in this diff Show More