Skip to content

Commit fa4fe14

Browse files
authored
feat: cluster autoscaling (#1092)
* feat: cluster autoscaling * lint * test * test * test * test * fix tests * fix test * use new instance for test * lint * add nonnull * add nonnull * add nonnull
1 parent d340be6 commit fa4fe14

File tree

10 files changed

+972
-5
lines changed

10 files changed

+972
-5
lines changed

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/BigtableInstanceAdminClient.java

+115-4
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@
2424
import com.google.bigtable.admin.v2.DeleteAppProfileRequest;
2525
import com.google.bigtable.admin.v2.GetAppProfileRequest;
2626
import com.google.bigtable.admin.v2.ListAppProfilesRequest;
27+
import com.google.bigtable.admin.v2.PartialUpdateClusterRequest;
2728
import com.google.cloud.Policy;
2829
import com.google.cloud.Policy.DefaultMarshaller;
2930
import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPage;
3031
import com.google.cloud.bigtable.admin.v2.BaseBigtableInstanceAdminClient.ListAppProfilesPagedResponse;
3132
import com.google.cloud.bigtable.admin.v2.internal.NameUtil;
3233
import com.google.cloud.bigtable.admin.v2.models.AppProfile;
3334
import com.google.cloud.bigtable.admin.v2.models.Cluster;
35+
import com.google.cloud.bigtable.admin.v2.models.ClusterAutoscalingConfig;
3436
import com.google.cloud.bigtable.admin.v2.models.CreateAppProfileRequest;
3537
import com.google.cloud.bigtable.admin.v2.models.CreateClusterRequest;
3638
import com.google.cloud.bigtable.admin.v2.models.CreateInstanceRequest;
@@ -49,6 +51,7 @@
4951
import com.google.iam.v1.TestIamPermissionsRequest;
5052
import com.google.iam.v1.TestIamPermissionsResponse;
5153
import com.google.protobuf.Empty;
54+
import com.google.protobuf.util.FieldMaskUtil;
5255
import java.io.IOException;
5356
import java.util.Arrays;
5457
import java.util.List;
@@ -660,8 +663,10 @@ public List<Cluster> apply(com.google.bigtable.admin.v2.ListClustersResponse pro
660663
}
661664

662665
/**
663-
* Modifies the cluster's node count. Please note that only clusters that belong to a production
664-
* instance can be resized.
666+
* Modifies the cluster's node count for manual scaling. If autoscaling is already enabled, manual
667+
* scaling will be silently ignored. If you wish to disable autoscaling and enable manual scaling,
668+
* please use {@link BigtableInstanceAdminClient#disableClusterAutoscaling(String, String, int)}
669+
* instead. Please note that only clusters that belong to a production instance can be resized.
665670
*
666671
* <p>Sample code:
667672
*
@@ -676,8 +681,11 @@ public Cluster resizeCluster(String instanceId, String clusterId, int numServeNo
676681
}
677682

678683
/**
679-
* Asynchronously modifies the cluster's node count. Please note that only clusters that belong to
680-
* a production instance can be resized.
684+
* Asynchronously modifies the cluster's node count for manual scaling. If autoscaling is already
685+
* enabled, manual scaling will be silently ignored. If you wish to disable autoscaling and enable
686+
* manual scaling, please use {@link BigtableInstanceAdminClient#disableClusterAutoscaling(String,
687+
* String, int)} instead. Please note that only clusters that belong to a production instance can
688+
* be resized.
681689
*
682690
* <pre>{@code
683691
* ApiFuture<Cluster> clusterFuture = client.resizeCluster("my-instance", "my-cluster", 30);
@@ -707,6 +715,109 @@ public Cluster apply(com.google.bigtable.admin.v2.Cluster proto) {
707715
MoreExecutors.directExecutor());
708716
}
709717

718+
/**
719+
* Modifies the cluster's autoscaling config. This will enable autoscaling and disable manual
720+
* scaling if the cluster is manually scaled. Please note that only clusters that belong to a
721+
* production instance can enable autoscaling.
722+
*
723+
* <p>Sample code:
724+
*
725+
* <pre>{@code
726+
* ClusterAutoscalingConfig clusterAutoscalingConfig =
727+
* ClusterAutoscalingConfig.of("my-instance", "my-cluster")
728+
* .setMinNodes(1)
729+
* .setMaxNodes(4)
730+
* .setCpuUtilizationTargetPercent(40);
731+
* Cluster cluster = client.updateClusterAutoscalingConfig(clusterAutoscalingConfig);
732+
* }</pre>
733+
*/
734+
public Cluster updateClusterAutoscalingConfig(
735+
@Nonnull ClusterAutoscalingConfig clusterAutoscalingConfig) {
736+
return ApiExceptions.callAndTranslateApiException(
737+
updateClusterAutoscalingConfigAsync(clusterAutoscalingConfig));
738+
}
739+
740+
/**
741+
* Asynchronously modifies the cluster's autoscaling config. This will enable autoscaling and
742+
* disable manual scaling if the cluster is manually scaled. Please note that only clusters that
743+
* belong to a production instance can enable autoscaling.
744+
*
745+
* <p>Sample code:
746+
*
747+
* <pre>{@code
748+
* ClusterAutoscalingConfig clusterAutoscalingConfig =
749+
* ClusterAutoscalingConfig.of(targetInstanceId, targetClusterId)
750+
* .setMinNodes(1)
751+
* .setMaxNodes(4)
752+
* .setCpuUtilizationTargetPercent(40);
753+
*
754+
* ApiFuture<Cluster> clusterApiFuture = client.updateClusterAutoscalingConfigAsync(clusterAutoscalingConfig);
755+
* Cluster cluster = clusterApiFuture.get();
756+
* }</pre>
757+
*/
758+
public ApiFuture<Cluster> updateClusterAutoscalingConfigAsync(
759+
@Nonnull ClusterAutoscalingConfig clusterAutoscalingConfig) {
760+
PartialUpdateClusterRequest proto = clusterAutoscalingConfig.toProto(projectId);
761+
762+
return ApiFutures.transform(
763+
stub.partialUpdateClusterOperationCallable().futureCall(proto),
764+
Cluster::fromProto,
765+
MoreExecutors.directExecutor());
766+
}
767+
768+
/**
769+
* Disables autoscaling and enables manual scaling by setting a static node count for the cluster.
770+
* Please note that only clusters that belong to a production instance can be resized.
771+
*
772+
* <p>Sample code:
773+
*
774+
* <pre>{@code
775+
* Cluster cluster = client.disableClusterAutoscaling("my-instance", "my-cluster", 3);
776+
* }</pre>
777+
*/
778+
public Cluster disableClusterAutoscaling(String instanceId, String clusterId, int staticSize) {
779+
return ApiExceptions.callAndTranslateApiException(
780+
disableClusterAutoscalingAsync(instanceId, clusterId, staticSize));
781+
}
782+
783+
/**
784+
* Asynchronously disables autoscaling and enables manual scaling by setting a static node count
785+
* for the cluster. Please note that only clusters that belong to a production instance can be
786+
* resized.
787+
*
788+
* <p>Sample code:
789+
*
790+
* <pre>{@code
791+
* ApiFuture<Cluster> clusterApiFuture = client.disableClusterAutoscalingAsync("my-instance", "my-cluster", 3);
792+
* Cluster cluster = clusterApiFuture.get();
793+
* }</pre>
794+
*/
795+
public ApiFuture<Cluster> disableClusterAutoscalingAsync(
796+
String instanceId, String clusterId, int staticSize) {
797+
String name = NameUtil.formatClusterName(projectId, instanceId, clusterId);
798+
799+
com.google.bigtable.admin.v2.Cluster request =
800+
com.google.bigtable.admin.v2.Cluster.newBuilder()
801+
.setName(name)
802+
.setServeNodes(staticSize)
803+
.setClusterConfig(
804+
com.google.bigtable.admin.v2.Cluster.ClusterConfig.getDefaultInstance())
805+
.build();
806+
807+
PartialUpdateClusterRequest partialUpdateClusterRequest =
808+
PartialUpdateClusterRequest.newBuilder()
809+
.setUpdateMask(
810+
FieldMaskUtil.fromStringList(
811+
com.google.bigtable.admin.v2.Cluster.class,
812+
Lists.newArrayList("cluster_config.cluster_autoscaling_config", "serve_nodes")))
813+
.setCluster(request)
814+
.build();
815+
return ApiFutures.transform(
816+
stub.partialUpdateClusterOperationCallable().futureCall(partialUpdateClusterRequest),
817+
Cluster::fromProto,
818+
MoreExecutors.directExecutor());
819+
}
820+
710821
/**
711822
* Deletes the specified cluster. Please note that an instance must have at least 1 cluster. To
712823
* remove the last cluster, please use {@link BigtableInstanceAdminClient#deleteInstance(String)}.

google-cloud-bigtable/src/main/java/com/google/cloud/bigtable/admin/v2/models/Cluster.java

+30
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,36 @@ public int getServeNodes() {
148148
return stateProto.getServeNodes();
149149
}
150150

151+
/** Get the minimum number of nodes to scale down to. */
152+
public int getAutoscalingMinServeNodes() {
153+
return stateProto
154+
.getClusterConfig()
155+
.getClusterAutoscalingConfig()
156+
.getAutoscalingLimits()
157+
.getMinServeNodes();
158+
}
159+
160+
/** Get the maximum number of nodes to scale up to. */
161+
public int getAutoscalingMaxServeNodes() {
162+
return stateProto
163+
.getClusterConfig()
164+
.getClusterAutoscalingConfig()
165+
.getAutoscalingLimits()
166+
.getMaxServeNodes();
167+
}
168+
169+
/**
170+
* Get the cpu utilization that the Autoscaler should be trying to achieve. This number is on a
171+
* scale from 0 (no utilization) to 100 (total utilization).
172+
*/
173+
public int getAutoscalingCpuPercentageTarget() {
174+
return stateProto
175+
.getClusterConfig()
176+
.getClusterAutoscalingConfig()
177+
.getAutoscalingTargets()
178+
.getCpuUtilizationPercent();
179+
}
180+
151181
/**
152182
* The type of storage used by this cluster to serve its parent instance's tables, unless
153183
* explicitly overridden.

0 commit comments

Comments
 (0)