diff options
author | Valerij Fredriksen <valerijf@yahooinc.com> | 2023-07-25 14:46:51 +0200 |
---|---|---|
committer | Valerij Fredriksen <valerijf@yahooinc.com> | 2023-07-25 14:47:20 +0200 |
commit | d876a7cb39a4fa8434bbb024618189167d1e4d9b (patch) | |
tree | 5acde24d1b83069842424aaaa21430876666efab | |
parent | 0ae98df65473a71af92ed665dbc6c4b9311e6ad7 (diff) |
Add NodeResourceLimits to NodeRepository
6 files changed, 21 insertions, 20 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 f3d69fdf103..602314bed96 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 @@ -17,6 +17,7 @@ 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.archive.ArchiveUriManager; import com.yahoo.vespa.hosted.provision.autoscale.MetricsDb; import com.yahoo.vespa.hosted.provision.lb.LoadBalancers; import com.yahoo.vespa.hosted.provision.maintenance.InfrastructureVersions; @@ -28,10 +29,10 @@ import com.yahoo.vespa.hosted.provision.persistence.CuratorDb; import com.yahoo.vespa.hosted.provision.persistence.DnsNameResolver; import com.yahoo.vespa.hosted.provision.persistence.JobControlFlags; import com.yahoo.vespa.hosted.provision.persistence.NameResolver; -import com.yahoo.vespa.hosted.provision.archive.ArchiveUriManager; import com.yahoo.vespa.hosted.provision.provisioning.ContainerImages; import com.yahoo.vespa.hosted.provision.provisioning.FirmwareChecks; import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator; +import com.yahoo.vespa.hosted.provision.provisioning.NodeResourceLimits; import com.yahoo.vespa.hosted.provision.provisioning.ProvisionServiceProvider; import com.yahoo.vespa.orchestrator.Orchestrator; @@ -52,6 +53,7 @@ public class NodeRepository extends AbstractComponent { private final Nodes nodes; private final NodeFlavors flavors; private final HostResourcesCalculator resourcesCalculator; + private final NodeResourceLimits nodeResourceLimits; private final NameResolver nameResolver; private final OsVersions osVersions; private final InfrastructureVersions infrastructureVersions; @@ -129,6 +131,7 @@ public class NodeRepository extends AbstractComponent { this.nodes = new Nodes(db, zone, clock, orchestrator, applications); this.flavors = flavors; this.resourcesCalculator = provisionServiceProvider.getHostResourcesCalculator(); + this.nodeResourceLimits = new NodeResourceLimits(this); this.nameResolver = nameResolver; this.osVersions = new OsVersions(this); this.infrastructureVersions = new InfrastructureVersions(db); @@ -181,6 +184,8 @@ public class NodeRepository extends AbstractComponent { public HostResourcesCalculator resourcesCalculator() { return resourcesCalculator; } + public NodeResourceLimits nodeResourceLimits() { return nodeResourceLimits; } + public FlagSource flagSource() { return flagSource; } public MetricsDb metricsDb() { return metricsDb; } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java index 40d1d50e0e8..c19d76efb35 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java @@ -9,7 +9,6 @@ import com.yahoo.config.provision.NodeResources; import com.yahoo.vespa.hosted.provision.Node; import com.yahoo.vespa.hosted.provision.NodeList; import com.yahoo.vespa.hosted.provision.NodeRepository; -import com.yahoo.vespa.hosted.provision.provisioning.NodeResourceLimits; import java.util.List; import java.util.Optional; @@ -161,7 +160,7 @@ public class AllocatableClusterResources { Limits applicationLimits, List<NodeResources> availableRealHostResources, NodeRepository nodeRepository) { - var systemLimits = new NodeResourceLimits(nodeRepository); + var systemLimits = nodeRepository.nodeResourceLimits(); boolean exclusive = nodeRepository.exclusiveAllocation(clusterSpec); if (! exclusive) { // We decide resources: Add overhead to what we'll request (advertised) to make sure real becomes (at least) cappedNodeResources @@ -245,7 +244,7 @@ public class AllocatableClusterResources { Limits applicationLimits, boolean exclusive, boolean bestCase) { - var systemLimits = new NodeResourceLimits(nodeRepository); + var systemLimits = nodeRepository.nodeResourceLimits(); var advertisedResources = nodeRepository.resourcesCalculator().realToRequest(wantedResources.nodeResources(), exclusive, bestCase); advertisedResources = systemLimits.enlargeToLegal(advertisedResources, applicationId, clusterSpec, exclusive, true); // Ask for something legal advertisedResources = applicationLimits.cap(advertisedResources); // Overrides other conditions, even if it will then fail diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java index 28caf26353b..b289a965567 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeAllocation.java @@ -83,7 +83,6 @@ class NodeAllocation { private final Supplier<Integer> nextIndex; private final NodeRepository nodeRepository; - private final NodeResourceLimits nodeResourceLimits; private final Optional<String> requiredHostFlavor; NodeAllocation(NodeList allNodes, ApplicationId application, ClusterSpec cluster, NodeSpec requested, @@ -94,7 +93,6 @@ class NodeAllocation { this.requested = requested; this.nextIndex = nextIndex; this.nodeRepository = nodeRepository; - this.nodeResourceLimits = new NodeResourceLimits(nodeRepository); this.requiredHostFlavor = Optional.of(PermanentFlags.HOST_FLAVOR.bindTo(nodeRepository.flagSource()) .with(FetchVector.Dimension.APPLICATION_ID, application.serializedForm()) .with(FetchVector.Dimension.CLUSTER_TYPE, cluster.type().name()) @@ -133,7 +131,7 @@ class NodeAllocation { } } else if (! saturated() && hasCompatibleResources(candidate)) { - if (! nodeResourceLimits.isWithinRealLimits(candidate, application, cluster)) { + if (! nodeRepository.nodeResourceLimits().isWithinRealLimits(candidate, application, cluster)) { ++rejectedDueToInsufficientRealResources; continue; } @@ -165,7 +163,7 @@ class NodeAllocation { boolean alreadyRetired = candidate.allocation().map(a -> a.membership().retired()).orElse(false); return alreadyRetired ? Retirement.alreadyRetired : Retirement.none; } - if ( ! nodeResourceLimits.isWithinRealLimits(candidate, application, cluster)) return Retirement.outsideRealLimits; + if ( ! nodeRepository.nodeResourceLimits().isWithinRealLimits(candidate, application, cluster)) return Retirement.outsideRealLimits; if (violatesParentHostPolicy(candidate)) return Retirement.violatesParentHostPolicy; if ( ! hasCompatibleResources(candidate)) return Retirement.incompatibleResources; if (candidate.parent.map(node -> node.status().wantToUpgradeFlavor()).orElse(false)) return Retirement.violatesHostFlavorGeneration; 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 bcc63a6704a..3d0c1069584 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 @@ -57,7 +57,6 @@ public class NodeRepositoryProvisioner implements Provisioner { private final Preparer preparer; private final Activator activator; private final Optional<LoadBalancerProvisioner> loadBalancerProvisioner; - private final NodeResourceLimits nodeResourceLimits; @Inject public NodeRepositoryProvisioner(NodeRepository nodeRepository, @@ -70,7 +69,6 @@ public class NodeRepositoryProvisioner implements Provisioner { this.zone = zone; this.loadBalancerProvisioner = provisionServiceProvider.getLoadBalancerService() .map(lbService -> new LoadBalancerProvisioner(nodeRepository, lbService)); - this.nodeResourceLimits = new NodeResourceLimits(nodeRepository); this.preparer = new Preparer(nodeRepository, provisionServiceProvider.getHostProvisioner(), loadBalancerProvisioner, @@ -115,8 +113,8 @@ public class NodeRepositoryProvisioner implements Provisioner { private void validate(ApplicationId application, ClusterSpec cluster, Capacity requested, ProvisionLogger logger) { if (cluster.group().isPresent()) throw new IllegalArgumentException("Node requests cannot specify a group"); - nodeResourceLimits.ensureWithinAdvertisedLimits("Min", requested.minResources().nodeResources(), application, cluster); - nodeResourceLimits.ensureWithinAdvertisedLimits("Max", requested.maxResources().nodeResources(), application, cluster); + nodeRepository.nodeResourceLimits().ensureWithinAdvertisedLimits("Min", requested.minResources().nodeResources(), application, cluster); + nodeRepository.nodeResourceLimits().ensureWithinAdvertisedLimits("Max", requested.maxResources().nodeResources(), application, cluster); if ( ! requested.minResources().nodeResources().gpuResources().equals(requested.maxResources().nodeResources().gpuResources())) throw new IllegalArgumentException(requested + " is invalid: Gpu capacity cannot have ranges"); @@ -126,7 +124,7 @@ public class NodeRepositoryProvisioner implements Provisioner { private void logInsufficientDiskResources(ClusterSpec cluster, Capacity requested, ProvisionLogger logger) { var resources = requested.minResources().nodeResources(); - if ( ! nodeResourceLimits.isWithinAdvertisedDiskLimits(resources, cluster)) { + if ( ! nodeRepository.nodeResourceLimits().isWithinAdvertisedDiskLimits(resources, cluster)) { logger.logApplicationPackage(Level.WARNING, "Requested disk (" + resources.diskGb() + "Gb) in " + cluster.id() + " is not large enough to fit " + "core/heap dumps. Minimum recommended disk resources " + diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java index 8c5a7b6c61e..47c388f97a8 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeResourceLimits.java @@ -2,17 +2,14 @@ package com.yahoo.vespa.hosted.provision.provisioning; import com.yahoo.config.provision.ApplicationId; -import com.yahoo.config.provision.Capacity; import com.yahoo.config.provision.ClusterSpec; import com.yahoo.config.provision.Environment; import com.yahoo.config.provision.NodeResources; import com.yahoo.config.provision.NodeType; -import com.yahoo.config.provision.ProvisionLogger; import com.yahoo.config.provision.Zone; import com.yahoo.vespa.hosted.provision.NodeRepository; import java.util.Locale; -import java.util.logging.Level; /** * Defines the resource limits for nodes in various zones @@ -91,7 +88,7 @@ public class NodeResourceLimits { } // TODO: Move this check into the above when we are ready to fail, not just warn on this. */ - private double minAdvertisedDiskGb(NodeResources requested, ClusterSpec cluster) { + private static double minAdvertisedDiskGb(NodeResources requested, ClusterSpec cluster) { return requested.memoryGb() * switch (cluster.type()) { case combined, content -> 3; case container -> 2; @@ -111,16 +108,16 @@ public class NodeResourceLimits { return minAdvertisedVcpu(applicationId, cluster); } - private double minRealMemoryGb(ClusterSpec cluster) { + private static double minRealMemoryGb(ClusterSpec cluster) { if (cluster.type() == ClusterSpec.Type.admin) return 0.95; // TODO: Increase to 1.05 after March 2023 return 2.3; } - private double minRealDiskGb() { return 6; } + private static double minRealDiskGb() { return 6; } private Zone zone() { return nodeRepository.zone(); } - private void illegal(String type, String resource, String unit, ClusterSpec cluster, double requested, double minAllowed) { + private static void illegal(String type, String resource, String unit, ClusterSpec cluster, double requested, double minAllowed) { if ( ! unit.isEmpty()) unit = " " + unit; String message = String.format(Locale.ENGLISH, diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java index 79b1bccbbde..470a267e75f 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java @@ -103,6 +103,10 @@ public class Preparer { allocation.offer(candidates); }; try { + if (throttler.throttle(allNodes, Agent.system)) { + throw new NodeAllocationException("Host provisioning is being throttled", true); + } + HostProvisionRequest request = new HostProvisionRequest(allocation.provisionIndices(deficit.count()), hostType, deficit.resources(), |