Compare commits

...

738 Commits

Author SHA1 Message Date
Dan Finneran
296c9c1580 Unintentionally created duplicate functions that can't be used
Signed-off-by: Dan Finneran <dan@thebsdbox.co.uk>
2025-08-12 12:17:20 +00: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
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
James Connor
6f2acf0198 Increase client QPS to reduce clientside k8api throttling 2023-05-30 12:54:46 +01:00
199 changed files with 15235 additions and 10188 deletions

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

View File

@@ -22,10 +22,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{ github.ref_name }}
- name: Anchore SBOM Action
uses: anchore/sbom-action@v0.12.0
uses: anchore/sbom-action@v0.20.4
with:
format: cyclonedx-json

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

@@ -0,0 +1,51 @@
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
max-parallel: 1
steps:
- 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@v4
- name: Install Go
uses: actions/setup-go@v5
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: make e2e-tests129-arp
if: matrix.mode== 'arp'
- name: Run RT mode tests v1.29.0 onwards
run: 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 make e2e-tests129-bgp
if: matrix.mode== 'bgp'
service-e2e-tests:
runs-on: ubuntu-latest
name: E2E service tests
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Build image with iptables
run: make dockerx86ActionIPTables
- name: Run tests
run: DOCKERTAG=action make service-tests

View File

@@ -1,28 +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@v3
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: '1.20'
- 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.53.3
- name: checks
run: make check
- name: test docker build
run: make dockerx86Action
- name: e2e controlplane
run: DOCKERTAG=action make e2e-tests
- name: e2e services
run: DOCKERTAG=action make service-tests
- 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@v4
- name: Install Go
uses: actions/setup-go@v5
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@v4
- name: Install Go
uses: actions/setup-go@v5
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@v4
- name: Install Go
uses: actions/setup-go@v5
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@v4
- 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"

View File

@@ -38,11 +38,16 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -53,7 +58,7 @@ jobs:
# 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@v1
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -67,4 +72,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v3

View File

@@ -11,25 +11,25 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v1
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to Github Packages
uses: docker/login-action@v1
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@v2
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
@@ -39,7 +39,7 @@ jobs:
ghcr.io/kube-vip/kube-vip:${{ github.ref_name }}
- name: Build iptables version
id: docker_build_iptables
uses: docker/build-push-action@v2
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile_iptables

View File

@@ -11,29 +11,36 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to Github Packages
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate Metadata
uses: docker/metadata-action@v5.7.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@v4
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,
@@ -41,12 +48,13 @@ jobs:
ghcr.io/kube-vip/kube-vip:latest
- name: Build iptables version and push main branch
id: docker_build_iptables
uses: docker/build-push-action@v4
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,

8
.gitignore vendored
View File

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

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:experimental
FROM golang:1.20.6-alpine3.17 as dev
FROM golang:1.24.5-alpine3.22 as dev
RUN apk add --no-cache git ca-certificates make
RUN adduser -D appuser
COPY . /src/

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:experimental
FROM golang:1.19.2-alpine3.16 as dev
FROM golang:1.24.5-alpine3.22 as dev
RUN apk add --no-cache git make
RUN adduser -D appuser
COPY . /src/
@@ -11,9 +11,11 @@ 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.16.2
# Add Certificates into the image, for anything that does API calls
RUN apk add --no-cache iptables
FROM alpine:3.22.1
# 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"]

View File

@@ -5,7 +5,7 @@ TARGET := kube-vip
.DEFAULT_GOAL := $(TARGET)
# These will be provided to the target
VERSION := v0.6.0
VERSION := v1.0.0
BUILD := `git rev-parse HEAD`
@@ -15,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 ?= 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
@@ -37,9 +37,6 @@ 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,linux/ppc64le,linux/s390x --push -t $(REPOSITORY)/$(TARGET):$(DOCKERTAG) .
@@ -59,6 +56,11 @@ dockerx86Iptables:
@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) .
@@ -81,18 +83,23 @@ 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,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'"
test -z $(shell gofmt -l *.go pkg cmd) || echo "[WARN] Fix formatting issues with 'make simplify'"
golangci-lint run
go vet ./...
@@ -108,11 +115,65 @@ manifests:
@./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 --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 --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 daemonset --interface eth0 --vip 192.168.0.1 --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 --arp --leaderElection --controlplane --services
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest pod --interface eth0 --vip 192.168.0.1 --arp --leaderElection --controlplane --services --enableLoadBalancer
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest pod --interface eth0 --vip 192.168.0.1 --bgp --controlplane --services
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest daemonset --interface eth0 --vip 192.168.0.1 --arp --leaderElection --controlplane --services --inCluster
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest daemonset --interface eth0 --vip 192.168.0.1 --arp --leaderElection --controlplane --services --inCluster --enableLoadBalancer
docker run $(REPOSITORY)/$(TARGET):$(DOCKERTAG) manifest daemonset --interface eth0 --vip 192.168.0.1 --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 -tags=e2e -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/e2e/services
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 --arp --servicesElection --interface eth0 | kubectl apply -f -
kind-reload:
kind load docker-image $(REPOSITORY)/$(TARGET):$(DOCKERTAG) --name kube-vip
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

@@ -4,7 +4,7 @@ High Availability and Load-Balancing
![](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)
[![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
@@ -32,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?

View File

@@ -4,8 +4,9 @@ import (
"fmt"
"os"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/kubevip"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -22,7 +23,7 @@ func init() {
var kubeKubeadm = &cobra.Command{
Use: "kubeadm",
Short: "Kubeadm functions",
Run: func(cmd *cobra.Command, args []string) {
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
_ = cmd.Help()
// TODO - A load of text detailing what's actually happening
},
@@ -32,63 +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
err := kubevip.ParseEnvironment(&initConfig)
if err != nil {
log.Fatalf("Error parsing environment from config: %v", err)
log.Error("parsing environment", "err", err)
return
}
// TODO - check for certain things VIP/interfaces
if initConfig.Interface == "" {
_ = cmd.Help()
log.Fatalln("No interface is specified for kube-vip to bind to")
log.Error("No interface is specified for kube-vip to bind to")
return
}
if initConfig.VIP == "" && initConfig.Address == "" {
_ = cmd.Help()
log.Fatalln("No address is specified for kube-vip to expose services on")
log.Error("No address is specified for kube-vip to expose services on")
return
}
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)
if err != nil {
log.Error("generating VIPSubnet", "err", err)
return
}
}
cfg := kubevip.GeneratePodManifestFromConfig(&initConfig, 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
err := kubevip.ParseEnvironment(&initConfig)
if err != nil {
log.Fatalf("Error parsing environment from config: %v", err)
log.Error("parsing environment", "err", err)
return
}
// TODO - check for certain things VIP/interfaces
if initConfig.Interface == "" {
_ = cmd.Help()
log.Fatalln("No interface is specified for kube-vip to bind to")
log.Error("No interface is specified for kube-vip to bind to")
return
}
if initConfig.VIP == "" && initConfig.Address == "" {
_ = cmd.Help()
log.Fatalln("No address is specified for kube-vip to expose services on")
log.Error("No address is specified for kube-vip to expose services on")
return
}
if _, err := os.Stat(kubeConfigPath); os.IsNotExist(err) {
log.Fatalf("Unable to find file [%s]", kubeConfigPath)
log.Error("kubeConfig not found", "Path", kubeConfigPath)
return
}
// Ensure there is an address to generate the CIDR from
if initConfig.VIPSubnet == "" && initConfig.Address != "" {
initConfig.VIPSubnet, err = GenerateCidrRange(initConfig.Address)
if err != nil {
log.Error("generating VIPSubnet", "err", err)
return
}
}
// Generate manifest and print
cfg := kubevip.GeneratePodManifestFromConfig(&initConfig, Release.Version, inCluster)
fmt.Println(cfg)
fmt.Println(cfg) // output manifest to stdout
},
}

View File

@@ -3,8 +3,9 @@ package cmd
import (
"fmt"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/kubevip"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -12,22 +13,25 @@ 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")
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) {
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
_ = cmd.Help()
// TODO - A load of text detailing what's actually happening
},
@@ -36,47 +40,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
if err := kubevip.ParseEnvironment(&initConfig); err != nil {
log.Fatalf("Error parsing environment from config: %v", err)
log.Error("parsing environment", "err", err)
return
}
// The control plane has a requirement for a VIP being specified
if initConfig.EnableControlPlane && (initConfig.VIP == "" && initConfig.Address == "" && !initConfig.DDNS) {
_ = cmd.Help()
log.Fatalln("No address is specified for kube-vip to expose services on")
log.Error("No address is specified for kube-vip to expose services on")
return
}
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)
if err != nil {
log.Error("config parse", "err", err)
return
}
}
cfg := kubevip.GeneratePodManifestFromConfig(&initConfig, 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
if err := kubevip.ParseEnvironment(&initConfig); err != nil {
log.Fatalf("error parsing environment config: %v", err)
log.Error("parsing environment", "err", err)
return
}
// The control plane has a requirement for a VIP being specified
if initConfig.EnableControlPlane && (initConfig.VIP == "" && initConfig.Address == "" && !initConfig.DDNS) {
_ = cmd.Help()
log.Error("No address is specified for kube-vip to expose services on")
return
}
// TODO - check for certain things VIP/interfaces
// Ensure there is an address to generate the CIDR from
if initConfig.VIPSubnet == "" && initConfig.Address != "" {
initConfig.VIPSubnet, err = GenerateCidrRange(initConfig.Address)
if err != nil {
log.Error("config parse", "err", err)
return
}
}
cfg := kubevip.GenerateDaemonsetManifestFromConfig(&initConfig, 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.EnableControlPlane && (initConfig.VIP == "" && initConfig.Address == "" && !initConfig.DDNS) {
_ = cmd.Help()
log.Fatalln("No address is specified for kube-vip to expose services on")
log.Error("No address is specified for kube-vip to expose services on")
return
}
cfg := kubevip.GenerateDaemonsetManifestFromConfig(&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)
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,114 +0,0 @@
package cmd
import (
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/cluster"
"github.com/kube-vip/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 separated 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 separated backends, format: address:port")
kubeVipStart.Flags().StringVar(&startConfigLB.ForwardingMethod, "lbForwardingMethod", "local", "The forwarding method of a load balancer instance")
// 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
// 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
if err := newCluster.StartSingleNode(&startConfig, disableVIP); err != nil {
log.Errorf("error starting single node: %v", err)
}
} 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 advertise VIP routes to VGP peers")
bgpServer, err = bgp.NewBGPServer(&startConfig.BGPConfig, nil)
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.StartCluster(&startConfig, cm, bgpServer)
if err != nil {
log.Fatalf("%v", err)
}
}
}
},
}

View File

