Skip to content

Commit 521c79f

Browse files
committed
sdn: fix initialization order to prevent crash on node startup
OsdnNode.Start() (node.pm == nil at this point) -> node.policy.Start() (which is multitenant policy) -> mp.vnids.Start() -> go vmap.watchNetNamespaces() -> (net namespace event happens) -> watchNetNamespaces() -> vmap.policy.AddNetNamespace() (policy is multitenant) -> mp.updatePodNetwork() -> mp.node.podManager.UpdateLocalMulticastRules() (and podManager is still nil) Create the PodManager earlier so it's not nil if we get early events. Fixes: #13742
1 parent 8ef58c5 commit 521c79f

File tree

3 files changed

+49
-46
lines changed

3 files changed

+49
-46
lines changed

pkg/sdn/plugin/node.go

+22-23
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ func NewNodePlugin(pluginName string, osClient *osclient.Client, kClient *kclien
120120
osClient: osClient,
121121
ovs: ovsif,
122122
localIP: selfIP,
123+
podManager: newPodManager(kClient, policy, mtu, ovsif),
123124
hostName: hostname,
124125
podNetworkReady: make(chan struct{}),
125126
kubeletInitReady: make(chan struct{}),
@@ -201,31 +202,11 @@ func (node *OsdnNode) Start() error {
201202
return fmt.Errorf("Failed to get network information: %v", err)
202203
}
203204

204-
nodeIPTables := newNodeIPTables(node.networkInfo.ClusterNetwork.String(), node.iptablesSyncPeriod)
205-
if err = nodeIPTables.Setup(); err != nil {
206-
return fmt.Errorf("Failed to set up iptables: %v", err)
207-
}
208-
209205
node.localSubnetCIDR, err = node.getLocalSubnet()
210206
if err != nil {
211207
return err
212208
}
213209

214-
networkChanged, err := node.SetupSDN()
215-
if err != nil {
216-
return err
217-
}
218-
219-
err = node.SubnetStartNode()
220-
if err != nil {
221-
return err
222-
}
223-
224-
if err = node.policy.Start(node); err != nil {
225-
return err
226-
}
227-
go kwait.Forever(node.watchServices, 0)
228-
229210
// Wait for kubelet to init the plugin so we get a knetwork.Host
230211
log.V(5).Infof("Waiting for kubelet network plugin initialization")
231212
<-node.kubeletInitReady
@@ -238,12 +219,30 @@ func (node *OsdnNode) Start() error {
238219
return true, nil
239220
})
240221

