aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@verizonmedia.com>2020-03-27 15:02:03 +0100
committerJon Bratseth <bratseth@verizonmedia.com>2020-03-27 15:02:03 +0100
commitb18e2939b6632e7bf02cc12dea096dabecb9e754 (patch)
tree6c6657cd78bf60e1f862c2308c329ef32843857b
parentbcaf74cc7cddd26f315ea9c60ceb8a5f9b665168 (diff)
Activate autoscaling
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Application.java36
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java5
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Cluster.java12
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/AllocatableClusterResources.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/autoscale/Autoscaler.java3
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/AutoscalingMaintainer.java44
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java19
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java3
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java11
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTest.java41
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingTester.java9
11 files changed, 148 insertions, 39 deletions
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Application.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Application.java
index 7dd2dc7be17..e56e426b499 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Application.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Application.java
@@ -18,20 +18,42 @@ import java.util.Optional;
*/
public class Application {
- private Map<ClusterSpec.Id, Cluster> clusters = new HashMap<>();
+ private final Map<ClusterSpec.Id, Cluster> clusters;
+
+ public Application() {
+ this(Map.of());
+ }
+
+ private Application(Map<ClusterSpec.Id, Cluster> clusters) {
+ this.clusters = Map.copyOf(clusters);
+ }
/** Returns the cluster with the given id or null if none */
public Cluster cluster(ClusterSpec.Id id) { return clusters.get(id); }
+ public Application with(ClusterSpec.Id id, Cluster cluster) {
+ Map<ClusterSpec.Id, Cluster> clusters = new HashMap<>(this.clusters);
+ clusters.put(id, cluster);
+ return new Application(clusters);
+ }
+
/**
- * Sets the min and max resource limits of the given cluster.
- * This will create the cluster with these limits if it does not exist.
+ * Returns an application with the given cluster having the min and max resource limits of the given cluster.
* If the cluster has a target which is not inside the new limits, the target is removed.
*/
- public void setClusterLimits(ClusterSpec.Id id, ClusterResources min, ClusterResources max, Mutex applicationLock) {
- Cluster cluster = clusters.computeIfAbsent(id, clusterId -> new Cluster(min, max, Optional.empty()));
- if (cluster.targetResources().isPresent() && ! cluster.targetResources().get().isWithin(min, max))
- clusters.put(id, cluster.withoutTarget());
+ public Application withClusterLimits(ClusterSpec.Id id, ClusterResources min, ClusterResources max) {
+ Cluster cluster = clusters.get(id);
+ return with(id, new Cluster(min, max, cluster == null ? Optional.empty() : cluster.targetResources()));
+ }
+
+ /**
+ * Returns an application with the given target for the given cluster,
+ * if it exists and the target is within the bounds
+ */
+ public Application withClusterTarget(ClusterSpec.Id id, ClusterResources target) {
+ Cluster cluster = clusters.get(id);
+ if (cluster == null) return this;
+ return with(id, cluster.withTarget(target));
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java
index 1409857df1a..879fcc5f6cb 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.hosted.provision.applications;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.transaction.Mutex;
import java.util.concurrent.ConcurrentHashMap;
@@ -21,4 +22,8 @@ public class Applications {
return applications.computeIfAbsent(applicationId, id -> create ? new Application() : null);
}
+ public void set(ApplicationId id, Application application, Mutex applicationLock) {
+ applications.put(id, application);
+ }
+
}
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 d4f7f10abfd..6ff827ac92b 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,6 +3,7 @@ package com.yahoo.vespa.hosted.provision.applications;
import com.yahoo.config.provision.ClusterResources;
+import java.util.Objects;
import java.util.Optional;
/**
@@ -18,9 +19,14 @@ public class Cluster {
private final Optional<ClusterResources> targetResources;
Cluster(ClusterResources minResources, ClusterResources maxResources, Optional<ClusterResources> targetResources) {
- this.minResources = minResources;
- this.maxResources = maxResources;
- this.targetResources = targetResources;
+ this.minResources = Objects.requireNonNull(minResources);
+ this.maxResources = Objects.requireNonNull(maxResources);
+ Objects.requireNonNull(targetResources);
+
+ if (targetResources.isPresent() && ! targetResources.get().isWithin(minResources, maxResources))
+ this.targetResources = Optional.empty();
+ else
+ this.targetResources = targetResources;
}
/** Returns the configured minimal resources in this cluster */
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 7a36103f337..f553a4c76a4 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
@@ -73,6 +73,10 @@ public class AllocatableClusterResources {
public int groups() { return groups; }
public ClusterSpec.Type clusterType() { return clusterType; }
+ public ClusterResources toAdvertisedClusterResources() {
+ return new ClusterResources(nodes, groups, advertisedResources);
+ }
+
@Override
public String toString() {
return "$" + cost() + ": " + realResources();
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 dc9699a7a0b..6612525685a 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
@@ -9,6 +9,7 @@ import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.host.FlavorOverrides;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
+import com.yahoo.vespa.hosted.provision.applications.Cluster;
import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator;
import com.yahoo.vespa.hosted.provision.provisioning.NodeResourceLimits;
@@ -66,7 +67,7 @@ public class Autoscaler {
* @param clusterNodes the list of all the active nodes in a cluster
* @return a new suggested allocation for this cluster, or empty if it should not be rescaled at this time
*/
- public Optional<AllocatableClusterResources> autoscale(List<Node> clusterNodes) {
+ public Optional<AllocatableClusterResources> autoscale(Cluster cluster, List<Node> clusterNodes) {
if (clusterNodes.stream().anyMatch(node -> node.status().wantToRetire() ||
node.allocation().get().membership().retired() ||
node.allocation().get().isRemovable())) {
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 3f26725da15..064c7db5e60 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
@@ -6,8 +6,11 @@ import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Deployer;
import com.yahoo.config.provision.NodeResources;
+import com.yahoo.transaction.Mutex;
import com.yahoo.vespa.hosted.provision.Node;
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.autoscale.AllocatableClusterResources;
import com.yahoo.vespa.hosted.provision.autoscale.Autoscaler;
import com.yahoo.vespa.hosted.provision.autoscale.NodeMetricsDb;
@@ -52,22 +55,49 @@ public class AutoscalingMaintainer extends Maintainer {
private void autoscale(ApplicationId application, List<Node> applicationNodes) {
try (MaintenanceDeployment deployment = new MaintenanceDeployment(application, deployer, nodeRepository())) {
if ( ! deployment.isValid()) return; // Another config server will consider this application
- nodesByCluster(applicationNodes).forEach((clusterId, clusterNodes) -> autoscale(application, clusterId, clusterNodes));
+ nodesByCluster(applicationNodes).forEach((clusterId, clusterNodes) -> autoscale(application, clusterId, clusterNodes, deployment));
}
}
- private void autoscale(ApplicationId application, ClusterSpec.Id clusterId, List<Node> clusterNodes) {
- Optional<AllocatableClusterResources> target = autoscaler.autoscale(clusterNodes);
- if (target.isEmpty()) return;
+ private void autoscale(ApplicationId applicationId,
+ ClusterSpec.Id clusterId,
+ List<Node> clusterNodes,
+ MaintenanceDeployment deployment) {
+ Application application = nodeRepository().applications().get(applicationId, true);
+ Cluster cluster = application.cluster(clusterId);
+ if (cluster == null) return; // no information on limits for this cluster
+ Optional<AllocatableClusterResources> target = autoscaler.autoscale(cluster, clusterNodes);
+ if (target.isEmpty()) return; // current resources are fine
+ if (cluster.minResources().equals(cluster.maxResources())) // autoscaling is deactivated
+ logAutoscaleSuggestion(target.get(), applicationId, clusterId, clusterNodes);
+ else
+ autoscaleTo(target.get(), applicationId, clusterId, application, deployment);
+ }
+
+ private void autoscaleTo(AllocatableClusterResources target,
+ ApplicationId applicationId,
+ ClusterSpec.Id clusterId,
+ Application application,
+ MaintenanceDeployment deployment) {
+ nodeRepository().applications().set(applicationId,
+ application.withClusterTarget(clusterId, target.toAdvertisedClusterResources()),
+ deployment.applicationLock().get());
+ deployment.activate();
+ }
+
+ private void logAutoscaleSuggestion(AllocatableClusterResources target,
+ ApplicationId application,
+ ClusterSpec.Id clusterId,
+ List<Node> clusterNodes) {
Instant lastLogTime = lastLogged.get(new Pair<>(application, clusterId));
if (lastLogTime != null && lastLogTime.isAfter(nodeRepository().clock().instant().minus(Duration.ofHours(1)))) return;
- int currentGroups = (int) clusterNodes.stream().map(node -> node.allocation().get().membership().cluster().group()).distinct().count();
+ int currentGroups = (int)clusterNodes.stream().map(node -> node.allocation().get().membership().cluster().group()).distinct().count();
ClusterSpec.Type clusterType = clusterNodes.get(0).allocation().get().membership().cluster().type();
- log.info("Autoscale: " + application + " " + clusterType + " " + clusterId +
+ log.info("Scaling suggestion: " + application + " " + clusterType + " " + clusterId +
"\nfrom " + toString(clusterNodes.size(), currentGroups, clusterNodes.get(0).flavor().resources()) +
- "\nto " + toString(target.get().nodes(), target.get().groups(), target.get().advertisedResources()));
+ "\nto " + toString(target.nodes(), target.groups(), target.advertisedResources()));
lastLogged.put(new Pair<>(application, clusterId), nodeRepository().clock().instant());
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java
index 856de2609be..c21c9d68c8a 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/maintenance/MaintenanceDeployment.java
@@ -36,10 +36,8 @@ class MaintenanceDeployment implements Closeable {
public MaintenanceDeployment(ApplicationId application, Deployer deployer, NodeRepository nodeRepository) {
this.application = application;
Optional<Mutex> lock = tryLock(application, nodeRepository);
-
try {
deployment = tryDeployment(lock, application, deployer, nodeRepository);
-
this.lock = lock;
lock = Optional.empty();
} finally {
@@ -52,6 +50,16 @@ class MaintenanceDeployment implements Closeable {
return deployment.isPresent();
}
+ /**
+ * Returns the application lock held by this, or empty if it is not held.
+ *
+ * @throws IllegalStateException id this is called when closed
+ */
+ public Optional<Mutex> applicationLock() {
+ if (closed) throw new IllegalStateException(this + "is closed");
+ return lock;
+ }
+
public boolean prepare() {
return doStep(() -> deployment.get().prepare());
}
@@ -61,7 +69,7 @@ class MaintenanceDeployment implements Closeable {
}
private boolean doStep(Runnable action) {
- if (closed) throw new IllegalStateException("Deployment of '" + application + "' is closed");
+ if (closed) throw new IllegalStateException(this + "' is closed");
if ( ! isValid()) return false;
try {
action.run();
@@ -101,4 +109,9 @@ class MaintenanceDeployment implements Closeable {
closed = true;
}
+ @Override
+ public String toString() {
+ return "deployment of " + application;
+ }
+
}
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 083f8db5aa5..6ae89f6c9ed 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
@@ -148,7 +148,8 @@ public class NodeRepositoryProvisioner implements Provisioner {
private ClusterResources decideTargetResources(ApplicationId applicationId, ClusterSpec.Id clusterId, Capacity requested) {
try (Mutex lock = nodeRepository.lock(applicationId)) {
Application application = nodeRepository.applications().get(applicationId, true);
- application.setClusterLimits(clusterId, requested.minResources(), requested.maxResources(), lock);
+ application = application.withClusterLimits(clusterId, requested.minResources(), requested.maxResources());
+ nodeRepository.applications().set(applicationId, application, lock);
return application.cluster(clusterId).targetResources()
.orElse(currentResources(applicationId, clusterId, requested)
.orElse(requested.minResources()));
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java
index d154af4f025..f02acdc1fca 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/autoscale/AutoscalingIntegrationTest.java
@@ -2,12 +2,15 @@
package com.yahoo.vespa.hosted.provision.autoscale;
import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.ClusterResources;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.test.ManualClock;
import com.yahoo.vespa.hosted.provision.Node;
+import com.yahoo.vespa.hosted.provision.applications.Application;
+import com.yahoo.vespa.hosted.provision.applications.Cluster;
import com.yahoo.vespa.hosted.provision.provisioning.HostResourcesCalculator;
import com.yahoo.vespa.hosted.provision.testutils.OrchestratorMock;
import org.junit.Test;
@@ -47,7 +50,13 @@ public class AutoscalingIntegrationTest {
tester.nodeMetricsDb().gc(tester.clock());
}
- var scaledResources = autoscaler.autoscale(tester.nodeRepository().getNodes(application1));
+ ClusterResources min = new ClusterResources(2, 1, nodes);
+ ClusterResources max = new ClusterResources(2, 1, nodes);
+
+ Application application = tester.nodeRepository().applications().get(application1, true).withClusterLimits(cluster1.id(), min, max);
+ tester.nodeRepository().applications().set(application1, application, tester.nodeRepository().lock(application1));
+ var scaledResources = autoscaler.autoscale(application.cluster(cluster1.id()),
+ tester.nodeRepository().getNodes(application1));
assertTrue(scaledResources.isPresent());
}
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 39259bf44f8..f3b6606a970 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
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.autoscale;
import com.google.common.collect.Sets;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.CloudName;
+import com.yahoo.config.provision.ClusterResources;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
@@ -31,6 +32,8 @@ public class AutoscalingTest {
@Test
public void testAutoscalingSingleContentGroup() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
+ ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
+ ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1));
AutoscalingTester tester = new AutoscalingTester(resources);
ApplicationId application1 = tester.applicationId("application1");
@@ -39,37 +42,39 @@ public class AutoscalingTest {
// deploy
tester.deploy(application1, cluster1, 5, 1, resources);
- assertTrue("No measurements -> No change", tester.autoscale(application1).isEmpty());
+ assertTrue("No measurements -> No change", tester.autoscale(application1, cluster1.id(), min, max).isEmpty());
tester.addMeasurements(Resource.cpu, 0.25f, 1f, 60, application1);
- assertTrue("Too few measurements -> No change", tester.autoscale(application1).isEmpty());
+ assertTrue("Too few measurements -> No change", tester.autoscale(application1, cluster1.id(), min, max).isEmpty());
tester.addMeasurements(Resource.cpu, 0.25f, 1f, 60, application1);
AllocatableClusterResources scaledResources = tester.assertResources("Scaling up since resource usage is too high",
15, 1, 1.3, 28.6, 28.6,
- tester.autoscale(application1));
+ tester.autoscale(application1, cluster1.id(), min, max));
tester.deploy(application1, cluster1, scaledResources);
- assertTrue("Cluster in flux -> No further change", tester.autoscale(application1).isEmpty());
+ assertTrue("Cluster in flux -> No further change", tester.autoscale(application1, cluster1.id(), min, max).isEmpty());
tester.deactivateRetired(application1, cluster1, scaledResources);
tester.addMeasurements(Resource.cpu, 0.8f, 1f, 3, application1);
assertTrue("Load change is large, but insufficient measurements for new config -> No change",
- tester.autoscale(application1).isEmpty());
+ tester.autoscale(application1, cluster1.id(), min, max).isEmpty());
tester.addMeasurements(Resource.cpu, 0.19f, 1f, 100, application1);
- assertEquals("Load change is small -> No change", Optional.empty(), tester.autoscale(application1));
+ assertEquals("Load change is small -> No change", Optional.empty(), tester.autoscale(application1, cluster1.id(), min, max));
tester.addMeasurements(Resource.cpu, 0.1f, 1f, 120, application1);
tester.assertResources("Scaling down since resource usage has gone down significantly",
26, 1, 0.6, 16.0, 16.0,
- tester.autoscale(application1));
+ tester.autoscale(application1, cluster1.id(), min, max));
}
/** We prefer fewer nodes for container clusters as (we assume) they all use the same disk and memory */
@Test
public void testAutoscalingSingleContainerGroup() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
+ ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
+ ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1));
AutoscalingTester tester = new AutoscalingTester(resources);
ApplicationId application1 = tester.applicationId("application1");
@@ -81,7 +86,7 @@ public class AutoscalingTest {
tester.addMeasurements(Resource.cpu, 0.25f, 1f, 120, application1);
AllocatableClusterResources scaledResources = tester.assertResources("Scaling up since cpu usage is too high",
7, 1, 2.6, 80.0, 80.0,
- tester.autoscale(application1));
+ tester.autoscale(application1, cluster1.id(), min, max));
tester.deploy(application1, cluster1, scaledResources);
tester.deactivateRetired(application1, cluster1, scaledResources);
@@ -89,12 +94,14 @@ public class AutoscalingTest {
tester.addMeasurements(Resource.cpu, 0.1f, 1f, 120, application1);
tester.assertResources("Scaling down since cpu usage has gone down",
4, 1, 2.4, 68.6, 68.6,
- tester.autoscale(application1));
+ tester.autoscale(application1, cluster1.id(), min, max));
}
@Test
public void testAutoscalingGroupSize1() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
+ ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
+ ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1));
AutoscalingTester tester = new AutoscalingTester(resources);
ApplicationId application1 = tester.applicationId("application1");
@@ -105,12 +112,14 @@ public class AutoscalingTest {
tester.addMeasurements(Resource.cpu, 0.25f, 1f, 120, application1);
tester.assertResources("Scaling up since resource usage is too high",
7, 7, 2.5, 80.0, 80.0,
- tester.autoscale(application1));
+ tester.autoscale(application1, cluster1.id(), min, max));
}
@Test
public void testAutoscalingGroupSize3() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
+ ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
+ ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1));
AutoscalingTester tester = new AutoscalingTester(resources);
ApplicationId application1 = tester.applicationId("application1");
@@ -121,12 +130,14 @@ public class AutoscalingTest {
tester.addMeasurements(Resource.cpu, 0.22f, 1f, 120, application1);
tester.assertResources("Scaling up since resource usage is too high",
9, 3, 2.7, 83.3, 83.3,
- tester.autoscale(application1));
+ tester.autoscale(application1, cluster1.id(), min, max));
}
@Test
public void testAutoscalingAvoidsIllegalConfigurations() {
NodeResources resources = new NodeResources(3, 100, 100, 1);
+ ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
+ ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1));
AutoscalingTester tester = new AutoscalingTester(resources);
ApplicationId application1 = tester.applicationId("application1");
@@ -137,11 +148,13 @@ public class AutoscalingTest {
tester.addMeasurements(Resource.memory, 0.02f, 1f, 120, application1);
tester.assertResources("Scaling down",
6, 1, 3.0, 4.0, 100.0,
- tester.autoscale(application1));
+ tester.autoscale(application1, cluster1.id(), min, max));
}
@Test
public void testAutoscalingAws() {
+ ClusterResources min = new ClusterResources( 2, 1, new NodeResources(1, 1, 1, 1));
+ ClusterResources max = new ClusterResources(20, 1, new NodeResources(100, 1000, 1000, 1));
List<Flavor> flavors = new ArrayList<>();
flavors.add(new Flavor("aws-xlarge", new NodeResources(3, 200, 100, 1, NodeResources.DiskSpeed.fast, NodeResources.StorageType.remote)));
flavors.add(new Flavor("aws-large", new NodeResources(3, 150, 100, 1, NodeResources.DiskSpeed.fast, NodeResources.StorageType.remote)));
@@ -160,7 +173,7 @@ public class AutoscalingTest {
tester.addMeasurements(Resource.memory, 0.9f, 0.6f, 120, application1);
AllocatableClusterResources scaledResources = tester.assertResources("Scaling up since resource usage is too high.",
8, 1, 3, 83, 34.3,
- tester.autoscale(application1));
+ tester.autoscale(application1, cluster1.id(), min, max));
tester.deploy(application1, cluster1, scaledResources);
tester.deactivateRetired(application1, cluster1, scaledResources);
@@ -168,7 +181,7 @@ public class AutoscalingTest {
tester.addMeasurements(Resource.memory, 0.3f, 0.6f, 1000, application1);
tester.assertResources("Scaling down since resource usage has gone down",
5, 1, 3, 83, 36,
- tester.autoscale(application1));
+ tester.autoscale(application1, cluster1.id(), min, max));
}
}
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 efb97841623..8043d5b2d39 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
@@ -20,6 +20,7 @@ import com.yahoo.vespa.flags.Flags;
import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeRepository;
+import com.yahoo.vespa.hosted.provision.applications.Application;
import com.yahoo.vespa.hosted.provision.node.Agent;
import com.yahoo.vespa.hosted.provision.node.IP;
import com.yahoo.vespa.hosted.provision.provisioning.FatalProvisioningException;
@@ -140,8 +141,12 @@ class AutoscalingTester {
}
}
- public Optional<AllocatableClusterResources> autoscale(ApplicationId application) {
- return autoscaler.autoscale(nodeRepository().getNodes(application, Node.State.active));
+ public Optional<AllocatableClusterResources> autoscale(ApplicationId applicationId, ClusterSpec.Id clusterId,
+ ClusterResources min, ClusterResources max) {
+ Application application = nodeRepository().applications().get(applicationId, true).withClusterLimits(clusterId, min, max);
+ nodeRepository().applications().set(applicationId, application, nodeRepository().lock(applicationId));
+ return autoscaler.autoscale(application.cluster(clusterId),
+ nodeRepository().getNodes(applicationId, Node.State.active));
}
public AllocatableClusterResources assertResources(String message,