Skip to content

Commit

Permalink
Implement cluster autoscaler as bootstrap addon
Browse files Browse the repository at this point in the history
Use provider-agnostic node definition for cas instead of aws auto-discovery

Validate clusterAutoscalerSpec

Add spec documentation

Add cas docs

Make CRDs

Apply suggestions from code review

Co-authored-by: John Gardiner Myers <[email protected]>

Add enabled flag to cas config
  • Loading branch information
Ole Markus With committed Aug 27, 2020
1 parent 7f0eaaf commit d598472
Show file tree
Hide file tree
Showing 17 changed files with 746 additions and 0 deletions.
17 changes: 17 additions & 0 deletions docs/cluster_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,23 @@ spec:

For more details on `horizontalPodAutoscaler` flags see the [official HPA docs](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) and the [Kops guides on how to set it up](horizontal_pod_autoscaling.md).

## Cluster autoscaler

{{ kops_feature_table(kops_added_default='1.19', k8s_min='1.15') }}

Cluster autoscaler can be enabled to automatically adjust the size of the kubernetes cluster.

```yaml
spec:
cluster:
clusterAutoscaler:
enabled: true
skipNodesWithLocalStorage: true
skipNodesWithSystemPods: true
```

Read more about cluster autoscaler in the [official documentation](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler).

### Feature Gates

Feature gates can be configured on the kubelet.
Expand Down
22 changes: 22 additions & 0 deletions k8s/crds/kops.k8s.io_clusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,28 @@ spec:
cloudProvider:
description: The CloudProvider to use (aws or gce)
type: string
clusterAutoscaler:
description: ClusterAutoscaler defines the cluaster autoscaler configuration.
properties:
balanceSimilarNodeGroups:
description: 'BalanceSimilarNodeGroups makes cluster autoscaler treat similar node groups as one. Default: false'
type: boolean
enabled:
description: 'Enabled enables the cluster autoscaler. Default: false'
type: boolean
expander:
description: 'Expander determines the strategy for which instance group gets expanded. Supported values: least-waste, most-pods, random. Default: least-waste'
type: string
scaleDownUtilizationThreshold:
description: 'ScaleDownUtilizationThreshold determines the utilization threshold for node scale-down. Default: 0.5'
type: string
skipNodesWithLocalStorage:
description: 'SkipNodesWithLocalStorage makes cluster autoscaler skip scale-down of nodes with local storage. Default: true'
type: boolean
skipNodesWithSystemPods:
description: 'SkipNodesWithSystemPods makes cluster autoscaler skip scale-down of nodes with non-DaemonSet pods in the kube-system namespace. Default: true'
type: boolean
type: object
clusterDNSDomain:
description: ClusterDNSDomain is the suffix we use for internal DNS names (normally cluster.local)
type: string
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/kops/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ type ClusterSpec struct {
SysctlParameters []string `json:"sysctlParameters,omitempty"`
// RollingUpdate defines the default rolling-update settings for instance groups
RollingUpdate *RollingUpdate `json:"rollingUpdate,omitempty"`

// ClusterAutoscaler defines the cluaster autoscaler configuration.
ClusterAutoscaler *ClusterAutoscalerConfig `json:"clusterAutoscaler,omitempty"`
}

// NodeAuthorizationSpec is used to node authorization
Expand Down
23 changes: 23 additions & 0 deletions pkg/apis/kops/componentconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,29 @@ type CloudConfiguration struct {
Openstack *OpenstackConfiguration `json:"openstack,omitempty"`
}

// ClusterAutoscalerConfig determines the cluster autoscaler configuration.
type ClusterAutoscalerConfig struct {
// Enabled enables the cluster autoscaler.
// Default: false
Enabled *bool `json:"enabled,omitempty"`
// Expander determines the strategy for which instance group gets expanded.
// Supported values: least-waste, most-pods, random.
// Default: least-waste
Expander *string `json:"expander,omitempty"`
// BalanceSimilarNodeGroups makes cluster autoscaler treat similar node groups as one.
// Default: false
BalanceSimilarNodeGroups *bool `json:"balanceSimilarNodeGroups,omitempty"`
// ScaleDownUtilizationThreshold determines the utilization threshold for node scale-down.
// Default: 0.5
ScaleDownUtilizationThreshold *string `json:"scaleDownUtilizationThreshold,omitempty"`
// SkipNodesWithSystemPods makes cluster autoscaler skip scale-down of nodes with non-DaemonSet pods in the kube-system namespace.
// Default: true
SkipNodesWithSystemPods *bool `json:"skipNodesWithSystemPods,omitempty"`
// SkipNodesWithLocalStorage makes cluster autoscaler skip scale-down of nodes with local storage.
// Default: true
SkipNodesWithLocalStorage *bool `json:"skipNodesWithLocalStorage,omitempty"`
}

