Skip to content

Add webhook for claiming load balancers without LoadBalancerClass #2925

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

Merged
merged 1 commit into from
Mar 23, 2023

Conversation

olemarkus
Copy link
Contributor

Description

Kubernetes on AWS have two service controllers, this one (LBC) and the one that sits with Cloud Controller Manager (CCM). The CCM repo has a significant amount of bugs/issues related to it, and the most common resolution is to refer the users to LBC.

As a secondary issue, CCM will default, and only fully support classic ELBs.

A third issue is that in IPv6-only clusters, you have to use NLBs, so the CCM controller doesn't work at all.

The requirements for a solution is something like this:

  • There should be a migration path for existing clusters.
  • Existing services should continue to work (i.e something still needs to support Classic ELBs) and preserve CCMs behavior.

I don't think implementing CCM's controller in LBC is all that feasible. And it may be a moving target, as behaviour in CCM may change as well.

The easiest solution I could think of is to add a webhook that mutates services, adding some annotations and LoadBalancerClass if none are set. This effectively makes LBC the default while CCM will continue to operate on existing services. Migrating an existing service would have to be done through deletion and recreation of the Service resource, but that would be the case today as well since LoadBalancerClass is immutable, and LBC has no way of just adopting an ELB from CCM.

This PR creates a proof of concept that makes the few cloud LB related e2e tests pass and does some minimal configuration of the appropriate annotations (e.g without service class set, the service should be internet-facing by default). More of the CCM annotations needs to be implemented here. There should also be an option to skip the mutation if a specific annotation is set if one really wants CCM to manage a specific service. A feature gate that just noops the webhook should also be added to allow the webhook configuration to exist in the cluster, but disable its functionality.

If this has merit, I can add this functionality, but right now I am just looking for input.

Checklist

  • Added tests that cover your change (if possible)
  • Added/modified documentation as required (such as the README.md, or the docs directory)
  • Manually tested
  • Made sure the title of the PR is a good description that can go into the release notes

BONUS POINTS checklist: complete for good vibes and maybe prizes?! 🤯

  • Backfilled missing tests for code in same general area 🎉
  • Refactored something and made the world a better place 🌟

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. labels Dec 13, 2022
@kishorj
Copy link
Collaborator

kishorj commented Dec 13, 2022

@olemarkus, thanks for the PR, we are also tracking this feature internally for the upcoming v2.5.0 release and working on the webhook changes :). We intend to make the lb controller default for all new services of type LoadBalancer either by adding the annotation or specifying the load balancer class. We will include some changes from your PR.

if svc.Annotations == nil {
svc.Annotations = make(map[string]string)
}
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-scheme"] = "internet-facing"
Copy link
Collaborator

Choose a reason for hiding this comment

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

due to security reasons, we do not want to create an internet-facing load balancer by default. The end user needs to be explicit they want to create an internet-facing load balancer.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm aware. But kubetest2 needs to confirm connectivity with the LB, so it would be a breaking change if we do not do this when the LB class is empty. One could very well say that kubernetes requires the CCM controller (and those that emulate it) to create a public cloud LB by default.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What we probably have to do here is to introduce a compatibility mode flag. I can imagine people want both behaviors.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm looking forward to merging the changes for v2.5.0. Lets limit the webhook to setting the spec.loadBalancerClass. We will leave the default service as internal for now. I'm open to providing a flag to change the default behavior in future releases.

svc.Annotations = make(map[string]string)
}
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-scheme"] = "internet-facing"
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-target-type"] = "instance"
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can make it default to the controller's configuration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We definitely want this one to be configurable. Especially since ipv6 NLBs doesn't support instance targeting.

Copy link
Collaborator

Choose a reason for hiding this comment

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

default target type is already configurable at the controller level, lets remove it as well.

@johngmyers
Copy link
Contributor

My approach to this problem is to add a flag that makes LBC the default service controller.

johngmyers@5f2da30 was my first attempt, but that commit incorrectly conflates being the default service controller with specifying the default target-type. #2840 addresses setting the default target-type; once that is resolved I was planning on sending a follow-up adding a flag to make LBC the default service controller.

@k8s-ci-robot k8s-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 4, 2023
@kishorj kishorj added the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label Mar 10, 2023
@k8s-ci-robot k8s-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Mar 10, 2023
@codecov-commenter
Copy link

Codecov Report

Patch and project coverage have no change.

Comparison is base (1392585) 54.40% compared to head (0449794) 54.40%.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2925   +/-   ##
=======================================
  Coverage   54.40%   54.40%           
=======================================
  Files         145      145           
  Lines        8429     8429           
=======================================
  Hits         4586     4586           
  Misses       3512     3512           
  Partials      331      331           

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

Copy link
Collaborator

@kishorj kishorj left a comment

Choose a reason for hiding this comment

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

I plan to include the webhook configuration in the helm chart, enabled by default the helm chart, with an option to disable if needed.

if svc.Annotations == nil {
svc.Annotations = make(map[string]string)
}
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-scheme"] = "internet-facing"
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm looking forward to merging the changes for v2.5.0. Lets limit the webhook to setting the spec.loadBalancerClass. We will leave the default service as internal for now. I'm open to providing a flag to change the default behavior in future releases.

svc.Annotations = make(map[string]string)
}
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-scheme"] = "internet-facing"
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-target-type"] = "instance"
Copy link
Collaborator

Choose a reason for hiding this comment

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

default target type is already configurable at the controller level, lets remove it as well.

@kishorj
Copy link
Collaborator

kishorj commented Mar 10, 2023

For v2.5.0, we intend to change the perquisite to k8s 1.22 or later. Setting the spec.loadBalancerClass would be sufficient to make the LBC the default controller for service of type load balancer.

Comment on lines 49 to 53
if svc.Annotations == nil {
svc.Annotations = make(map[string]string)
}
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-scheme"] = "internet-facing"
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-target-type"] = "instance"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
if svc.Annotations == nil {
svc.Annotations = make(map[string]string)
}
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-scheme"] = "internet-facing"
svc.Annotations["service.beta.kubernetes.io/aws-load-balancer-target-type"] = "instance"

@olemarkus
Copy link
Contributor Author

Thanks for the comments. How do you want to proceed with this this? Should I amend this PR and then you pull this into your internal changes?

@kishorj
Copy link
Collaborator

kishorj commented Mar 23, 2023

Thanks for the comments. How do you want to proceed with this this? Should I amend this PR and then you pull this into your internal changes?

Lets amend the PR, I can merge in the suggested changes as well. Once we merge this change, we can add the webhook manifest.

@olemarkus
Copy link
Contributor Author

Cool. Amended.

@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: kishorj, olemarkus

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

The pull request process is described 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

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 23, 2023
@kishorj
Copy link
Collaborator

kishorj commented Mar 23, 2023

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Mar 23, 2023
@k8s-ci-robot k8s-ci-robot merged commit 161168e into kubernetes-sigs:main Mar 23, 2023
Timothy-Dougherty pushed a commit to adammw/aws-load-balancer-controller that referenced this pull request Nov 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/M Denotes a PR that changes 30-99 lines, ignoring generated files. tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants