Skip to content

Commit 441b9f6

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 d4bc564 commit 441b9f6

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
@@ -47,6 +47,7 @@ const (
4747
pathPrependRepeatNAnnotation = "kube-router.io/path-prepend.repeat-n"
4848
peerASNAnnotation = "kube-router.io/peer.asns"
4949
peerIPAnnotation = "kube-router.io/peer.ips"
50+
peerLocalIPAnnotation = "kube-router.io/peer.localips"
5051
//nolint:gosec // this is not a hardcoded password
5152
peerPasswordAnnotation = "kube-router.io/peer.passwords"
5253
peerPortAnnotation = "kube-router.io/peer.ports"
@@ -1130,9 +1131,38 @@ func (nrc *NetworkRoutingController) startBgpServer(grpcServer bool) error {
11301131
}
11311132
}
11321133

1134+
// Get Global Peer Router LocalIP configs
1135+
var peerLocalIPs []string
1136+
nodeBGPPeerLocalIPs, ok := node.ObjectMeta.Annotations[peerLocalIPAnnotation]
1137+
if !ok {
1138+
klog.Infof("Could not find BGP peer local ip info in the node's annotations. Assuming node IP.")
1139+
} else {
1140+
peerLocalIPs = stringToSlice(nodeBGPPeerLocalIPs, ",")
1141+
err = func() error {
1142+
for _, s := range peerLocalIPs {
1143+
if s != "" {
1144+
ip := net.ParseIP(s)
1145+
if ip == nil {
1146+
return fmt.Errorf("could not parse \"%s\" as an IP", s)
1147+
}
1148+
}
1149+
}
1150+
1151+
return nil
1152+
}()
1153+
if err != nil {
1154+
err2 := nrc.bgpServer.StopBgp(context.Background(), &gobgpapi.StopBgpRequest{})
1155+
if err2 != nil {
1156+
klog.Errorf("Failed to stop bgpServer: %s", err2)
1157+
}
1158+
1159+
return fmt.Errorf("failed to parse node's Peer Local Addresses Annotation: %s", err)
1160+
}
1161+
}
1162+
11331163
// Create and set Global Peer Router complete configs
1134-
nrc.globalPeerRouters, err = newGlobalPeers(peerIPs, peerPorts, peerASNs, peerPasswords, nrc.bgpHoldtime,
1135-
nrc.nodeIP.String())
1164+
nrc.globalPeerRouters, err = newGlobalPeers(peerIPs, peerPorts, peerASNs, peerPasswords, peerLocalIPs,
1165+
nrc.bgpHoldtime, nrc.nodeIP.String())
11361166
if err != nil {
11371167
err2 := nrc.bgpServer.StopBgp(context.Background(), &gobgpapi.StopBgpRequest{})
11381168
if err2 != nil {
@@ -1327,7 +1357,7 @@ func NewNetworkRoutingController(clientset kubernetes.Interface,
13271357
}
13281358

13291359
nrc.globalPeerRouters, err = newGlobalPeers(kubeRouterConfig.PeerRouters, peerPorts,
1330-
peerASNs, peerPasswords, nrc.bgpHoldtime, nrc.nodeIP.String())
1360+
peerASNs, peerPasswords, nil, nrc.bgpHoldtime, nrc.nodeIP.String())
13311361
if err != nil {
13321362
return nil, fmt.Errorf("error processing Global Peer Router configs: %s", err)
13331363
}

0 commit comments

Comments
 (0)