diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/examples/external-grpc-cloud-provider-service/wrapper/wrapper.go b/cluster-autoscaler/cloudprovider/externalgrpc/examples/external-grpc-cloud-provider-service/wrapper/wrapper.go index 9f25e15478c6..d82a66a889d9 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/examples/external-grpc-cloud-provider-service/wrapper/wrapper.go +++ b/cluster-autoscaler/cloudprovider/externalgrpc/examples/external-grpc-cloud-provider-service/wrapper/wrapper.go @@ -20,10 +20,12 @@ import ( "context" "fmt" "reflect" + "time" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/durationpb" apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -388,8 +390,13 @@ func (w *Wrapper) NodeGroupTemplateNodeInfo(_ context.Context, req *protos.NodeG } return nil, err } + infoBytes, err := info.Node().Marshal() + if err != nil { + return nil, err + } return &protos.NodeGroupTemplateNodeInfoResponse{ - NodeInfo: info.Node(), + NodeInfo: info.Node(), + NodeBytes: infoBytes, }, nil } @@ -406,12 +413,37 @@ func (w *Wrapper) NodeGroupGetOptions(_ context.Context, req *protos.NodeGroupAu if pbDefaults == nil { return nil, fmt.Errorf("request fields were nil") } + + var scaleDownUnneededTime time.Duration + if d := pbDefaults.GetScaleDownUnneededDuration(); d != nil { + scaleDownUnneededTime = d.AsDuration() + } else { + // fall back to deprecated field removed in 1.35 + scaleDownUnneededTime = pbDefaults.GetScaleDownUnneededTime().Duration + } + + var scaleDownUnreadyTime time.Duration + if d := pbDefaults.GetScaleDownUnreadyDuration(); d != nil { + scaleDownUnreadyTime = d.AsDuration() + } else { + // fall back to deprecated field removed in 1.35 + scaleDownUnreadyTime = pbDefaults.GetScaleDownUnreadyTime().Duration + } + + var maxNodeProvisionTime time.Duration + if d := pbDefaults.GetMaxNodeProvisionDuration(); d != nil { + maxNodeProvisionTime = d.AsDuration() + } else { + // fall back to deprecated field removed in 1.35 + maxNodeProvisionTime = pbDefaults.GetMaxNodeProvisionTime().Duration + } + defaults := config.NodeGroupAutoscalingOptions{ ScaleDownUtilizationThreshold: pbDefaults.GetScaleDownGpuUtilizationThreshold(), ScaleDownGpuUtilizationThreshold: pbDefaults.GetScaleDownGpuUtilizationThreshold(), - ScaleDownUnneededTime: pbDefaults.GetScaleDownUnneededTime().Duration, - ScaleDownUnreadyTime: pbDefaults.GetScaleDownUnneededTime().Duration, - MaxNodeProvisionTime: pbDefaults.GetMaxNodeProvisionTime().Duration, + ScaleDownUnneededTime: scaleDownUnneededTime, + ScaleDownUnreadyTime: scaleDownUnreadyTime, + MaxNodeProvisionTime: maxNodeProvisionTime, ZeroOrMaxNodeScaling: pbDefaults.GetZeroOrMaxNodeScaling(), IgnoreDaemonSetsUtilization: pbDefaults.GetIgnoreDaemonSetsUtilization(), } @@ -438,6 +470,9 @@ func (w *Wrapper) NodeGroupGetOptions(_ context.Context, req *protos.NodeGroupAu MaxNodeProvisionTime: &metav1.Duration{ Duration: opts.MaxNodeProvisionTime, }, + ScaleDownUnneededDuration: durationpb.New(opts.ScaleDownUnneededTime), + ScaleDownUnreadyDuration: durationpb.New(opts.ScaleDownUnreadyTime), + MaxNodeProvisionDuration: durationpb.New(opts.MaxNodeProvisionTime), ZeroOrMaxNodeScaling: opts.ZeroOrMaxNodeScaling, IgnoreDaemonSetsUtilization: opts.IgnoreDaemonSetsUtilization, }, diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_node_group.go b/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_node_group.go index f62f3133eaac..cf9aab49c657 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_node_group.go +++ b/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_node_group.go @@ -23,6 +23,8 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/durationpb" + apiv1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/autoscaler/cluster-autoscaler/cloudprovider" @@ -227,7 +229,16 @@ func (n *NodeGroup) TemplateNodeInfo() (*framework.NodeInfo, error) { klog.V(1).Infof("Error on gRPC call NodeGroupTemplateNodeInfo: %v", err) return nil, err } - pbNodeInfo := res.GetNodeInfo() + var pbNodeInfo *apiv1.Node + if pbNodeBytes := res.GetNodeBytes(); pbNodeBytes != nil { + pbNodeInfo = &apiv1.Node{} + if err := pbNodeInfo.Unmarshal(pbNodeBytes); err != nil { + return nil, err + } + } else { + // Fall back to deprecated field removed in 1.35 + pbNodeInfo = res.GetNodeInfo() + } if pbNodeInfo == nil { n.nodeInfo = new(*framework.NodeInfo) return nil, nil @@ -283,6 +294,9 @@ func (n *NodeGroup) GetOptions(defaults config.NodeGroupAutoscalingOptions) (*co MaxNodeProvisionTime: &metav1.Duration{ Duration: defaults.MaxNodeProvisionTime, }, + ScaleDownUnneededDuration: durationpb.New(defaults.ScaleDownUnneededTime), + ScaleDownUnreadyDuration: durationpb.New(defaults.ScaleDownUnreadyTime), + MaxNodeProvisionDuration: durationpb.New(defaults.MaxNodeProvisionTime), ZeroOrMaxNodeScaling: defaults.ZeroOrMaxNodeScaling, IgnoreDaemonSetsUtilization: defaults.IgnoreDaemonSetsUtilization, }, @@ -299,12 +313,37 @@ func (n *NodeGroup) GetOptions(defaults config.NodeGroupAutoscalingOptions) (*co if pbOpts == nil { return nil, nil } + + var scaleDownUnneededTime time.Duration + if d := pbOpts.GetScaleDownUnneededDuration(); d != nil { + scaleDownUnneededTime = d.AsDuration() + } else { + // fall back to deprecated field removed in 1.35 + scaleDownUnneededTime = pbOpts.GetScaleDownUnneededTime().Duration + } + + var scaleDownUnreadyTime time.Duration + if d := pbOpts.GetScaleDownUnreadyDuration(); d != nil { + scaleDownUnreadyTime = d.AsDuration() + } else { + // fall back to deprecated field removed in 1.35 + scaleDownUnreadyTime = pbOpts.GetScaleDownUnreadyTime().Duration + } + + var maxNodeProvisionTime time.Duration + if d := pbOpts.GetMaxNodeProvisionDuration(); d != nil { + maxNodeProvisionTime = d.AsDuration() + } else { + // fall back to deprecated field removed in 1.35 + maxNodeProvisionTime = pbOpts.GetMaxNodeProvisionTime().Duration + } + opts := &config.NodeGroupAutoscalingOptions{ ScaleDownUtilizationThreshold: pbOpts.GetScaleDownUtilizationThreshold(), ScaleDownGpuUtilizationThreshold: pbOpts.GetScaleDownGpuUtilizationThreshold(), - ScaleDownUnneededTime: pbOpts.GetScaleDownUnneededTime().Duration, - ScaleDownUnreadyTime: pbOpts.GetScaleDownUnreadyTime().Duration, - MaxNodeProvisionTime: pbOpts.GetMaxNodeProvisionTime().Duration, + ScaleDownUnneededTime: scaleDownUnneededTime, + ScaleDownUnreadyTime: scaleDownUnreadyTime, + MaxNodeProvisionTime: maxNodeProvisionTime, ZeroOrMaxNodeScaling: pbOpts.GetZeroOrMaxNodeScaling(), IgnoreDaemonSetsUtilization: pbOpts.GetIgnoreDaemonSetsUtilization(), } diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_node_group_test.go b/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_node_group_test.go index d4544e12d9cb..75493202c3f6 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_node_group_test.go +++ b/cluster-autoscaler/cloudprovider/externalgrpc/externalgrpc_node_group_test.go @@ -25,6 +25,8 @@ import ( "github.com/stretchr/testify/mock" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/durationpb" + apiv1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/autoscaler/cluster-autoscaler/cloudprovider" @@ -124,9 +126,11 @@ func TestCloudProvider_TemplateNodeInfo(t *testing.T) { // test correct call apiv1Node1 := &apiv1.Node{} apiv1Node1.Name = "node1" + apiv1Node1Bytes, _ := apiv1Node1.Marshal() apiv1Node2 := &apiv1.Node{} apiv1Node2.Name = "node2" + apiv1Node2Bytes, _ := apiv1Node2.Marshal() m.On( "NodeGroupTemplateNodeInfo", mock.Anything, mock.MatchedBy(func(req *protos.NodeGroupTemplateNodeInfoRequest) bool { @@ -134,7 +138,8 @@ func TestCloudProvider_TemplateNodeInfo(t *testing.T) { }), ).Return( &protos.NodeGroupTemplateNodeInfoResponse{ - NodeInfo: apiv1Node1, + NodeInfo: apiv1Node1, + NodeBytes: apiv1Node1Bytes, }, nil, ).Once() @@ -144,7 +149,8 @@ func TestCloudProvider_TemplateNodeInfo(t *testing.T) { }), ).Return( &protos.NodeGroupTemplateNodeInfoResponse{ - NodeInfo: apiv1Node2, + NodeInfo: apiv1Node2, + NodeBytes: apiv1Node2Bytes, }, nil, ).Once() @@ -181,7 +187,8 @@ func TestCloudProvider_TemplateNodeInfo(t *testing.T) { }), ).Return( &protos.NodeGroupTemplateNodeInfoResponse{ - NodeInfo: nil, + NodeInfo: nil, + NodeBytes: nil, }, nil, ).Once() @@ -202,7 +209,8 @@ func TestCloudProvider_TemplateNodeInfo(t *testing.T) { }), ).Return( &protos.NodeGroupTemplateNodeInfoResponse{ - NodeInfo: nil, + NodeInfo: nil, + NodeBytes: nil, }, fmt.Errorf("mock error"), ).Once() @@ -223,7 +231,8 @@ func TestCloudProvider_TemplateNodeInfo(t *testing.T) { }), ).Return( &protos.NodeGroupTemplateNodeInfoResponse{ - NodeInfo: nil, + NodeInfo: nil, + NodeBytes: nil, }, status.Error(codes.Unimplemented, "mock error"), ).Once() @@ -257,6 +266,9 @@ func TestCloudProvider_GetOptions(t *testing.T) { ScaleDownUnneededTime: &v1.Duration{Duration: time.Minute}, ScaleDownUnreadyTime: &v1.Duration{Duration: time.Hour}, MaxNodeProvisionTime: &v1.Duration{Duration: time.Minute}, + ScaleDownUnneededDuration: durationpb.New(time.Minute), + ScaleDownUnreadyDuration: durationpb.New(time.Hour), + MaxNodeProvisionDuration: durationpb.New(time.Minute), ZeroOrMaxNodeScaling: true, IgnoreDaemonSetsUtilization: true, }, @@ -365,6 +377,9 @@ func TestCloudProvider_GetOptions(t *testing.T) { ScaleDownUnneededTime: &v1.Duration{Duration: time.Minute}, ScaleDownUnreadyTime: &v1.Duration{Duration: time.Hour}, MaxNodeProvisionTime: &v1.Duration{Duration: time.Minute}, + ScaleDownUnneededDuration: durationpb.New(time.Minute), + ScaleDownUnreadyDuration: durationpb.New(time.Hour), + MaxNodeProvisionDuration: durationpb.New(time.Minute), }, }, nil, diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.pb.go b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.pb.go index ab69bb2ac2fb..68e5661ec4b0 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.pb.go +++ b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.pb.go @@ -26,6 +26,7 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" _ "google.golang.org/protobuf/types/descriptorpb" anypb "google.golang.org/protobuf/types/known/anypb" + durationpb "google.golang.org/protobuf/types/known/durationpb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" v11 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -1674,7 +1675,14 @@ func (x *NodeGroupTemplateNodeInfoRequest) GetId() string { type NodeGroupTemplateNodeInfoResponse struct { state protoimpl.MessageState `protogen:"open.v1"` // nodeInfo is the extracted data from the cloud provider, as a primitive Kubernetes Node type. - NodeInfo *v11.Node `protobuf:"bytes,1,opt,name=nodeInfo,proto3" json:"nodeInfo,omitempty"` + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and nodeBytes. Readers should prefer nodeBytes if set. + // + // Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. + NodeInfo *v11.Node `protobuf:"bytes,1,opt,name=nodeInfo,proto3" json:"nodeInfo,omitempty"` + // nodeBytes is a proto-serialized v1.Node object. + // Generated by calling v1.Node#Marshal(). + // Convertable to a node by calling v1.Node#Unmarshal(). + NodeBytes []byte `protobuf:"bytes,2,opt,name=nodeBytes,proto3" json:"nodeBytes,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1709,6 +1717,7 @@ func (*NodeGroupTemplateNodeInfoResponse) Descriptor() ([]byte, []int) { return file_cloudprovider_externalgrpc_protos_externalgrpc_proto_rawDescGZIP(), []int{32} } +// Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. func (x *NodeGroupTemplateNodeInfoResponse) GetNodeInfo() *v11.Node { if x != nil { return x.NodeInfo @@ -1716,6 +1725,13 @@ func (x *NodeGroupTemplateNodeInfoResponse) GetNodeInfo() *v11.Node { return nil } +func (x *NodeGroupTemplateNodeInfoResponse) GetNodeBytes() []byte { + if x != nil { + return x.NodeBytes + } + return nil +} + type NodeGroupAutoscalingOptions struct { state protoimpl.MessageState `protogen:"open.v1"` // ScaleDownUtilizationThreshold sets threshold for nodes to be considered for scale down @@ -1726,18 +1742,35 @@ type NodeGroupAutoscalingOptions struct { ScaleDownGpuUtilizationThreshold float64 `protobuf:"fixed64,2,opt,name=scaleDownGpuUtilizationThreshold,proto3" json:"scaleDownGpuUtilizationThreshold,omitempty"` // ScaleDownUnneededTime sets the duration CA expects a node to be // unneeded/eligible for removal before scaling down the node. + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and scaleDownUnneededDuration. Readers should prefer scaleDownUnneededDuration if set. + // + // Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. ScaleDownUnneededTime *v1.Duration `protobuf:"bytes,3,opt,name=scaleDownUnneededTime,proto3" json:"scaleDownUnneededTime,omitempty"` // ScaleDownUnreadyTime represents how long an unready node should be // unneeded before it is eligible for scale down. + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and scaleDownUnreadyDuration. Readers should prefer scaleDownUnreadyDuration if set. + // + // Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. ScaleDownUnreadyTime *v1.Duration `protobuf:"bytes,4,opt,name=scaleDownUnreadyTime,proto3" json:"scaleDownUnreadyTime,omitempty"` // MaxNodeProvisionTime time CA waits for node to be provisioned + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and MaxNodeProvisionDuration. Readers should prefer MaxNodeProvisionDuration if set. + // + // Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. MaxNodeProvisionTime *v1.Duration `protobuf:"bytes,5,opt,name=MaxNodeProvisionTime,proto3" json:"MaxNodeProvisionTime,omitempty"` // ZeroOrMaxNodeScaling means that a node group should be scaled up to maximum size or down to zero nodes all at once instead of one-by-one. ZeroOrMaxNodeScaling bool `protobuf:"varint,6,opt,name=zeroOrMaxNodeScaling,proto3" json:"zeroOrMaxNodeScaling,omitempty"` // IgnoreDaemonSetsUtilization sets if daemonsets utilization should be considered during node scale-down IgnoreDaemonSetsUtilization bool `protobuf:"varint,7,opt,name=ignoreDaemonSetsUtilization,proto3" json:"ignoreDaemonSetsUtilization,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + // scaleDownUnneededDuration sets the duration CA expects a node to be + // unneeded/eligible for removal before scaling down the node. + ScaleDownUnneededDuration *durationpb.Duration `protobuf:"bytes,8,opt,name=scaleDownUnneededDuration,proto3" json:"scaleDownUnneededDuration,omitempty"` + // scaleDownUnreadyDuration represents how long an unready node should be + // unneeded before it is eligible for scale down. + ScaleDownUnreadyDuration *durationpb.Duration `protobuf:"bytes,9,opt,name=scaleDownUnreadyDuration,proto3" json:"scaleDownUnreadyDuration,omitempty"` + // MaxNodeProvisionDuration time CA waits for node to be provisioned + MaxNodeProvisionDuration *durationpb.Duration `protobuf:"bytes,10,opt,name=MaxNodeProvisionDuration,proto3" json:"MaxNodeProvisionDuration,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *NodeGroupAutoscalingOptions) Reset() { @@ -1784,6 +1817,7 @@ func (x *NodeGroupAutoscalingOptions) GetScaleDownGpuUtilizationThreshold() floa return 0 } +// Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. func (x *NodeGroupAutoscalingOptions) GetScaleDownUnneededTime() *v1.Duration { if x != nil { return x.ScaleDownUnneededTime @@ -1791,6 +1825,7 @@ func (x *NodeGroupAutoscalingOptions) GetScaleDownUnneededTime() *v1.Duration { return nil } +// Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. func (x *NodeGroupAutoscalingOptions) GetScaleDownUnreadyTime() *v1.Duration { if x != nil { return x.ScaleDownUnreadyTime @@ -1798,6 +1833,7 @@ func (x *NodeGroupAutoscalingOptions) GetScaleDownUnreadyTime() *v1.Duration { return nil } +// Deprecated: Marked as deprecated in cloudprovider/externalgrpc/protos/externalgrpc.proto. func (x *NodeGroupAutoscalingOptions) GetMaxNodeProvisionTime() *v1.Duration { if x != nil { return x.MaxNodeProvisionTime @@ -1819,6 +1855,27 @@ func (x *NodeGroupAutoscalingOptions) GetIgnoreDaemonSetsUtilization() bool { return false } +func (x *NodeGroupAutoscalingOptions) GetScaleDownUnneededDuration() *durationpb.Duration { + if x != nil { + return x.ScaleDownUnneededDuration + } + return nil +} + +func (x *NodeGroupAutoscalingOptions) GetScaleDownUnreadyDuration() *durationpb.Duration { + if x != nil { + return x.ScaleDownUnreadyDuration + } + return nil +} + +func (x *NodeGroupAutoscalingOptions) GetMaxNodeProvisionDuration() *durationpb.Duration { + if x != nil { + return x.MaxNodeProvisionDuration + } + return nil +} + type NodeGroupAutoscalingOptionsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // ID of the node group for the request. @@ -1922,7 +1979,7 @@ var File_cloudprovider_externalgrpc_protos_externalgrpc_proto protoreflect.FileD const file_cloudprovider_externalgrpc_protos_externalgrpc_proto_rawDesc = "" + "\n" + - "4cloudprovider/externalgrpc/protos/externalgrpc.proto\x12/clusterautoscaler.cloudprovider.v1.externalgrpc\x1a\x19google/protobuf/any.proto\x1a google/protobuf/descriptor.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\"k8s.io/api/core/v1/generated.proto\x1a4k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto\"e\n" + + "4cloudprovider/externalgrpc/protos/externalgrpc.proto\x12/clusterautoscaler.cloudprovider.v1.externalgrpc\x1a\x19google/protobuf/any.proto\x1a google/protobuf/descriptor.proto\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\"k8s.io/api/core/v1/generated.proto\x1a4k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto\x1a\x1egoogle/protobuf/duration.proto\"e\n" + "\tNodeGroup\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12\x18\n" + "\aminSize\x18\x02 \x01(\x05R\aminSize\x12\x18\n" + @@ -2018,17 +2075,22 @@ const file_cloudprovider_externalgrpc_protos_externalgrpc_proto_rawDesc = "" + "\ferrorMessage\x18\x02 \x01(\tR\ferrorMessage\x12.\n" + "\x12instanceErrorClass\x18\x03 \x01(\x05R\x12instanceErrorClass\"2\n" + " NodeGroupTemplateNodeInfoRequest\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\"Y\n" + - "!NodeGroupTemplateNodeInfoResponse\x124\n" + - "\bnodeInfo\x18\x01 \x01(\v2\x18.k8s.io.api.core.v1.NodeR\bnodeInfo\"\xd3\x04\n" + + "\x02id\x18\x01 \x01(\tR\x02id\"{\n" + + "!NodeGroupTemplateNodeInfoResponse\x128\n" + + "\bnodeInfo\x18\x01 \x01(\v2\x18.k8s.io.api.core.v1.NodeB\x02\x18\x01R\bnodeInfo\x12\x1c\n" + + "\tnodeBytes\x18\x02 \x01(\fR\tnodeBytes\"\xe6\x06\n" + "\x1bNodeGroupAutoscalingOptions\x12D\n" + "\x1dscaleDownUtilizationThreshold\x18\x01 \x01(\x01R\x1dscaleDownUtilizationThreshold\x12J\n" + - " scaleDownGpuUtilizationThreshold\x18\x02 \x01(\x01R scaleDownGpuUtilizationThreshold\x12d\n" + - "\x15scaleDownUnneededTime\x18\x03 \x01(\v2..k8s.io.apimachinery.pkg.apis.meta.v1.DurationR\x15scaleDownUnneededTime\x12b\n" + - "\x14scaleDownUnreadyTime\x18\x04 \x01(\v2..k8s.io.apimachinery.pkg.apis.meta.v1.DurationR\x14scaleDownUnreadyTime\x12b\n" + - "\x14MaxNodeProvisionTime\x18\x05 \x01(\v2..k8s.io.apimachinery.pkg.apis.meta.v1.DurationR\x14MaxNodeProvisionTime\x122\n" + + " scaleDownGpuUtilizationThreshold\x18\x02 \x01(\x01R scaleDownGpuUtilizationThreshold\x12h\n" + + "\x15scaleDownUnneededTime\x18\x03 \x01(\v2..k8s.io.apimachinery.pkg.apis.meta.v1.DurationB\x02\x18\x01R\x15scaleDownUnneededTime\x12f\n" + + "\x14scaleDownUnreadyTime\x18\x04 \x01(\v2..k8s.io.apimachinery.pkg.apis.meta.v1.DurationB\x02\x18\x01R\x14scaleDownUnreadyTime\x12f\n" + + "\x14MaxNodeProvisionTime\x18\x05 \x01(\v2..k8s.io.apimachinery.pkg.apis.meta.v1.DurationB\x02\x18\x01R\x14MaxNodeProvisionTime\x122\n" + "\x14zeroOrMaxNodeScaling\x18\x06 \x01(\bR\x14zeroOrMaxNodeScaling\x12@\n" + - "\x1bignoreDaemonSetsUtilization\x18\a \x01(\bR\x1bignoreDaemonSetsUtilization\"\x9e\x01\n" + + "\x1bignoreDaemonSetsUtilization\x18\a \x01(\bR\x1bignoreDaemonSetsUtilization\x12W\n" + + "\x19scaleDownUnneededDuration\x18\b \x01(\v2\x19.google.protobuf.DurationR\x19scaleDownUnneededDuration\x12U\n" + + "\x18scaleDownUnreadyDuration\x18\t \x01(\v2\x19.google.protobuf.DurationR\x18scaleDownUnreadyDuration\x12U\n" + + "\x18MaxNodeProvisionDuration\x18\n" + + " \x01(\v2\x19.google.protobuf.DurationR\x18MaxNodeProvisionDuration\"\x9e\x01\n" + "\"NodeGroupAutoscalingOptionsRequest\x12\x0e\n" + "\x02id\x18\x01 \x01(\tR\x02id\x12h\n" + "\bdefaults\x18\x02 \x01(\v2L.clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsR\bdefaults\"\xb6\x01\n" + @@ -2112,7 +2174,8 @@ var file_cloudprovider_externalgrpc_protos_externalgrpc_proto_goTypes = []any{ (*v11.Pod)(nil), // 42: k8s.io.api.core.v1.Pod (*v11.Node)(nil), // 43: k8s.io.api.core.v1.Node (*v1.Duration)(nil), // 44: k8s.io.apimachinery.pkg.apis.meta.v1.Duration - (*anypb.Any)(nil), // 45: google.protobuf.Any + (*durationpb.Duration)(nil), // 45: google.protobuf.Duration + (*anypb.Any)(nil), // 46: google.protobuf.Any } var file_cloudprovider_externalgrpc_protos_externalgrpc_proto_depIdxs = []int32{ 37, // 0: clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode.labels:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.ExternalGrpcNode.LabelsEntry @@ -2140,44 +2203,47 @@ var file_cloudprovider_externalgrpc_protos_externalgrpc_proto_depIdxs = []int32{ 44, // 22: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.scaleDownUnneededTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Duration 44, // 23: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.scaleDownUnreadyTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Duration 44, // 24: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.MaxNodeProvisionTime:type_name -> k8s.io.apimachinery.pkg.apis.meta.v1.Duration - 34, // 25: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest.defaults:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions - 34, // 26: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse.nodeGroupAutoscalingOptions:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions - 45, // 27: clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.GpuTypesEntry.value:type_name -> google.protobuf.Any - 3, // 28: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroups:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupsRequest - 5, // 29: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupForNode:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupForNodeRequest - 7, // 30: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingNodePrice:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceRequest - 9, // 31: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingPodPrice:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest - 11, // 32: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GPULabel:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GPULabelRequest - 13, // 33: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GetAvailableGPUTypes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesRequest - 15, // 34: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Cleanup:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.CleanupRequest - 17, // 35: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Refresh:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.RefreshRequest - 19, // 36: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTargetSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTargetSizeRequest - 21, // 37: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupIncreaseSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupIncreaseSizeRequest - 23, // 38: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDeleteNodes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesRequest - 25, // 39: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDecreaseTargetSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeRequest - 27, // 40: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupNodes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesRequest - 32, // 41: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTemplateNodeInfo:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoRequest - 35, // 42: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupGetOptions:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest - 4, // 43: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroups:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupsResponse - 6, // 44: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupForNode:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupForNodeResponse - 8, // 45: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingNodePrice:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceResponse - 10, // 46: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingPodPrice:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceResponse - 12, // 47: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GPULabel:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GPULabelResponse - 14, // 48: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GetAvailableGPUTypes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse - 16, // 49: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Cleanup:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.CleanupResponse - 18, // 50: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Refresh:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.RefreshResponse - 20, // 51: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTargetSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTargetSizeResponse - 22, // 52: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupIncreaseSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupIncreaseSizeResponse - 24, // 53: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDeleteNodes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesResponse - 26, // 54: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDecreaseTargetSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeResponse - 28, // 55: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupNodes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesResponse - 33, // 56: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTemplateNodeInfo:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoResponse - 36, // 57: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupGetOptions:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse - 43, // [43:58] is the sub-list for method output_type - 28, // [28:43] is the sub-list for method input_type - 28, // [28:28] is the sub-list for extension type_name - 28, // [28:28] is the sub-list for extension extendee - 0, // [0:28] is the sub-list for field type_name + 45, // 25: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.scaleDownUnneededDuration:type_name -> google.protobuf.Duration + 45, // 26: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.scaleDownUnreadyDuration:type_name -> google.protobuf.Duration + 45, // 27: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions.MaxNodeProvisionDuration:type_name -> google.protobuf.Duration + 34, // 28: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest.defaults:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions + 34, // 29: clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse.nodeGroupAutoscalingOptions:type_name -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptions + 46, // 30: clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse.GpuTypesEntry.value:type_name -> google.protobuf.Any + 3, // 31: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroups:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupsRequest + 5, // 32: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupForNode:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupForNodeRequest + 7, // 33: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingNodePrice:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceRequest + 9, // 34: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingPodPrice:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceRequest + 11, // 35: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GPULabel:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GPULabelRequest + 13, // 36: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GetAvailableGPUTypes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesRequest + 15, // 37: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Cleanup:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.CleanupRequest + 17, // 38: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Refresh:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.RefreshRequest + 19, // 39: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTargetSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTargetSizeRequest + 21, // 40: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupIncreaseSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupIncreaseSizeRequest + 23, // 41: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDeleteNodes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesRequest + 25, // 42: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDecreaseTargetSize:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeRequest + 27, // 43: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupNodes:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesRequest + 32, // 44: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTemplateNodeInfo:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoRequest + 35, // 45: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupGetOptions:input_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsRequest + 4, // 46: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroups:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupsResponse + 6, // 47: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupForNode:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupForNodeResponse + 8, // 48: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingNodePrice:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingNodePriceResponse + 10, // 49: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.PricingPodPrice:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.PricingPodPriceResponse + 12, // 50: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GPULabel:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GPULabelResponse + 14, // 51: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.GetAvailableGPUTypes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.GetAvailableGPUTypesResponse + 16, // 52: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Cleanup:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.CleanupResponse + 18, // 53: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.Refresh:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.RefreshResponse + 20, // 54: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTargetSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTargetSizeResponse + 22, // 55: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupIncreaseSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupIncreaseSizeResponse + 24, // 56: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDeleteNodes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDeleteNodesResponse + 26, // 57: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupDecreaseTargetSize:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupDecreaseTargetSizeResponse + 28, // 58: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupNodes:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupNodesResponse + 33, // 59: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupTemplateNodeInfo:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupTemplateNodeInfoResponse + 36, // 60: clusterautoscaler.cloudprovider.v1.externalgrpc.CloudProvider.NodeGroupGetOptions:output_type -> clusterautoscaler.cloudprovider.v1.externalgrpc.NodeGroupAutoscalingOptionsResponse + 46, // [46:61] is the sub-list for method output_type + 31, // [31:46] is the sub-list for method input_type + 31, // [31:31] is the sub-list for extension type_name + 31, // [31:31] is the sub-list for extension extendee + 0, // [0:31] is the sub-list for field type_name } func init() { file_cloudprovider_externalgrpc_protos_externalgrpc_proto_init() } diff --git a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto index b90f011d2801..50b28c196a2c 100644 --- a/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto +++ b/cluster-autoscaler/cloudprovider/externalgrpc/protos/externalgrpc.proto @@ -23,6 +23,7 @@ import "google/protobuf/descriptor.proto"; import "google/protobuf/timestamp.proto"; import "k8s.io/api/core/v1/generated.proto"; import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto"; +import "google/protobuf/duration.proto"; option go_package = "cloudprovider/externalgrpc/protos"; @@ -342,7 +343,13 @@ message NodeGroupTemplateNodeInfoRequest { message NodeGroupTemplateNodeInfoResponse { // nodeInfo is the extracted data from the cloud provider, as a primitive Kubernetes Node type. - k8s.io.api.core.v1.Node nodeInfo = 1; + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and nodeBytes. Readers should prefer nodeBytes if set. + k8s.io.api.core.v1.Node nodeInfo = 1 [deprecated = true]; + + // nodeBytes is a proto-serialized v1.Node object. + // Generated by calling v1.Node#Marshal(). + // Convertable to a node by calling v1.Node#Unmarshal(). + bytes nodeBytes = 2; } message NodeGroupAutoscalingOptions { @@ -356,20 +363,34 @@ message NodeGroupAutoscalingOptions { // ScaleDownUnneededTime sets the duration CA expects a node to be // unneeded/eligible for removal before scaling down the node. - k8s.io.apimachinery.pkg.apis.meta.v1.Duration scaleDownUnneededTime = 3; + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and scaleDownUnneededDuration. Readers should prefer scaleDownUnneededDuration if set. + k8s.io.apimachinery.pkg.apis.meta.v1.Duration scaleDownUnneededTime = 3 [deprecated = true]; // ScaleDownUnreadyTime represents how long an unready node should be // unneeded before it is eligible for scale down. - k8s.io.apimachinery.pkg.apis.meta.v1.Duration scaleDownUnreadyTime = 4; + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and scaleDownUnreadyDuration. Readers should prefer scaleDownUnreadyDuration if set. + k8s.io.apimachinery.pkg.apis.meta.v1.Duration scaleDownUnreadyTime = 4 [deprecated = true]; // MaxNodeProvisionTime time CA waits for node to be provisioned - k8s.io.apimachinery.pkg.apis.meta.v1.Duration MaxNodeProvisionTime = 5; + // Deprecated: Writers cannot set this field in Kubernetes 1.35 and higher, and should set this field and MaxNodeProvisionDuration. Readers should prefer MaxNodeProvisionDuration if set. + k8s.io.apimachinery.pkg.apis.meta.v1.Duration MaxNodeProvisionTime = 5 [deprecated = true]; // ZeroOrMaxNodeScaling means that a node group should be scaled up to maximum size or down to zero nodes all at once instead of one-by-one. bool zeroOrMaxNodeScaling = 6; // IgnoreDaemonSetsUtilization sets if daemonsets utilization should be considered during node scale-down bool ignoreDaemonSetsUtilization = 7; + + // scaleDownUnneededDuration sets the duration CA expects a node to be + // unneeded/eligible for removal before scaling down the node. + google.protobuf.Duration scaleDownUnneededDuration = 8; + + // scaleDownUnreadyDuration represents how long an unready node should be + // unneeded before it is eligible for scale down. + google.protobuf.Duration scaleDownUnreadyDuration = 9; + + // MaxNodeProvisionDuration time CA waits for node to be provisioned + google.protobuf.Duration MaxNodeProvisionDuration = 10; } message NodeGroupAutoscalingOptionsRequest {