diff options
Diffstat (limited to 'node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java')
-rw-r--r-- | node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java index de132d53d63..4c5ace3d51a 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterModel.java @@ -8,7 +8,6 @@ import com.yahoo.vespa.hosted.provision.NodeRepository; import com.yahoo.vespa.hosted.provision.applications.Application; import com.yahoo.vespa.hosted.provision.applications.Cluster; import com.yahoo.vespa.hosted.provision.provisioning.CapacityPolicies; -import com.yahoo.vespa.hosted.provision.provisioning.AllocationParams; import java.time.Clock; import java.time.Duration; @@ -47,8 +46,9 @@ public class ClusterModel { // TODO: Measure this, and only take it into account with queries private static final double fixedCpuCostFraction = 0.1; - private final AllocationParams params; + private final NodeRepository nodeRepository; private final Application application; + private final ClusterSpec clusterSpec; private final Cluster cluster; private final AllocatableResources current; @@ -74,28 +74,31 @@ public class ClusterModel { private Double maxQueryGrowthRate = null; private OptionalDouble averageQueryRate = null; - public ClusterModel(AllocationParams params, + public ClusterModel(NodeRepository nodeRepository, Application application, + ClusterSpec clusterSpec, Cluster cluster, NodeList clusterNodes, AllocatableResources current, MetricsDb metricsDb, Clock clock) { - this.params = params; + this.nodeRepository = nodeRepository; this.application = application; + this.clusterSpec = clusterSpec; this.cluster = cluster; this.nodes = clusterNodes; this.current = current; this.clock = clock; - this.scalingDuration = cluster.scalingDuration(params.cluster()); - this.allocationDuration = cluster.allocationDuration(params.cluster()); + this.scalingDuration = cluster.scalingDuration(clusterSpec); + this.allocationDuration = cluster.allocationDuration(clusterSpec); this.clusterTimeseries = metricsDb.getClusterTimeseries(application.id(), cluster.id()); this.nodeTimeseries = new ClusterNodesTimeseries(scalingDuration(), cluster, nodes, metricsDb); this.at = clock.instant(); } - ClusterModel(AllocationParams params, + ClusterModel(NodeRepository nodeRepository, Application application, + ClusterSpec clusterSpec, Cluster cluster, AllocatableResources current, Clock clock, @@ -103,8 +106,9 @@ public class ClusterModel { Duration allocationDuration, ClusterTimeseries clusterTimeseries, ClusterNodesTimeseries nodeTimeseries) { - this.params = params; + this.nodeRepository = nodeRepository; this.application = application; + this.clusterSpec = clusterSpec; this.cluster = cluster; this.nodes = NodeList.of(); this.current = current; @@ -118,7 +122,7 @@ public class ClusterModel { } public Application application() { return application; } - public ClusterSpec clusterSpec() { return params.cluster(); } + public ClusterSpec clusterSpec() { return clusterSpec; } public AllocatableResources current() { return current; } private ClusterNodesTimeseries nodeTimeseries() { return nodeTimeseries; } private ClusterTimeseries clusterTimeseries() { return clusterTimeseries; } @@ -140,7 +144,7 @@ public class ClusterModel { public Duration allocationDuration() { return allocationDuration; } public boolean isContent() { - return params.cluster().type().isContent(); + return clusterSpec.type().isContent(); } /** Returns the predicted duration of data redistribution in this cluster. */ @@ -165,7 +169,7 @@ public class ClusterModel { } public boolean isExclusive() { - return params.exclusiveAllocation(); + return nodeRepository.exclusiveAllocation(clusterSpec); } /** Returns the relative load adjustment that should be made to this cluster given available measurements. */ @@ -273,7 +277,7 @@ public class ClusterModel { * cluster.bcpGroupInfo().growthRateHeadroom() * trafficShiftHeadroom(); double neededTotalVcpuPerGroup = cluster.bcpGroupInfo().cpuCostPerQuery() * targetQueryRateToHandle / groupCount() + ( 1 - cpu.queryFraction()) * cpu.idealLoad() * - (params.cluster().type().isContainer() ? 1 : groupSize()); + (clusterSpec.type().isContainer() ? 1 : groupSize()); // Max 1: Only use bcp group info if it indicates that we need to scale *up* double cpuAdjustment = Math.max(1.0, neededTotalVcpuPerGroup / currentClusterTotalVcpuPerGroup); return ideal.withCpu(ideal.cpu() / cpuAdjustment); @@ -337,7 +341,7 @@ public class ClusterModel { /** Returns the headroom for growth during organic traffic growth as a multiple of current resources. */ private double growthRateHeadroom() { - if ( ! params.nodeRepository().zone().environment().isProduction()) return 1; + if ( ! nodeRepository.zone().environment().isProduction()) return 1; double growthRateHeadroom = 1 + maxQueryGrowthRate() * scalingDuration().toMinutes(); // Cap headroom at 10% above the historical observed peak if (queryFractionOfMax() != 0) @@ -351,7 +355,7 @@ public class ClusterModel { * as a multiple of current resources. */ private double trafficShiftHeadroom() { - if ( ! params.nodeRepository().zone().environment().isProduction()) return 1; + if ( ! nodeRepository.zone().environment().isProduction()) return 1; if (canRescaleWithinBcpDeadline()) return 1; double trafficShiftHeadroom; if (application.status().maxReadShare() == 0) // No traffic fraction data @@ -387,7 +391,7 @@ public class ClusterModel { OptionalDouble costPerQuery() { if (averageQueryRate().isEmpty() || averageQueryRate().getAsDouble() == 0.0) return OptionalDouble.empty(); // TODO: Query rate should generally be sampled at the time where we see the peak resource usage - int fanOut = params.cluster().type().isContainer() ? 1 : groupSize(); + int fanOut = clusterSpec.type().isContainer() ? 1 : groupSize(); return OptionalDouble.of(peakLoad().cpu() * cpu.queryFraction() * fanOut * nodes.not().retired().first().get().resources().vcpu() / averageQueryRate().getAsDouble() / groupCount()); } @@ -410,8 +414,8 @@ public class ClusterModel { private class MemoryModel { double idealLoad() { - if (params.cluster().type().isContainer()) return idealContainerMemoryLoad; - if (params.cluster().type() == ClusterSpec.Type.admin) return idealContainerMemoryLoad; // Not autoscaled, but ideal shown in console + if (clusterSpec.type().isContainer()) return idealContainerMemoryLoad; + if (clusterSpec.type() == ClusterSpec.Type.admin) return idealContainerMemoryLoad; // Not autoscaled, but ideal shown in console return idealContentMemoryLoad; } @@ -428,12 +432,16 @@ public class ClusterModel { double averageReal() { if (nodes.isEmpty()) { // we're estimating - var initialResources = new CapacityPolicies(params.nodeRepository()).specifyFully(params, cluster.minResources().nodeResources()); - return params.nodeRepository().resourcesCalculator().requestToReal(initialResources, params.exclusiveAllocation(), false).memoryGb(); + var initialResources = new CapacityPolicies(nodeRepository).specifyFully(cluster.minResources().nodeResources(), + clusterSpec, + application.id()); + return nodeRepository.resourcesCalculator().requestToReal(initialResources, + nodeRepository.exclusiveAllocation(clusterSpec), + false).memoryGb(); } else { return nodes.stream() - .mapToDouble(node -> params.nodeRepository().resourcesCalculator().realResourcesOf(node, params.nodeRepository()).memoryGb()) + .mapToDouble(node -> nodeRepository.resourcesCalculator().realResourcesOf(node, nodeRepository).memoryGb()) .average() .getAsDouble(); } @@ -446,7 +454,7 @@ public class ClusterModel { double idealLoad() { // Stateless clusters are not expected to consume more disk over time - // if they do it is due to logs which will be rotated away right before the disk is full - return params.cluster().isStateful() ? idealContentDiskLoad : idealContainerDiskLoad; + return clusterSpec.isStateful() ? idealContentDiskLoad : idealContainerDiskLoad; } } |