@@ -3,46 +3,33 @@ package cmd
import (
"context"
"fmt"
"net"
"net/http"
"os"
"strings"
"time"
log "log/slog"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/vishvananda/netlink"
"golang.org/x/sys/unix"
"github.com/kube-vip/kube-vip/pkg/equinixmetal"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/manager"
"github.com/kube-vip/kube-vip/pkg/vip"
)
// Path to the configuration file
var configPath 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 {
@@ -56,9 +43,6 @@ var (
initLoadBalancer kubevip.LoadBalancer
)
// Points to a kubernetes configuration file
var kubeConfigPath string
var kubeVipCmd = &cobra.Command{
Use: "kube-vip",
Short: "This is a server for providing a Virtual IP and load-balancer for the Kubernetes control-plane",
@@ -69,35 +53,30 @@ func init() {
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..")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.VIPCIDR, "cidr", "32", "The CIDR range for the virtual IP address") // todo: deprecate
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, "Port for the VIP")
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")
// LoadBalancer flags
kubeVipCmd.PersistentFlags().BoolVar(&initConfig.EnableLoadBalancer, "enableLoadBalancer", false, "enable loadbalancing on the VIP with IPVS")
kubeVipCmd.PersistentFlags().IntVar(&initConfig.LoadBalancerPort, "lbPort", 6443, "loadbalancer port for the VIP")
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().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 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")
// Equinix Metal 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, "metalProjectID", "", "The ID of project already created within Equinix Metal")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.ProviderConfig, "provider-config", "", "The path to a provider configuration")
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")
@@ -105,6 +84,8 @@ func init() {
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")
@@ -112,38 +93,66 @@ func init() {
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")
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")
// 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, "Enable load balancing only for services with LoadBalancerClass \"kube-vip.io/kube-vip-class\"")
kubeVipCmd.PersistentFlags().StringVar(&initConfig.LoadBalancerClassName, "lbClassName", "kube-vip.io/kube-vip-class", "Name of load balancer class for kube-VIP, defaults to \"kube-vip.io/kube-vip-class\"")
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, "Enable leader node labeling with \"kube-vip.io/has-ip=<VIP address>\", defaults to false")
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, "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")
kubeVipCmd.AddCommand(kubeKubeadm)
kubeVipCmd.AddCommand(kubeManifest)
kubeVipCmd.AddCommand(kubeVipManager)
kubeVipCmd.AddCommand(kubeVipSample)
kubeVipCmd.AddCommand(kubeVipService)
kubeVipCmd.AddCommand(kubeVipStart)
kubeVipCmd.AddCommand(kubeVipVersion)
// Set the logging level for all subsequent functions
log.SetLogLoggerLevel(log.Level(initConfig.Logging))
}
// Execute - starts the command parsing process
@@ -157,7 +166,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)
@@ -167,7 +176,7 @@ var kubeVipVersion = &cobra.Command{
var kubeVipSample = &cobra.Command{
Use: "sample",
Short: "Generate a Sample configuration",
Run: func(cmd *cobra.Command, args []string) {
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
_ = cmd.Help()
},
}
@@ -175,18 +184,26 @@ var kubeVipSample = &cobra.Command{
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
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.Fatalln(err)
log.Error("checking interface", "err", err)
return
}
// User Environment variables as an option to make manifest clearer
@@ -195,16 +212,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)
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
}
},
}
@@ -212,19 +240,33 @@ var kubeVipService = &cobra.Command{
var kubeVipManager = &cobra.Command{
Use: "manager",
Short: "Start the kube-vip manager",
Run: func(cmd *cobra.Command, args []string) {
Run: func(cmd *cobra.Command, args []string) { //nolint TODO
// parse environment variables, these will overwrite anything loaded or flags
err := kubevip.ParseEnvironment(&initConfig)
if err != nil {
log.Fatalln(err)
log.Error("parsing environment", "err", err)
return
}
// 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.SetLevel(log.Level(initConfig.Logging))
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)
if err != nil {
log.Error("No interface is specified for kube-vip to bind to")
return
}
}
// Welome messages
log.Infof("Starting kube-vip.io [%s]", Release.Version)
log.Debugf("Build kube-vip.io [%s]", Release.Build)
log.Info("kube-vip.io", "version", Release.Version, "build", Release.Build)
// start prometheus server
if initConfig.PrometheusHTTPServer != "" {
@@ -252,11 +294,22 @@ var kubeVipManager = &cobra.Command{
}
// Provide configuration to output/logging
log.Infof("namespace [%s], Mode: [%s], Features(s): Control Plane:[%t], Services:[%t]", initConfig.Namespace, mode, initConfig.EnableControlPlane, initConfig.EnableServices)
log.Info("starting", "namespace", initConfig.Namespace, "Mode", mode, "Control Plane", initConfig.EnableControlPlane, "Services", initConfig.EnableServices)
// End if nothing is enabled
if !initConfig.EnableServices && !initConfig.EnableControlPlane {
log.Fatalln("no features are enabled")
log.Error("no features are enabled")
return
}
if !initConfig.EnableARP && strings.Contains(initConfig.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
@@ -266,48 +319,55 @@ var kubeVipManager = &cobra.Command{
initConfig.Interface = "wg0"
}
log.Infof("configuring Wireguard networking")
log.Info("configuring Wireguard networking")
l, err := netlink.LinkByName(initConfig.Interface)
if err != nil {
if strings.Contains(err.Error(), "Link not found") {
log.Warnf("interface \"%s\" doesn't exist, attempting to create wireguard interface", initConfig.Interface)
log.Warn("attempting to create wireguard interface", "interface not found", initConfig.Interface)
err = netlink.LinkAdd(&netlink.Wireguard{LinkAttrs: netlink.LinkAttrs{Name: initConfig.Interface}})
if err != nil {
log.Fatalln(err)
log.Error("adding link", "err", err)
return
}
l, err = netlink.LinkByName(initConfig.Interface)
if err != nil {
log.Fatalln(err)
log.Error("finding link", "err", err)
return
}
}
}
err = netlink.LinkSetUp(l)
if err != nil {
log.Fatalln(err)
log.Error("setting link UP", "err", err)
return
}
} else { // if we're not using Wireguard then we'll need to use an actual interface
// Check if the interface needs auto-detecting
if initConfig.Interface == "" {
log.Infof("No interface is specified for VIP in config, auto-detecting default Interface")
log.Info("No interface is specified for VIP in config, auto-detecting default Interface")
defaultIF, err := vip.GetDefaultGatewayInterface()
if err != nil {
_ = cmd.Help()
log.Fatalf("unable to detect default interface -> [%v]", err)
log.Error("detecting interface", "err", err)
return
}
initConfig.Interface = defaultIF.Name
log.Infof("kube-vip will bind to interface [%s]", initConfig.Interface)
log.Info("kube-vip bind", "interface", initConfig.Interface)
go func() {
if err := vip.MonitorDefaultInterface(context.TODO(), defaultIF); err != nil {
log.Fatalf("crash: %s", err.Error())
log.Error("interface monitor", "err", err)
return
}
}()
}
}
// Perform a check on th state of the interface
// Perform a check on the state of the interface
if err := initConfig.CheckInterface(); err != nil {
log.Fatalln(err)
log.Error("checking interface", "err", err)
return
}
// User Environment variables as an option to make manifest clearer
@@ -316,22 +376,11 @@ var kubeVipManager = &cobra.Command{
configMap = envConfigMap
}
// If Equinix Metal is enabled and there is a provider configuration passed
if initConfig.EnableMetal {
if providerConfig != "" {
providerAPI, providerProject, err := equinixmetal.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("configuring new Manager error -> %v", err)
log.Error("new manager", "err", err)
return
}
prometheus.MustRegister(mgr.PrometheusCollector()...)
@@ -339,7 +388,8 @@ var kubeVipManager = &cobra.Command{
// Start the service manager, this will watch the config Map and construct kube-vip services for it
err = mgr.Start()
if err != nil {
log.Fatalf("starting new Manager error -> %v", err)
log.Error("start manager", "err", err)
return
}
},
}
@@ -354,6 +404,15 @@ 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,
@@ -363,15 +422,16 @@ func servePrometheusHTTPServer(ctx context.Context, config PrometheusHTTPServerC
go func() {
if err = srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("listen:%+s\n", err)
log.Error("prometheus HTTP server", "err", err)
return
}
}()
log.Printf("prometheus HTTP server started")
log.Info("prometheus HTTP server started")
<-ctx.Done()
log.Printf("prometheus HTTP server stopped")
log.Info("prometheus HTTP server stopped")
ctxShutDown, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer func() {
@@ -379,10 +439,35 @@ 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) (string, error) {
var cidrs []string
addresses := strings.Split(address, ",")
for _, a := range addresses {
ip := net.ParseIP(a)
if ip == nil {
ips, err := net.LookupIP(a)
if len(ips) == 0 || err != nil {
return "", fmt.Errorf("invalid IP address: %s from [%s], %v", a, address, err)
}
ip = ips[0]
}
if ip.To4() != nil {
cidrs = append(cidrs, "32")
} else {
cidrs = append(cidrs, "128")
}
}
return strings.Join(cidrs, ","), nil
}

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")
@@ -60,7 +60,7 @@ func main() {
fmt.Println("error: ", err)
}
ServerConn.WriteTo(buf[0:n])
ServerConn.WriteTo(buf[0:n], addr)
}
}
}

View File

@@ -1,5 +0,0 @@
FROM nginx:latest
RUN apt-get update; apt-get install -y nodejs npm; npm install -g markdown-styles;
COPY . /docs
WORKDIR /docs
RUN generate-md --layout github --input ./ --output /usr/share/nginx/html/

View File