241-
log.V(5).Infof("Creating and initializing openshift-sdn pod manager")
242-
node.podManager, err = newPodManager(node.host, node.localSubnetCIDR, node.networkInfo, node.kClient, node.policy, node.mtu, node.ovs)
222+
//**** After this point, all OsdnNode fields have been initialized
223+
224+
nodeIPTables := newNodeIPTables(node.networkInfo.ClusterNetwork.String(), node.iptablesSyncPeriod)
225+
if err = nodeIPTables.Setup(); err != nil {
226+
return fmt.Errorf("Failed to set up iptables: %v", err)
227+
}
228+
229+
networkChanged, err := node.SetupSDN()
243230
if err != nil {
244231
return err
245232
}
246-
if err := node.podManager.Start(cniserver.CNIServerSocketPath); err != nil {
233+
234+
err = node.SubnetStartNode()
235+
if err != nil {
236+
return err
237+
}
238+
239+
if err = node.policy.Start(node); err != nil {
240+
return err
241+
}
242+
go kwait.Forever(node.watchServices, 0)
243+
244+
log.V(5).Infof("Starting openshift-sdn pod manager")
245+
if err := node.podManager.Start(cniserver.CNIServerSocketPath, node.host, node.localSubnetCIDR, node.networkInfo.ClusterNetwork); err != nil {
247246
return err
248247
}
249248

pkg/sdn/plugin/pod.go

+21-19
Original file line numberDiff line numberDiff line change
@@ -38,45 +38,39 @@ type podManager struct {
3838
cniServer *cniserver.CNIServer
3939
// Request queue for pod operations incoming from the CNIServer
4040
requests chan (*cniserver.PodRequest)
41-
// Tracks pod :: IP address for hostport handling
41+
// Tracks pod :: IP address for hostport and multicast handling
4242
runningPods map[string]*runningPod
4343
runningPodsLock sync.Mutex
4444

4545
// Live pod setup/teardown stuff not used in testing code
46-
kClient *kclientset.Clientset
47-
policy osdnPolicy
46+
kClient *kclientset.Clientset
47+
policy osdnPolicy
48+
mtu uint32
49+
ovs *ovs.Interface
50+
51+
// Things only accessed through the processCNIRequests() goroutine
52+
// and thus can be set from Start()
4853
ipamConfig []byte
49-
mtu uint32
5054
hostportHandler kubehostport.HostportHandler
5155
host knetwork.Host
52-
ovs *ovs.Interface
5356
}
5457

5558
// Creates a new live podManager; used by node code
56-
func newPodManager(host knetwork.Host, localSubnetCIDR string, netInfo *NetworkInfo, kClient *kclientset.Clientset, policy osdnPolicy, mtu uint32, ovs *ovs.Interface) (*podManager, error) {
57-
pm := newDefaultPodManager(host)
59+
func newPodManager(kClient *kclientset.Clientset, policy osdnPolicy, mtu uint32, ovs *ovs.Interface) *podManager {
60+
pm := newDefaultPodManager()
5861
pm.kClient = kClient
5962
pm.policy = policy
6063
pm.mtu = mtu
61-
pm.hostportHandler = kubehostport.NewHostportHandler()
6264
pm.podHandler = pm
6365
pm.ovs = ovs
64-
65-
var err error
66-
pm.ipamConfig, err = getIPAMConfig(netInfo.ClusterNetwork, localSubnetCIDR)
67-
if err != nil {
68-
return nil, err
69-
}
70-
71-
return pm, nil
66+
return pm
7267
}
7368

7469
// Creates a new basic podManager; used by testcases
75-
func newDefaultPodManager(host knetwork.Host) *podManager {
70+
func newDefaultPodManager() *podManager {
7671
return &podManager{
7772
runningPods: make(map[string]*runningPod),
7873
requests: make(chan *cniserver.PodRequest, 20),
79-
host: host,
8074
}
8175
}
8276

@@ -134,7 +128,15 @@ func getIPAMConfig(clusterNetwork *net.IPNet, localSubnet string) ([]byte, error
134128
}
135129

136130
// Start the CNI server and start processing requests from it
137-
func (m *podManager) Start(socketPath string) error {
131+
func (m *podManager) Start(socketPath string, host knetwork.Host, localSubnetCIDR string, clusterNetwork *net.IPNet) error {
132+
m.host = host
133+
m.hostportHandler = kubehostport.NewHostportHandler()
134+
135+
var err error
136+
if m.ipamConfig, err = getIPAMConfig(clusterNetwork, localSubnetCIDR); err != nil {
137+
return err
138+
}
139+
138140
go m.processCNIRequests()
139141

140142
m.cniServer = cniserver.NewCNIServer(socketPath)

pkg/sdn/plugin/pod_test.go

+6-4
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,10 @@ func TestPodManager(t *testing.T) {
368368

369369
for k, tc := range testcases {
370370
podTester := newPodTester(t, k, socketPath)
371-
podManager := newDefaultPodManager(newFakeHost())
371+
podManager := newDefaultPodManager()
372372
podManager.podHandler = podTester
373-
podManager.Start(socketPath)
373+
_, net, _ := net.ParseCIDR("1.2.0.0/16")
374+
podManager.Start(socketPath, newFakeHost(), "1.2.3.0/24", net)
374375

375376
// Add pods to our expected pod list before kicking off the
376377
// actual pod setup to ensure we don't concurrently access
@@ -463,9 +464,10 @@ func TestDirectPodUpdate(t *testing.T) {
463464
socketPath := filepath.Join(tmpDir, "cni-server.sock")
464465

465466
podTester := newPodTester(t, "update", socketPath)
466-
podManager := newDefaultPodManager(newFakeHost())
467+
podManager := newDefaultPodManager()
467468
podManager.podHandler = podTester
468-
podManager.Start(socketPath)
469+
_, net, _ := net.ParseCIDR("1.2.0.0/16")
470+
podManager.Start(socketPath, newFakeHost(), "1.2.3.0/24", net)
469471

470472
op := &operation{
471473
command: cniserver.CNI_UPDATE,

0 commit comments

Comments
 (0)