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

Implement cluster autoscaler as bootstrap addon #9787

Merged
merged 1 commit into from
Sep 5, 2020
Merged
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
17 changes: 17 additions & 0 deletions docs/cluster_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,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
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,7 @@ k8s.io/cloud-provider v0.19.0/go.mod h1:TYh7b7kQ6wiqF7Ftb+u3lN4IwvgOPbBrcvC3TDAW
k8s.io/cloud-provider-openstack v1.18.0 h1:v/ebjNEdx0hBaygsRohSS643f41lj2CwvapCbn+aLOs=
k8s.io/cloud-provider-openstack v1.18.0/go.mod h1:03202t5Sp+4Vmk6pxJ/hVH0fEkm9gMc/pku/QpkJQMQ=
k8s.io/cluster-bootstrap v0.19.0/go.mod h1:kBn1DKyqoM245wzz+AAnGkuysJ+9GqVbPYveTo4KiaA=
k8s.io/code-generator v0.19.0 h1:r0BxYnttP/r8uyKd4+Njg0B57kKi8wLvwEzaaVy3iZ8=
k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk=
k8s.io/component-base v0.19.0 h1:OueXf1q3RW7NlLlUCj2Dimwt7E1ys6ZqRnq53l2YuoE=
k8s.io/component-base v0.19.0/go.mod h1:dKsY8BxkA+9dZIAh2aWJLL/UdASFDNtGYTCItL4LM7Y=
Expand Down
25 changes: 25 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,31 @@ spec:
cloudProvider:
description: The CloudProvider to use (aws or gce)
type: string
clusterAutoscaler:
description: ClusterAutoscaler defines the cluaster autoscaler configuration.
olemarkus marked this conversation as resolved.
Show resolved Hide resolved
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'
hakman marked this conversation as resolved.
Show resolved Hide resolved
type: string
image:
description: 'Image is the docker container used. Default: the latest supported image for the specified kubernetes version.'
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 cluster autoscaler configuration.
ClusterAutoscaler *ClusterAutoscalerConfig `json:"clusterAutoscaler,omitempty"`
}

// NodeAuthorizationSpec is used to node authorization
Expand Down
26 changes: 26 additions & 0 deletions pkg/apis/kops/componentconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,32 @@ 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"`
// Image is the docker container used.
// Default: the latest supported image for the specified kubernetes version.
Image *string `json:"image,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
26 changes: 26 additions & 0 deletions pkg/apis/kops/v1alpha2/componentconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,32 @@ 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"`
// Image is the docker container used.
// Default: the latest supported image for the specified kubernetes version.
Image *string `json:"image,omitempty"`
}

// HasAdmissionController checks if a specific admission controller is enabled
func (c *KubeAPIServerConfig) HasAdmissionController(name string) bool {
for _, x := range c.AdmissionControl {
Expand Down
60 changes: 60 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.

56 changes: 56 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.12") {
allErrs = append(allErrs, field.Forbidden(fldPath, "Cluster autoscaler requires kubernetesVersion 1.12 or higher"))
}

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"))
johngmyers marked this conversation as resolved.
Show resolved Hide resolved
}

return allErrs
}
Loading