Skip to content

Commit b60f14a

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 b60f14a

File tree

3 files changed

+38
-35
lines changed

3 files changed

+38
-35
lines changed

pkg/sdn/plugin/node.go

+11-11
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,16 +202,18 @@ 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

210+
//**** After this point, all OsdnNode fields have been initialized
211+
212+
nodeIPTables := newNodeIPTables(node.networkInfo.ClusterNetwork.String(), node.iptablesSyncPeriod)
213+
if err = nodeIPTables.Setup(); err != nil {
214+
return fmt.Errorf("Failed to set up iptables: %v", err)
215+
}
216+
214217
networkChanged, err := node.SetupSDN()
215218
if err != nil {
216219
return err
@@ -238,12 +241,9 @@ func (node *OsdnNode) Start() error {
238241
return true, nil
239242
})
240243

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)
243-
if err != nil {
244-
return err
245-
}
246-
if err := node.podManager.Start(cniserver.CNIServerSocketPath); err != nil {
244+
// Kubelet has initialized, now we have a valid node.host
245+
log.V(5).Infof("Starting openshift-sdn pod manager")
246+
if err := node.podManager.Start(cniserver.CNIServerSocketPath, node.host, node.localSubnetCIDR, node.networkInfo.ClusterNetwork); err != nil {
247247
return err
248248
}
249249

pkg/sdn/plugin/pod.go

+21-20
Original file line numberDiff line numberDiff line change
@@ -38,45 +38,38 @@ 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()
62-
pm.podHandler = pm
6364
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
65+
return pm
7266
}
7367

7468
// Creates a new basic podManager; used by testcases
75-
func newDefaultPodManager(host knetwork.Host) *podManager {
69+
func newDefaultPodManager() *podManager {
7670
return &podManager{
7771
runningPods: make(map[string]*runningPod),
7872
requests: make(chan *cniserver.PodRequest, 20),
79-
host: host,
8073
}
8174
}
8275

@@ -134,7 +127,15 @@ func getIPAMConfig(clusterNetwork *net.IPNet, localSubnet string) ([]byte, error
134127
}
135128

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

140141
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)