Skip to content

Commit 31e0245

Browse files
rkojedzinszkyaauren
authored andcommitted
Support for kube-router.io/peer.localips annotation (#1392)
* Support for kube-router.io/peer.localips annotation * Fix checking for valid addresses in kube-router.io/peer.localips
1 parent fb5905e commit 31e0245

File tree

3 files changed

+66
-7
lines changed

3 files changed

+66
-7
lines changed

docs/bgp.md

+20
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,36 @@ kubectl annotate node <kube-node> "kube-router.io/peer.asns=65000,65000"
9797

9898
For traffic shaping purposes, you may want to prepend the AS path announced to peers.
9999
This can be accomplished on a per-node basis with annotations:
100+
100101
- `kube-router.io/path-prepend.as`
101102
- `kube-router.io/path-prepend.repeat-n`
102103

103104
If you wanted to prepend all routes from a particular node with the AS 65000 five times,
104105
you would run the following commands:
106+
105107
```
106108
kubectl annotate node <kube-node> "kube-router.io/path-prepend.as=65000"
107109
kubectl annotate node <kube-node> "kube-router.io/path-prepend.repeat-n=5"
108110
```
109111

112+
### BGP Peer Local IP configuration
113+
114+
In some setups it might be desirable to set local IP address used for connectin external BGP
115+
peers. This can be accomplished on nodes with annotations:
116+
117+
- `kube-router.io/peer.localips`
118+
119+
If set, this must be a list with a local IP address for each peer, or left empty to use nodeIP.
120+
121+
Example:
122+
123+
```
124+
kubectl annotate node <kube-node> "kube-router.io/peer.localips=10.1.1.1,10.1.1.2"
125+
```
126+
127+
This will instruct kube-router to use IP `10.1.1.1` for first BGP peer as a local address, and use `10.1.1.2`
128+
for the second.
129+
110130
### BGP Peer Password Authentication
111131

112132
The examples above have assumed there is no password authentication with BGP

pkg/controllers/routing/bgp_peers.go

+13-4
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,8 @@ func (nrc *NetworkRoutingController) connectToExternalBGPPeers(server *gobgp.Bgp
254254
}
255255

256256
// Does validation and returns neighbor configs
257-
func newGlobalPeers(ips []net.IP, ports []uint32, asns []uint32, passwords []string, holdtime float64,
258-
localAddress string) ([]*gobgpapi.Peer, error) {
257+
func newGlobalPeers(ips []net.IP, ports []uint32, asns []uint32, passwords []string, localips []string,
258+
holdtime float64, localAddress string) ([]*gobgpapi.Peer, error) {
259259
peers := make([]*gobgpapi.Peer, 0)
260260

261261
// Validations
@@ -275,6 +275,12 @@ func newGlobalPeers(ips []net.IP, ports []uint32, asns []uint32, passwords []str
275275
"Example: \"port,,port\" OR [\"port\",\"\",\"port\"]", strconv.Itoa(options.DefaultBgpPort))
276276
}
277277

278+
if len(ips) != len(localips) && len(localips) != 0 {
279+
return nil, fmt.Errorf("invalid peer router config. The number of localIPs should either be zero, or "+
280+
"one per peer router. If blank items are used, it will default to nodeIP, %s. "+
281+
"Example: \"10.1.1.1,,10.1.1.2\" OR [\"10.1.1.1\",\"\",\"10.1.1.2\"]", localAddress)
282+
}
283+
278284
for i := 0; i < len(ips); i++ {
279285
if !((asns[i] >= 1 && asns[i] <= 23455) ||
280286
(asns[i] >= 23457 && asns[i] <= 63999) ||
@@ -285,8 +291,7 @@ func newGlobalPeers(ips []net.IP, ports []uint32, asns []uint32, passwords []str
285291
asns[i])
286292
}
287293

288-
// explicitly set neighbors.transport.config.local-address with nodeIP which is configured
289-
// as their neighbor address at the remote peers.
294+
// explicitly set neighbors.transport.config.local-address
290295
// this prevents the controller from initiating connection to its peers with a different IP address
291296
// when multiple L3 interfaces are active.
292297
peer := &gobgpapi.Peer{
@@ -309,6 +314,10 @@ func newGlobalPeers(ips []net.IP, ports []uint32, asns []uint32, passwords []str
309314
peer.Conf.AuthPassword = passwords[i]
310315
}
311316

317+
if len(localips) != 0 && localips[i] != "" {
318+
peer.Transport.LocalAddress = localips[i]
319+
}
320+
312321
peers = append(peers, peer)
313322
}
314323

pkg/controllers/routing/network_routes_controller.go

+33-3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const (
4949
pathPrependRepeatNAnnotation = "kube-router.io/path-prepend.repeat-n"
5050
peerASNAnnotation = "kube-router.io/peer.asns"
5151
peerIPAnnotation = "kube-router.io/peer.ips"
52+
peerLocalIPAnnotation = "kube-router.io/peer.localips"
5253
//nolint:gosec // this is not a hardcoded password
5354
peerPasswordAnnotation = "kube-router.io/peer.passwords"
5455
peerPortAnnotation = "kube-router.io/peer.ports"
@@ -1115,9 +1116,38 @@ func (nrc *NetworkRoutingController) startBgpServer(grpcServer bool) error {
11151116
}
11161117
}
11171118

1119+
// Get Global Peer Router LocalIP configs
1120+
var peerLocalIPs []string
1121+
nodeBGPPeerLocalIPs, ok := node.ObjectMeta.Annotations[peerLocalIPAnnotation]
1122+
if !ok {
1123+
klog.Infof("Could not find BGP peer local ip info in the node's annotations. Assuming node IP.")
1124+
} else {
1125+
peerLocalIPs = stringToSlice(nodeBGPPeerLocalIPs, ",")
1126+
err = func() error {
1127+
for _, s := range peerLocalIPs {
1128+
if s != "" {
1129+
ip := net.ParseIP(s)
1130+
if ip == nil {
1131+
return fmt.Errorf("could not parse \"%s\" as an IP", s)
1132+
}
1133+
}
1134+
}
1135+
1136+
return nil
1137+
}()
1138+
if err != nil {
1139+
err2 := nrc.bgpServer.StopBgp(context.Background(), &gobgpapi.StopBgpRequest{})
1140+
if err2 != nil {
1141+
klog.Errorf("Failed to stop bgpServer: %s", err2)
1142+
}
1143+
1144+
return fmt.Errorf("failed to parse node's Peer Local Addresses Annotation: %s", err)
1145+
}
1146+
}
1147+
11181148
// Create and set Global Peer Router complete configs
1119-
nrc.globalPeerRouters, err = newGlobalPeers(peerIPs, peerPorts, peerASNs, peerPasswords, nrc.bgpHoldtime,
1120-
nrc.nodeIP.String())
1149+
nrc.globalPeerRouters, err = newGlobalPeers(peerIPs, peerPorts, peerASNs, peerPasswords, peerLocalIPs,
1150+
nrc.bgpHoldtime, nrc.nodeIP.String())
11211151
if err != nil {
11221152
err2 := nrc.bgpServer.StopBgp(context.Background(), &gobgpapi.StopBgpRequest{})
11231153
if err2 != nil {
@@ -1312,7 +1342,7 @@ func NewNetworkRoutingController(clientset kubernetes.Interface,
13121342
}
13131343

13141344
nrc.globalPeerRouters, err = newGlobalPeers(kubeRouterConfig.PeerRouters, peerPorts,
1315-
peerASNs, peerPasswords, nrc.bgpHoldtime, nrc.nodeIP.String())
1345+
peerASNs, peerPasswords, nil, nrc.bgpHoldtime, nrc.nodeIP.String())
13161346
if err != nil {
13171347
return nil, fmt.Errorf("error processing Global Peer Router configs: %s", err)
13181348
}

0 commit comments

Comments
 (0)