// HasAdmissionController checks if a specific admission controller is enabled
func (c *KubeAPIServerConfig) HasAdmissionController(name string) bool {
for _, x := range c.AdmissionControl {
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/kops/v1alpha2/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ type ClusterSpec struct {
SysctlParameters []string `json:"sysctlParameters,omitempty"`
// RollingUpdate defines the default rolling-update settings for instance groups
RollingUpdate *RollingUpdate `json:"rollingUpdate,omitempty"`

// ClusterAutoscaler defines the cluaster autoscaler configuration.
ClusterAutoscaler *ClusterAutoscalerConfig `json:"clusterAutoscaler,omitempty"`
}

// NodeAuthorizationSpec is used to node authorization
Expand Down
23 changes: 23 additions & 0 deletions pkg/apis/kops/v1alpha2/componentconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,29 @@ type CloudConfiguration struct {
Openstack *OpenstackConfiguration `json:"openstack,omitempty"`
}

// ClusterAutoscalerConfig determines the cluster autoscaler configuration.
type ClusterAutoscalerConfig struct {
// Enabled enables the cluster autoscaler.
// Default: false
Enabled *bool `json:"enabled,omitempty"`
// Expander determines the strategy for which instance group gets expanded.
// Supported values: least-waste, most-pods, random.
// Default: least-waste
Expander *string `json:"expander,omitempty"`
// BalanceSimilarNodeGroups makes cluster autoscaler treat similar node groups as one.
// Default: false
BalanceSimilarNodeGroups *bool `json:"balanceSimilarNodeGroups,omitempty"`
// ScaleDownUtilizationThreshold determines the utilization threshold for node scale-down.
// Default: 0.5
ScaleDownUtilizationThreshold *string `json:"scaleDownUtilizationThreshold,omitempty"`
// SkipNodesWithSystemPods makes cluster autoscaler skip scale-down of nodes with non-DaemonSet pods in the kube-system namespace.
// Default: true
SkipNodesWithSystemPods *bool `json:"skipNodesWithSystemPods,omitempty"`
// SkipNodesWithLocalStorage makes cluster autoscaler skip scale-down of nodes with local storage.
// Default: true
SkipNodesWithLocalStorage *bool `json:"skipNodesWithLocalStorage,omitempty"`
}

// HasAdmissionController checks if a specific admission controller is enabled
func (c *KubeAPIServerConfig) HasAdmissionController(name string) bool {
for _, x := range c.AdmissionControl {
Expand Down
58 changes: 58 additions & 0 deletions pkg/apis/kops/v1alpha2/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 51 additions & 0 deletions pkg/apis/kops/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 18 additions & 0 deletions pkg/apis/kops/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ func validateClusterSpec(spec *kops.ClusterSpec, c *kops.Cluster, fieldPath *fie
allErrs = append(allErrs, validateNodeAuthorization(spec.NodeAuthorization, c, fieldPath.Child("nodeAuthorization"))...)
}

if spec.ClusterAutoscaler != nil {
allErrs = append(allErrs, validateClusterAutoscaler(c, spec.ClusterAutoscaler, fieldPath.Child("clusterAutoscaler"))...)
}

// IAM additionalPolicies
if spec.AdditionalPolicies != nil {
for k, v := range *spec.AdditionalPolicies {
Expand Down Expand Up @@ -1113,3 +1117,17 @@ func validateNodeLocalDNS(spec *kops.ClusterSpec, fldpath *field.Path) field.Err

return allErrs
}

func validateClusterAutoscaler(cluster *kops.Cluster, spec *kops.ClusterAutoscalerConfig, fldPath *field.Path) (allErrs field.ErrorList) {
if !cluster.IsKubernetesGTE("1.15") || cluster.IsKubernetesGTE("1.20") {
allErrs = append(allErrs, field.Forbidden(fldPath, "Cluster autoscaler requires kubernetesVersion between 1.11 and 1.19"))
}

allErrs = append(allErrs, IsValidValue(fldPath.Child("expander"), spec.Expander, []string{"least-waste", "random", "most-pods"})...)

if kops.CloudProviderID(cluster.Spec.CloudProvider) == kops.CloudProviderOpenstack {
allErrs = append(allErrs, field.Forbidden(fldPath, "Cluster autoscaler is not supported on OpenStack"))
}

return allErrs
}
51 changes: 51 additions & 0 deletions pkg/apis/kops/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/model/components/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go_library(
srcs = [
"apiserver.go",
"cilium.go",
"clusterautoscaler.go",
"containerd.go",
"context.go",
"defaults.go",
Expand Down
Loading

0 comments on commit d598472

Please sign in to comment.