Skip to content

Commit 41332a1

Browse files
authored
Ability to enable/disable node advertising its pod CIDR to external BGP peers (#408)
* Node should advertise its pod CIDR to external BGP peers only if --advertise-node-pod-cidr is set to true (defaults to true). This is to enable a case where pod's remain non-routable from out of the cluster but service VIP's can be routable from out side the cluster. * fix unit test * address review comments
1 parent 23d4362 commit 41332a1

File tree

5 files changed

+69
-8
lines changed

5 files changed

+69
-8
lines changed

docs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ Usage of kube-router:
103103
--advertise-cluster-ip Add Cluster IP of the service to the RIB so that it gets advertises to the BGP peers.
104104
--advertise-external-ip Add External IP of service to the RIB so that it gets advertised to the BGP peers.
105105
--advertise-loadbalancer-ip Add LoadbBalancer IP of service status as set by the LB provider to the RIB so that it gets advertised to the BGP peers.
106+
--advertise-pod-cidr Add Node's POD cidr to the RIB so that it gets advertised to the BGP peers. (default true)
106107
--bgp-graceful-restart Enables the BGP Graceful Restart capability so that routes are preserved on unexpected restarts
107108
--cleanup-config Cleanup iptables rules, ipvs, ipset configuration and exit.
108109
--cluster-asn uint ASN number under which cluster nodes will run iBGP.

pkg/controllers/routing/export_policies.go

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,27 @@ package routing
22

33
import (
44
"errors"
5+
"fmt"
56

67
"github.com/cloudnativelabs/kube-router/pkg/utils"
78
"github.com/osrg/gobgp/config"
89
"github.com/osrg/gobgp/table"
10+
v1core "k8s.io/api/core/v1"
911
)
1012

11-
// Each node advertises its pod CIDR to the nodes with same ASN (iBGP peers) and to the global BGP peer
12-
// or per node BGP peer. Each node ends up advertising not only pod CIDR assigned to the self but other
13-
// learned routes to the node pod CIDR's as well to global BGP peer or per node BGP peers. external BGP
14-
// peer will randomly (since all path have equal selection attributes) select the routes from multiple
15-
// routes to a pod CIDR which will result in extra hop. To prevent this behaviour this methods add
16-
// defult export policy to reject everything and an explicit policy is added so that each node only
17-
// advertised the pod CIDR assigned to it. Additionally export policy is added so that each node
18-
// advertises cluster IP's ONLY to the external BGP peers (and not to iBGP peers).
13+
// BGP export policies are added so that following conditions are met
14+
//
15+
// - by default export of all routes from the RIB to the neighbour's is denied, and explicity statements are added i
16+
// to permit the desired routes to be exported
17+
// - each node is allowed to advertise its assigned pod CIDR's to all of its iBGP peer neighbours with same ASN
18+
// - each node is allowed to advertise its assigned pod CIDR's to all of its external BGP peer neighbours
19+
// only if --advertise-pod-cidr flag is set to true
20+
// - each node is NOT allowed to advertise its assigned pod CIDR's to all of its external BGP peer neighbours
21+
// only if --advertise-pod-cidr flag is set to false
22+
// - each node is allowed to advertise service VIP's (cluster ip, load balancer ip, external IP) ONLY to external
23+
// BGP peers
24+
// - each node is NOT allowed to advertise service VIP's (cluster ip, load balancer ip, external IP) to
25+
// iBGP peers
1926
func (nrc *NetworkRoutingController) addExportPolicies() error {
2027

2128
// we are rr server do not add export policies
@@ -59,13 +66,35 @@ func (nrc *NetworkRoutingController) addExportPolicies() error {
5966

6067
statements := make([]config.Statement, 0)
6168

69+
// Get the current list of the nodes from the local cache
70+
nodes := nrc.nodeLister.List()
71+
iBGPPeers := make([]string, 0)
72+
for _, node := range nodes {
73+
nodeObj := node.(*v1core.Node)
74+
nodeIP, err := utils.GetNodeIP(nodeObj)
75+
if err != nil {
76+
return fmt.Errorf("Failed to find a node IP: %s", err)
77+
}
78+
iBGPPeers = append(iBGPPeers, nodeIP.String())
79+
}
80+
iBGPPeerNS, _ := table.NewNeighborSet(config.NeighborSet{
81+
NeighborSetName: "iBGPpeerset",
82+
NeighborInfoList: iBGPPeers,
83+
})
84+
err = nrc.bgpServer.ReplaceDefinedSet(iBGPPeerNS)
85+
if err != nil {
86+
nrc.bgpServer.AddDefinedSet(iBGPPeerNS)
87+
}
6288
// statement to represent the export policy to permit advertising node's pod CIDR
6389
statements = append(statements,
6490
config.Statement{
6591
Conditions: config.Conditions{
6692
MatchPrefixSet: config.MatchPrefixSet{
6793
PrefixSet: "podcidrprefixset",
6894
},
95+
MatchNeighborSet: config.MatchNeighborSet{
96+
NeighborSet: "iBGPpeerset",
97+
},
6998
},
7099
Actions: config.Actions{
71100
RouteDisposition: config.ROUTE_DISPOSITION_ACCEPT_ROUTE,
@@ -107,6 +136,21 @@ func (nrc *NetworkRoutingController) addExportPolicies() error {
107136
RouteDisposition: config.ROUTE_DISPOSITION_ACCEPT_ROUTE,
108137
},
109138
})
139+
if nrc.advertisePodCidr {
140+
statements = append(statements, config.Statement{
141+
Conditions: config.Conditions{
142+
MatchPrefixSet: config.MatchPrefixSet{
143+
PrefixSet: "podcidrprefixset",
144+
},
145+
MatchNeighborSet: config.MatchNeighborSet{
146+
NeighborSet: "externalpeerset",
147+
},
148+
},
149+
Actions: config.Actions{
150+
RouteDisposition: config.ROUTE_DISPOSITION_ACCEPT_ROUTE,
151+
},
152+
})
153+
}
110154
}
111155

112156
definition := config.PolicyDefinition{

pkg/controllers/routing/network_routes_controller.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ type NetworkRoutingController struct {
6666
advertiseClusterIP bool
6767
advertiseExternalIP bool
6868
advertiseLoadBalancerIP bool
69+
advertisePodCidr bool
6970
defaultNodeAsnNumber uint32
7071
nodeAsnNumber uint32
7172
globalPeerRouters []*config.NeighborConfig
@@ -753,6 +754,7 @@ func NewNetworkRoutingController(clientset kubernetes.Interface,
753754
nrc.advertiseClusterIP = kubeRouterConfig.AdvertiseClusterIp
754755
nrc.advertiseExternalIP = kubeRouterConfig.AdvertiseExternalIp
755756
nrc.advertiseLoadBalancerIP = kubeRouterConfig.AdvertiseLoadBalancerIp
757+
nrc.advertisePodCidr = kubeRouterConfig.AdvertiseNodePodCidr
756758

757759
nrc.enableOverlays = kubeRouterConfig.EnableOverlay
758760

pkg/controllers/routing/network_routes_controller_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,10 @@ func Test_addExportPolicies(t *testing.T) {
12361236
PrefixSet: "podcidrprefixset",
12371237
MatchSetOptions: config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY,
12381238
},
1239+
MatchNeighborSet: config.MatchNeighborSet{
1240+
NeighborSet: "iBGPpeerset",
1241+
MatchSetOptions: config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY,
1242+
},
12391243
},
12401244
Actions: config.Actions{
12411245
RouteDisposition: config.ROUTE_DISPOSITION_ACCEPT_ROUTE,
@@ -1350,6 +1354,10 @@ func Test_addExportPolicies(t *testing.T) {
13501354
PrefixSet: "podcidrprefixset",
13511355
MatchSetOptions: config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY,
13521356
},
1357+
MatchNeighborSet: config.MatchNeighborSet{
1358+
NeighborSet: "iBGPpeerset",
1359+
MatchSetOptions: config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY,
1360+
},
13531361
},
13541362
Actions: config.Actions{
13551363
RouteDisposition: config.ROUTE_DISPOSITION_ACCEPT_ROUTE,
@@ -1408,6 +1416,9 @@ func Test_addExportPolicies(t *testing.T) {
14081416
testcase.nrc.advertiseExternalIP = true
14091417
testcase.nrc.advertiseLoadBalancerIP = false
14101418

1419+
informerFactory := informers.NewSharedInformerFactory(testcase.nrc.clientset, 0)
1420+
nodeInformer := informerFactory.Core().V1().Nodes().Informer()
1421+
testcase.nrc.nodeLister = nodeInformer.GetIndexer()
14111422
err = testcase.nrc.addExportPolicies()
14121423
if !reflect.DeepEqual(err, testcase.err) {
14131424
t.Logf("expected err %v", testcase.err)

pkg/options/options.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
type KubeRouterConfig struct {
1111
AdvertiseClusterIp bool
1212
AdvertiseExternalIp bool
13+
AdvertiseNodePodCidr bool
1314
AdvertiseLoadBalancerIp bool
1415
BGPGracefulRestart bool
1516
CleanupConfig bool
@@ -90,6 +91,8 @@ func (s *KubeRouterConfig) AddFlags(fs *pflag.FlagSet) {
9091
"Add External IP of service to the RIB so that it gets advertised to the BGP peers.")
9192
fs.BoolVar(&s.AdvertiseLoadBalancerIp, "advertise-loadbalancer-ip", false,
9293
"Add LoadbBalancer IP of service status as set by the LB provider to the RIB so that it gets advertised to the BGP peers.")
94+
fs.BoolVar(&s.AdvertiseNodePodCidr, "advertise-pod-cidr", true,
95+
"Add Node's POD cidr to the RIB so that it gets advertised to the BGP peers.")
9396
fs.IPSliceVar(&s.PeerRouters, "peer-router-ips", s.PeerRouters,
9497
"The ip address of the external router to which all nodes will peer and advertise the cluster ip and pod cidr's.")
9598
fs.UintVar(&s.ClusterAsn, "cluster-asn", s.ClusterAsn,

0 commit comments

Comments
 (0)