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

Add the VPAAndHPAForAPIServer feature gate for the gardener-operator #9735

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

ialidzhikov
Copy link
Member

@ialidzhikov ialidzhikov commented May 10, 2024

How to categorize this PR?

/area auto-scaling
/kind enhancement

What this PR does / why we need it:

Which issue(s) this PR fixes:
Part of #9562
A follow-up of #9678

Special notes for your reviewer:

Release note:

The `VPAAndHPAForAPIServer` feature gate is now also implemented for the gardener-operator. When enabled, the virtual-garden-kube-apiserver and gardener-apiserver are scaled simultaneously by VPA and HPA on the same metric (CPU and memory usage).

Copy link
Contributor

gardener-prow bot commented May 10, 2024

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@gardener-prow gardener-prow bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. area/auto-scaling Auto-scaling (CA/HPA/VPA/HVPA, predominantly control plane, but also otherwise) related kind/enhancement Enhancement, improvement, extension labels May 10, 2024
Copy link
Contributor

gardener-prow bot commented May 10, 2024

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from ialidzhikov. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@gardener-prow gardener-prow bot added the cla: yes Indicates the PR's author has signed the cla-assistant.io CLA. label May 10, 2024
@gardener-prow gardener-prow bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label May 10, 2024
@gardener-prow gardener-prow bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels May 15, 2024
@ialidzhikov ialidzhikov marked this pull request as ready for review May 15, 2024 13:16
@gardener-prow gardener-prow bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 15, 2024
@voelzmo
Copy link
Member

voelzmo commented May 17, 2024

Hey @ialidzhikov, thanks for the PR! While looking at the changes, I was wondering if we're missing the removal code for HVPA, HPA and VPA objects for the cases when the autoscalingMode is changed? This seems to have been broken already for any switch between HVPA enabled or HVPA disabled, but we never saw this?
Once we merge this and the mode gets changed from HVPA to VPAAndHPA, I guess we would still have an HVPA object and the corresponding VPA and HPA objects created by the hvpa-controller, right?

@ialidzhikov
Copy link
Member Author

While looking at the changes, I was wondering if we're missing the removal code for HVPA, HPA and VPA objects for the cases when the autoscalingMode is changed? This seems to have been broken already for any switch between HVPA enabled or HVPA disabled, but we never saw this?
Once we merge this and the mode gets changed from HVPA to VPAAndHPA, I guess we would still have an HVPA object and the corresponding VPA and HPA objects created by the hvpa-controller, right?

For the kubernetes apiserver component (pkg/component/kubernetes/apiserver, used for the Shoot kube-apiserver and virtual-garden-kube-apiserver) - this is a component that is NOT deployed via GRM, but with a client. Hence, we have everywhere explicit client invocations to delete the no longer needed objects:

  • if k.values.Autoscaling.Mode != apiserver.AutoscalingModeHVPA ||
    k.values.Autoscaling.Replicas == nil ||
    *k.values.Autoscaling.Replicas == 0 {
    return kubernetesutils.DeleteObject(ctx, k.client.Client(), hvpa)
    }
  • func (k *kubeAPIServer) reconcileVerticalPodAutoscaler(ctx context.Context, verticalPodAutoscaler *vpaautoscalingv1.VerticalPodAutoscaler, deployment *appsv1.Deployment) error {
    switch k.values.Autoscaling.Mode {
    case apiserver.AutoscalingModeHVPA:
    return kubernetesutils.DeleteObject(ctx, k.client.Client(), verticalPodAutoscaler)
    case apiserver.AutoscalingModeVPAAndHPA:
    return k.reconcileVerticalPodAutoscalerInVPAAndHPAMode(ctx, verticalPodAutoscaler, deployment)
    default:
    return k.reconcileVerticalPodAutoscalerInBaselineMode(ctx, verticalPodAutoscaler, deployment)
    }
    }
  • func (k *kubeAPIServer) reconcileHorizontalPodAutoscaler(ctx context.Context, hpa *autoscalingv2.HorizontalPodAutoscaler, deployment *appsv1.Deployment) error {
    if k.values.Autoscaling.Mode == apiserver.AutoscalingModeHVPA ||
    k.values.Autoscaling.Replicas == nil ||
    *k.values.Autoscaling.Replicas == 0 {
    return kubernetesutils.DeleteObject(ctx, k.client.Client(), hpa)
    }
    if k.values.Autoscaling.Mode == apiserver.AutoscalingModeVPAAndHPA {
    return k.reconcileHorizontalPodAutoscalerInVPAAndHPAMode(ctx, hpa, deployment)
    }
    return k.reconcileHorizontalPodAutoscalerInBaselineMode(ctx, hpa, deployment)
    }

For the gardener apiserver (pkg/component/gardener/apiserver) - this is a component deployed via GRM:

runtimeResources, err := runtimeRegistry.AddAllAndSerialize(
g.podDisruptionBudget(),
g.serviceRuntime(),
g.horizontalPodAutoscaler(),
g.verticalPodAutoscaler(),
g.hvpa(),
g.deployment(secretCAETCD, secretETCDClient, secretGenericTokenKubeconfig, secretServer, secretAdmissionKubeconfigs, secretETCDEncryptionConfiguration, secretAuditWebhookKubeconfig, secretVirtualGardenAccess, configMapAuditPolicy, configMapAdmissionConfigs),
g.serviceMonitor(),
)

Hence, for the gardener apiserver component returning nil from the verticalPodAutoscaler/horizontalPodAutoscaler/hvpa funcs is enough, GRM takes care to delete the no longer desired objects.

@rfranzke
Copy link
Member

/assign

@@ -203,4 +203,4 @@ A *General Availability* (GA) feature is also referred to as a *stable* feature.
| UseNamespacedCloudProfile | `gardener-apiserver` | Enables usage of `NamespacedCloudProfile`s in `Shoot`s. |
| ShootManagedIssuer | `gardenlet` | Enables the shoot managed issuer functionality described in GEP 24. |
| VPAForETCD | `gardenlet`, `gardener-operator` | Enables VPA for `etcd-main` and `etcd-events`, regardless of HVPA enablement. |
| VPAAndHPAForAPIServer | `gardenlet` | Enables an autoscaling mechanism for shoot kube-apiserver where it is scaled simultaneously by VPA and HPA on the same metric (CPU and memory usage). The pod-trashing cycle between VPA and HPA scaling on the same metric is avoided by configuring the HPA to scale on average usage (not on average utilization) and by picking the target average utilization values in sync with VPA's allowed maximums. The feature gate takes precedence over the `HVPA` feature gate when they are both enabled. |
| VPAAndHPAForAPIServer | `gardenlet`, `gardener-operator` | Enables an autoscaling mechanism for shoot kube-apiserver where it is scaled simultaneously by VPA and HPA on the same metric (CPU and memory usage). The pod-trashing cycle between VPA and HPA scaling on the same metric is avoided by configuring the HPA to scale on average usage (not on average utilization) and by picking the target average utilization values in sync with VPA's allowed maximums. The feature gate takes precedence over the `HVPA` feature gate when they are both enabled. |
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
| VPAAndHPAForAPIServer | `gardenlet`, `gardener-operator` | Enables an autoscaling mechanism for shoot kube-apiserver where it is scaled simultaneously by VPA and HPA on the same metric (CPU and memory usage). The pod-trashing cycle between VPA and HPA scaling on the same metric is avoided by configuring the HPA to scale on average usage (not on average utilization) and by picking the target average utilization values in sync with VPA's allowed maximums. The feature gate takes precedence over the `HVPA` feature gate when they are both enabled. |
| VPAAndHPAForAPIServer | `gardenlet`, `gardener-operator` | Enables an autoscaling mechanism for `kube-apiserver` of shoot or virtual garden clusters, and the `gardener-apiserver`. They are scaled simultaneously by VPA and HPA on the same metric (CPU and memory usage). The pod-trashing cycle between VPA and HPA scaling on the same metric is avoided by configuring the HPA to scale on average usage (not on average utilization) and by picking the target average utilization values in sync with VPA's allowed maximums. The feature gate takes precedence over the `HVPA` feature gate when they are both enabled. |

Comment on lines +25 to +28
return g.horizontalPodAutoscalerInVPAAndHPAMode()
}

func (g *gardenerAPIServer) horizontalPodAutoscalerInVPAAndHPAMode() *autoscalingv2.HorizontalPodAutoscaler {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return g.horizontalPodAutoscalerInVPAAndHPAMode()
}
func (g *gardenerAPIServer) horizontalPodAutoscalerInVPAAndHPAMode() *autoscalingv2.HorizontalPodAutoscaler {

Comment on lines +29 to +32
// The chosen value is 6 CPU: 1 CPU less than the VPA's maxAllowed 7 CPU in VPAAndHPA mode to have a headroom for the horizontal scaling.
hpaTargetAverageValueCPU := resource.MustParse("6")
// The chosen value is 24G: 4G less than the VPA's maxAllowed 28G in VPAAndHPA mode to have a headroom for the horizontal scaling.
hpaTargetAverageValueMemory := resource.MustParse("24G")
Copy link
Member

Choose a reason for hiding this comment

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

You could use ptr.To() instead of defining these variables here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/auto-scaling Auto-scaling (CA/HPA/VPA/HVPA, predominantly control plane, but also otherwise) related cla: yes Indicates the PR's author has signed the cla-assistant.io CLA. kind/enhancement Enhancement, improvement, extension size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants