Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

auto-scaler types #5492

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/api/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ func init() {
&NamespaceList{},
&Secret{},
&SecretList{},
&AutoScaler{},
&AutoScalerList{},
)
// Legacy names are supported
Scheme.AddKnownTypeWithName("", "Minion", &Node{})
Expand Down Expand Up @@ -85,3 +87,5 @@ func (*Namespace) IsAnAPIObject() {}
func (*NamespaceList) IsAnAPIObject() {}
func (*Secret) IsAnAPIObject() {}
func (*SecretList) IsAnAPIObject() {}
func (*AutoScaler) IsAnAPIObject() {}
func (*AutoScalerList) IsAnAPIObject() {}
27 changes: 27 additions & 0 deletions pkg/api/rest/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,30 @@ func (nodeStrategy) Validate(obj runtime.Object) errors.ValidationErrorList {
node := obj.(*api.Node)
return validation.ValidateMinion(node)
}

// namespaceStrategy implements behavior for nodes
type namespaceStrategy struct {
runtime.ObjectTyper
api.NameGenerator
}

// Namespaces is the default logic that applies when creating and updating Namespace
// objects.
var Namespaces RESTCreateStrategy = namespaceStrategy{api.Scheme, api.SimpleNameGenerator}

// NamespaceScoped is false for namespaces.
func (namespaceStrategy) NamespaceScoped() bool {
return false
}

// ResetBeforeCreate clears fields that are not allowed to be set by end users on creation.
func (namespaceStrategy) ResetBeforeCreate(obj runtime.Object) {
_ = obj.(*api.Namespace)
// Namespace allow *all* fields, including status, to be set.
}

// Validate validates a new namespace.
func (namespaceStrategy) Validate(obj runtime.Object) errors.ValidationErrorList {
namespace := obj.(*api.Namespace)
return validation.ValidateNamespace(namespace)
}
5 changes: 5 additions & 0 deletions pkg/api/testing/fuzzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
ss.ContainerPort.StrVal = "x" + ss.ContainerPort.StrVal // non-empty
}
},
func(a *api.AutoScaler, c fuzz.Continue) {
c.Fuzz(&a.TypeMeta)
c.Fuzz(&a.ObjectMeta)
c.Fuzz(&a.Spec)
},
)
return f
}
88 changes: 88 additions & 0 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1443,3 +1443,91 @@ func AddToNodeAddresses(addresses *[]NodeAddress, addAddresses ...NodeAddress) {
}
}
}

// AutoScaler monitors other resources that are resizeable and adjusts them according to configuration.
type AutoScaler struct {
TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`

// Spec defines the auto-scaler targets and thresholds.
Spec AutoScalerSpec `json:"spec,omitempty"`

// Status defines the actions the auto-scaler has taken.
Status AutoScalerStatus `json:"status,omitempty"`
}

// AutoScalerStatus provides the status of an auto-scaler.
type AutoScalerStatus struct {
// TODO: open for discussion on what meaningful information can be reported in the status
// The status may return the replica count here but we may want more information
// such as if the count reflects a threshold being passed.
}

// AutoScalerSpec defines the auto-scaler targets and thresholds.
type AutoScalerSpec struct {
// Thresholds holds a collection of AutoScaleThresholds that drive the auto-scaler.
Thresholds []AutoScaleThreshold `json:"thresholds,omitempty"`

// MaxAutoScaleCount defines the max replicas that the auto-scaler can use. This value must be
// >= MinAutoScaleCount.
MaxAutoScaleCount int64 `json:"maxAutoScaleCount,omitempty"`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make these int64

// MinAutoScaleCount defines the minimum number replicas that the auto-scaler can reduce to,
// 0 means that the application is allowed to idle.
MinAutoScaleCount int64 `json:"minAutoScaleCount,omitempty"`

// TargetSelector provides the resizeable target(s). Right now this is a ReplicationController
// in the future it could be a job or any resource that implements resize. If multiple targets
// are resolved by the selector the auto-scaler will resize the largest one.
TargetSelector map[string]string `json:"targetSelector,omitempty"`

// MonitorSelector defines a set of resources that the auto-scaler is monitoring
// (replication controllers). Monitored objects are used by thresholds to examine
// statistics. Example: get statistic X for object Y (the monitored object) to see if threshold is passed.
MonitorSelector map[string]string `json:"monitorSelector,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either the comment is unclear or I'm dumb, but I don't know how monitor selector is used. The example doesn't relate to things I use selectors on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The monitor selector provides the set of objects that they auto-scaler is responsible for monitoring. The thresholds may use these objects to retrieve statistics from the store. In the example object Y is an object returned by the monitor selector.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put that in the comment :)

On Mar 16, 2015, at 8:45 AM, Paul notifications@github.com wrote:

In pkg/api/types.go:

  • // >= MinAutoScaleCount.
  • MaxAutoScaleCount int json:"maxAutoScaleCount,omitempty"
  • // MinAutoScaleCount defines the minimum number replicas that the auto-scaler can reduce to,
  • // 0 means that the application is allowed to idle.
  • MinAutoScaleCount int json:"minAutoScaleCount,omitempty"
  • // TargetSelector provides the resizeable target(s). Right now this is a ReplicationController
  • // in the future it could be a job or any resource that implements resize. If multiple targets
  • // are resolved by the selector the auto-scaler will resize the largest one.
  • TargetSelector map[string]string json:"targetSelector,omitempty"
  • // MonitorSelector defines a set of capacity that the auto-scaler is monitoring
  • // (replication controllers). Monitored objects are used by thresholds to examine
  • // statistics. Example: get statistic X for object Y to see if threshold is passed.
  • MonitorSelector map[string]string json:"monitorSelector,omitempty"
    The monitor selector provides the set of objects that they auto-scaler is responsible for monitoring. The thresholds may use these objects to retrieve statistics from the store. In the example object Y is an object returned by the monitor selector.


Reply to this email directly or view it on GitHub.

}

// AutoScaleThreshold is a behavior based on statistics used to drive the auto-scaler in scaling decisions.
type AutoScaleThreshold struct {
// Type is the type of threshold being used, intention or value.
Type AutoScaleThresholdType `json:"type,omitempty"`

// IntentionConfig holds the config for intention based thresholds.
IntentionConfig AutoScaleIntentionThresholdConfig `json:"intentionConfig,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember discussing this in the other thread but these seem more like resources (thresholds). Also, just looking at the names I have no idea what these things do - I would look to focus on recognizable concepts in these names. Threshold is fine - the action is not.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention based thresholds started with item 5 in this comment #2863 (comment) and were confirmed in this one #2863 (comment)

I can add the value based thresholds in the implementation, it just sounded as if intent based was the way folks were leaning.

}

// AutoScaleIntentionThresholdConfig holds configuration for intention based thresholds.
// The scaler will adjust by 1 accordingly and maintain once the intention is reached.
type AutoScaleIntentionThresholdConfig struct {
// Intent is the lexicon of what intention is requested.
Intent AutoScaleIntentionType `json:"intent,omitempty"`

// Value is intention dependent in terms of above, below, equal and represents
// the value to check against.
Value float32 `json:"value,omitempty"`
}

// AutoScaleThresholdType is either intention based or value based.
type AutoScaleThresholdType string

// AutoScaleIntentionType is a lexicon for intentions such as "cpu-utilization",
// "max-rps-per-endpoint".
type AutoScaleIntentionType string

// Constants for auto-scalers and any auto-scaling child types like intentions
const (
// AutoScaleThresholdTypeIntention is used when defining an intention based threshold.
AutoScaleThresholdTypeIntention AutoScaleThresholdType = "Intention"

// TODO: AutoScaleIntentionType types
// example: AutoScaleIntentionTypeMaxRPS AutoScaleIntentionType = "MaxRPS"
)

// AutoScalerList is a list of AutoScaler items
type AutoScalerList struct {
TypeMeta `json:",inline"`
ListMeta `json:"metadata,omitempty"`

// Items is a list of AutoScaler objects.
Items []AutoScaler `json:"items"`
}
42 changes: 42 additions & 0 deletions pkg/api/v1beta1/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -1369,6 +1369,48 @@ func init() {
out.PodID = in.Name
return nil
},
func(in *newer.AutoScaler, out *AutoScaler, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil {
return err
}

if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil {
return err
}

if err := s.Convert(&in.Status, &out.Status, 0); err != nil {
return err
}

return nil
},
func(in *AutoScaler, out *newer.AutoScaler, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil {
return err
}

if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil {
return err
}

if err := s.Convert(&in.Status, &out.Status, 0); err != nil {
return err
}

return nil
},
)
if err != nil {
// If one of the conversion functions is malformed, detect it immediately.
Expand Down
4 changes: 4 additions & 0 deletions pkg/api/v1beta1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func init() {
&NamespaceList{},
&Secret{},
&SecretList{},
&AutoScaler{},
&AutoScalerList{},
)
// Future names are supported
api.Scheme.AddKnownTypeWithName("v1beta1", "Node", &Minion{})
Expand Down Expand Up @@ -92,3 +94,5 @@ func (*Namespace) IsAnAPIObject() {}
func (*NamespaceList) IsAnAPIObject() {}
func (*Secret) IsAnAPIObject() {}
func (*SecretList) IsAnAPIObject() {}
func (*AutoScaler) IsAnAPIObject() {}
func (*AutoScalerList) IsAnAPIObject() {}
87 changes: 87 additions & 0 deletions pkg/api/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1181,3 +1181,90 @@ type SecretList struct {

Items []Secret `json:"items" description:"items is a list of secret objects"`
}

// AutoScaler monitors other resources that are resizeable and adjusts them according to configuration.
type AutoScaler struct {
TypeMeta `json:",inline"`
Labels map[string]string `json:"labels,omitempty"`

// Spec defines the auto-scaler targets and thresholds.
Spec AutoScalerSpec `json:"spec,omitempty"`

// Status defines the actions the auto-scaler has taken.
Status AutoScalerStatus `json:"status,omitempty"`
}

// AutoScalerStatus provides the status of an auto-scaler.
type AutoScalerStatus struct {
// TODO: open for discussion on what meaningful information can be reported in the status
// The status may return the replica count here but we may want more information
// such as if the count reflects a threshold being passed.
}

// AutoScalerSpec defines the auto-scaler targets and thresholds.
type AutoScalerSpec struct {
// Thresholds holds a collection of AutoScaleThresholds that drive the auto-scaler.
Thresholds []AutoScaleThreshold `json:"thresholds,omitempty"`

// MaxAutoScaleCount defines the max replicas that the auto-scaler can use. This value must be
// >= MinAutoScaleCount.
MaxAutoScaleCount int64 `json:"maxAutoScaleCount,omitempty"`

// MinAutoScaleCount defines the minimum number replicas that the auto-scaler can reduce to,
// 0 means that the application is allowed to idle.
MinAutoScaleCount int64 `json:"minAutoScaleCount,omitempty"`

// TargetSelector provides the resizeable target(s). Right now this is a ReplicationController
// in the future it could be a job or any resource that implements resize. If multiple targets
// are resolved by the selector the auto-scaler will resize the largest one.
TargetSelector map[string]string `json:"targetSelector,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Selector api has changed, update this to be consistent

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear, are you asking me to change this into a labels.Set? It looks like everything is still using maps of strings in the type definitions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sync with Dario

On Mar 16, 2015, at 10:18 AM, Paul notifications@github.com wrote:

In pkg/api/v1beta1/types.go:

  • // Enabled turns auto scaling on or off.
  • Enabled bool json:"enabled,omitempty"
  • // MaxAutoScaleCount defines the max replicas that the auto-scaler can use. This value must be
  • // >= MinAutoScaleCount.
  • MaxAutoScaleCount int json:"maxAutoScaleCount,omitempty"
  • // MinAutoScaleCount defines the minimum number replicas that the auto-scaler can reduce to,
  • // 0 means that the application is allowed to idle.
  • MinAutoScaleCount int json:"minAutoScaleCount,omitempty"
  • // TargetSelector provides the resizeable target(s). Right now this is a ReplicationController
  • // in the future it could be a job or any resource that implements resize. If multiple targets
  • // are resolved by the selector the auto-scaler will resize the largest one.
  • TargetSelector map[string]string json:"targetSelector,omitempty"
    To be clear, are you asking me to change this into a labels.Set? It looks like everything is still using maps of strings in the type definitions.


Reply to this email directly or view it on GitHub.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@smarterclayton
so....when using labels.Set in an api type I end up with the circular dependency of

  1. api imports labels
  2. labels imports validations
  3. validations imports api.errors
  4. errors imports api

Breaking up the label types into two packages, one with Lables, Set, and Selector and another with all the current implementations (selectors, validations, etc) has yielded a pretty large refactoring effort considering all the places that reference selectors.

Captain, permission to abort for this PR or shall I carry on?

Just to rule out any PEBKAC, this is how I chose to refactor to try and minimize how many files were touched. I left everything that existed in the labels package mostly untouched. I then broke out the types in labels.go and selector.go into their own package and added some utility methods to labels.go to easily make a Labels struct without importing the types directly. That still left me with at least 75 files to touch. https://github.com/pweil-/kubernetes/tree/labels-as-apitype/pkg/labels

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(a compare on that link will show the unfinished refactoring that I was doing this afternoon)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check with Dario

On Mar 17, 2015, at 5:58 PM, Paul notifications@github.com wrote:

In pkg/api/v1beta1/types.go:

  • // Enabled turns auto scaling on or off.
  • Enabled bool json:"enabled,omitempty"
  • // MaxAutoScaleCount defines the max replicas that the auto-scaler can use. This value must be
  • // >= MinAutoScaleCount.
  • MaxAutoScaleCount int json:"maxAutoScaleCount,omitempty"
  • // MinAutoScaleCount defines the minimum number replicas that the auto-scaler can reduce to,
  • // 0 means that the application is allowed to idle.
  • MinAutoScaleCount int json:"minAutoScaleCount,omitempty"
  • // TargetSelector provides the resizeable target(s). Right now this is a ReplicationController
  • // in the future it could be a job or any resource that implements resize. If multiple targets
  • // are resolved by the selector the auto-scaler will resize the largest one.
  • TargetSelector map[string]string json:"targetSelector,omitempty"
    @smarterclayton
    so....when using labels.Set in an api type I end up with the circular dependency of

api imports labels
labels imports validations
validations imports api.errors
errors imports api
Breaking up the label types into two packages, one with Lables, Set, and Selector and another with all the current implementations (selectors, validations, etc) has yielded a pretty large refactoring effort considering all the places that reference selectors.

Captain, permission to abort for this PR or shall I carry on?

Just to rule out any PEBKAC, this is how I chose to refactor to try and minimize how many files were touched. I left everything that existed in the labels package mostly untouched. I then broke out the types in labels.go and selector.go into their own package and added some utility methods to labels.go to easily make a Labels struct without importing the types directly. That still left me with at least 75 files to touch. https://github.com/pweil-/kubernetes/tree/labels-as-apitype/pkg/labels


Reply to this email directly or view it on GitHub.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #341 and https://github.com/GoogleCloudPlatform/kubernetes/blob/master/pkg/labels/selector.go#L156.

We're working towards supporting generalized label selectors in the API, but it doesn't exist yet. In any case, labels.Set isn't the right representation -- that a label set, not a selector.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @bgrant0607, understood.

@smarterclayton - I'll check with @sdminonne on the timing for this (#341 (comment) item 1) and put a TODO here since it is not quite ready. If he has a quick(er) strategy in mind for implementation that I can help out with I'll submit a PR for it and rebase to use it.

Based on that, this PR is read for the round 2 of reviews from the initial feedback.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've fixed the error circular reference in #5771

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 🏆


// MonitorSelector defines a set of resources that the auto-scaler is monitoring
// (replication controllers). Monitored objects are used by thresholds to examine
// statistics. Example: get statistic X for object Y (the monitored object) to see if threshold is passed.
MonitorSelector map[string]string `json:"monitorSelector,omitempty"`
}

// AutoScaleThreshold is a behavior based on statistics used to drive the auto-scaler in scaling decisions.
type AutoScaleThreshold struct {
// Type is the type of threshold being used, intention or value.
Type AutoScaleThresholdType `json:"type,omitempty"`

// IntentionConfig holds the config for intention based thresholds.
IntentionConfig AutoScaleIntentionThresholdConfig `json:"intentionConfig,omitempty"`
}

// AutoScaleIntentionThresholdConfig holds configuration for intention based thresholds.
// The scaler will adjust by 1 accordingly and maintain once the intention is reached.
type AutoScaleIntentionThresholdConfig struct {
// Intent is the lexicon of what intention is requested.
Intent AutoScaleIntentionType `json:"intent,omitempty"`

// Value is intention dependent in terms of above, below, equal and represents
// the value to check against.
Value float32 `json:"value,omitempty"`
}

// AutoScaleThresholdType is either intention based or value based.
type AutoScaleThresholdType string

// AutoScaleIntentionType is a lexicon for intentions such as "cpu-utilization",
// "max-rps-per-endpoint".
type AutoScaleIntentionType string

// Constants for auto-scalers and any auto-scaling child types like intentions
const (
// AutoScaleThresholdTypeIntention is used when defining an intention based threshold.
AutoScaleThresholdTypeIntention AutoScaleThresholdType = "Intention"

// TODO: AutoScaleIntentionType types
// example: AutoScaleIntentionTypeMaxRPS AutoScaleIntentionType = "MaxRPS"
)

