Skip to content

Commit 0743278

Browse files
authored
feat: compare node IP with NNCs node IP (#1527)
* feat: compare node IP with NNCs node IP * fix: don't block reconciler from starting if nnc doesn't have status
1 parent 46321fb commit 0743278

File tree

5 files changed

+61
-9
lines changed

5 files changed

+61
-9
lines changed

cns/configuration/env.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
const (
1010
// EnvNodeName is the NODENAME env var string key.
1111
EnvNodeName = "NODENAME"
12+
// EnvNodeIP is the IP of the node running this CNS binary
13+
EnvNodeIP = "NODE_IP"
1214
)
1315

1416
// ErrNodeNameUnset indicates the the $EnvNodeName variable is unset in the environment.
@@ -22,3 +24,8 @@ func NodeName() (string, error) {
2224
}
2325
return nodeName, nil
2426
}
27+
28+
// NodeIP returns the value of the NODE_IP environment variable, or empty string if unset.
29+
func NodeIP() string {
30+
return os.Getenv(EnvNodeIP)
31+
}

cns/kubecontroller/nodenetworkconfig/conversion_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ const (
2222
subnetPrefixLen = 24
2323
testSecIP = "10.0.0.2"
2424
version = 1
25+
nodeIP = "10.1.0.5"
2526
)
2627

