m/node/allocs: split new package off m/node

The metropolis/node package contains various unrelated things. One of
these things are node-wide allocations of identifiers.
These are moved here to the new metropolis/node/allocs package.
Additionally, the constants are renamed to move the type of identifier
in front.

Change-Id: Ibc841ca64d4450a7054463e6d2d44753a118e07a
Reviewed-on: https://review.monogon.dev/c/monogon/+/4566
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/node/core/BUILD.bazel b/metropolis/node/core/BUILD.bazel
index db96103..6fdf353 100644
--- a/metropolis/node/core/BUILD.bazel
+++ b/metropolis/node/core/BUILD.bazel
@@ -22,7 +22,7 @@
     visibility = ["//visibility:private"],
     deps = [
         "//go/logging",
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/cluster",
         "//metropolis/node/core/devmgr",
         "//metropolis/node/core/localstorage",
diff --git a/metropolis/node/core/consensus/BUILD.bazel b/metropolis/node/core/consensus/BUILD.bazel
index 5c58c2a..6532f4f 100644
--- a/metropolis/node/core/consensus/BUILD.bazel
+++ b/metropolis/node/core/consensus/BUILD.bazel
@@ -13,7 +13,7 @@
     visibility = ["//:__subpackages__"],
     deps = [
         "//go/logging",
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/consensus/client",
         "//metropolis/node/core/localstorage",
         "//osbase/event",
diff --git a/metropolis/node/core/consensus/configuration.go b/metropolis/node/core/consensus/configuration.go
index 8c4bd06..dfd70f2 100644
--- a/metropolis/node/core/consensus/configuration.go
+++ b/metropolis/node/core/consensus/configuration.go
@@ -15,7 +15,7 @@
 	clientv3 "go.etcd.io/etcd/client/v3"
 	"go.etcd.io/etcd/server/v3/embed"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/localstorage"
 	"source.monogon.dev/osbase/pki"
 )
@@ -90,7 +90,7 @@
 // over TLS. This requires TLS credentials to be present on disk, and will be
 // disabled for bootstrapping the instance.
 func (c *Config) build(enablePeers bool) *embed.Config {
-	port := int(node.ConsensusPort)
+	port := int(allocs.PortConsensus)
 	if p := c.testOverrides.externalPort; p != 0 {
 		port = p
 	}
@@ -98,7 +98,7 @@
 	if c.testOverrides.externalAddress != "" {
 		host = c.testOverrides.externalAddress
 	}
-	etcdPort := int(node.MetricsEtcdListenerPort)
+	etcdPort := int(allocs.PortMetricsEtcdListener)
 	if p := c.testOverrides.etcdMetricsPort; p != 0 {
 		etcdPort = p
 	}
diff --git a/metropolis/node/core/consensus/consensus.go b/metropolis/node/core/consensus/consensus.go
index f6addd8..f00a7a9 100644
--- a/metropolis/node/core/consensus/consensus.go
+++ b/metropolis/node/core/consensus/consensus.go
@@ -33,12 +33,12 @@
 //   | node-foo            |
 //   |---------------------|
 //   | .--------------------.
-//   | | etcd               |<---etcd/TLS--.   (node.ConsensusPort)
+//   | | etcd               |<---etcd/TLS--.   (allocs.PortConsensus)
 //   | '--------------------'              |
 //   |     ^ Domain Socket |               |
 //   |     | etcd/plain    |               |
 //   | .--------------------.              |
-//   | | curator            |<---gRPC/TLS----. (node.CuratorServicePort)
+//   | | curator            |<---gRPC/TLS----. (allocs.PortCuratorService)
 //   | '--------------------'              | |
 //   |     ^ Domain Socket |               | |
 //   |     | gRPC/plain    |               | |
diff --git a/metropolis/node/core/consensus/status.go b/metropolis/node/core/consensus/status.go
index 0886531..5bf0416 100644
--- a/metropolis/node/core/consensus/status.go
+++ b/metropolis/node/core/consensus/status.go
@@ -13,7 +13,7 @@
 
 	clientv3 "go.etcd.io/etcd/client/v3"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/consensus/client"
 	"source.monogon.dev/osbase/event"
 	"source.monogon.dev/osbase/pki"
@@ -103,7 +103,7 @@
 
 	var extraNames []string
 	name := nodeID
-	port := int(node.ConsensusPort)
+	port := int(allocs.PortConsensus)
 	for _, opt := range opts {
 		if opt.externalAddress != "" {
 			name = opt.externalAddress
diff --git a/metropolis/node/core/curator/BUILD.bazel b/metropolis/node/core/curator/BUILD.bazel
index 4ff34f1..42cdffa 100644
--- a/metropolis/node/core/curator/BUILD.bazel
+++ b/metropolis/node/core/curator/BUILD.bazel
@@ -26,6 +26,7 @@
     visibility = ["//visibility:public"],
     deps = [
         "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/consensus",
         "//metropolis/node/core/consensus/client",
         "//metropolis/node/core/curator/proto/api",
@@ -72,7 +73,7 @@
     ],
     embed = [":curator"],
     deps = [
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/consensus",
         "//metropolis/node/core/consensus/client",
         "//metropolis/node/core/curator/proto/api",
diff --git a/metropolis/node/core/curator/impl_follower.go b/metropolis/node/core/curator/impl_follower.go
index 96a9385..b6d59e6 100644
--- a/metropolis/node/core/curator/impl_follower.go
+++ b/metropolis/node/core/curator/impl_follower.go
@@ -9,7 +9,7 @@
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 
-	common "source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/consensus/client"
 	cpb "source.monogon.dev/metropolis/node/core/curator/proto/api"
 	"source.monogon.dev/metropolis/node/core/identity"
@@ -73,7 +73,7 @@
 		err = srv.Send(&cpb.GetCurrentLeaderResponse{
 			LeaderNodeId: lock.NodeId,
 			LeaderHost:   node.status.ExternalAddress,
-			LeaderPort:   int32(common.CuratorServicePort),
+			LeaderPort:   int32(allocs.PortCuratorService),
 			ThisNodeId:   f.followerID,
 		})
 		if err != nil {
diff --git a/metropolis/node/core/curator/impl_leader_curator.go b/metropolis/node/core/curator/impl_leader_curator.go
index bcf7d42..8fa651f 100644
--- a/metropolis/node/core/curator/impl_leader_curator.go
+++ b/metropolis/node/core/curator/impl_leader_curator.go
@@ -20,6 +20,7 @@
 	tpb "google.golang.org/protobuf/types/known/timestamppb"
 
 	common "source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/consensus"
 	ipb "source.monogon.dev/metropolis/node/core/curator/proto/api"
 	"source.monogon.dev/metropolis/node/core/identity"
@@ -601,7 +602,7 @@
 	err = srv.Send(&ipb.GetCurrentLeaderResponse{
 		LeaderNodeId: l.leaderID,
 		LeaderHost:   host,
-		LeaderPort:   int32(common.CuratorServicePort),
+		LeaderPort:   int32(allocs.PortCuratorService),
 		ThisNodeId:   l.leaderID,
 	})
 	if err != nil {
diff --git a/metropolis/node/core/curator/impl_leader_test.go b/metropolis/node/core/curator/impl_leader_test.go
index 7e31aeb..1621be6 100644
--- a/metropolis/node/core/curator/impl_leader_test.go
+++ b/metropolis/node/core/curator/impl_leader_test.go
@@ -30,7 +30,7 @@
 	"google.golang.org/protobuf/types/known/timestamppb"
 	"k8s.io/utils/ptr"
 
-	common "source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/consensus"
 	"source.monogon.dev/metropolis/node/core/consensus/client"
 	ipb "source.monogon.dev/metropolis/node/core/curator/proto/api"
@@ -1416,7 +1416,7 @@
 	if want, got := cl.localNodeID, res.ThisNodeId; want != got {
 		t.Errorf("Wanted local node ID %q, got %q", want, got)
 	}
-	if want, got := int32(common.CuratorServicePort), res.LeaderPort; want != got {
+	if want, got := int32(allocs.PortCuratorService), res.LeaderPort; want != got {
 		t.Errorf("Wanted leader port %d, got %d", want, got)
 	}
 }
diff --git a/metropolis/node/core/curator/listener.go b/metropolis/node/core/curator/listener.go
index cb79cd8..114a02c 100644
--- a/metropolis/node/core/curator/listener.go
+++ b/metropolis/node/core/curator/listener.go
@@ -12,7 +12,7 @@
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/keepalive"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/consensus"
 	"source.monogon.dev/metropolis/node/core/consensus/client"
 	cpb "source.monogon.dev/metropolis/node/core/curator/proto/api"
@@ -89,7 +89,7 @@
 		PermitWithoutStream: true,
 	}))
 	srv := grpc.NewServer(opts...)
-	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", node.CuratorServicePort))
+	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", allocs.PortCuratorService))
 	if err != nil {
 		return fmt.Errorf("failed to listen on curator socket: %w", err)
 	}
diff --git a/metropolis/node/core/debug_service_enabled.go b/metropolis/node/core/debug_service_enabled.go
index ff20a55..9a9a02d 100644
--- a/metropolis/node/core/debug_service_enabled.go
+++ b/metropolis/node/core/debug_service_enabled.go
@@ -18,13 +18,13 @@
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/localstorage"
 	"source.monogon.dev/metropolis/node/core/mgmt"
 	"source.monogon.dev/metropolis/node/core/roleserve"
 	"source.monogon.dev/osbase/logtree"
 	"source.monogon.dev/osbase/supervisor"
 
-	common "source.monogon.dev/metropolis/node"
 	apb "source.monogon.dev/metropolis/proto/api"
 )
 
@@ -47,7 +47,7 @@
 	}
 	dbgSrv := grpc.NewServer()
 	apb.RegisterNodeDebugServiceServer(dbgSrv, dbg)
-	dbgLis, err := net.Listen("tcp", fmt.Sprintf(":%d", common.DebugServicePort))
+	dbgLis, err := net.Listen("tcp", fmt.Sprintf(":%d", allocs.PortDebugService))
 	if err != nil {
 		return fmt.Errorf("failed to listen on debug service: %w", err)
 	}
diff --git a/metropolis/node/core/delve_enabled.go b/metropolis/node/core/delve_enabled.go
index 54a64c7..038d1ac 100644
--- a/metropolis/node/core/delve_enabled.go
+++ b/metropolis/node/core/delve_enabled.go
@@ -8,12 +8,12 @@
 	"fmt"
 	"os/exec"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/network"
 )
 
 // initializeDebugger attaches Delve to ourselves and exposes it on
-// common.DebuggerPort
+// allocs.PortDebugger
 // This is coupled to compilation_mode=dbg because otherwise Delve doesn't have
 // the necessary DWARF debug info
 func initializeDebugger(networkSvc *network.Service) {
@@ -27,7 +27,7 @@
 		if err != nil {
 			panic(err)
 		}
-		dlvCmd := exec.Command("/dlv", "--headless=true", fmt.Sprintf("--listen=:%v", node.DebuggerPort),
+		dlvCmd := exec.Command("/dlv", "--headless=true", fmt.Sprintf("--listen=:%v", allocs.PortDebugger),
 			"--accept-multiclient", "--only-same-user=false", "attach", "--continue", "1", "/init")
 		if err := dlvCmd.Start(); err != nil {
 			panic(err)
diff --git a/metropolis/node/core/metrics/BUILD.bazel b/metropolis/node/core/metrics/BUILD.bazel
index bc94863..861d59f 100644
--- a/metropolis/node/core/metrics/BUILD.bazel
+++ b/metropolis/node/core/metrics/BUILD.bazel
@@ -11,7 +11,7 @@
     visibility = ["//visibility:public"],
     deps = [
         "//go/types/mapsets",
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/curator/proto/api",
         "//metropolis/node/core/curator/watcher",
         "//metropolis/node/core/identity",
@@ -32,7 +32,7 @@
         "xFakeExporterPath": "$(rlocationpath //metropolis/node/core/metrics/fake_exporter )",
     },
     deps = [
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/curator/proto/api",
         "//metropolis/test/util",
         "//osbase/supervisor",
diff --git a/metropolis/node/core/metrics/exporters.go b/metropolis/node/core/metrics/exporters.go
index 003a690..fe7044d 100644
--- a/metropolis/node/core/metrics/exporters.go
+++ b/metropolis/node/core/metrics/exporters.go
@@ -11,7 +11,7 @@
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/osbase/supervisor"
 )
 
@@ -36,7 +36,7 @@
 	Gatherer prometheus.Gatherer
 	// Port on which an exporter is/will be running to which metrics requests will be
 	// proxied to. Exactly one of Gatherer or Port must be set.
-	Port node.Port
+	Port allocs.Port
 	// Executable to run to start the exporter. If empty, no executable will be
 	// started.
 	Executable string
@@ -59,10 +59,10 @@
 	},
 	{
 		Name:       "node",
-		Port:       node.MetricsNodeListenerPort,
+		Port:       allocs.PortMetricsNodeListener,
 		Executable: "/metrics/bin/node_exporter",
 		Arguments: []string{
-			"--web.listen-address=127.0.0.1:" + node.MetricsNodeListenerPort.PortString(),
+			"--web.listen-address=127.0.0.1:" + allocs.PortMetricsNodeListener.PortString(),
 			"--collector.buddyinfo",
 			"--collector.zoneinfo",
 			"--collector.tcpstat",
@@ -77,23 +77,23 @@
 	},
 	{
 		Name: "etcd",
-		Port: node.MetricsEtcdListenerPort,
+		Port: allocs.PortMetricsEtcdListener,
 	},
 	{
 		Name: "kubernetes-scheduler",
-		Port: node.MetricsKubeSchedulerListenerPort,
+		Port: allocs.PortMetricsKubeSchedulerListener,
 	},
 	{
 		Name: "kubernetes-controller-manager",
-		Port: node.MetricsKubeControllerManagerListenerPort,
+		Port: allocs.PortMetricsKubeControllerManagerListener,
 	},
 	{
 		Name: "kubernetes-apiserver",
-		Port: node.MetricsKubeAPIServerListenerPort,
+		Port: allocs.PortMetricsKubeAPIServerListener,
 	},
 	{
 		Name: "containerd",
-		Port: node.MetricsContainerdListenerPort,
+		Port: allocs.PortMetricsContainerdListener,
 		Path: "/v1/metrics",
 	},
 }
diff --git a/metropolis/node/core/metrics/metrics.go b/metropolis/node/core/metrics/metrics.go
index 9abed54..e547c5d 100644
--- a/metropolis/node/core/metrics/metrics.go
+++ b/metropolis/node/core/metrics/metrics.go
@@ -12,7 +12,7 @@
 	"net/http"
 	"os/exec"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/identity"
 	"source.monogon.dev/osbase/supervisor"
 )
@@ -29,7 +29,7 @@
 // Each exporter is exposed on a separate path, /metrics/<name>, where <name> is
 // the name of the exporter.
 //
-// The HTTPS listener is bound to node.MetricsPort.
+// The HTTPS listener is bound to allocs.PortMetrics.
 type Service struct {
 	// Credentials used to run the TLS/HTTPS listener and verify incoming
 	// connections.
@@ -67,7 +67,7 @@
 		// anyone/anything with a valid cluster certificate to access them.
 	}
 
-	addr := net.JoinHostPort("", node.MetricsPort.PortString())
+	addr := net.JoinHostPort("", allocs.PortMetrics.PortString())
 	if s.enableDynamicAddr {
 		addr = ""
 	}
diff --git a/metropolis/node/core/metrics/metrics_test.go b/metropolis/node/core/metrics/metrics_test.go
index ebb59a9..d494222 100644
--- a/metropolis/node/core/metrics/metrics_test.go
+++ b/metropolis/node/core/metrics/metrics_test.go
@@ -20,7 +20,7 @@
 
 	apb "source.monogon.dev/metropolis/node/core/curator/proto/api"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/test/util"
 	"source.monogon.dev/osbase/supervisor"
 	"source.monogon.dev/osbase/test/freeport"
@@ -51,7 +51,7 @@
 		panic(err)
 	}
 	defer closer.Close()
-	port := node.Port(p)
+	port := allocs.Port(p)
 
 	return &Exporter{
 		Name:       name,
diff --git a/metropolis/node/core/mgmt/BUILD.bazel b/metropolis/node/core/mgmt/BUILD.bazel
index b95565b..24d0439 100644
--- a/metropolis/node/core/mgmt/BUILD.bazel
+++ b/metropolis/node/core/mgmt/BUILD.bazel
@@ -11,7 +11,7 @@
     importpath = "source.monogon.dev/metropolis/node/core/mgmt",
     visibility = ["//visibility:public"],
     deps = [
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/identity",
         "//metropolis/node/core/rpc",
         "//metropolis/node/core/update",
diff --git a/metropolis/node/core/mgmt/mgmt.go b/metropolis/node/core/mgmt/mgmt.go
index 78961f2..8bfb7ed 100644
--- a/metropolis/node/core/mgmt/mgmt.go
+++ b/metropolis/node/core/mgmt/mgmt.go
@@ -13,7 +13,7 @@
 
 	"google.golang.org/grpc"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/identity"
 	"source.monogon.dev/metropolis/node/core/rpc"
 	"source.monogon.dev/metropolis/node/core/update"
@@ -54,7 +54,7 @@
 	}
 	logger := supervisor.MustSubLogger(ctx, "rpc")
 	opts := sec.GRPCOptions(logger)
-	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", node.NodeManagementPort))
+	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", allocs.PortNodeManagement))
 	if err != nil {
 		return fmt.Errorf("failed to listen on node management socket socket: %w", err)
 	}
diff --git a/metropolis/node/core/network/BUILD.bazel b/metropolis/node/core/network/BUILD.bazel
index 23fdd5d..a3f6066 100644
--- a/metropolis/node/core/network/BUILD.bazel
+++ b/metropolis/node/core/network/BUILD.bazel
@@ -16,6 +16,7 @@
         "//go/algorithm/toposort",
         "//go/logging",
         "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/network/ipam",
         "//metropolis/node/core/network/workloads",
         "//metropolis/node/core/productinfo",
diff --git a/metropolis/node/core/network/main.go b/metropolis/node/core/network/main.go
index 2dcf7bb..419c256 100644
--- a/metropolis/node/core/network/main.go
+++ b/metropolis/node/core/network/main.go
@@ -17,6 +17,7 @@
 	"github.com/vishvananda/netlink"
 
 	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/network/ipam"
 	"source.monogon.dev/metropolis/node/core/network/workloads"
 	"source.monogon.dev/osbase/event"
@@ -285,7 +286,7 @@
 			&expr.Cmp{
 				Op:       expr.CmpOpEq,
 				Register: 8,
-				Data:     binaryutil.NativeEndian.PutUint32(node.LinkGroupK8sPod),
+				Data:     binaryutil.NativeEndian.PutUint32(allocs.LinkGroupK8sPod),
 			},
 			&expr.Meta{
 				Key:      expr.MetaKeyOIFGROUP,
@@ -295,13 +296,13 @@
 			&expr.Cmp{
 				Op:       expr.CmpOpNeq,
 				Register: 8,
-				Data:     binaryutil.NativeEndian.PutUint32(node.LinkGroupK8sPod),
+				Data:     binaryutil.NativeEndian.PutUint32(allocs.LinkGroupK8sPod),
 			},
 			// Check if outgoing interface is not part of the overlay
 			&expr.Cmp{
 				Op:       expr.CmpOpNeq,
 				Register: 8,
-				Data:     binaryutil.NativeEndian.PutUint32(node.LinkGroupOverlay),
+				Data:     binaryutil.NativeEndian.PutUint32(allocs.LinkGroupOverlay),
 			},
 			&expr.Masq{},
 		},
diff --git a/metropolis/node/core/network/overlay/BUILD.bazel b/metropolis/node/core/network/overlay/BUILD.bazel
index 4054127..2941e9d 100644
--- a/metropolis/node/core/network/overlay/BUILD.bazel
+++ b/metropolis/node/core/network/overlay/BUILD.bazel
@@ -10,7 +10,7 @@
     importpath = "source.monogon.dev/metropolis/node/core/network/overlay",
     visibility = ["//visibility:public"],
     deps = [
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/curator/proto/api",
         "//metropolis/node/core/curator/watcher",
         "//metropolis/node/core/localstorage",
@@ -30,7 +30,7 @@
     srcs = ["overlay_test.go"],
     embed = [":overlay"],
     deps = [
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/curator/proto/api",
         "//metropolis/node/core/localstorage",
         "//metropolis/node/core/localstorage/declarative",
diff --git a/metropolis/node/core/network/overlay/overlay_test.go b/metropolis/node/core/network/overlay/overlay_test.go
index 4409e09..78a1424 100644
--- a/metropolis/node/core/network/overlay/overlay_test.go
+++ b/metropolis/node/core/network/overlay/overlay_test.go
@@ -16,7 +16,7 @@
 	"golang.zx2c4.com/wireguard/wgctrl"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 
-	common "source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/localstorage"
 	"source.monogon.dev/metropolis/node/core/localstorage/declarative"
 	"source.monogon.dev/metropolis/node/core/network/ipam"
@@ -309,7 +309,7 @@
 	if want, got := key, wgDev.PrivateKey.String(); want != got {
 		t.Errorf("Wireguard key mismatch, wanted %q, got %q", want, got)
 	}
-	if want, got := int(common.WireGuardPort), wgDev.ListenPort; want != got {
+	if want, got := int(allocs.PortWireGuard), wgDev.ListenPort; want != got {
 		t.Errorf("Wireguard port mismatch, wanted %d, got %d", want, got)
 	}
 
@@ -366,7 +366,7 @@
 			if want, got := pkeys[i].PublicKey().String(), wgDev.Peers[i].PublicKey.String(); want != got {
 				t.Errorf("Peer %d should have key %q, got %q", i, want, got)
 			}
-			if want, got := fmt.Sprintf("10.100.%d.1:%s", i, common.WireGuardPort.PortString()), wgDev.Peers[i].Endpoint.String(); want != got {
+			if want, got := fmt.Sprintf("10.100.%d.1:%s", i, allocs.PortWireGuard.PortString()), wgDev.Peers[i].Endpoint.String(); want != got {
 				t.Errorf("Peer %d should have endpoint %q, got %q", i, want, got)
 			}
 			if want, got := 2, len(wgDev.Peers[i].AllowedIPs); want != got {
@@ -409,7 +409,7 @@
 		if want, got := pkeys[0].PublicKey().String(), wgDev.Peers[0].PublicKey.String(); want != got {
 			t.Errorf("Peer 0 should have key %q, got %q", want, got)
 		}
-		if want, got := fmt.Sprintf("10.100.0.3:%s", common.WireGuardPort.PortString()), wgDev.Peers[0].Endpoint.String(); want != got {
+		if want, got := fmt.Sprintf("10.100.0.3:%s", allocs.PortWireGuard.PortString()), wgDev.Peers[0].Endpoint.String(); want != got {
 			t.Errorf("Peer 0 should have endpoint %q, got %q", want, got)
 		}
 		if want, got := 1, len(wgDev.Peers[0].AllowedIPs); want != got {
diff --git a/metropolis/node/core/network/overlay/wireguard.go b/metropolis/node/core/network/overlay/wireguard.go
index 5054553..c830dd5 100644
--- a/metropolis/node/core/network/overlay/wireguard.go
+++ b/metropolis/node/core/network/overlay/wireguard.go
@@ -12,7 +12,7 @@
 	"golang.zx2c4.com/wireguard/wgctrl"
 	"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
 
-	common "source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	ipb "source.monogon.dev/metropolis/node/core/curator/proto/api"
 	"source.monogon.dev/metropolis/node/core/localstorage"
 )
@@ -89,7 +89,7 @@
 		}
 	}
 
-	wgInterface := &netlink.Wireguard{LinkAttrs: netlink.LinkAttrs{Name: clusterNetDeviceName, Flags: net.FlagUp, Group: common.LinkGroupOverlay}}
+	wgInterface := &netlink.Wireguard{LinkAttrs: netlink.LinkAttrs{Name: clusterNetDeviceName, Flags: net.FlagUp, Group: allocs.LinkGroupOverlay}}
 	if err := netlink.LinkAdd(wgInterface); err != nil {
 		return fmt.Errorf("when adding network interface: %w", err)
 	}
@@ -100,7 +100,7 @@
 	}
 	s.wgClient = wgClient
 
-	listenPort := int(common.WireGuardPort)
+	listenPort := int(allocs.PortWireGuard)
 	if err := s.wgClient.ConfigureDevice(clusterNetDeviceName, wgtypes.Config{
 		PrivateKey: &s.privKey,
 		ListenPort: &listenPort,
@@ -111,7 +111,7 @@
 	if err := netlink.RouteAdd(&netlink.Route{
 		Dst:       clusterNet,
 		LinkIndex: wgInterface.Index,
-		Protocol:  netlink.RouteProtocol(common.ProtocolOverlay),
+		Protocol:  netlink.RouteProtocol(allocs.ProtocolOverlay),
 	}); err != nil && !os.IsExist(err) {
 		return fmt.Errorf("when creating cluster route: %w", err)
 	}
@@ -145,7 +145,7 @@
 			}
 			allowedIPs = append(allowedIPs, *podNet)
 		}
-		endpoint := net.UDPAddr{Port: int(common.WireGuardPort), IP: addressParsed}
+		endpoint := net.UDPAddr{Port: int(allocs.PortWireGuard), IP: addressParsed}
 		configs = append(configs, wgtypes.PeerConfig{
 			PublicKey:         pubkeyParsed,
 			Endpoint:          &endpoint,
diff --git a/metropolis/node/core/network/workloads/BUILD.bazel b/metropolis/node/core/network/workloads/BUILD.bazel
index e031fca..6ae3132 100644
--- a/metropolis/node/core/network/workloads/BUILD.bazel
+++ b/metropolis/node/core/network/workloads/BUILD.bazel
@@ -6,7 +6,7 @@
     importpath = "source.monogon.dev/metropolis/node/core/network/workloads",
     visibility = ["//visibility:public"],
     deps = [
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/network/ipam",
         "//metropolis/node/core/network/workloads/spec",
         "//osbase/event",
diff --git a/metropolis/node/core/network/workloads/workloads.go b/metropolis/node/core/network/workloads/workloads.go
index dfe3eca..fae175c 100644
--- a/metropolis/node/core/network/workloads/workloads.go
+++ b/metropolis/node/core/network/workloads/workloads.go
@@ -19,7 +19,7 @@
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/network/ipam"
 	wlapi "source.monogon.dev/metropolis/node/core/network/workloads/spec"
 	"source.monogon.dev/osbase/event"
@@ -192,7 +192,7 @@
 	}
 
 	linkAttrs := netlink.NewLinkAttrs()
-	linkAttrs.Group = node.LinkGroupK8sPod
+	linkAttrs.Group = allocs.LinkGroupK8sPod
 	linkAttrs.Name = intf
 	linkAttrs.HardwareAddr = firstHopMAC
 
@@ -307,7 +307,7 @@
 	if err != nil {
 		return nil, status.Errorf(codes.Unavailable, "error getting interface for deletion: %v", err)
 	}
-	if hostIf.Attrs().Group != node.LinkGroupK8sPod {
+	if hostIf.Attrs().Group != allocs.LinkGroupK8sPod {
 		return nil, status.Errorf(codes.InvalidArgument, "refusing to delete interface not belonging to workload, has group %d", hostIf.Attrs().Group)
 	}
 	// Routes and addresses do not need to be cleaned up as Linux already takes
diff --git a/metropolis/node/core/roleserve/BUILD.bazel b/metropolis/node/core/roleserve/BUILD.bazel
index c753683..b170ec2 100644
--- a/metropolis/node/core/roleserve/BUILD.bazel
+++ b/metropolis/node/core/roleserve/BUILD.bazel
@@ -18,7 +18,7 @@
     importpath = "source.monogon.dev/metropolis/node/core/roleserve",
     visibility = ["//visibility:public"],
     deps = [
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/consensus",
         "//metropolis/node/core/curator",
         "//metropolis/node/core/curator/proto/api",
@@ -64,7 +64,7 @@
         "source.monogon.dev/metropolis/node/core/productinfo.path": "$(rlocationpath //metropolis/node:product_info )",
     },
     deps = [
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/consensus",
         "//metropolis/node/core/curator",
         "//metropolis/node/core/curator/proto/api",
diff --git a/metropolis/node/core/roleserve/roleserve.go b/metropolis/node/core/roleserve/roleserve.go
index 918b466..6ddda1e 100644
--- a/metropolis/node/core/roleserve/roleserve.go
+++ b/metropolis/node/core/roleserve/roleserve.go
@@ -42,7 +42,7 @@
 	"context"
 	"crypto/ed25519"
 
-	common "source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/curator"
 	"source.monogon.dev/metropolis/node/core/identity"
 	"source.monogon.dev/metropolis/node/core/localstorage"
@@ -215,8 +215,8 @@
 func (s *Service) ProvideBootstrapData(data *BootstrapData) {
 	// This is the first time we have the node ID, tell the resolver that it's
 	// available on the loopback interface.
-	s.Resolver.AddOverride(data.Node.ID, resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
-	s.Resolver.AddEndpoint(resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
+	s.Resolver.AddOverride(data.Node.ID, resolver.NodeByHostPort("127.0.0.1", uint16(allocs.PortCuratorService)))
+	s.Resolver.AddEndpoint(resolver.NodeByHostPort("127.0.0.1", uint16(allocs.PortCuratorService)))
 
 	s.bootstrapData.Set(data)
 }
@@ -224,7 +224,7 @@
 func (s *Service) ProvideRegisterData(credentials identity.NodeCredentials, directory *cpb.ClusterDirectory) {
 	// This is the first time we have the node ID, tell the resolver that it's
 	// available on the loopback interface.
-	s.Resolver.AddOverride(credentials.ID(), resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
+	s.Resolver.AddOverride(credentials.ID(), resolver.NodeByHostPort("127.0.0.1", uint16(allocs.PortCuratorService)))
 	// Also tell the resolver about all the existing nodes in the cluster we just
 	// registered into. The directory passed here was used to issue the initial
 	// Register call, which means at least one of the nodes was running the control
@@ -241,7 +241,7 @@
 func (s *Service) ProvideJoinData(credentials identity.NodeCredentials, directory *cpb.ClusterDirectory) {
 	// This is the first time we have the node ID, tell the resolver that it's
 	// available on the loopback interface.
-	s.Resolver.AddOverride(credentials.ID(), resolver.NodeByHostPort("127.0.0.1", uint16(common.CuratorServicePort)))
+	s.Resolver.AddOverride(credentials.ID(), resolver.NodeByHostPort("127.0.0.1", uint16(allocs.PortCuratorService)))
 	// Also tell the resolver about all the existing nodes in the cluster we just
 	// joined into. The directory passed here was used to issue the initial
 	// Join call, which means at least one of the nodes was running the control
diff --git a/metropolis/node/core/roleserve/worker_statuspush.go b/metropolis/node/core/roleserve/worker_statuspush.go
index 62355bc..5b7ee71 100644
--- a/metropolis/node/core/roleserve/worker_statuspush.go
+++ b/metropolis/node/core/roleserve/worker_statuspush.go
@@ -12,7 +12,7 @@
 	"github.com/google/uuid"
 	"google.golang.org/protobuf/encoding/prototext"
 
-	common "source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/network"
 	"source.monogon.dev/metropolis/node/core/productinfo"
 	"source.monogon.dev/osbase/event"
@@ -102,7 +102,7 @@
 			if status.RunningCurator == nil && lcp.exists() {
 				supervisor.Logger(ctx).Infof("Got new local curator state: running")
 				status.RunningCurator = &cpb.NodeStatus_RunningCurator{
-					Port: int32(common.CuratorServicePort),
+					Port: int32(allocs.PortCuratorService),
 				}
 				changed = true
 			}
diff --git a/metropolis/node/core/roleserve/worker_statuspush_test.go b/metropolis/node/core/roleserve/worker_statuspush_test.go
index 40764f2..0f25f3b 100644
--- a/metropolis/node/core/roleserve/worker_statuspush_test.go
+++ b/metropolis/node/core/roleserve/worker_statuspush_test.go
@@ -18,7 +18,7 @@
 	"google.golang.org/grpc/test/bufconn"
 	"google.golang.org/protobuf/testing/protocmp"
 
-	common "source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/consensus"
 	"source.monogon.dev/metropolis/node/core/curator"
 	"source.monogon.dev/metropolis/node/core/productinfo"
@@ -182,7 +182,7 @@
 		{NodeId: nodeID, Status: &cpb.NodeStatus{
 			ExternalAddress: "192.0.2.11",
 			RunningCurator: &cpb.NodeStatus_RunningCurator{
-				Port: int32(common.CuratorServicePort),
+				Port: int32(allocs.PortCuratorService),
 			},
 			Version: productInfo.Version,
 			BootId:  []byte{1, 2, 3},
diff --git a/metropolis/node/core/rpc/resolver/BUILD.bazel b/metropolis/node/core/rpc/resolver/BUILD.bazel
index 6438c62..0b041f6 100644
--- a/metropolis/node/core/rpc/resolver/BUILD.bazel
+++ b/metropolis/node/core/rpc/resolver/BUILD.bazel
@@ -11,7 +11,7 @@
     visibility = ["//visibility:public"],
     deps = [
         "//go/logging",
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//metropolis/node/core/curator/proto/api",
         "//metropolis/node/core/curator/watcher",
         "//metropolis/proto/common",
diff --git a/metropolis/node/core/rpc/resolver/resolver.go b/metropolis/node/core/rpc/resolver/resolver.go
index c865130..95c5837 100644
--- a/metropolis/node/core/rpc/resolver/resolver.go
+++ b/metropolis/node/core/rpc/resolver/resolver.go
@@ -17,7 +17,7 @@
 	"google.golang.org/grpc/keepalive"
 
 	"source.monogon.dev/go/logging"
-	common "source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/metropolis/node/core/curator/watcher"
 
 	apb "source.monogon.dev/metropolis/node/core/curator/proto/api"
@@ -144,13 +144,13 @@
 	if m, _ := regexp.MatchString(`metropolis-[a-f0-9]+`, id); !m {
 		return nil, fmt.Errorf("invalid node ID")
 	}
-	return NodeByHostPort(id, uint16(common.CuratorServicePort)), nil
+	return NodeByHostPort(id, uint16(allocs.PortCuratorService)), nil
 }
 
 // NodeAtAddressWithDefaultPort returns a NodeEndpoint referencing the default
 // control plane port (the Curator port) of a node at a given address.
 func NodeAtAddressWithDefaultPort(host string) *NodeEndpoint {
-	return NodeByHostPort(host, uint16(common.CuratorServicePort))
+	return NodeByHostPort(host, uint16(allocs.PortCuratorService))
 }
 
 // NodeByHostPort returns a NodeEndpoint for a fully specified host + port pair.
diff --git a/metropolis/node/core/time/BUILD.bazel b/metropolis/node/core/time/BUILD.bazel
index f113153..3f318e0 100644
--- a/metropolis/node/core/time/BUILD.bazel
+++ b/metropolis/node/core/time/BUILD.bazel
@@ -6,7 +6,7 @@
     importpath = "source.monogon.dev/metropolis/node/core/time",
     visibility = ["//visibility:public"],
     deps = [
-        "//metropolis/node",
+        "//metropolis/node/allocs",
         "//osbase/fileargs",
         "//osbase/supervisor",
     ],
diff --git a/metropolis/node/core/time/time.go b/metropolis/node/core/time/time.go
index 23400ef..d7cd721 100644
--- a/metropolis/node/core/time/time.go
+++ b/metropolis/node/core/time/time.go
@@ -20,7 +20,7 @@
 	"strconv"
 	"strings"
 
-	"source.monogon.dev/metropolis/node"
+	"source.monogon.dev/metropolis/node/allocs"
 	"source.monogon.dev/osbase/fileargs"
 	"source.monogon.dev/osbase/supervisor"
 )
@@ -53,8 +53,8 @@
 	cmd := exec.CommandContext(ctx,
 		"/time/chrony",
 		"-d",
-		"-i", strconv.Itoa(node.TimeUid),
-		"-g", strconv.Itoa(node.TimeUid),
+		"-i", strconv.Itoa(allocs.UidTime),
+		"-g", strconv.Itoa(allocs.UidTime),
 		"-f", args.ArgPath("chrony.conf", []byte(config)),
 	)
 	cmd.Stdout = supervisor.RawLogger(ctx)