Skip to content

Commit 4e768b1

Browse files
ut0mt8murali-reddy
authored andcommitted
Feature Route Reflector (#325)
* Add Route Reflector feature * Update documentation for route reflector * Gofmt fix
1 parent df6b375 commit 4e768b1

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

Documentation/bgp.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ This model support more than a single AS per cluster to allow AS per rack or AS
2222
per node models. Nodes in the cluster does not form full node-to-node mesh.
2323
Users has to explicitly select this mode by specifying `--nodes-full-mesh=false`
2424
when launching kube-router. In this mode kube-router expects each node is
25-
configured with an ASN number from the node's API object annoations. Kube-router
25+
configured with an ASN number from the node's API object annonations. Kube-router
2626
will use the node's `kube-router.io/node.asn` annotation value as the ASN
2727
number for the node.
2828

@@ -35,6 +35,33 @@ kubectl annotate node <kube-node> "kube-router.io/node.asn=64512"
3535
Only nodes with in same ASN form full mesh. Two nodes with different ASNs never
3636
get peered.
3737

38+
### Route-Reflector setup Without Full Mesh
39+
40+
This model support the common scheme of using Route Reflector Server node to concentrate
41+
peering from Client Peer. This has the big advantage of not needing full mesh, and
42+
scale better. In this mode kube-router expects each node is configured either in
43+
Route Reflector server mode or in Route Reflector client mode. This is done
44+
with node `kube-router.io/rr.server=ClusterID`, `kube-router.io/rr.client=ClusterId`
45+
respectively. In this mode each Route Reflector Client will only peer with Route
46+
Reflector Servers. Each Route Route Reflector Server will peer other Route Reflector
47+
Server and with Route Reflector Clients enabling reflection.
48+
49+
Users can annotate node objects with the following command:
50+
51+
```
52+
kubectl annotate node <kube-node> "kube-router.io/rr.server=42"
53+
```
54+
55+
for Route Reflector server mode, and
56+
57+
```
58+
kubectl annotate node <kube-node> "kube-router.io/rr.client=42"
59+
```
60+
61+
for Route Reflector client mode.
62+
63+
Only nodes with the same ClusterID in client and server mode will peer together.
64+
3865
## Peering Outside The Cluster
3966
### Global External BGP Peers
4067

app/controllers/network_routes_controller.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ type NetworkRoutingController struct {
6363
peerMultihopTtl uint8
6464
MetricsEnabled bool
6565
bgpServerStarted bool
66+
bgpRRClient bool
67+
bgpRRServer bool
68+
bgpClusterId uint32
6669
}
6770

6871
var (
@@ -616,6 +619,11 @@ func (nrc *NetworkRoutingController) AdvertiseClusterIp(clusterIp string) error
616619
// advertises cluster IP's ONLY to the external BGP peers (and not to iBGP peers).
617620
func (nrc *NetworkRoutingController) addExportPolicies() error {
618621

622+
// we are rr server do not add export policies
623+
if nrc.bgpRRServer {
624+
return nil
625+
}
626+
619627
cidr, err := utils.GetPodCidrFromNodeSpec(nrc.clientset, nrc.hostnameOverride)
620628
if err != nil {
621629
return err
@@ -1005,6 +1013,13 @@ func (nrc *NetworkRoutingController) syncInternalPeers() {
10051013
continue
10061014
}
10071015

1016+
// we are rr-client peer only with rr-server
1017+
if nrc.bgpRRClient {
1018+
if _, ok := node.ObjectMeta.Annotations["kube-router.io/rr.server"]; !ok {
1019+
continue
1020+
}
1021+
}
1022+
10081023
// if node full mesh is not requested then just peer with nodes with same ASN
10091024
// (run iBGP among same ASN peers)
10101025
if !nrc.bgpFullMeshMode {
@@ -1064,6 +1079,23 @@ func (nrc *NetworkRoutingController) syncInternalPeers() {
10641079
}
10651080
}
10661081

1082+
// we are rr-server peer with other rr-client with reflection enabled
1083+
if nrc.bgpRRServer {
1084+
if _, ok := node.ObjectMeta.Annotations["kube-router.io/rr.client"]; ok {
1085+
//add rr options with clusterId
1086+
n.RouteReflector = config.RouteReflector{
1087+
Config: config.RouteReflectorConfig{
1088+
RouteReflectorClient: true,
1089+
RouteReflectorClusterId: config.RrClusterIdType(nrc.bgpClusterId),
1090+
},
1091+
State: config.RouteReflectorState{
1092+
RouteReflectorClient: true,
1093+
RouteReflectorClusterId: config.RrClusterIdType(nrc.bgpClusterId),
1094+
},
1095+
}
1096+
}
1097+
}
1098+
10671099
// TODO: check if a node is alredy added as nieighbour in a better way than add and catch error
10681100
if err := nrc.bgpServer.AddNeighbor(n); err != nil {
10691101
if !strings.Contains(err.Error(), "Can't overwrite the existing peer") {
@@ -1271,6 +1303,24 @@ func (nrc *NetworkRoutingController) startBgpServer() error {
12711303
nrc.nodeAsnNumber = nodeAsnNumber
12721304
}
12731305

1306+
if clusterid, ok := node.ObjectMeta.Annotations["kube-router.io/rr.server"]; ok {
1307+
glog.Infof("Found rr.server for the node to be %s from the node annotation", clusterid)
1308+
clusterId, err := strconv.ParseUint(clusterid, 0, 32)
1309+
if err != nil {
1310+
return errors.New("Failed to parse rr.server clusterId number specified for the the node")
1311+
}
1312+
nrc.bgpClusterId = uint32(clusterId)
1313+
nrc.bgpRRServer = true
1314+
} else if clusterid, ok := node.ObjectMeta.Annotations["kube-router.io/rr.client"]; ok {
1315+
glog.Infof("Found rr.client for the node to be %s from the node annotation", clusterid)
1316+
clusterId, err := strconv.ParseUint(clusterid, 0, 32)
1317+
if err != nil {
1318+
return errors.New("Failed to parse rr.client clusterId number specified for the the node")
1319+
}
1320+
nrc.bgpClusterId = uint32(clusterId)
1321+
nrc.bgpRRClient = true
1322+
}
1323+
12741324
nrc.bgpServer = gobgp.NewBgpServer()
12751325
go nrc.bgpServer.Serve()
12761326

@@ -1448,6 +1498,8 @@ func NewNetworkRoutingController(clientset *kubernetes.Clientset,
14481498
nrc.syncPeriod = kubeRouterConfig.RoutesSyncPeriod
14491499
nrc.clientset = clientset
14501500
nrc.activeNodes = make(map[string]bool)
1501+
nrc.bgpRRClient = false
1502+
nrc.bgpRRServer = false
14511503
nrc.bgpServerStarted = false
14521504

14531505
nrc.ipSetHandler, err = utils.NewIPSet()

0 commit comments

Comments
 (0)