// AutoScalerList is a list of AutoScaler items
type AutoScalerList struct {
TypeMeta `json:",inline"`

// Items is a list of AutoScaler objects.
Items []AutoScaler `json:"items"`
}
42 changes: 42 additions & 0 deletions pkg/api/v1beta2/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -1297,6 +1297,48 @@ func init() {
out.PodID = in.Name
return nil
},
func(in *newer.AutoScaler, out *AutoScaler, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil {
return err
}

if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil {
return err
}

if err := s.Convert(&in.Status, &out.Status, 0); err != nil {
return err
}

return nil
},
func(in *AutoScaler, out *newer.AutoScaler, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.Labels, &out.Labels, 0); err != nil {
return err
}

if err := s.Convert(&in.Spec, &out.Spec, 0); err != nil {
return err
}

if err := s.Convert(&in.Status, &out.Status, 0); err != nil {
return err
}

return nil
},
)
if err != nil {
// If one of the conversion functions is malformed, detect it immediately.
Expand Down
4 changes: 4 additions & 0 deletions pkg/api/v1beta2/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func init() {
&NamespaceList{},
&Secret{},
&SecretList{},
&AutoScaler{},
&AutoScalerList{},
)
// Future names are supported
api.Scheme.AddKnownTypeWithName("v1beta2", "Node", &Minion{})
Expand Down Expand Up @@ -92,3 +94,5 @@ func (*Namespace) IsAnAPIObject() {}
func (*NamespaceList) IsAnAPIObject() {}
func (*Secret) IsAnAPIObject() {}
func (*SecretList) IsAnAPIObject() {}
func (*AutoScaler) IsAnAPIObject() {}
func (*AutoScalerList) IsAnAPIObject() {}
Loading