Skip to content

Commit d0a1c5e

Browse files
committed
manager/allocator: lift portAllocator out of CNM
The port allocation logic does not depend on the network allocator implementation in any meaningful way. It has no knowledge of the CNM network allocator's state, and it does not need to change if the network allocator changes. Allocating node ports is fundamentally a seaparate concern from allocating network resources for services and tasks. Therefore the low-level network allocator should not be responsible for allocating both. Lift the port allocator into the Allocator's network context as a sibling of the low-level network allocator. Signed-off-by: Cory Snider <[email protected]>
1 parent 196c38f commit d0a1c5e

File tree

6 files changed

+43
-41
lines changed

6 files changed

+43
-41
lines changed

manager/allocator/cnmallocator/networkallocator.go

-24
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@ type cnmNetworkAllocator struct {
4040
// The driver registry for all internal and external network drivers.
4141
networkRegistry drvregistry.Networks
4242

43-
// The port allocator instance for allocating node ports
44-
portAllocator *portAllocator
45-
4643
// Local network state used by cnmNetworkAllocator to do network management.
4744
networks map[string]*network
4845

@@ -108,8 +105,6 @@ func New(pg plugingetter.PluginGetter, netConfig *NetworkConfig) (networkallocat
108105
tasks: make(map[string]struct{}),
109106
nodes: make(map[string]map[string]struct{}),
110107
pg: pg,
111-
112-
portAllocator: newPortAllocator(),
113108
}
114109

115110
for ntype, i := range initializers {
@@ -207,9 +202,6 @@ func (na *cnmNetworkAllocator) Deallocate(n *api.Network) error {
207202
// AllocateService allocates all the network resources such as virtual
208203
// IP and ports needed by the service.
209204
func (na *cnmNetworkAllocator) AllocateService(s *api.Service) (err error) {
210-
if err = na.portAllocator.serviceAllocatePorts(s); err != nil {
211-
return err
212-
}
213205
defer func() {
214206
if err != nil {
215207
na.DeallocateService(s)
@@ -312,7 +304,6 @@ func (na *cnmNetworkAllocator) DeallocateService(s *api.Service) error {
312304
}
313305
s.Endpoint.VirtualIPs = nil
314306

315-
na.portAllocator.serviceDeallocatePorts(s)
316307
delete(na.services, s.ID)
317308

318309
return nil
@@ -369,19 +360,8 @@ func (na *cnmNetworkAllocator) IsTaskAllocated(t *api.Task) bool {
369360
return true
370361
}
371362

372-
// HostPublishPortsNeedUpdate returns true if the passed service needs
373-
// allocations for its published ports in host (non ingress) mode
374-
func (na *cnmNetworkAllocator) HostPublishPortsNeedUpdate(s *api.Service) bool {
375-
return na.portAllocator.hostPublishPortsNeedUpdate(s)
376-
}
377-
378363
// IsServiceAllocated returns false if the passed service needs to have network resources allocated/updated.
379364
func (na *cnmNetworkAllocator) IsServiceAllocated(s *api.Service, flags ...func(*networkallocator.ServiceAllocationOpts)) bool {
380-
var options networkallocator.ServiceAllocationOpts
381-
for _, flag := range flags {
382-
flag(&options)
383-
}
384-
385365
specNetworks := serviceNetworks(s)
386366

387367
// If endpoint mode is VIP and allocator does not have the
@@ -443,10 +423,6 @@ func (na *cnmNetworkAllocator) IsServiceAllocated(s *api.Service, flags ...func(
443423
}
444424
}
445425

446-
if (s.Spec.Endpoint != nil && len(s.Spec.Endpoint.Ports) != 0) ||
447-
(s.Endpoint != nil && len(s.Endpoint.Ports) != 0) {
448-
return na.portAllocator.isPortsAllocatedOnInit(s, options.OnInit)
449-
}
450426
return true
451427
}
452428

manager/allocator/cnmallocator/networkallocator_test.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -564,10 +564,11 @@ func TestAllocateService(t *testing.T) {
564564
err = na.AllocateService(s)
565565
assert.NoError(t, err)
566566
assert.Equal(t, 2, len(s.Endpoint.Ports))
567-
assert.True(t, s.Endpoint.Ports[0].PublishedPort >= dynamicPortStart &&
568-
s.Endpoint.Ports[0].PublishedPort <= dynamicPortEnd)
569-
assert.True(t, s.Endpoint.Ports[1].PublishedPort >= dynamicPortStart &&
570-
s.Endpoint.Ports[1].PublishedPort <= dynamicPortEnd)
567+
assert.True(t, s.Endpoint.Ports[0].PublishedPort >= 1 &&
568+
s.Endpoint.Ports[0].PublishedPort <= 65535)
569+
assert.True(t, s.Endpoint.Ports[1].PublishedPort >= 1 &&
570+
s.Endpoint.Ports[1].PublishedPort <= 65535)
571+
assert.NotEqual(t, s.Endpoint.Ports[0].PublishedPort, s.Endpoint.Ports[1].PublishedPort)
571572

572573
assert.Equal(t, 1, len(s.Endpoint.VirtualIPs))
573574

manager/allocator/network.go

+36-7
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ type networkContext struct {
3737
// the actual network allocation.
3838
nwkAllocator networkallocator.NetworkAllocator
3939

40+
// The port allocator instance for allocating node ports
41+
portAllocator *portAllocator
42+
4043
// A set of tasks which are ready to be allocated as a batch. This is
4144
// distinct from "unallocatedTasks" which are tasks that failed to
4245
// allocate on the first try, being held for a future retry.
@@ -95,6 +98,7 @@ func (a *Allocator) doNetworkInit(ctx context.Context) (err error) {
9598

9699
nc := &networkContext{
97100
nwkAllocator: na,
101+
portAllocator: newPortAllocator(),
98102
pendingTasks: make(map[string]*api.Task),
99103
unallocatedTasks: make(map[string]*api.Task),
100104
unallocatedServices: make(map[string]*api.Service),
@@ -233,7 +237,7 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
233237
break
234238
}
235239

236-
if nc.nwkAllocator.IsServiceAllocated(s) {
240+
if nc.isServiceAllocated(s) {
237241
break
238242
}
239243

@@ -261,8 +265,8 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
261265
break
262266
}
263267

264-
if nc.nwkAllocator.IsServiceAllocated(s) {
265-
if !nc.nwkAllocator.HostPublishPortsNeedUpdate(s) {
268+
if nc.isServiceAllocated(s) {
269+
if !nc.portAllocator.hostPublishPortsNeedUpdate(s) {
266270
break
267271
}
268272
updatePortsInHostPublishMode(s)
@@ -287,6 +291,7 @@ func (a *Allocator) doNetworkAlloc(ctx context.Context, ev events.Event) {
287291
if err := nc.nwkAllocator.DeallocateService(s); err != nil {
288292
log.G(ctx).WithError(err).Errorf("Failed deallocation during delete of service %s", s.ID)
289293
} else {
294+
nc.portAllocator.serviceDeallocatePorts(s)
290295
nc.somethingWasDeallocated = true
291296
}
292297

@@ -681,7 +686,7 @@ func (a *Allocator) allocateServices(ctx context.Context, existingAddressesOnly
681686

682687
var allocatedServices []*api.Service
683688
for _, s := range services {
684-
if nc.nwkAllocator.IsServiceAllocated(s, networkallocator.OnInit) {
689+
if nc.isServiceAllocated(s, networkallocator.OnInit) {
685690
continue
686691
}
687692
if existingAddressesOnly &&
@@ -713,6 +718,23 @@ func (a *Allocator) allocateServices(ctx context.Context, existingAddressesOnly
713718
return nil
714719
}
715720

721+
// isServiceAllocated returns false if the passed service needs to have network resources allocated/updated.
722+
func (nc *networkContext) isServiceAllocated(s *api.Service, flags ...func(*networkallocator.ServiceAllocationOpts)) bool {
723+
if !nc.nwkAllocator.IsServiceAllocated(s, flags...) {
724+
return false
725+
}
726+
727+
var options networkallocator.ServiceAllocationOpts
728+
for _, flag := range flags {
729+
flag(&options)
730+
}
731+
if (s.Spec.Endpoint != nil && len(s.Spec.Endpoint.Ports) != 0) ||
732+
(s.Endpoint != nil && len(s.Endpoint.Ports) != 0) {
733+
return nc.portAllocator.isPortsAllocatedOnInit(s, options.OnInit)
734+
}
735+
return true
736+
}
737+
716738
// allocateTasks allocates tasks in the store so far before we started watching.
717739
func (a *Allocator) allocateTasks(ctx context.Context, existingAddressesOnly bool) error {
718740
var (
@@ -815,7 +837,7 @@ func taskReadyForNetworkVote(t *api.Task, s *api.Service, nc *networkContext) bo
815837
// network configured or service endpoints have been
816838
// allocated.
817839
return (len(t.Networks) == 0 || nc.nwkAllocator.IsTaskAllocated(t)) &&
818-
(s == nil || nc.nwkAllocator.IsServiceAllocated(s))
840+
(s == nil || nc.isServiceAllocated(s))
819841
}
820842

821843
func taskUpdateNetworks(t *api.Task, networks []*api.NetworkAttachment) {
@@ -1203,10 +1225,15 @@ func (a *Allocator) allocateService(ctx context.Context, s *api.Service, existin
12031225
if err := nc.nwkAllocator.DeallocateService(s); err != nil {
12041226
return err
12051227
}
1228+
nc.portAllocator.serviceDeallocatePorts(s)
12061229
nc.somethingWasDeallocated = true
12071230
}
12081231

1232+
if err := nc.portAllocator.serviceAllocatePorts(s); err != nil {
1233+
return err
1234+
}
12091235
if err := nc.nwkAllocator.AllocateService(s); err != nil {
1236+
nc.portAllocator.serviceDeallocatePorts(s)
12101237
nc.unallocatedServices[s.ID] = s
12111238
return err
12121239
}
@@ -1243,6 +1270,8 @@ func (a *Allocator) commitAllocatedService(ctx context.Context, batch *store.Bat
12431270
}); err != nil {
12441271
if err := a.netCtx.nwkAllocator.DeallocateService(s); err != nil {
12451272
log.G(ctx).WithError(err).Errorf("failed rolling back allocation of service %s", s.ID)
1273+
} else {
1274+
a.netCtx.portAllocator.serviceDeallocatePorts(s)
12461275
}
12471276

12481277
return err
@@ -1298,7 +1327,7 @@ func (a *Allocator) allocateTask(ctx context.Context, t *api.Task) (err error) {
12981327
return
12991328
}
13001329

1301-
if !nc.nwkAllocator.IsServiceAllocated(s) {
1330+
if !nc.isServiceAllocated(s) {
13021331
err = fmt.Errorf("service %s to which task %s belongs has pending allocations", s.ID, t.ID)
13031332
return
13041333
}
@@ -1423,7 +1452,7 @@ func (a *Allocator) procUnallocatedServices(ctx context.Context) {
14231452
nc := a.netCtx
14241453
var allocatedServices []*api.Service
14251454
for _, s := range nc.unallocatedServices {
1426-
if !nc.nwkAllocator.IsServiceAllocated(s) {
1455+
if !nc.isServiceAllocated(s) {
14271456
if err := a.allocateService(ctx, s, false); err != nil {
14281457
log.G(ctx).WithError(err).Debugf("Failed allocation of unallocated service %s", s.ID)
14291458
continue

manager/allocator/networkallocator/networkallocator.go

-4
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,6 @@ type NetworkAllocator interface {
6161
// virtual IP and ports associated with the service.
6262
DeallocateService(s *api.Service) error
6363

64-
// HostPublishPortsNeedUpdate returns true if the passed service needs
65-
// allocations for its published ports in host (non ingress) mode
66-
HostPublishPortsNeedUpdate(s *api.Service) bool
67-
6864
//
6965
// Task Allocation
7066
//

manager/allocator/cnmallocator/portallocator.go manager/allocator/portallocator.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package cnmallocator
1+
package allocator
22

33
import (
44
"github.com/moby/swarmkit/v2/api"

manager/allocator/cnmallocator/portallocator_test.go manager/allocator/portallocator_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package cnmallocator
1+
package allocator
22

33
import (
44
"testing"

0 commit comments

Comments
 (0)