2728
var invalidStatusMultiNC = v1alpha.NodeNetworkConfigStatus{
@@ -46,6 +47,7 @@ var validSwiftNC = v1alpha.NetworkContainer{
4647
DefaultGateway: defaultGateway,
4748
SubnetAddressSpace: subnetAddressSpace,
4849
Version: version,
50+
NodeIP: nodeIP,
4951
}
5052

5153
var validSwiftStatus = v1alpha.NodeNetworkConfigStatus{
@@ -55,7 +57,8 @@ var validSwiftStatus = v1alpha.NodeNetworkConfigStatus{
5557
}
5658

5759
var validSwiftRequest = &cns.CreateNetworkContainerRequest{
58-
Version: strconv.FormatInt(version, 10),
60+
HostPrimaryIP: nodeIP,
61+
Version: strconv.FormatInt(version, 10),
5962
IPConfiguration: cns.IPConfiguration{
6063
GatewayIPAddress: defaultGateway,
6164
IPSubnet: cns.IPSubnet{
@@ -78,6 +81,7 @@ var validOverlayNC = v1alpha.NetworkContainer{
7881
AssignmentMode: v1alpha.Static,
7982
Type: v1alpha.Overlay,
8083
PrimaryIP: overlayPrimaryIP,
84+
NodeIP: nodeIP,
8185
SubnetName: subnetName,
8286
SubnetAddressSpace: subnetAddressSpace,
8387
Version: version,
@@ -162,6 +166,7 @@ func TestCreateNCRequestFromDynamicNC(t *testing.T) {
162166
input: v1alpha.NetworkContainer{
163167
PrimaryIP: ipIsCIDR,
164168
ID: ncID,
169+
NodeIP: nodeIP,
165170
IPAssignments: []v1alpha.IPAssignment{
166171
{
167172
Name: uuid,

cns/kubecontroller/nodenetworkconfig/reconciler.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,20 @@ type Reconciler struct {
4040
nnccli nncGetter
4141
once sync.Once
4242
started chan interface{}
43+
nodeIP string
4344
}
4445

4546
// NewReconciler creates a NodeNetworkConfig Reconciler which will get updates from the Kubernetes
4647
// apiserver for NNC events.
4748
// Provided nncListeners are passed the NNC after the Reconcile preprocesses it. Note: order matters! The
4849
// passed Listeners are notified in the order provided.
49-
func NewReconciler(cnscli cnsClient, nnccli nncGetter, ipampoolmonitorcli nodeNetworkConfigListener) *Reconciler {
50+
func NewReconciler(cnscli cnsClient, nnccli nncGetter, ipampoolmonitorcli nodeNetworkConfigListener, nodeIP string) *Reconciler {
5051
return &Reconciler{
5152
cnscli: cnscli,
5253
ipampoolmonitorcli: ipampoolmonitorcli,
5354
nnccli: nnccli,
5455
started: make(chan interface{}),
56+
nodeIP: nodeIP,
5557
}
5658
}
5759

@@ -71,8 +73,19 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
7173
logger.Printf("[cns-rc] CRD Spec: %+v", nnc.Spec)
7274

7375
ipAssignments := 0
76+
7477
// for each NC, parse it in to a CreateNCRequest and forward it to the appropriate Listener
7578
for i := range nnc.Status.NetworkContainers {
79+
// check if this NC matches the Node IP if we have one to check against
80+
if r.nodeIP != "" {
81+
if r.nodeIP != nnc.Status.NetworkContainers[i].NodeIP {
82+
// skip this NC since it was created for a different node
83+
logger.Debugf("[cns-rc] skipping network container %s found in NNC because node IP doesn't match, got %s, expected %s",
84+
nnc.Status.NetworkContainers[i].ID, nnc.Status.NetworkContainers[i].NodeIP, r.nodeIP)
85+
continue
86+
}
87+
}
88+
7689
var req *cns.CreateNetworkContainerRequest
7790
var err error
7891
switch nnc.Status.NetworkContainers[i].AssignmentMode { //nolint:exhaustive // skipping dynamic case
@@ -98,6 +111,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco
98111
}
99112
ipAssignments += len(req.SecondaryIPConfigs)
100113
}
114+
101115
// record assigned IPs metric
102116
allocatedIPs.Set(float64(ipAssignments))
103117

cns/kubecontroller/nodenetworkconfig/reconciler_test.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func TestReconcile(t *testing.T) {
5353
in reconcile.Request
5454
ncGetter mockNCGetter
5555
cnsClient mockCNSClient
56+
nodeIP string
5657
want reconcile.Result
5758
wantCNSClientState cnsClientState
5859
wantErr bool
@@ -145,11 +146,35 @@ func TestReconcile(t *testing.T) {
145146
},
146147
},
147148
},
149+
{
150+
name: "node IP mismatch",
151+
ncGetter: mockNCGetter{
152+
get: func(context.Context, types.NamespacedName) (*v1alpha.NodeNetworkConfig, error) {
153+
return &v1alpha.NodeNetworkConfig{
154+
Status: validSwiftStatus,
155+
Spec: v1alpha.NodeNetworkConfigSpec{
156+
RequestedIPCount: 1,
157+
},
158+
}, nil
159+
},
160+
},
161+
cnsClient: mockCNSClient{
162+
createOrUpdateNC: func(*cns.CreateNetworkContainerRequest) cnstypes.ResponseCode {
163+
return cnstypes.Success
164+
},
165+
update: func(*v1alpha.NodeNetworkConfig) error {
166+
return nil
167+
},
168+
},
169+
nodeIP: "192.168.1.5", // nodeIP in above NNC status is 10.1.0.5
170+
wantErr: false,
171+
wantCNSClientState: cnsClientState{}, // state should be empty since we should skip this NC
172+
},
148173
}
149174
for _, tt := range tests {
150175
tt := tt
151176
t.Run(tt.name, func(t *testing.T) {
152-
r := NewReconciler(&tt.cnsClient, &tt.ncGetter, &tt.cnsClient)
177+
r := NewReconciler(&tt.cnsClient, &tt.ncGetter, &tt.cnsClient, tt.nodeIP)
153178
got, err := r.Reconcile(context.Background(), tt.in)
154179
if tt.wantErr {
155180
require.Error(t, err)

cns/service/main.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,8 +1080,11 @@ func InitializeCRDState(ctx context.Context, httpRestService cns.HTTPService, cn
10801080
return errors.Wrapf(err, "failed to get node %s", nodeName)
10811081
}
10821082

1083+
// get CNS Node IP to compare NC Node IP with this Node IP to ensure NCs were created for this node
1084+
nodeIP := configuration.NodeIP()
1085+
10831086
// NodeNetworkConfig reconciler
1084-
nncReconciler := nncctrl.NewReconciler(httpRestServiceImplementation, nnccli, poolMonitor)
1087+
nncReconciler := nncctrl.NewReconciler(httpRestServiceImplementation, nnccli, poolMonitor, nodeIP)
10851088
// pass Node to the Reconciler for Controller xref
10861089
if err := nncReconciler.SetupWithManager(manager, node); err != nil { //nolint:govet // intentional shadow
10871090
return errors.Wrapf(err, "failed to setup nnc reconciler with manager")
@@ -1141,11 +1144,9 @@ func InitializeCRDState(ctx context.Context, httpRestService cns.HTTPService, cn
11411144
}
11421145
}()
11431146
logger.Printf("initialized NodeNetworkConfig reconciler")
1144-
// wait for up to 10m for the Reconciler to run once.
1145-
timedCtx, cancel := context.WithTimeout(ctx, 10*time.Minute) //nolint:gomnd // default 10m
1146-
defer cancel()
1147-
if started := nncReconciler.Started(timedCtx); !started {
1148-
return errors.Errorf("timed out waiting for reconciler start")
1147+
// wait for the Reconciler to run once on a NNC that was made for this Node
1148+
if started := nncReconciler.Started(ctx); !started {
1149+
return errors.Errorf("context cancelled while waiting for reconciler start")
11491150
}
11501151
logger.Printf("started NodeNetworkConfig reconciler")
11511152

0 commit comments

Comments
 (0)