diff options
Diffstat (limited to 'node-repository/src/main/java/com/yahoo')
4 files changed, 33 insertions, 17 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Cluster.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Cluster.java index 90133f7499e..c996daf588b 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Cluster.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Cluster.java @@ -3,9 +3,8 @@ package com.yahoo.vespa.hosted.provision.applications; import com.yahoo.config.provision.ClusterResources; import com.yahoo.config.provision.ClusterSpec; -import com.yahoo.config.provision.NodeResources; -import com.yahoo.vespa.hosted.provision.lb.LoadBalancer; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -19,11 +18,15 @@ import java.util.Optional; */ public class Cluster { + public static final int maxScalingEvents = 15; + private final ClusterSpec.Id id; private final boolean exclusive; private final ClusterResources min, max; private final Optional<ClusterResources> suggested; private final Optional<ClusterResources> target; + + /** The maxScalingEvents last scaling events of this, sorted by increasing time (newest last) */ private final List<ScalingEvent> scalingEvents; private final String autoscalingStatus; @@ -45,7 +48,7 @@ public class Cluster { this.target = Optional.empty(); else this.target = targetResources; - this.scalingEvents = scalingEvents; + this.scalingEvents = List.copyOf(scalingEvents); this.autoscalingStatus = autoscalingStatus; } @@ -97,8 +100,10 @@ public class Cluster { } public Cluster with(ScalingEvent scalingEvent) { - // NOTE: We're just storing the latest scaling event so far - return new Cluster(id, exclusive, min, max, suggested, target, List.of(scalingEvent), autoscalingStatus); + List<ScalingEvent> scalingEvents = new ArrayList<>(this.scalingEvents); + scalingEvents.add(scalingEvent); + prune(scalingEvents); + return new Cluster(id, exclusive, min, max, suggested, target, scalingEvents, autoscalingStatus); } public Cluster withAutoscalingStatus(String autoscalingStatus) { @@ -120,4 +125,9 @@ public class Cluster { return "cluster '" + id + "'"; } + private void prune(List<ScalingEvent> scalingEvents) { + while (scalingEvents.size() > maxScalingEvents) + scalingEvents.remove(0); + } + } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java index 3a01e2c7287..66c6d68931c 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java @@ -200,6 +200,13 @@ public class Autoscaler { private static Advice scaleTo(ClusterResources target) { return new Advice(Optional.of(target), true, "Scaling due to load changes"); } + + @Override + public String toString() { + return "autoscaling advice: " + + (present ? (target.isPresent() ? "Scale to " + target.get() : "Don't scale") : " None"); + } + } } diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterTimeseries.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterTimeseries.java index 2b4ba3fbbcb..769174a188e 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterTimeseries.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/ClusterTimeseries.java @@ -60,8 +60,8 @@ public class ClusterTimeseries { List<NodeTimeseries> nodeTimeseries, NodeRepository nodeRepository) { Map<String, Instant> startTimePerHost = new HashMap<>(); - if ( ! cluster.scalingEvents().isEmpty()) { - var deployment = cluster.scalingEvents().get(cluster.scalingEvents().size() - 1); + if (cluster.lastScalingEvent().isPresent()) { + var deployment = cluster.lastScalingEvent().get(); for (Node node : clusterNodes) { startTimePerHost.put(node.hostname(), nodeRepository.clock().instant()); // Discard all unless we can prove otherwise var nodeGenerationMeasurements = diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java index 809c54146d0..1197a01b9c7 100644 --- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java +++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java @@ -14,6 +14,7 @@ import com.yahoo.vespa.hosted.provision.applications.Cluster; import com.yahoo.vespa.hosted.provision.autoscale.AllocatableClusterResources; import com.yahoo.vespa.hosted.provision.autoscale.Autoscaler; import com.yahoo.vespa.hosted.provision.autoscale.MetricsDb; +import com.yahoo.vespa.orchestrator.status.ApplicationLock; import java.time.Duration; import java.util.List; @@ -66,19 +67,17 @@ public class AutoscalingMaintainer extends NodeRepositoryMaintainer { List<Node> clusterNodes, MaintenanceDeployment deployment) { Application application = nodeRepository().applications().get(applicationId).orElse(new Application(applicationId)); - Optional<Cluster> cluster = application.cluster(clusterId); - if (cluster.isEmpty()) return; + if (application.cluster(clusterId).isEmpty()) return; + Cluster cluster = application.cluster(clusterId).get(); - var advice = autoscaler.autoscale(cluster.get(), clusterNodes); - - application = application.with(cluster.get().withAutoscalingStatus(advice.reason())); + var advice = autoscaler.autoscale(cluster, clusterNodes); + cluster = cluster.withAutoscalingStatus(advice.reason()); if (advice.isEmpty()) { - applications().put(application, deployment.applicationLock().get()); - } - else if ( ! cluster.get().targetResources().equals(advice.target())) { - applications().put(application.with(cluster.get().withTarget(advice.target())), deployment.applicationLock().get()); + applications().put(application.with(cluster), deployment.applicationLock().get()); + } else if (!cluster.targetResources().equals(advice.target())) { + applications().put(application.with(cluster.withTarget(advice.target())), deployment.applicationLock().get()); if (advice.target().isPresent()) { - logAutoscaling(advice.target().get(), applicationId, cluster.get(), clusterNodes); + logAutoscaling(advice.target().get(), applicationId, cluster, clusterNodes); deployment.activate(); } } |