@@ -1,157 +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.
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 but has since expanded to provide the same functionality for Service resources within a Kubernetes cluster.
Additionally, `kube-vip` is designed to be lightweight and multi-architecture. All of the components are built for Linux on `x86`, `armv7`, `armhvf`, `ppc64le` and `s390x` architectures. This means that `kube-vip` will run fine in bare metal, virtual, and edge (Raspberry Pi or small ARM SoC) use cases.
## Technologies
There are a number of technologies or functional design choices that provide high availability and 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 which 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 [Layer 2](https://osi-model.com/data-link-layer/) it will use [leader election](https://godoc.org/k8s.io/client-go/tools/leaderelection).
### 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-to-MAC address mapping until the old ARP entry expires (typically within 30 seconds) and retrieves a new mapping. This can be improved by using [Gratuitous ARP](https://wiki.wireshark.org/Gratuitous_ARP) broadcasts when enabled (detailed below).
### ARP
`kube-vip` can optionally be configured to broadcast a Gratuitous ARP that will typically immediately notify all local hosts that the VIP-to-MAC address mapping has changed.
Below we can see that the failover is typically done within a few seconds as the ARP broadcast is received.
```
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
`kube-vip` has the capability to provide a high availability address for both the Kubernetes control plane and for a Kubernetes Service. As of v0.4.0, `kube-vip` implements support for true load balancing for the control plane to distribute API requests across control plane nodes.
#### Kubernetes Service Load Balancing
The following is required in the `kube-vip` manifest to enable Service of type `LoadBalancer`:
```yaml
- name: svc_enable
value: "true"
```
This section details the flow of events in order for `kube-vip` to advertise a Kubernetes Service:
1. An end user exposes an application through Kubernetes as a Service type `LoadBalancer`. For example, imperatively using `kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx`
2. Within the Kubernetes cluster, a Service object is created with the `spec.type` set to `LoadBalancer`.
3. A controller (typically a [Cloud Controller](/usage/cloud-provider)) 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 field `metadata.annotations["kube-vip.io/loadbalancerIPs"]` and `spec.loadBalancerIP` with the IP address. `spec.loadBalancerIP` is deprecated in k8s 1.24, will not be updated in future release
6. `kube-vip` Pods implement a "watcher" for Services that have a `metadata.annotations["kube-vip.io/loadbalancerIPs"]` address attached. If the annotation is not presented, it will fallback to check `spec.loadBalancerIP`.
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 the object is ready. This is done by updating the `status.loadBalancer.ingress` with the VIP address.
#### Control Plane Load-Balancing
As of `kube-vip` v0.4.0, IPVS load balancing is configured for having the VIP in the same subnet as the control plane nodes. NAT-based load balancing will follow later.
To enable control plane load balancing using IPVS, the environment variable `lb_enable` is required in the `kube-vip` manifest:
```yaml
- name : lb_enable
value: "true"
```
The load balancing is provided through IPVS (IP Virtual Server) and provides a Layer 4 (TCP-based) round-robin across all of the control plane nodes. By default, the load balancer will listen on the default port of 6443 as the Kubernetes API server. The IPVS virtual server lives in kernel space and doesn't create an "actual" service that listens on port 6443. This allows the kernel to parse packets before they're sent to an actual TCP port. This is important to know because it means we don't have any port conflicts having the IPVS load balancer listening on the same port as the API server on the same host.
The load balancer port can be customised by changing the `lb_port` environment variable in the `kube-vip` manifest:
```yaml
- name: lb_port
value: "6443"
```
##### How it works
Once the `lb_enable` variable is set to `true`, `kube-vip` will do the following:
- In Layer 2 it will create an IPVS service on the leader.
- In Layer 3 all nodes will create an IPVS service.
- It will start a Kubernetes node watcher for nodes with the control plane label.
- It will add/delete them as they're added and removed from the cluster.
#### Debugging control plane load balancing
In order to inspect and debug traffic, install the `ipvsadm` tool.
##### View the configuration
The command `sudo ipvsadm -ln` will display the load balancer configuration.
```sh
$ sudo ipvsadm -ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.0.40:6443 rr
-> 192.168.0.41:6443 Local 1 4 0
-> 192.168.0.42:6443 Local 1 3 0
-> 192.168.0.43:6443 Local 1 3 0
```
##### Watch things interact with the API server
The command `watch sudo ipvsadm -lnc` will auto-refresh the connections to the load balancer.
```sh
$ watch sudo ipvsadm -lnc
<snip>
sudo ipvsadm -lnc k8s01: Tue Nov 9 11:39:39 2021
IPVS connection entries
pro expire state source virtual destination
TCP 14:49 ESTABLISHED 192.168.0.42:37090 192.168.0.40:6443 192.168.0.41:6443
TCP 14:55 ESTABLISHED 192.168.0.45:46510 192.168.0.40:6443 192.168.0.41:6443
TCP 14:54 ESTABLISHED 192.168.0.43:39602 192.168.0.40:6443 192.168.0.43:6443
TCP 14:58 ESTABLISHED 192.168.0.44:50458 192.168.0.40:6443 192.168.0.42:6443
TCP 14:32 ESTABLISHED 192.168.0.43:39648 192.168.0.40:6443 192.168.0.42:6443
TCP 14:58 ESTABLISHED 192.168.0.40:55944 192.168.0.40:6443 192.168.0.41:6443
TCP 14:54 ESTABLISHED 192.168.0.42:36950 192.168.0.40:6443 192.168.0.41:6443
TCP 14:42 ESTABLISHED 192.168.0.44:50488 192.168.0.40:6443 192.168.0.43:6443
TCP 14:53 ESTABLISHED 192.168.0.45:46528 192.168.0.40:6443 192.168.0.43:6443
TCP 14:49 ESTABLISHED 192.168.0.40:56040 192.168.0.40:6443 192.168.0.42:6443
```
## Components within a Kubernetes Cluster
The `kube-vip` Kubernetes load balancer requires a number of components in order to function:
- [Kube-Vip Cloud Provider](https://github.com/kube-vip/kube-vip-cloud-provider)
- [Kube-Vip Deployment](https://github.com/kube-vip/kube-vip)

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 ghcr.io/kube-vip/kube-vip:0.3.7 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 ghcr.io/kube-vip/kube-vip:0.3.7 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 ghcr.io/kube-vip/kube-vip:0.3.7 \
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: ghcr.io/kube-vip/kube-vip:0.3.7
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 ghcr.io/kube-vip/kube-vip:0.3.7 \
manifest pod \
--interface ens192 \
--vip 192.168.0.75 \
--arp \
--leaderElection | sudo tee /etc/kubernetes/manifests/vip.yaml
```
Ensure that `image: ghcr.io/kube-vip/kube-vip:<x>` is modified to point to a specific version (`0.3.7` at the time of writing), refer to [GitHyb](https://github.com/kube-vip/kube-vip/pkgs/container/kube-vip) 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 ghcr.io/kube-vip/kube-vip:0.3.7 \
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 ghcr.io/kube-vip/kube-vip:0.3.7 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 ghcr.io/kube-vip/kube-vip:0.3.7 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,101 +0,0 @@
# Kube-Vip Flag / Environment Variable reference
## Flags
These flags are typically used in the `kube-vip` manifest generation process.
| Category | Flag | Usage | Notes |
| ------------------- | ---------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------- |
| **Troubleshooting** | | | |
| | `--log` | default 4 | Set to `5` for debugging logs |
| **Mode** | | | |
| | `--controlplane` | Enables `kube-vip` control plane functionality | |
| | `--services` | Enables `kube-vip` to watch services of type `LoadBalancer` | |
| **VIP Config** | | | |
| | `--arp` | Enables ARP broadcasts from Leader | |
| | `--bgp` | Enables BGP peering from `kube-vip` | |
| | `--vip` | `<IP Address>` | (deprecated) |
| | `--address` | `<IP Address>` or `<DNS name>` | |
| | `--interface` | Linux interface on the node | |
| | `--leaderElection` | Enables Kubernetes LeaderElection | Used by ARP, as only the leader can broadcast |
| | `--enableLoadBalancer` | Enables IPVS load balancer | `kube-vip` ≥ 0.4.0 |
| | `--lbPort` | 6443 | The port that the api server will load-balanced on |
| | `--lbForwardingMethod` | Select the forwarding method (default local) | The IPVS forwarding method (local, masquerade, tunnel, direct, bypass) |
| **Services** | | | |
| | `--serviceInterface` | "" | Defines an optional different interface to bind services too |
| | `--cidr` | Defaults "32" | Used when advertising BGP addresses (typically as `x.x.x.x/32`) |
| **Kubernetes** | | | |
| | `--inCluster` | Required for `kube-vip` as DaemonSet. | Runs `kube-vip` with a ServiceAccount called `kube-vip`. |
| | `--taint` | Required for `kube-vip` as DaemonSet. | Adds node affinity rules forcing `kube-vip` Pods to run on control plane. |
| **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:multihop>` | Comma separated 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 |
| | `--sourceif` | Source Interface | Determines which interface BGP should peer _from_ |
| | `--sourceip` | Source Address | Determines which IP address BGP should peer _from_ |
| | `--annotations` | `<provider string>` | Startup will be paused until the node annotations 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 |
## Environment Variables
These environment variables are usually part of a `kube-vip` manifest and used when running the `kube-vip` Pod.
More environment variables can be read through the `pkg/kubevip/config_envvar.go` file.
| Category | Environment Variable | Usage | Notes |
| ------------------- | ---------------------- |-------------------------------------------------------------|---------------------------------------------------------------------------------|
| **Troubleshooting** | | | |
| | `vip_loglevel` | default 4 | Set to `5` for debugging logs |
| **Mode** | | | |
| | `cp_enable` | Enables `kube-vip` control plane functionality | |
| | `svc_enable` | Enables `kube-vip` to watch Services of type `LoadBalancer` | |
| **VIP Config** | | | |
| | `vip_arp` | Enables ARP broadcasts from Leader | |
| | `bgp_enable` | Enables BGP peering from `kube-vip` | |
| | `vip_address` | `<IP Address>` | (deprecated) |
| | `address` | `<IP Address>` or `<DNS name>` | |
| | `vip_interface` | `<linux interface>` | |
| | `vip_leaderelection` | Enables Kubernetes LeaderElection | Used by ARP, as only the leader can broadcast |
| | `lb_enable` | Enables IPVS LoadBalancer | `kube-vip` ≥ 0.4.0. Adds nodes to the IPVS load balancer |
| | `lb_port` | 6443 | The IPVS port that will be used to load-balance control plane requests |
| | `lb_fwdmethod` | Select the forwarding method (default local) | The IPVS forwarding method (local, masquerade, tunnel, direct, bypass) |
| **Services** | | | |
| | `vip_servicesinterface`| "" | Defines an optional different interface to bind services too |
| | `vip_cidr` | Defaults "32" | Used when advertising BGP addresses (typically as `x.x.x.x/32`) |
| **LeaderElection** | | | |
| | `vip_leaseduration` | default 5 | Seconds a lease is held for |
| | `vip_renewdeadline` | default 3 | Seconds a leader can attempt to renew the lease |
| | `vip_retryperiod` | default 1 | Number of times the leader will hold the lease for |
| | `cp_namespace` | "kube-vip" | The namespace where the lease will reside |
| **BGP** | | | |
| | `bgp_routerid` | `<IP Address>` | Typically the address of the local node |
| | `bgp_routerinterface` | Interface name | Used to associate the `routerID` with the control plane's interface. |
| | `bgp_as` | default 65000 | The AS we peer from |
| | `bgp_peers` | `<address:AS[:password[:multihop]]>` | Comma separated list of BGP peers (IPv6 addresses should be enclosed with `[]`) |
| | `bgp_peeraddress` | `<IP Address>` | Address of a single BGP Peer |
| | `bgp_peeras` | default 65000 | AS of a single BGP Peer |
| | `bgp_peerpass` | "" | Password to work with a single BGP Peer |
| | `bgp_multihop` | Enables eBGP MultiHop | Enable multiHop with a single BGP Peer |
| | `bgp_sourceif` | Source Interface | Determines which interface BGP should peer _from_ |
| | `bgp_sourceip` | Source Address | Determines which IP address BGP should peer _from_ |
| | `annotations` | `<provider string>` | Startup will be paused until the node annotations contain the BGP configuration |
| **Equinix Metal** | | | (May be deprecated) |
| | `vip_packet` | Enables Equinix Metal API calls | |
| | `PACKET_AUTH_TOKEN` | Equinix Metal API token | |
| | `vip_packetproject` | Equinix Metal Project (Name) | |
| | `vip_packetprojectid` | Equinix Metal Project (UUID) | |
| | `provider_config` | Path to the Equinix Metal provider configuration | Requires the Equinix Metal CCM |

View File

@@ -1,242 +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 `service.metadata.annotations["kube-vip.io/loadbalancerIPs"]` or `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 ghcr.io/kube-vip/kube-vip:0.3.7 vip"`
#### Docker
`alias kube-vip="docker run --network host --rm ghcr.io/kube-vip/kube-vip:0.3.7"`
### 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: ghcr.io/kube-vip/kube-vip:0.3.7
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.
As of Equinix Metal's CCM v3.3.0, the annotations format was changed. This means, you should expect either of the following:
1. Equinix Metal's CCM v3.3.0 onwards:
```
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/bgp-peers-0-node-asn: 65000
metal.equinix.com/bgp-peers-0-peer-asn: 65530
metal.equinix.com/bgp-peers-0-peer-ip: x.x.x.x
metal.equinix.com/bgp-peers-0-src-ip: x.x.x.x
```
2. Equinix Metal's CCM before v3.0.0:
```
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,142 +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 successfully.
## 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 broadcasts 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:multihop>` | Comma separated 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 |
| | `--annotations` | `<provider string>` | Startup will be paused until the node annotations 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,269 +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 `spec.Type = LoadBalancer`
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 field `metadata.annotations["kube-vip.io/loadbalancerIPs"]` and `spec.loadBalancerIP` with the IP address. `spec.loadBalancerIP` is deprecated in k8s 1.24, will not be updated in future release
6. `kube-vip` Pods implement a "watcher" for Services that have a `metadata.annotations["kube-vip.io/loadbalancerIPs"]` address attached. If the annotation is not presented, it will fallback to check `spec.loadBalancerIP`.
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 `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 existing 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.
## Using the Kube-vip Cloud Provider
The below instructions *should just work* on Kubernetes regardless of architecture (Linux Operating System is the only requirement) - you can quickly install the "latest" components:
**Install the `kube-vip-cloud-provider`**
```
$ kubectl apply -f https://raw.githubusercontent.com/kube-vip/kube-vip-cloud-provider/main/manifest/kube-vip-cloud-controller.yaml
```
It uses a `statefulSet` and can always be viewed with the following command:
```
kubectl describe pods -n kube-system kube-vip-cloud-provider-0
```
**Create a global CIDR or IP Range**
Any `service` in any `namespace` can use an address from the global CIDR `cidr-global` or range `range-global`
```
kubectl create configmap --namespace kube-system kubevip --from-literal cidr-global=192.168.0.220/29
```
or
```
kubectl create configmap --namespace kube-system kubevip --from-literal range-global=192.168.1.220-192.168.1.230
```
Creating services of `type: LoadBalancer` in *any namespace* will now take addresses from the **global** cidr defined in the `configmap` unless a specific
## The Detailed guide
### Deploy the Kube-vip Cloud Provider
**Install the `kube-vip-cloud-provider`**
```
$ kubectl apply -f https://raw.githubusercontent.com/kube-vip/kube-vip-cloud-provider/main/manifest/kube-vip-cloud-controller.yaml
```
The following output should appear when the manifest is applied:
```
serviceaccount/kube-vip-cloud-controller created
clusterrole.rbac.authorization.k8s.io/system:kube-vip-cloud-controller-role created
clusterrolebinding.rbac.authorization.k8s.io/system:kube-vip-cloud-controller-binding created
statefulset.apps/kube-vip-cloud-provider created
```
We can validate the cloud provider by examining the pods and following the logs:
```
kubectl describe pods -n kube-system kube-vip-cloud-provider-0
kubectl logs -n kube-system kube-vip-cloud-provider-0 -f
```
### The Kube-vip Cloud Provider `configmap`
To manage the IP address ranges for the load balancer instances the `kube-vip-cloud-provider` uses a `configmap` held in the `kube-system` namespace. IP address ranges can be configured using:
- IP address pools by CIDR
- IP ranges [start address - end address]
- Multiple pools by CIDR per namespace
- Multiple IP ranges per namespace (handles overlapping ranges)
- Setting of static addresses through --load-balancer-ip=x.x.x.x
To control which IP address range is used for which service the following rules are applied:
- Global address pools (`cidr-global` or `range-global`) are available for use by *any* `service` in *any* `namespace`
- Namespace specific address pools (`cidr-<namespace>` or `range-<namespace>`) are *only* available for use by `service` in the *specific* `namespace`
- Static IP addresses can be applied to a load balancer `service` using the `loadbalancerIP` setting, even outside of the assigned ranges
Example Configmap:
```
$ kubectl get configmap -n kube-system kubevip -o yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kubevip
namespace: kube-system
data:
cidr-default: 192.168.0.200/29 # CIDR-based IP range for use in the default namespace
range-development: 192.168.0.210-192.168.0.219 # Range-based IP range for use in the development namespace
cidr-finance: 192.168.0.220/29,192.168.0.230/29 # Multiple CIDR-based ranges for use in the finance namespace
cidr-global: 192.168.0.240/29 # CIDR-based range which can be used in any namespace
```
### 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
```
or via a `service` YAML definition
```
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- name: http
port: 80
protocol: TCP
selector:
app: nginx
type: LoadBalancer
```
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
```
or including it in the `service` definition:
```
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- name: http
port: 80
protocol: TCP
selector:
app: nginx
type: LoadBalancer
loadBalancerIP: "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 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 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 `kube-vip-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 `service.metadata.annotations["kube-vip.io/loadbalancerIPs"]` or `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 ghcr.io/kube-vip/kube-vip:0.3.7 vip /kube-vip"`
#### Docker
`alias kube-vip="docker run --network host --rm ghcr.io/kube-vip/kube-vip:0.3.7"`
### 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,70 +0,0 @@
![kube-vip.png](kube-vip.png)
## Overview
Kube-Vip provides Kubernetes clusters a virtual IP and load balancer for both control plane and Kubernetes Services.
The idea behind `kube-vip` is a small, self-contained, highly-available option for all environments, especially:
- Bare metal
- On-Premises
- Edge (ARM / Raspberry Pi)
- Virtualisation
- Pretty much anywhere else :)
## Features
Kube-Vip was originally created to provide a HA solution for the Kubernetes control plane, but over time it has evolved to incorporate that same functionality for Kubernetes Services of type [LoadBalancer](https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer). Some of the features include:
- VIP addresses can be either 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)
- Control Plane HA with K3s/and others (DaemonSets)
- Control Plane LoadBalancing with IPVS (kube-vip ≥ 0.4)
- Service LoadBalancer using [leader election](https://godoc.org/k8s.io/client-go/tools/leaderelection) for ARP (Layer 2)
- Service LoadBalancer using multiple nodes with BGP
- 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 more...
## Why?
The "original" purpose of `kube-vip` was to simplify the building of HA Kubernetes clusters, which at the time involved a few components and configurations that all needed to be managed. This was blogged about in detail by [thebsdbox](https://twitter.com/thebsdbox/) [here](https://thebsdbox.co.uk/2020/01/02/Designing-Building-HA-bare-metal-Kubernetes-cluster/#Networking-load-balancing). Since the project has evolved, it can now use those same technologies to provide load balancing capabilities within a Kubernetes Cluster.
## Architecture
The architecture for `kube-vip` (and associated Kubernetes components) is covered in detail [here](/architecture/).
## Installation
There are two main routes for deploying `kube-vip`: either through a [static Pod](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/) when bringing up a Kubernetes cluster with [kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/) or as a [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) (typically with distributions like [K3s](https://k3s.io)).
- [Static Pod](/install_static)
- [DaemonSet](/install_daemonset)
## Usage
- [On-Prem with the kube-vip cloud controller](/usage/on-prem)
- [KinD](/usage/kind)
- [Equinix Metal](/usage/EquinixMetal)
- [k3s](/usage/k3s)
## Flags/Environment Variables
- [Flags and Environment variables](/flags/)
## Links
- [Kube-Vip Cloud Provider Repository](https://github.com/kube-vip/kube-vip-cloud-provider)
- [Kube-Vip Repository](https://github.com/kube-vip/kube-vip)
- [Kube-Vip RBAC manifest (required for the DaemonSet)](https://kube-vip.io/manifests/rbac.yaml)
## Copyright
© 2021 [The Linux Foundation](https://www.linuxfoundation.org/). All rights reserved.
The Linux Foundation has registered trademarks and uses trademarks.
For a list trademarks of The Linux Foundation, please see our [Trademark Usage page](https://www.linuxfoundation.org/en/trademark-usage).

View File

@@ -1,253 +0,0 @@
# Kube-Vip as a DaemonSet
## DaemonSet
Some Kubernetes distributions can bring up a Kubernetes cluster without depending on a pre-existing VIP (but they may be configured to support one). A prime example of this would be K3s which 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.
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, we can apply `kube-vip` to the cluster once the first node has been brought up.
Unlike running `kube-vip` as a [static Pod](/install_static) there are a few more things that may need configuring when running `kube-vip` as a DaemonSet. This page will cover primarily the differences.
## Kube-Vip as HA, Load Balancer, or both
The functionality of `kube-vip` depends on the flags used to create the static Pod manifest. By passing in `--controlplane` we instruct `kube-vip` to provide and advertise a virtual IP to be used by the control plane. By passing in `--services` we tell `kube-vip` to provide load balancing for Kubernetes Service resources created inside the cluster. With both enabled, `kube-vip` will manage a virtual IP address that is passed through its configuration for a highly available Kubernetes cluster. It will also watch Services of type `LoadBalancer` and once their `service.metadata.annotations["kube-vip.io/loadbalancerIPs"]` or `spec.LoadBalancerIP` is updated (typically by a cloud controller, including (optionally) the one provided by kube-vip in [on-prem](/usage/on-prem) scenarios) it will advertise this address using BGP/ARP. In this example, we will use both when generating the manifest.
## Create the RBAC settings
Since `kube-vip` as a DaemonSet runs as a regular resource instead of a static Pod, it still needs the correct access to be able to watch Kubernetes Services and other objects. In order to do this, RBAC resources must be created which include a ServiceAccount, ClusterRole, and ClusterRoleBinding and can be applied this with the command:
```
kubectl apply -f https://kube-vip.io/manifests/rbac.yaml
```
## Generating a Manifest
In order to create an easier experience of consuming the various functionality within `kube-vip`, we can use the `kube-vip` container itself to generate our DaemonSet manifest. We do this by running the `kube-vip` image as a container and passing in the various [flags](/flags/) for the capabilities we want to enable. Generating a `kube-vip` manifest for running as a DaemonSet is almost identical to the process when running `kube-vip` as a [static Pod](/install_static). Only a few flags are different between the two processes. Therefore, refer back to the [Generating a Manifest](/install_static/#generating-a-manifest) section on the [static Pod installation page](/install_static) for the main process steps.
### ARP Example for DaemonSet
When creating the `kube-vip` installation manifest as a DaemonSet, the `manifest` subcommand takes the value `daemonset` as opposed to the `pod` value. The flags `--inCluster` and `--taint` are also needed to configure the DaemonSet to use a ServiceAccount and affine the `kube-vip` Pods to control plane nodes thereby preventing them from running on worker instances.
```
kube-vip manifest daemonset \
--interface $INTERFACE \
--address $VIP \
--inCluster \
--taint \
--controlplane \
--services \
--arp \
--leaderElection
```
#### Example ARP Manifest
```yaml
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:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/master
operator: Exists
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: Exists
containers:
- args:
- manager
env:
- name: vip_arp
value: "true"
- name: port
value: "6443"
- name: vip_interface
value: ens160
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: address
value: 192.168.0.40
image: ghcr.io/kube-vip/kube-vip:v0.4.0
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
hostNetwork: true
serviceAccountName: kube-vip
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0
```
### BGP Example for DaemonSet
This configuration will create a manifest that starts `kube-vip` providing control plane VIP and Kubernetes Service 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-separated list in the format of `address:AS:password:multihop`.
`export INTERFACE=lo`
```
kube-vip manifest daemonset \
--interface $INTERFACE \
--address $VIP \
--inCluster \
--taint \
--controlplane \
--services \
--bgp \
--localAS 65000 \
--bgpRouterID 192.168.0.2 \
--bgppeers 192.168.0.10:65000::false,192.168.0.11:65000::false
```
#### Example BGP Manifest
```yaml
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:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/master
operator: Exists
- matchExpressions:
- key: node-role.kubernetes.io/control-plane
operator: Exists
containers:
- args:
- manager
env:
- name: vip_arp
value: "false"
- name: port
value: "6443"
- name: vip_interface
value: ens160
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- name: svc_enable
value: "true"
- name: bgp_enable
value: "true"
- name: bgp_routerid
value: 192.168.0.2
- name: bgp_as
value: "65000"
- name: bgp_peeraddress
- name: bgp_peerpass
- name: bgp_peeras
value: "65000"
- name: bgp_peers
value: 192.168.0.10:65000::false,192.168.0.11:65000::false
- name: address
value: 192.168.0.40
image: ghcr.io/kube-vip/kube-vip:v0.4.0
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
hostNetwork: true
serviceAccountName: kube-vip
tolerations:
- effect: NoSchedule
operator: Exists
- effect: NoExecute
operator: Exists
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0
```
#### Managing a `routerID` as a DaemonSet
The `routerID` needs to be unique on each node that participates in BGP advertisements. In order to do this, we can modify the manifest so that when `kube-vip` starts it will look up its local address and use that as the `routerID`. Add the following to the `env[]` array of the container:
```yaml
- name: bgp_routerinterface
value: "ens160"
```
### DaemonSet Manifest Overview
Once the manifest for `kube-vip` as a DaemonSet is generated, these are some of the notable differences over the [static Pod](/install_static) manifest and their significance.
- `nodeSelector`: Ensures that DaemonSet Pods only run on control plane nodes.
- `serviceAccountName: kube-vip`: Specifies the ServiceAccount name that will be used to get/update Kubernetes Service resources.
- `tolerations`: Allows scheduling to control plane nodes that normally specify `NoSchedule` or `NoExecute` taints.

View File

@@ -1,228 +0,0 @@
# Kube-Vip as a Static Pod
## Static Pods
[Static Pods](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/) are Kubernetes Pods that are run by the `kubelet` on a single node and are 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 ConfigMap resources). The static Pod approach is primarily required for [kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/) as this is due to the sequence of actions performed by `kubeadm`. Ideally, we want `kube-vip` to be part of the Kubernetes cluster, but 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 building a highly available Kubernetes cluster with `kubeadm` and `kube-vip` are as follows:
1. Generate a `kube-vip` manifest in the static Pods manifest directory (see the [generating a manifest](#generating-a-manifest) section below).
2. Run `kubeadm init` with the `--control-plane-endpoint` flag using the VIP address provided when generating the static Pod manifest.
3. The `kubelet` will parse and execute all manifests, including the `kube-vip` manifest generated in step one and the other control plane components including `kube-apiserver`.
4. `kube-vip` starts and advertises the VIP address.
5. The `kubelet` on this first control plane will connect to the VIP advertised in the previous step.
6. `kubeadm init` finishes successfully on the first control plane.
7. Using the output from the `kubeadm init` command on the first control plane, run the `kubeadm join` command on the remainder of the control planes.
8. Copy the generated `kube-vip` manifest to the remainder of the control planes and place in their static Pods manifest directory (default of `/etc/kubernetes/manifests/`).
## Kube-Vip as HA, Load Balancer, or both
The functionality of `kube-vip` depends on the flags used to create the static Pod manifest. By passing in `--controlplane` we instruct `kube-vip` to provide and advertise a virtual IP to be used by the control plane. By passing in `--services` we tell `kube-vip` to provide load balancing for Kubernetes Service resources created inside the cluster. With both enabled, `kube-vip` will manage a virtual IP address that is passed through its configuration for a highly available Kubernetes cluster. It will also watch Services of type `LoadBalancer` and once their `service.metadata.annotations["kube-vip.io/loadbalancerIPs"]` or `spec.LoadBalancerIP` is updated (typically by a cloud controller, including (optionally) the one provided by kube-vip in [on-prem](/usage/on-prem) scenarios) it will advertise this address using BGP/ARP. In this example, we will use both when generating the manifest.
## Generating a Manifest
In order to create an easier experience of consuming the various functionality within `kube-vip`, we can use the `kube-vip` container itself to generate our static Pod manifest. We do this by running the `kube-vip` image as a container and passing in the various [flags](/flags/) for the capabilities we want to enable.
### Set configuration details
We use environment variables to predefine the values of the inputs to supply to `kube-vip`.
Set the `VIP` address to be used for the control plane:
`export VIP=192.168.0.40`
Set the `INTERFACE` name to the name of the interface on the control plane(s) which will announce the VIP. In many Linux distributions this can be found with the `ip a` command.
`export INTERFACE=ens160`
Get the latest version of the `kube-vip` release by parsing the GitHub API. This step requires that `jq` and `curl` are installed.
`KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases | jq -r ".[0].name")`
To set manually instead, find the desired [release tag](https://github.com/kube-vip/kube-vip/releases):
`export KVVERSION=v0.4.0`
### Creating the manifest
With the input values now set, we can pull and run the `kube-vip` image supplying it the desired flags and values. Once the static Pod manifest is generated for your desired method (ARP or BGP), if running multiple control plane nodes, ensure it is placed in each control plane's static manifest directory (by default, `/etc/kubernetes/manifests`).
Depending on the container runtime, use one of the two aliased commands to create a `kube-vip` command which runs the `kube-vip` image as a container.
For containerd, run the below command:
`alias kube-vip="ctr run --rm --net-host ghcr.io/kube-vip/kube-vip:$KVVERSION vip /kube-vip"`
For Docker, run the below command:
`alias kube-vip="docker run --network host --rm ghcr.io/kube-vip/kube-vip:$KVVERSION"`
### ARP
With the inputs and alias command set, we can run the `kube-vip` container to generate a static Pod manifest which will be directed to a file at `/etc/kubernetes/manifests/kube-vip.yaml`. As such, this is assumed to run on the first control plane node.
This configuration will create a manifest that starts `kube-vip` providing control plane VIP and Kubernetes Service management using the `leaderElection` method and ARP. When this instance is elected as the leader, it will bind the `vip` to the specified `interface`. This is the same behavior for Services of type `LoadBalancer`.
> Note: When running these commands on a to-be control plane node, `sudo` access may be required along with pre-creation of the `/etc/kubernetes/manifests/` directory.
```
kube-vip manifest pod \
--interface $INTERFACE \
--address $VIP \
--controlplane \
--services \
--arp \
--leaderElection | tee /etc/kubernetes/manifests/kube-vip.yaml
```
#### Example ARP Manifest
```
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "true"
- name: port
value: "6443"
- name: vip_interface
value: ens192
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: address
value: 192.168.0.40
image: ghcr.io/kube-vip/kube-vip:v0.4.0
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}
```
### BGP
This configuration will create a manifest that starts `kube-vip` providing control plane VIP and Kubernetes Service 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-separated list in the format of `address:AS:password:multihop`.
`export INTERFACE=lo`
```
kube-vip manifest pod \
--interface $INTERFACE \
--address $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
```
#### Example BGP Manifest
```
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "false"
- name: port
value: "6443"
- name: vip_interface
value: ens192
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- name: bgp_enable
value: "true"
- name: bgp_routerid
value: 192.168.0.2
- name: bgp_as
value: "65000"
- name: bgp_peeraddress
- name: bgp_peerpass
- name: bgp_peeras
value: "65000"
- name: bgp_peers
value: 192.168.0.10:65000::false,192.168.0.11:65000::false
- name: address
value: 192.168.0.40
image: ghcr.io/kube-vip/kube-vip:v0.3.9
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}
```

View File

@@ -1,61 +0,0 @@
#!/bin/bash
echo "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: \"true\"
- name: vip_interface
value: $vipInterface
- name: port
value: \"6443\"
- name: vip_cidr
value: \"32\"
- name: cp_enable
value: \"true\"
- name: cp_namespace
value: kube-system
- name: svc_enable
value: \"false\"
- name: vip_address
value: $vipAddress
image: ghcr.io/kube-vip/kube-vip:v0.3.7
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
hostNetwork: true
nodeSelector:
node-role.kubernetes.io/master: \"true\"
serviceAccountName: kube-vip
tolerations:
- effect: NoSchedule
key: node-role.kubernetes.io/master
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0"

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/kube-vip/kube-vip/tree/master/example/deploy](https://github.com/kube-vip/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/kube-vip/kube-vip/tree/master/example/deploy](https://github.com/kube-vip/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/kube-vip/plndr-cloud-provider/tree/master/example/pod](https://github.com/kube-vip/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,63 +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: "true"
- 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: 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,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,70 +0,0 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: kube-vip-cloud-controller
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
name: system:kube-vip-cloud-controller-role
rules:
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["get", "create", "update", "list", "put"]
- apiGroups: [""]
resources: ["configmaps", "endpoints","events","services/status", "leases"]
verbs: ["*"]
- apiGroups: [""]
resources: ["nodes", "services"]
verbs: ["list","get","watch","update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: system:kube-vip-cloud-controller-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-vip-cloud-controller-role
subjects:
- kind: ServiceAccount
name: kube-vip-cloud-controller
namespace: kube-system
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: kube-vip-cloud-provider
namespace: kube-system
spec:
serviceName: kube-vip-cloud-provider
podManagementPolicy: OrderedReady
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: kube-vip
component: kube-vip-cloud-provider
template:
metadata:
labels:
app: kube-vip
component: kube-vip-cloud-provider
spec:
containers:
- command:
- /kube-vip-cloud-provider
- --leader-elect-resource-name=kube-vip-cloud-controller
image: kubevip/kube-vip-cloud-provider:latest
name: kube-vip-cloud-provider
imagePullPolicy: Always
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
serviceAccountName: kube-vip-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: ghcr.io/kube-vip/kube-vip:0.3.7
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: ghcr.io/kube-vip/kube-vip:0.3.7
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: ghcr.io/kube-vip/kube-vip:0.3.7
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: ghcr.io/kube-vip/kube-vip:0.3.7
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", "endpoints"]
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,65 +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: "true"
- 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: vip_ddns
value: "false"
- 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: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.3.7
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,57 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "true"
- 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: vip_ddns
value: "false"
- 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: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.3.7
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,74 +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: vip_ddns
value: "false"
- 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: ghcr.io/kube-vip/kube-vip:v0.3.7
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,84 +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: vip_ddns
value: "false"
- 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: ghcr.io/kube-vip/kube-vip:v0.3.7
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: metal-cloud-config
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0

View File

@@ -1,64 +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: vip_ddns
value: "false"
- 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: ghcr.io/kube-vip/kube-vip:v0.3.7
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,65 +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: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.3.9
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,61 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.3.9
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}

View File

@@ -1,74 +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: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: ghcr.io/kube-vip/kube-vip:v0.3.9
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,84 +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: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: ghcr.io/kube-vip/kube-vip:v0.3.9
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: metal-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: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- name: svc_enable
value: "true"
- 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: ghcr.io/kube-vip/kube-vip:v0.3.9
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}

View File

@@ -1,69 +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: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: lb_enable
value: "true"
- name: lb_port
value: "6443"
- name: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.4.0
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,65 +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: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.4.0
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,65 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: lb_enable
value: "true"
- name: lb_port
value: "6443"
- name: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.4.0
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}

View File

@@ -1,61 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.4.0
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}

View File

@@ -1,74 +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: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: ghcr.io/kube-vip/kube-vip:v0.4.0
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,84 +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: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: ghcr.io/kube-vip/kube-vip:v0.4.0
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: metal-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: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- name: svc_enable
value: "true"
- 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: ghcr.io/kube-vip/kube-vip:v0.4.0
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
- SYS_TIME
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}

View File

@@ -1,70 +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: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: lb_enable
value: "true"
- name: lb_port
value: "6443"
- name: lb_fwdmethod
value: local
- name: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.4.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
hostNetwork: true
serviceAccountName: kube-vip
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0

View File

@@ -1,64 +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: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.4.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
hostNetwork: true
serviceAccountName: kube-vip
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0

View File

@@ -1,66 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: lb_enable
value: "true"
- name: lb_port
value: "6443"
- name: lb_fwdmethod
value: local
- name: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.4.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}

View File

@@ -1,60 +0,0 @@
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: vip_arp
value: "true"
- name: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: vip_address
value: 192.168.0.1
image: ghcr.io/kube-vip/kube-vip:v0.4.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}

View File

@@ -1,73 +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: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: ghcr.io/kube-vip/kube-vip:v0.4.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
hostNetwork: true
serviceAccountName: kube-vip
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0

View File

@@ -1,83 +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: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- 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: ghcr.io/kube-vip/kube-vip:v0.4.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
volumeMounts:
- mountPath: /etc/cloud-sa
name: cloud-sa-volume
readOnly: true
hostNetwork: true
serviceAccountName: kube-vip
volumes:
- name: cloud-sa-volume
secret:
secretName: metal-cloud-config
updateStrategy: {}
status:
currentNumberScheduled: 0
desiredNumberScheduled: 0
numberMisscheduled: 0
numberReady: 0

View File

@@ -1,61 +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: port
value: "6443"
- name: vip_interface
value: eth0
- name: vip_cidr
value: "32"
- name: cp_enable
value: "true"
- name: cp_namespace
value: kube-system
- name: vip_ddns
value: "false"
- name: svc_enable
value: "true"
- 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: ghcr.io/kube-vip/kube-vip:v0.4.1
imagePullPolicy: Always
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
hostNetwork: true
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
name: kubeconfig
status: {}

View File

@@ -1,9 +0,0 @@
#!/bin/bash
echo Deploying updated documentation
# Sleep for dramatic purposes!
sleep 5
generate-md --layout github --input ./ --output /var/www/kube-vip/

View File

@@ -1,163 +0,0 @@
# Equinix Metal Overview (using the [Equinix Metal CCM](https://github.com/equinix/cloud-provider-equinix-metal))
## 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 (VIP) 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/equinix/cloud-provider-equinix-metal)) 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`.
## Configure to use a container runtime
### Get latest version
We can parse the GitHub API to find the latest version (or we can set this manually)
`KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases | jq -r ".[0].name")`
or manually:
`export KVVERSION=vx.x.x`
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 ghcr.io/kube-vip/kube-vip:$KVVERSION vip /kube-vip"`
### Docker
`alias kube-vip="docker run --network host --rm ghcr.io/kube-vip/kube-vip:KVVERSION"`
## Creating HA clusters in Equinix Metal
### 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.
```
export VIP= metal_EIP
export INTERFACE=<interface>
```
where metal_EIP is the Elastic IP (EIP) address your requested via Metal's UI or API. For more informaiton on how to request a Metal's EIP, please see the following [Equinix Metal's EIP document](https://metal.equinix.com/developers/docs/networking/elastic-ips/#elastic-ip-addresses)
<interface> is the interface you announce your VIP from via BGP. By default it's lo:0 in Equinix Metal.
```
kube-vip manifest pod \
--interface $INTERFACE\
--vip $VIP \
--controlplane \
--services \
--bgp \
--metal \
--metalKey xxxxxxx \
--metalProjectID xxxxx | tee /etc/kubernetes/manifests/kube-vip.yaml
```
where metalKey is your "personal API key" under "Personal Settings" of your Metal's portal, and MetalProjectID is your Metal's "Project ID" under "Project Settings"
### 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
```
## Load Balancing servies on Equinix Metal
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/equinix/cloud-provider-equinix-metal) to be installed prior to the kube-vip setup and that the cluster/kubelet is configured to use an "external" cloud provider.
```
export INTERFACE=<interface>
```
where <interface> is the interface you announce your VIP from via BGP. By default it's lo:0 in Equinix Metal.
### 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 -
```
### Expose with [Equinix Metal CCM](https://github.com/equinix/cloud-provider-equinix-metal)
Follow the [Equinix Metal's Elastic IP (EIP) document](https://metal.equinix.com/developers/docs/networking/elastic-ips/#elastic-ip-addresses) either through the API, CLI or through the UI, to create a public IPv4 EIP address, for example (145.75.75.1) and this is the address you can expose through BGP as the service loadbalancer.
```
# metal ip request -p xxx-bbb-ccc -f ams1 -q 1 -t public_ipv4
+-------+---------------+--------+----------------------+
| ID | ADDRESS | PUBLIC | CREATED |
+-------+---------------+--------+----------------------+
| xxxxx | 147.75.75.1 | true | 2020-11-10T15:57:39Z |
+-------+---------------+--------+----------------------+
kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx --load-balancer-ip=147.75.75.1
```
## 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.
As of Equinix Metal's CCM v3.3.0, the annotations format was changed. This means, you should expect either of the following:
1. Equinix Metal's CCM v3.3.0 onwards:
```
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/bgp-peers-0-node-asn: 65000
metal.equinix.com/bgp-peers-0-peer-asn: 65530
metal.equinix.com/bgp-peers-0-peer-ip: x.x.x.x
metal.equinix.com/bgp-peers-0-src-ip: x.x.x.x
```
2. Equinix Metal's CCM before v3.0.0:
```
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 Equinix Metal's CCM may reveal why the node is not yet ready.

View File

@@ -1,53 +0,0 @@
# K3s Overview
`kube-vip` works on [K3s environments](https://k3s.io/) similar to most others with the exception of how it gets deployed. Because K3s is able to bootstrap a single server (control plane node) without the availability of the load balancer fronting it, `kube-vip` can be installed as a DaemonSet.
## Prerequisites (on Equinix Metal)
In order to make ARP work on Equinix Metal, follow the [metal-gateway](https://metal.equinix.com/developers/docs/networking/metal-gateway/) guide to have public VLAN subnet which can be used for the load balancer IP.
## Clean Environment
This step is optional but recommended if a K3s installation previously existed.
```
rm -rf /var/lib/rancher /etc/rancher ~/.kube/*; \
ip addr flush dev lo; \
ip addr add 127.0.0.1/8 dev lo;
```
## Step 1: Create Manifests Folder
K3s has an optional manifests directory that will be searched to [auto-deploy](https://rancher.com/docs/k3s/latest/en/advanced/#auto-deploying-manifests) any manifests found within. Create this directory first in order to later place the `kube-vip` resources inside.
```
mkdir -p /var/lib/rancher/k3s/server/manifests/
```
## Step 2: Upload Kube-Vip RBAC Manifest
As `kube-vip` runs as a DaemonSet under K3s and not a static Pod, we will need to ensure that the required permissions exist for it to communicate with the API server. RBAC resources are needed to ensure a ServiceAccount exists with those permissions and bound appropriately.
Get the RBAC manifest and place in the auto-deploy directory:
```
curl https://kube-vip.io/manifests/rbac.yaml > /var/lib/rancher/k3s/server/manifests/kube-vip-rbac.yaml
```
## Step 3: Generate a Kube-Vip DaemonSet Manifest
Refer to the [DaemonSet manifest generation documentation](/docs/install_daemonset/index.md#generating-a-manifest) for the process to complete this step.
Either store this generated manifest separately in the `/var/lib/rancher/k3s/server/manifests/` directory, or append to the existing RBAC manifest called `kube-vip-rbac.yaml`. As a general best practice, it is a cleaner approach to place all related resources into a single YAML file.
> Note: Remember to include YAML document delimiters (`---`) when composing multiple documents.
## Step 4: Install a HA K3s Cluster
There are multiple ways to install K3s including `[k3sup](https://k3sup.dev/)` or [running the binary](https://rancher.com/docs/k3s/latest/en/quick-start/) locally. Whichever method you choose, the `--tls-san` flag must be passed with the same IP when generating the `kube-vip` DaemonSet manifest when installing the first server (control plane) instance. This is so that K3s generates an API server certificate with the `kube-vip` virtual IP address.
Once the cluster is installed, you should be able to edit the `kubeconfig` file generated from the process and use the `kube-vip` VIP address to access the control plane.
## Step 5: Service Load Balancing
If wanting to use the `kube-vip` [cloud controller](/docs/usage/cloud-provider/), pass the `--disable servicelb` flag so K3s will not attempt to render Kubernetes Service resources of type `LoadBalancer`. If building with `k3sup`, the flag should be given as an argument to the `--k3s-extra-args` flag itself: `--k3s-extra-args "--disable servicelb"`. To install the `kube-vip` cloud controller, follow the additional steps in the [cloud controller guide](/docs/usage/cloud-provider/#install-the-kube-vip-cloud-provider).

View File

@@ -1,80 +0,0 @@
# Kube-vip on KIND
## Deploying KIND
The documentation for KIND is fantastic and its [quick start](https://kind.sigs.k8s.io/docs/user/quick-start/) guide will have you up and running in no time.
## Find Address Pool for Kube-Vip
We will need to find addresses that can be used by Kube-Vip:
```
docker network inspect kind -f '{{ range $i, $a := .IPAM.Config }}{{ println .Subnet }}{{ end }}'
```
This will return a CIDR range such as `172.18.0.0/16` and from here we can select a range.
## Deploy the Kube-Vip Cloud Controller
```
kubectl apply -f https://raw.githubusercontent.com/kube-vip/kube-vip-cloud-provider/main/manifest/kube-vip-cloud-controller.yaml
```
## Add our Address range
```
kubectl create configmap --namespace kube-system kubevip --from-literal range-global=172.18.100.10-172.18.100.30
```
## Install kube-vip
### Create the RBAC settings
Since `kube-vip` as a DaemonSet runs as a regular resource instead of a static Pod, it still needs the correct access to be able to watch Kubernetes Services and other objects. In order to do this, RBAC resources must be created which include a ServiceAccount, ClusterRole, and ClusterRoleBinding and can be applied this with the command:
```
kubectl apply -f https://kube-vip.io/manifests/rbac.yaml
```
### Get latest version
We can parse the GitHub API to find the latest version (or we can set this manually)
`KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases | jq -r ".[0].name")`
or manually:
`export KVVERSION=vx.x.x`
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 ghcr.io/kube-vip/kube-vip:$KVVERSION vip /kube-vip"`
### Docker
`alias kube-vip="docker run --network host --rm ghcr.io/kube-vip/kube-vip:$KVVERSION"`
## Deploy Kube-vip as a DaemonSet
```
kube-vip manifest daemonset --services --inCluster --arp --interface eth0 | kubectl apply -f -
```
## Test
```
kubectl apply -f https://k8s.io/examples/application/deployment.yaml
```
```
kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx
```
```
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 74m
nginx LoadBalancer 10.96.196.235 172.18.100.11 80:31236/TCP 6s
```

View File

@@ -1,182 +0,0 @@
# Kube-Vip On-Prem
We've designed `kube-vip` to be as decoupled 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.
## Cloud Controller Manager
`kube-vip` isn't coupled to anything other than the Kubernetes API and will only act upon an existing Kubernetes primitive (in this case the object of type `Service`). This makes it easy for existing [cloud controller managers (CCMs)](https://kubernetes.io/docs/concepts/architecture/cloud-controller/) 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.
## Using the Kube-Vip Cloud Provider
The `kube-vip` cloud provider can be used to populate an IP address for Services of type `LoadBalancer` similar to what public cloud providers allow through a Kubernetes CCM. The below instructions *should just work* on Kubernetes regardless of the architecture (a Linux OS being the only requirement) and will install the latest components.
## Install the Kube-Vip Cloud Provider
The `kube-vip` cloud provider can be installed from the latest release in the `main` branch by using the following command:
```
kubectl apply -f https://raw.githubusercontent.com/kube-vip/kube-vip-cloud-provider/main/manifest/kube-vip-cloud-controller.yaml
```
## Create a global CIDR or IP Range
In order for `kube-vip` to set an IP address for a Service of type `LoadBalancer`, it needs to have an availability of IP address to assign. This information is stored in a Kubernetes ConfigMap to which `kube-vip` has access. You control the scope of the IP allocations with the `key` within the ConfigMap. Either CIDR blocks or IP ranges may be specified and scoped either globally (cluster-side) or per-Namespace.
To allow a global (cluster-wide) CIDR block which `kube-vip` can use to allocate an IP to Services of type `LoadBalancer` in any Namespace, create a ConfigMap named `kubevip` with the key `cidr-global` and value equal to a CIDR block available in your environment. For example, the below command creates a global CIDR with value `192.168.0.220/29` from which `kube-vip` will allocate IP addresses.
```
kubectl create configmap -n kube-system kubevip --from-literal cidr-global=192.168.0.220/29
```
To use a global range instead, create the key `range-global` with the value set to a valid range of IP addresses. For example, the below command creates a global range using the pool `192.168.1.220-192.168.1.230`.
```
kubectl create configmap -n kube-system kubevip --from-literal range-global=192.168.1.220-192.168.1.230
```
Creating services of type `LoadBalancer` in any Namespace will now take addresses from one of the global pools defined in the ConfigMap unless a Namespace-specific pool is created.
### The Kube-Vip Cloud Provider ConfigMap
To manage the IP address ranges for Services of type `LoadBalancer`, the `kube-vip-cloud-provider` uses a ConfigMap held in the `kube-system` Namespace. IP addresses can be configured using one or multiple formats:
- CIDR blocks
- IP ranges [start address - end address]
- Multiple pools by CIDR per Namespace
- Multiple IP ranges per Namespace (handles overlapping ranges)
- Setting of static addresses through service.metadata.annotations `kube-vip.io/loadbalancerIPs`
- Setting of static addresses through --load-balancer-ip=x.x.x.x (`kubectl expose` command)
To control which IP address range is used for which Service, the following rules are applied:
- Global address pools (`cidr-global` or `range-global`) are available for use by *any* Service in *any* Namespace
- Namespace specific address pools (`cidr-<namespace>` or `range-<namespace>`) are *only* available for use by a Service in the *specific* Namespace
- Static IP addresses can be applied to a Service of type `LoadBalancer` using the `spec.loadBalancerIP` field, even outside of the assigned ranges
Example Configmap:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kubevip
namespace: kube-system
data:
cidr-default: 192.168.0.200/29 # CIDR-based IP range for use in the default Namespace
range-development: 192.168.0.210-192.168.0.219 # Range-based IP range for use in the development Namespace
cidr-finance: 192.168.0.220/29,192.168.0.230/29 # Multiple CIDR-based ranges for use in the finance Namespace
cidr-global: 192.168.0.240/29 # CIDR-based range which can be used in any Namespace
```
### 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
```
or via a Service YAML definition:
```
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- name: http
port: 80
protocol: TCP
selector:
app: nginx
type: LoadBalancer
```
We can also expose a specific address by specifying it imperatively in the Service definition:
```
apiVersion: v1
kind: Service
metadata:
annotations:
"kube-vip.io/loadbalancerIPs": "1.1.1.1"
name: nginx
spec:
ports:
- name: http
port: 80
protocol: TCP
selector:
app: nginx
type: LoadBalancer
```
Or set it through command line.
```
kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx --load-balancer-ip=1.1.1.1
```
Since k8s 1.24, loadbalancerIP field [is deprecated](https://github.com/kubernetes/kubernetes/pull/107235). It's recommended to use the annotations instead of command line or `service.spec.loadBalancerIP` to specify the ip.
### Using DHCP for Load Balancers (experimental)
With `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 `LoadBalancer` IP and update the Kubernetes Service.
```
$ kubectl expose deployment nginx-deployment --port=80 --type=LoadBalancer --name=nginx-dhcp --load-balancer-ip=0.0.0.0; kubectl 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 ... }
$ kubectl 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 `kube-vip` > 0.2.1, it is possible to expose a Service of type `LoadBalancer` on a specific port to the Internet by using UPnP (on a supported gateway).
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 of either the static Pod or DaemonSet for `kube-vip`, and the rest should be completely automated.
**Note** some environments may require (Unifi) `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>
...
```

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

210
go.mod
View File

@@ -1,111 +1,165 @@
module github.com/kube-vip/kube-vip
go 1.19
go 1.24.4
require (
github.com/cloudflare/ipvs v0.9.1
github.com/davecgh/go-spew v1.1.1
github.com/cloudflare/ipvs v0.11.0
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/docker/docker v28.3.3+incompatible
github.com/florianl/go-conntrack v0.4.0
github.com/golang/protobuf v1.5.3
github.com/insomniacslk/dhcp v0.0.0-20230731140434-0f9eb93a696c
github.com/google/go-cmp v0.7.0
github.com/google/nftables v0.3.0
github.com/gookit/slog v0.5.8
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/kamhlos/upnp v0.0.0-20210324072331-5661950dff08
github.com/mdlayher/ndp v1.0.1
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.27.10
github.com/osrg/gobgp/v3 v3.17.0
github.com/packethost/packngo v0.30.0
github.com/mdlayher/ndp v1.1.0
github.com/onsi/ginkgo/v2 v2.23.4
github.com/onsi/gomega v1.37.0
github.com/osrg/gobgp/v3 v3.37.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.16.0
github.com/prometheus/client_golang v1.22.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
github.com/vishvananda/netlink v1.2.1-beta.2
golang.org/x/sys v0.10.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
k8s.io/api v0.27.4
k8s.io/apimachinery v0.27.4
k8s.io/client-go v0.27.4
k8s.io/klog/v2 v2.100.1
sigs.k8s.io/kind v0.20.0
sigs.k8s.io/yaml v1.3.0
github.com/spf13/cobra v1.9.1
github.com/stretchr/testify v1.10.0
github.com/vishvananda/netlink v1.3.1
go.etcd.io/etcd/api/v3 v3.6.1
go.etcd.io/etcd/client/pkg/v3 v3.6.1
go.etcd.io/etcd/client/v3 v3.6.1
go.uber.org/zap v1.27.0
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329
golang.org/x/sync v0.15.0
golang.org/x/sys v0.33.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20241231184526-a9ab2273dd10
google.golang.org/grpc v1.73.0
google.golang.org/protobuf v1.36.6
k8s.io/api v0.33.3
k8s.io/apimachinery v0.33.3
k8s.io/client-go v0.33.3
k8s.io/klog/v2 v2.130.1
sigs.k8s.io/kind v0.29.0
sigs.k8s.io/yaml v1.4.0
)
require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/alessio/shellescape v1.4.1 // indirect
al.essio.dev/pkg/shellescape v1.5.1 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/Microsoft/go-winio v0.4.14 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // 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/containerd/log v0.1.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.9.0 // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.1 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/emicklei/go-restful/v3 v3.12.1 // 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.7.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/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.9 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gookit/goutil v0.6.18 // indirect
github.com/gookit/gsr v0.1.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.12 // 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.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // 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.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.4.1 // 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/atomicwriter v0.1.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.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nxadm/tail v1.4.8 // 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.0.7 // indirect
github.com/pierrec/lz4/v4 v4.1.18 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.15.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/net v0.12.0 // indirect
golang.org/x/oauth2 v0.5.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/term v0.10.0 // indirect
golang.org/x/text v0.11.0 // indirect
golang.org/x/time v0.1.0 // indirect
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230320184635-7606e756e683 // indirect
google.golang.org/grpc v1.53.0 // indirect
google.golang.org/protobuf v1.30.0 // 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.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.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.6 // 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.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel v1.37.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect
go.opentelemetry.io/otel/metric v1.37.0 // indirect
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
go.opentelemetry.io/otel/trace v1.37.0 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.39.0 // indirect
golang.org/x/mod v0.25.0 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/term v0.32.0 // indirect
golang.org/x/text v0.26.0 // indirect
golang.org/x/time v0.9.0 // indirect
golang.org/x/tools v0.33.0 // indirect
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // 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/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
k8s.io/utils v0.0.0-20241210054802-24370beab758 // 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/v4 v4.6.0 // indirect
)

910
go.sum

File diff suppressed because it is too large Load Diff

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

@@ -0,0 +1,149 @@
package arp
import (
"context"
log "log/slog"
"sync"
"time"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/vip"
)
type Manager struct {
instances map[string]*Instance
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{
instances: make(map[string]*Instance),
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, ok := m.instances[instance.Name()]
if !ok {
log.Info("inserting ARP/NDP instance", "name", instance.Name())
m.instances[instance.Name()] = instance
} else {
i.mu.Lock()
defer i.mu.Unlock()
i.counter++
}
}
func (m *Manager) Remove(instance *Instance) {
if i, ok := m.instances[instance.Name()]; ok {
i.mu.Lock()
defer i.mu.Unlock()
if i.counter > 1 {
i.counter--
} else {
log.Info("removing ARP/NDP instance", "name", instance.Name())
delete(m.instances, instance.Name())
}
}
}
func (m *Manager) Count(name string) int {
if i, ok := m.instances[name]; ok {
i.mu.Lock()
defer i.mu.Unlock()
return i.counter
}
return 0
}
func (m *Manager) StartAdvertisement(ctx context.Context) {
log.Info("Starting ARP/NDP advertisement")
for {
select {
case <-ctx.Done(): // if cancel() execute
return
default:
for _, instance := range m.instances {
if instance.counter > 0 {
ensureIPAndSendGratuitous(instance)
}
}
}
if m.config.ArpBroadcastRate < 500 {
log.Error("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)
}
}
// 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", "IP", ipString, "interface", iface)
// if _, err := instance.network.AddIP(false); err != nil {
// log.Error("failed to recreate address", "IP", ipString, "interface", iface)
// }
}
}
// Ensure the address exists on the interface before attempting to ARP
// if instance.network.HasEndpoints() {
if added, err := instance.network.AddIP(true); err != nil {
log.Warn(err.Error())
} else if added {
log.Warn("Re-applied the VIP configuration", "ip", ipString, "interface", iface)
}
// }
if vip.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())
}
}
}

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

@@ -0,0 +1,88 @@
package backend
import (
"fmt"
"time"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/k8s"
"github.com/kube-vip/kube-vip/pkg/utils"
"github.com/kube-vip/kube-vip/pkg/vip"
"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 vip.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

@@ -7,9 +7,11 @@ import (
"strconv"
"strings"
"github.com/golang/protobuf/ptypes" //nolint
"github.com/golang/protobuf/ptypes/any"
//nolint
"github.com/kube-vip/kube-vip/pkg/vip"
api "github.com/osrg/gobgp/v3/api"
"github.com/osrg/gobgp/v3/pkg/server"
"google.golang.org/protobuf/types/known/anypb"
)
// AddPeer will add peers to the BGP configuration
@@ -23,7 +25,9 @@ func (b *Server) AddPeer(peer Peer) (err error) {
Timers: &api.Timers{
Config: &api.TimersConfig{
ConnectRetry: 10,
ConnectRetry: 10,
HoldTime: b.c.HoldTime,
KeepaliveInterval: b.c.KeepaliveInterval,
},
},
@@ -40,36 +44,94 @@ func (b *Server) AddPeer(peer Peer) (err error) {
},
}
if b.c.SourceIP != "" {
p.Transport.LocalAddress = b.c.SourceIP
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,
},
},
}
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 vip.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
}
}
if b.c.SourceIF != "" {
p.Transport.BindInterface = b.c.SourceIF
if err := b.s.AddPeer(context.Background(), &api.AddPeerRequest{Peer: p}); err != nil {
return fmt.Errorf("failed to add peer: %v", err)
}
return b.s.AddPeer(context.Background(), &api.AddPeerRequest{
Peer: p,
})
return nil
}
func (b *Server) getPath(ip net.IP) (path *api.Path) {
isV6 := ip.To4() == nil
//nolint
originAttr, _ := ptypes.MarshalAny(&api.OriginAttribute{
originAttr, _ := anypb.New(&api.OriginAttribute{
Origin: 0,
})
if !isV6 {
//nolint
nlri, _ := ptypes.MarshalAny(&api.IPAddressPrefix{
nlri, _ := anypb.New(&api.IPAddressPrefix{
Prefix: ip.String(),
PrefixLen: 32,
})
//nolint
nhAttr, _ := ptypes.MarshalAny(&api.NextHopAttribute{
nhAttr, _ := anypb.New(&api.NextHopAttribute{
NextHop: "0.0.0.0", // gobgp will fill this
})
@@ -79,11 +141,11 @@ func (b *Server) getPath(ip net.IP) (path *api.Path) {
Safi: api.Family_SAFI_UNICAST,
},
Nlri: nlri,
Pattrs: []*any.Any{originAttr, nhAttr},
Pattrs: []*anypb.Any{originAttr, nhAttr},
}
} else {
//nolint
nlri, _ := ptypes.MarshalAny(&api.IPAddressPrefix{
nlri, _ := anypb.New(&api.IPAddressPrefix{
Prefix: ip.String(),
PrefixLen: 128,
})
@@ -94,16 +156,16 @@ func (b *Server) getPath(ip net.IP) (path *api.Path) {
}
//nolint
mpAttr, _ := ptypes.MarshalAny(&api.MpReachNLRIAttribute{
mpAttr, _ := anypb.New(&api.MpReachNLRIAttribute{
Family: v6Family,
NextHops: []string{"::"}, // gobgp will fill this
Nlris: []*any.Any{nlri},
Nlris: []*anypb.Any{nlri},
})
path = &api.Path{
Family: v6Family,
Nlri: nlri,
Pattrs: []*any.Any{originAttr, mpAttr},
Pattrs: []*anypb.Any{originAttr, mpAttr},
}
}
return
@@ -113,11 +175,13 @@ func (b *Server) getPath(ip net.IP) (path *api.Path) {
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")
return nil, fmt.Errorf("no BGP Peer configurations found")
}
for x := range peers {
peerStr := peers[x]
config := strings.Split(peerStr, "/")
peerStr = config[0]
if peerStr == "" {
continue
}
@@ -160,14 +224,118 @@ func ParseBGPPeerConfig(config string) (bgpPeers []Peer, err error) {
}
}
var port uint64
if len(peer) >= 5 {
port, err = strconv.ParseUint(peer[4], 10, 16)
if err != nil {
return nil, fmt.Errorf("BGP Peer AS format error [%s]", peer[1])
}
} else {
port = 179
}
var mpbgpNexthop, mpbgpIPv4, mpbgpIPv6 string
if len(config) > 1 {
configData := strings.Split(config[1], ";")
for _, cfg := range configData {
c := strings.Split(cfg, "=")
switch c[0] {
case "mpbgp_nexthop":
mpbgpNexthop = c[1]
case "mpbgp_ipv4":
mpbgpIPv4 = c[1]
case "mpbgp_ipv6":
mpbgpIPv6 = c[1]
default:
return nil, fmt.Errorf("peer configuration parameter '%s' is not supported", c[0])
}
}
}
peerConfig := Peer{
Address: address,
AS: uint32(ASNumber),
Password: password,
MultiHop: multiHop,
Address: address,
AS: uint32(ASNumber),
Port: uint16(port),
Password: password,
MultiHop: multiHop,
MpbgpNexthop: mpbgpNexthop,
MpbgpIPv4: mpbgpIPv4,
MpbgpIPv6: mpbgpIPv6,
}
bgpPeers = append(bgpPeers, peerConfig)
}
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
}

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

@@ -0,0 +1,54 @@
package bgp
import (
"reflect"
"testing"
)
func TestParseBGPPeerConfig(t *testing.T) {
type args struct {
config string
}
tests := []struct {
name string
args args
wantBgpPeers []Peer
wantErr bool
}{
{
name: "IPv4, default port",
args: args{config: "192.168.0.10:65000::false,192.168.0.11:65000::false"},
wantBgpPeers: []Peer{
{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: []Peer{
{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: []Peer{
{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 := 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,37 +3,51 @@ package bgp
import (
"context"
"fmt"
"log"
"time"
log "log/slog"
api "github.com/osrg/gobgp/v3/api"
gobgp "github.com/osrg/gobgp/v3/pkg/server"
"github.com/prometheus/client_golang/prometheus"
)
// NewBGPServer takes a configuration and returns a running BGP server instance
func NewBGPServer(c *Config, peerStateChangeCallback func(*api.WatchEventResponse_PeerEvent)) (b *Server, err error) {
func NewBGPServer(c *Config) (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")
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,
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{
Asn: c.AS,
RouterId: c.RouterID,
Asn: b.c.AS,
RouterId: b.c.RouterID,
ListenPort: -1,
},
}); err != nil {
@@ -42,7 +56,7 @@ func NewBGPServer(c *Config, peerStateChangeCallback func(*api.WatchEventRespons
if err = b.s.WatchEvent(context.Background(), &api.WatchEventRequest{Peer: &api.WatchEventRequest_Peer{}}, func(r *api.WatchEventResponse) {
if p := r.GetPeer(); p != nil && p.Type == api.WatchEventResponse_PeerEvent_STATE {
log.Println(p)
log.Info("[BGP]", "peer", p.String())
if peerStateChangeCallback != nil {
peerStateChangeCallback(p)
}
@@ -51,12 +65,23 @@ func NewBGPServer(c *Config, peerStateChangeCallback func(*api.WatchEventRespons
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,27 +1,145 @@
package bgp
import gobgp "github.com/osrg/gobgp/v3/pkg/server"
import (
"fmt"
"net"
"github.com/kube-vip/kube-vip/pkg/vip"
api "github.com/osrg/gobgp/v3/api"
gobgp "github.com/osrg/gobgp/v3/pkg/server"
"github.com/prometheus/client_golang/prometheus"
"github.com/vishvananda/netlink"
)
// Peer defines a BGP Peer
type Peer struct {
Address string
AS uint32
Password string
MultiHop bool
Address string
Port uint16
AS uint32
Password string
MultiHop bool
MpbgpNexthop string
MpbgpIPv4 string
MpbgpIPv6 string
}
func (p *Peer) setMpbgpOptions(server *Config) {
if p.MpbgpNexthop == "" {
p.MpbgpNexthop = server.MpbgpNexthop
}
if p.MpbgpIPv4 == "" {
p.MpbgpIPv4 = server.MpbgpIPv4
}
if p.MpbgpIPv6 == "" {
p.MpbgpIPv6 = server.MpbgpIPv6
}
}
func (p *Peer) findMpbgpAddresses(ap *api.Peer, server *Config) (string, string, error) {
var ipv4Address, ipv6Address string
switch p.MpbgpNexthop {
case "fixed":
ap.Transport.LocalAddress = server.SourceIP
if p.MpbgpIPv4 == "" && p.MpbgpIPv6 == "" {
return "", "", fmt.Errorf("to use MP-BGP with fixed address at least one IPv4 or IPv6 address has to be provided [current - IPv4: %s, IPv6: %s]",
p.MpbgpIPv4, p.MpbgpIPv6)
}
if p.MpbgpIPv4 != "" {
if net.ParseIP(p.MpbgpIPv4) == nil {
return "", "", fmt.Errorf("provided address '%s' is not a valid IPv4 address", p.MpbgpIPv4)
}
}
if p.MpbgpIPv6 != "" {
if net.ParseIP(p.MpbgpIPv6) == nil {
return "", "", fmt.Errorf("provided address '%s' is not a valid IPv6 address", p.MpbgpIPv6)
}
}
ipv4Address = p.MpbgpIPv4
ipv6Address = p.MpbgpIPv6
case "auto_sourceip":
ap.Transport.LocalAddress = server.SourceIP
// Resolve the local interface by SourceIP
iface, err := vip.GetInterfaceByIP(server.SourceIP)
if err != nil {
return "", "", fmt.Errorf("failed to get interface by IP: %v", err)
}
if vip.IsIPv4(server.SourceIP) {
// Get the non link-local IPv6 address on that interface
ipv6Address, err = vip.GetNonLinkLocalIP(iface, netlink.FAMILY_V6)
if err != nil {
return "", "", fmt.Errorf("failed to get non link-local IPv6 address: %v", err)
}
} else {
// Get the non link-local IPv4 address on that interface
ipv4Address, err = vip.GetNonLinkLocalIP(iface, netlink.FAMILY_V4)
if err != nil {
return "", "", fmt.Errorf("failed to get non link-local IPv4 address: %v", err)
}
}
case "auto_sourceif":
ap.Transport.BindInterface = server.SourceIF
iface, err := netlink.LinkByName(server.SourceIF)
if err != nil {
return "", "", fmt.Errorf("failed to get interface by name: %v", err)
}
// Get the non link-local IPv4 address on that interface
ipv4Address, err = vip.GetNonLinkLocalIP(&iface, netlink.FAMILY_V4)
if err != nil {
return "", "", fmt.Errorf("failed to get non link-local IPv4 address: %v", err)
}
// Get the non link-local IPv6 address on that interface
ipv6Address, err = vip.GetNonLinkLocalIP(&iface, netlink.FAMILY_V6)
if err != nil {
return "", "", fmt.Errorf("failed to get non link-local IPv6 address: %v", err)
}
default:
return "", "", fmt.Errorf("option %s for MP-BPG nexthop is not supported", server.MpbgpNexthop)
}
return ipv4Address, ipv6Address, nil
}
// Config defines the BGP server configuration
type Config struct {
AS uint32
RouterID string
SourceIP string
SourceIF string
AS uint32
RouterID string
SourceIP string
SourceIF string
MpbgpNexthop string
MpbgpIPv4 string
MpbgpIPv6 string
HoldTime uint64
KeepaliveInterval uint64
Peers []Peer
Zebra ZebraConfig
}
// Defines Zebra connection configuration. More on the topic - https://github.com/osrg/gobgp/blob/master/docs/sources/zebra.md#configuration
type ZebraConfig struct {
Enabled bool
URL string
Version uint32
SoftwareName string
}
// Server manages a server object
type Server struct {
s *gobgp.BgpServer
c *Config
// This is a prometheus gauge indicating the state of the sessions.
// 1 means "ESTABLISHED", 0 means "NOT ESTABLISHED"
BGPSessionInfoGauge *prometheus.GaugeVec
}

View File

@@ -3,9 +3,11 @@ package cluster
import (
"sync"
log "github.com/sirupsen/logrus"
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"
)
@@ -14,49 +16,59 @@ type Cluster struct {
stop chan bool
completed chan bool
once sync.Once
Network vip.Network
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) {
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.Debugf("init enable service security: %t", c.EnableServiceSecurity)
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.VIPSubnet, c.DDNS, c.RoutingTableID)
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 chanel, which will shut down the VIP (if needed)
// 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)

View File

@@ -13,11 +13,16 @@ import (
// 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)
ip, err := ddnsMgr.Start()
if err != nil {
return err
for i := range cluster.Network {
ddnsMgr := vip.NewDDNSManager(ctx, cluster.Network[i])
ip, err := ddnsMgr.Start()
if err != nil {
return err
}
if err = cluster.Network[i].SetIP(ip); err != nil {
return err
}
}
return cluster.Network.SetIP(ip)
return nil
}

View File

@@ -11,14 +11,14 @@ import (
"github.com/davecgh/go-spew/spew"
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/equinixmetal"
"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/packethost/packngo"
log "log/slog"
log "github.com/sirupsen/logrus"
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"
@@ -32,9 +32,12 @@ import (
// Manager degines the manager of the load-balancing services
type Manager struct {
KubernetesClient *kubernetes.Clientset
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
@@ -60,38 +63,38 @@ func NewManager(path string, inCluster bool, port int) (*Manager, error) {
hostname = fmt.Sprintf("%s:%v", id, port)
}
clientset, err := k8s.NewClientset(path, inCluster, hostname)
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,
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 {
id, err := os.Hostname()
if err != nil {
return err
}
var err error
log.Infof("Beginning cluster membership, namespace [%s], lock name [%s], id [%s]", c.Namespace, c.LeaseName, 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: c.LeaseName,
Namespace: c.Namespace,
Annotations: c.LeaseAnnotations,
},
Client: sm.KubernetesClient.CoordinationV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: id,
},
}
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
@@ -126,10 +129,16 @@ func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *
// Cancel the arp context, which will in turn stop any broadcasts
}()
// (attempt to) Remove the virtual IP, incase it already exists
err = cluster.Network.DeleteIP()
if err != nil {
log.Errorf("could not delete virtualIP: %v", err)
// (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
@@ -139,42 +148,105 @@ func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *
}
}()
// If Equinix Metal is enabled then we can begin our preparation work
var packetClient *packngo.Client
if c.EnableMetal {
if c.ProviderConfig != "" {
key, project, err := equinixmetal.GetPacketConfig(c.ProviderConfig)
if err != nil {
log.Error(err)
} else {
// Set the environment variable with the key for the project
os.Setenv("PACKET_AUTH_TOKEN", key)
// Update the configuration with the project key
c.MetalProjectID = project
}
}
packetClient, err = packngo.NewClient()
if err != nil {
log.Error(err)
}
// We're using Equinix Metal with BGP, populate the Peer information from the API
if c.EnableBGP {
log.Infoln("Looking up the BGP configuration from Equinix Metal")
err = equinixmetal.BGPLookup(packetClient, c)
if err != nil {
log.Error(err)
}
}
}
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, nil)
bgpServer, err = bgp.NewBGPServer(&c.BGPConfig)
if err != nil {
log.Error(err)
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
// 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)
}
}
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)
},
}
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
@@ -187,62 +259,42 @@ func (cluster *Cluster) StartCluster(c *kubevip.Config, sm *Manager, bgpServer *
// 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,
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: func(ctx context.Context) {
// As we're leading lets start the vip service
err = cluster.vipService(ctxArp, ctxDNS, c, sm, bgpServer, packetClient)
if err != nil {
log.Errorf("Error starting the VIP service on the leader [%s]", err)
}
},
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)
}
}
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)
},
OnStartedLeading: run.onStartedLeading,
OnStoppedLeading: run.onStoppedLeading,
OnNewLeader: run.onNewLeader,
},
})
return nil
}
func (sm *Manager) NodeWatcher(lb *loadbalancer.IPVSLoadBalancer, port int) error {
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.Infof("Kube-Vip is watching nodes for control-plane labels")
log.Info("Kube-Vip is watching nodes for control-plane labels")
listOptions := metav1.ListOptions{
LabelSelector: "node-role.kubernetes.io/control-plane",
}
rw, err := watchtools.NewRetryWatcher("1", &cache.ListWatch{
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
return sm.KubernetesClient.CoreV1().Nodes().Watch(context.Background(), listOptions)
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 {
@@ -270,9 +322,16 @@ func (sm *Manager) NodeWatcher(lb *loadbalancer.IPVSLoadBalancer, port int) erro
// 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.AddBackend(node.Status.Addresses[x].Address, port)
if err != nil {
log.Errorf("add IPVS backend [%v]", err)
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)
}
}
}
}
@@ -287,12 +346,12 @@ func (sm *Manager) NodeWatcher(lb *loadbalancer.IPVSLoadBalancer, port int) erro
if node.Status.Addresses[x].Type == v1.NodeInternalIP {
err = lb.RemoveBackend(node.Status.Addresses[x].Address, port)
if err != nil {
log.Errorf("Del IPVS backend [%v]", err)
log.Error("Del IPVS backend", "err", err)
}
}
}
log.Infof("Node [%s] has been deleted", node.Name)
log.Info("Node deleted", "name", node.Name)
case watch.Bookmark:
// Un-used
@@ -303,15 +362,29 @@ func (sm *Manager) NodeWatcher(lb *loadbalancer.IPVSLoadBalancer, port int) erro
errObject := apierrors.FromObject(event.Object)
statusErr, ok := errObject.(*apierrors.StatusError)
if !ok {
log.Errorf(spew.Sprintf("Received an error which is not *metav1.Status but %#+v", event.Object))
log.Error(spew.Sprintf("Received an error which is not *metav1.Status but %#+v", event.Object))
}
status := statusErr.ErrStatus
log.Errorf("%v", status)
log.Error("watcher", "status", status)
default:
}
}
log.Infoln("Exiting Node watcher")
log.Info("Exiting Node watcher")
return nil
}
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

@@ -2,26 +2,32 @@ package cluster
import (
"context"
"errors"
"fmt"
"io/fs"
"net"
"os"
"os/signal"
"sync"
"syscall"
"time"
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/equinixmetal"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/kube-vip/kube-vip/pkg/loadbalancer"
"github.com/kube-vip/kube-vip/pkg/vip"
"github.com/packethost/packngo"
log "github.com/sirupsen/logrus"
"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, packetClient *packngo.Client) error {
id, err := os.Hostname()
if err != nil {
return err
}
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
@@ -33,245 +39,343 @@ func (cluster *Cluster) vipService(ctxArp, ctxDNS context.Context, c *kubevip.Co
// Add Notification for SIGTERM (sent from Kubernetes)
signal.Notify(signalChan, syscall.SIGTERM)
if cluster.Network.IsDDNS() {
if err := cluster.StartDDNS(ctxDNS); err != nil {
log.Error(err)
loadbalancers := []*loadbalancer.IPVSLoadBalancer{}
var arpWG sync.WaitGroup
for i := range cluster.Network {
network := cluster.Network[i]
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 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 Equinix Metal with BGP
if !c.EnableBGP {
// Attempt to attach the EIP in the standard manner
log.Debugf("Attaching the Equinix Metal EIP through the API to this host")
err = equinixmetal.AttachEIP(packetClient, c, id)
if err != nil {
log.Error(err)
if network.IsDDNS() {
if err := cluster.StartDDNS(ctxDNS); err != nil {
log.Error(err.Error())
}
}
}
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)
// 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)
}
err = bgpServer.AddHost(cidrVip)
if err != nil {
log.Error(err)
if !c.EnableRoutingTable {
if _, err = network.AddIP(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 {
log.Infof("Starting IPVS LoadBalancer")
lb, err := loadbalancer.NewIPVSLB(cluster.Network.IP(), c.LoadBalancerPort, c.LoadBalancerForwardingMethod)
if err != nil {
log.Errorf("Error creating IPVS LoadBalancer [%s]", err)
}
go func() {
err = sm.NodeWatcher(lb, c.Port)
if err != nil {
log.Errorf("Error watching node labels [%s]", err)
}
}()
// Shutdown function that will wait on this signal, unless we call it ourselves
go func() {
<-signalChan
<-signalChan
for _, lb := range loadbalancers {
err = lb.RemoveIPVSLB()
if err != nil {
log.Errorf("Error stopping IPVS LoadBalancer [%s]", err)
}
log.Info("Stopping IPVS LoadBalancer")
}()
}
if c.EnableARP {
// ctxArp, cancelArp = context.WithCancel(context.Background())
ipString := cluster.Network.IP()
isIPv6 := vip.IsIPv6(ipString)
var ndp *vip.NdpResponder
if isIPv6 {
ndp, err = vip.NewNDPResponder(c.Interface)
if err != nil {
log.Fatalf("failed to create new NDP Responder")
log.Error("Error stopping IPVS LoadBalancer", "err", err)
}
}
go func(ctx context.Context) {
if ndp != nil {
defer ndp.Close()
}
log.Infof("Gratuitous Arp broadcast will repeat every 3 seconds for [%s]", ipString)
for {
select {
case <-ctx.Done(): // if cancel() execute
return
default:
cluster.ensureIPAndSendGratuitous(c.Interface, ndp)
}
time.Sleep(3 * time.Second)
}
}(ctxArp)
}
if c.EnableRoutingTable {
err = cluster.Network.AddRoute()
if err != nil {
log.Warnf("%v", err)
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
}
backendMap := &backendMapV4
if isNetworkV6 {
backendMap = &backendMapV6
}
for entry := range *backendMap {
if entry.Check() {
_, err = network.AddIP(true)
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(c *kubevip.Config, bgp *bgp.Server) {
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(context.Background())
ctxArp, cancelArp := context.WithCancel(ctx)
cluster.stop = make(chan bool, 1)
cluster.completed = make(chan bool, 1)
err := cluster.Network.DeleteIP()
if err != nil {
log.Warnf("Attempted to clean existing VIP => %v", err)
}
if c.EnableRoutingTable {
err = cluster.Network.AddRoute()
if err != nil {
log.Warnf("%v", err)
}
} else {
err = cluster.Network.AddIP()
if err != nil {
log.Warnf("%v", err)
}
}
if c.EnableARP {
// ctxArp, cancelArp = context.WithCancel(context.Background())
var arpWG sync.WaitGroup
ipString := cluster.Network.IP()
for i := range cluster.Network {
network := cluster.Network[i]
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)
}
var ndp *vip.NdpResponder
if vip.IsIPv6(ipString) {
ndp, err = vip.NewNDPResponder(c.Interface)
if c.EnableRoutingTable && (c.EnableLeaderElection || c.EnableServicesElection) {
err = network.AddRoute(false)
if err != nil {
log.Fatalf("failed to create new NDP Responder")
log.Warn(err.Error())
}
} else if !c.EnableRoutingTable {
if _, err = network.AddIP(false); err != nil {
log.Warn(err.Error())
}
}
go func(ctx context.Context) {
if ndp != nil {
defer ndp.Close()
}
log.Debugf("Broadcasting ARP update for %s via %s, every %dms", ipString, c.Interface, c.ArpBroadcastRate)
for {
select {
case <-ctx.Done(): // if cancel() execute
return
default:
cluster.ensureIPAndSendGratuitous(c.Interface, ndp)
}
if c.ArpBroadcastRate < 500 {
log.Errorf("arp broadcast rate is [%d], this shouldn't be lower that 300ms (defaulting to 3000)", c.ArpBroadcastRate)
c.ArpBroadcastRate = 3000
}
time.Sleep(time.Duration(c.ArpBroadcastRate) * time.Millisecond)
}
}(ctxArp)
log.Debugf("ending ARP update for %s via %s, every %dms", ipString, c.Interface, c.ArpBroadcastRate)
}
if c.EnableARP {
arpWG.Add(1)
go cluster.layer2Update(ctxArp, network, c, &arpWG)
}
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)
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() {
//nolint
for {
select {
case <-cluster.stop:
// Stop the Arp context if it is running
cancelArp()
<-cluster.stop
// Stop the Arp context if it is running
cancelArp()
log.Info("[LOADBALANCER] Stopping load balancers")
log.Infof("[VIP] Releasing the Virtual IP [%s]", c.VIP)
err = cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
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
close(cluster.completed)
return
}
for i := range cluster.Network {
if c.EnableARP && cluster.arpMgr.Count(cluster.Network[i].ARPName()) > 0 {
continue
}
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)
}()
}
// 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 (cluster *Cluster) ensureIPAndSendGratuitous(iface string, ndp *vip.NdpResponder) {
ipString := cluster.Network.IP()
isIPv6 := vip.IsIPv6(ipString)
// Check if IP is dadfailed
if cluster.Network.IsDADFAIL() {
log.Warnf("IP address is in dadfailed state, removing [%s] from interface [%s]", ipString, iface)
err := cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
// 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 vip.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()
}
}
}
}
// Ensure the address exists on the interface before attempting to ARP
set, err := cluster.Network.IsSet()
if err != nil {
log.Warnf("%v", err)
}
if !set {
log.Warnf("Re-applying the VIP configuration [%s] to the interface [%s]", ipString, iface)
err = cluster.Network.AddIP()
if err != nil {
log.Warnf("%v", err)
}
}
log.Debug("layer 2 update", "ip", ipString, "interface", network.Interface(), "ms", c.ArpBroadcastRate)
if isIPv6 {
// Gratuitous NDP, will broadcast new MAC <-> IPv6 address
err := ndp.SendGratuitous(ipString)
if err != nil {
log.Warnf("%v", err)
}
} else {
// Gratuitous ARP, will broadcast to new MAC <-> IPv4 address
err := vip.ARPSendGratuitous(ipString, iface)
if err != nil {
log.Warnf("%v", err)
}
}
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.Remove(arpInstance)
}

View File

@@ -3,8 +3,7 @@ package cluster
import (
"context"
"github.com/packethost/packngo"
log "github.com/sirupsen/logrus"
log "log/slog"
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/kubevip"
@@ -16,58 +15,61 @@ func (cluster *Cluster) StartSingleNode(c *kubevip.Config, disableVIP bool) erro
// Start kube-vip as a single node server
// TODO - Split all this code out as a separate function
log.Infoln("Starting kube-vip as a single node cluster")
log.Info("Starting kube-vip as a single node cluster")
log.Info("This node is assuming leadership of the cluster")
cluster.stop = make(chan bool, 1)
cluster.completed = make(chan bool, 1)
if !disableVIP {
err := cluster.Network.DeleteIP()
if err != nil {
log.Warnf("Attempted to clean existing VIP => %v", err)
for i := range cluster.Network {
if !disableVIP {
deleted, err := cluster.Network[i].DeleteIP()
if err != nil {
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())
}
_, err = cluster.Network[i].AddIP(false)
if err != nil {
log.Warn(err.Error())
}
}
err = cluster.Network.AddIP()
if err != nil {
log.Warnf("%v", err)
}
}
if c.EnableARP {
// 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.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())
}
}
}
go func() {
//nolint
for {
select {
case <-cluster.stop:
<-cluster.stop
if !disableVIP {
log.Info("[VIP] Releasing the Virtual IP")
err := cluster.Network.DeleteIP()
if err != nil {
log.Warnf("%v", err)
}
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.Warn(err.Error())
}
if deleted {
log.Info("deleted address", "IP", cluster.Network[i].IP(), "interface", cluster.Network[i].Interface())
}
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
}
func (cluster *Cluster) StartVipService(c *kubevip.Config, sm *Manager, bgp *bgp.Server, packetClient *packngo.Client) error {
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())
@@ -78,5 +80,5 @@ func (cluster *Cluster) StartVipService(c *kubevip.Config, sm *Manager, bgp *bgp
ctxDNS, cancelDNS := context.WithCancel(context.Background())
defer cancelDNS()
return cluster.vipService(ctxArp, ctxDNS, c, sm, bgp, packetClient)
return cluster.vipService(ctxArp, ctxDNS, c, sm, bgp, nil)
}

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

@@ -0,0 +1,99 @@
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/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 vip.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,125 @@
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])
*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) {
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,178 @@
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.FindServiceInstance(service, *rt.instances)
if instance == nil {
log.Error("failed to find the instance", "service", 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 instance := instance.FindServiceInstance(service, *instances); instance != nil {
for _, cluster := range instance.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 {
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
}

View File

@@ -1,63 +0,0 @@
package equinixmetal
import (
"fmt"
"github.com/kube-vip/kube-vip/pkg/bgp"
"github.com/kube-vip/kube-vip/pkg/kubevip"
"github.com/packethost/packngo"
log "github.com/sirupsen/logrus"
)
// BGPLookup will use the Equinix Metal API functions to populate the BGP information
func BGPLookup(c *packngo.Client, k *kubevip.Config) error {
var thisDevice *packngo.Device
if k.MetalProjectID == "" {
proj := findProject(k.MetalProject, c)
if proj == nil {
return fmt.Errorf("Unable to find Project [%s]", k.MetalProject)
}
thisDevice = findSelf(c, proj.ID)
} else {
thisDevice = findSelf(c, k.MetalProjectID)
}
if thisDevice == nil {
return fmt.Errorf("Unable to find local/this device in Equinix Metal API")
}
fmt.Printf("Querying BGP settings for [%s]", thisDevice.Hostname)
neighbours, _, err := c.Devices.ListBGPNeighbors(thisDevice.ID, &packngo.ListOptions{})
if err != nil {
return err
}
// Ensure neighbours exist (and it's enabled)
if len(neighbours) == 0 {
return fmt.Errorf("The server [%s]/[%s] has no BGP neighbours, ensure BGP is enabled", thisDevice.Hostname, thisDevice.ID)
}
// Add a warning (TODO)
if len(neighbours) > 1 {
log.Warnf("There are [%d] neighbours, only designed to manage one", len(neighbours))
}
// Ensure a peer exists
if len(neighbours[0].PeerIps) == 0 {
return fmt.Errorf("The server [%s]/[%s] has no BGP peers, ensure BGP is enabled", thisDevice.Hostname, thisDevice.ID)
}
k.BGPConfig.RouterID = neighbours[0].CustomerIP
k.BGPConfig.AS = uint32(neighbours[0].CustomerAs)
// Add the peer(s)
for x := range neighbours[0].PeerIps {
peer := bgp.Peer{
Address: neighbours[0].PeerIps[x],
AS: uint32(neighbours[0].PeerAs),
MultiHop: neighbours[0].Multihop,
Password: neighbours[0].Md5Password,
}
k.BGPConfig.Peers = append(k.BGPConfig.Peers, peer)
}
return nil
}

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