diff options
author | Jon Bratseth <bratseth@gmail.com> | 2022-11-20 14:43:52 +0100 |
---|---|---|
committer | Jon Bratseth <bratseth@gmail.com> | 2022-11-20 14:43:52 +0100 |
commit | ae3872afc0b8a694944e235fdf08c45a12e0e5b1 (patch) | |
tree | 36c2a7712ed160388e55bc263b41cc75f50be8b1 /node-repository | |
parent | c535f7e9b1e641d88a0460dc43a47562481770ce (diff) |
Set decided exclusivity on ClusterSpec
Diffstat (limited to 'node-repository')
6 files changed, 30 insertions, 24 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java index 0bf32e534b7..c26278e948d 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/NodeRepository.java @@ -12,6 +12,9 @@ import com.yahoo.config.provision.Zone; import com.yahoo.config.provisioning.NodeRepositoryConfig; import com.yahoo.vespa.curator.Curator; import com.yahoo.vespa.flags.FlagSource; +import com.yahoo.vespa.flags.JacksonFlag; +import com.yahoo.vespa.flags.PermanentFlags; +import com.yahoo.vespa.flags.custom.SharedHost; import com.yahoo.vespa.hosted.provision.Node.State; import com.yahoo.vespa.hosted.provision.applications.Applications; import com.yahoo.vespa.hosted.provision.autoscale.MetricsDb; @@ -62,6 +65,7 @@ public class NodeRepository extends AbstractComponent { private final MetricsDb metricsDb; private final Orchestrator orchestrator; private final int spareCount; + private final JacksonFlag<SharedHost> sharedHosts; /** * Creates a node repository from a zookeeper provider. @@ -134,6 +138,7 @@ public class NodeRepository extends AbstractComponent { this.metricsDb = metricsDb; this.orchestrator = orchestrator; this.spareCount = spareCount; + this.sharedHosts = PermanentFlags.SHARED_HOST.bindTo(flagSource()); nodes.rewrite(); } @@ -197,7 +202,8 @@ public class NodeRepository extends AbstractComponent { * perfectly. */ public boolean exclusiveAllocation(ClusterSpec clusterSpec) { - return clusterSpec.isExclusive() || ! zone().cloud().allowHostSharing(); + return clusterSpec.isExclusive() || + ( !zone().cloud().allowHostSharing() && !sharedHosts.value().isEnabled(clusterSpec.type().name())); } /** diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java index 36b32f0b099..cb5d8dd5042 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Limits.java @@ -63,7 +63,7 @@ public class Limits { public Limits fullySpecified(ClusterSpec clusterSpec, NodeRepository nodeRepository, ApplicationId applicationId) { if (this.isEmpty()) throw new IllegalStateException("Unspecified limits can not be made fully specified"); - var defaultResources = new CapacityPolicies(nodeRepository).defaultNodeResources(clusterSpec, applicationId, clusterSpec.isExclusive()); + var defaultResources = new CapacityPolicies(nodeRepository).defaultNodeResources(clusterSpec, applicationId); var specifiedMin = min.nodeResources().isUnspecified() ? min.with(defaultResources) : min; var specifiedMax = max.nodeResources().isUnspecified() ? max.with(defaultResources) : max; return new Limits(specifiedMin, specifiedMax); diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java index 8d6c6b4bb62..b1b876c5699 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/CapacityPolicies.java @@ -79,16 +79,15 @@ public class CapacityPolicies { return target; } - public NodeResources defaultNodeResources(ClusterSpec clusterSpec, ApplicationId applicationId, boolean exclusive) { + public NodeResources defaultNodeResources(ClusterSpec clusterSpec, ApplicationId applicationId) { if (clusterSpec.type() == ClusterSpec.Type.admin) { Architecture architecture = adminClusterArchitecture(applicationId); if (clusterSpec.id().value().equals("cluster-controllers")) { - return clusterControllerResources(clusterSpec, exclusive) - .with(architecture); + return clusterControllerResources(clusterSpec).with(architecture); } - return (requiresExclusiveHost(clusterSpec.type(), exclusive) + return (requiresExclusiveHost(clusterSpec) ? versioned(clusterSpec, Map.of(new Version(0), smallestExclusiveResources())) : versioned(clusterSpec, Map.of(new Version(0), smallestSharedResources()))) .with(architecture); @@ -107,8 +106,8 @@ public class CapacityPolicies { } } - private NodeResources clusterControllerResources(ClusterSpec clusterSpec, boolean exclusive) { - if (requiresExclusiveHost(clusterSpec.type(), exclusive)) { + private NodeResources clusterControllerResources(ClusterSpec clusterSpec) { + if (requiresExclusiveHost(clusterSpec)) { return versioned(clusterSpec, Map.of(new Version(0), smallestExclusiveResources())); } return versioned(clusterSpec, Map.of(new Version(0), new NodeResources(0.25, 1.14, 10, 0.3))); @@ -119,8 +118,8 @@ public class CapacityPolicies { } /** Returns whether an exclusive host is required for given cluster type and exclusivity requirement */ - private boolean requiresExclusiveHost(ClusterSpec.Type type, boolean exclusive) { - return ! zone.cloud().allowHostSharing() && (exclusive || !sharedHosts.value().isEnabled(type.name())); + private boolean requiresExclusiveHost(ClusterSpec cluster) { + return ! zone.cloud().allowHostSharing() && (cluster.isExclusive() || !sharedHosts.value().isEnabled(cluster.type().name())); } /** Returns the resources for the newest version not newer than that requested in the cluster spec. */ @@ -145,9 +144,10 @@ public class CapacityPolicies { } /** Returns whether the nodes requested can share physical host with other applications */ - public boolean decideExclusivity(Capacity capacity, boolean requestedExclusivity) { - if (capacity.cloudAccount().isPresent()) return true; // Implicit exclusive when using custom cloud account - return requestedExclusivity && (capacity.isRequired() || zone.environment() == Environment.prod); + public ClusterSpec decideExclusivity(Capacity capacity, ClusterSpec requestedCluster) { + if (capacity.cloudAccount().isPresent()) return requestedCluster.withExclusivity(true); // Implicit exclusive + boolean exclusive = requestedCluster.isExclusive() && (capacity.isRequired() || zone.environment() == Environment.prod); + return requestedCluster.withExclusivity(exclusive); } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java index dad1bf8b2fa..7160c9ba045 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java @@ -95,28 +95,29 @@ public class NodeRepositoryProvisioner implements Provisioner { NodeResources resources; NodeSpec nodeSpec; if (requested.type() == NodeType.tenant) { - boolean exclusive = capacityPolicies.decideExclusivity(requested, cluster.isExclusive()); - Capacity actual = capacityPolicies.applyOn(requested, application, exclusive); + cluster = capacityPolicies.decideExclusivity(requested, cluster); + Capacity actual = capacityPolicies.applyOn(requested, application, cluster.isExclusive()); ClusterResources target = decideTargetResources(application, cluster, actual); ensureRedundancy(target.nodes(), cluster, actual.canFail(), application); logIfDownscaled(requested.minResources().nodes(), actual.minResources().nodes(), cluster, logger); groups = target.groups(); - resources = getNodeResources(cluster, target.nodeResources(), application, exclusive); - nodeSpec = NodeSpec.from(target.nodes(), resources, exclusive, actual.canFail(), + resources = getNodeResources(cluster, target.nodeResources(), application); + nodeSpec = NodeSpec.from(target.nodes(), resources, cluster.isExclusive(), actual.canFail(), requested.cloudAccount().orElse(nodeRepository.zone().cloud().account())); } else { groups = 1; // type request with multiple groups is not supported - resources = getNodeResources(cluster, requested.minResources().nodeResources(), application, true); + cluster = cluster.withExclusivity(true); + resources = getNodeResources(cluster, requested.minResources().nodeResources(), application); nodeSpec = NodeSpec.from(requested.type(), nodeRepository.zone().cloud().account()); } return asSortedHosts(preparer.prepare(application, cluster, nodeSpec, groups), resources); } - private NodeResources getNodeResources(ClusterSpec cluster, NodeResources nodeResources, ApplicationId applicationId, boolean exclusive) { + private NodeResources getNodeResources(ClusterSpec cluster, NodeResources nodeResources, ApplicationId applicationId) { return nodeResources.isUnspecified() - ? capacityPolicies.defaultNodeResources(cluster, applicationId, exclusive) + ? capacityPolicies.defaultNodeResources(cluster, applicationId) : nodeResources; } @@ -177,8 +178,7 @@ public class NodeRepositoryProvisioner implements Provisioner { private ClusterResources initialResourcesFrom(Capacity requested, ClusterSpec clusterSpec, ApplicationId applicationId) { var initial = requested.minResources(); if (initial.nodeResources().isUnspecified()) - initial = initial.with(capacityPolicies.defaultNodeResources(clusterSpec, applicationId, - capacityPolicies.decideExclusivity(requested, clusterSpec.isExclusive()))); + initial = initial.with(capacityPolicies.defaultNodeResources(clusterSpec, applicationId)); return initial; } diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java index 6c8c3c571f5..d0232f6f62f 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java @@ -272,7 +272,7 @@ public class AutoscalingTest { .build(); NodeResources defaultResources = - new CapacityPolicies(fixture.tester().nodeRepository()).defaultNodeResources(fixture.clusterSpec, fixture.applicationId, false); + new CapacityPolicies(fixture.tester().nodeRepository()).defaultNodeResources(fixture.clusterSpec, fixture.applicationId); fixture.tester().assertResources("Min number of nodes and default resources", 2, 1, defaultResources, diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java index 3134d378c1c..00797cd6305 100644 --- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java +++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java @@ -142,7 +142,7 @@ class AutoscalingTester { } public Autoscaler.Advice autoscale(ApplicationId applicationId, ClusterSpec cluster, Capacity capacity) { - capacity = capacityPolicies.applyOn(capacity, applicationId, capacityPolicies.decideExclusivity(capacity, cluster.isExclusive())); + capacity = capacityPolicies.applyOn(capacity, applicationId, capacityPolicies.decideExclusivity(capacity, cluster).isExclusive()); Application application = nodeRepository().applications().get(applicationId).orElse(Application.empty(applicationId)) .withCluster(cluster.id(), false, capacity); try (Mutex lock = nodeRepository().applications().lock(applicationId)) { |