-
Notifications
You must be signed in to change notification settings - Fork 39.8k
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
[GCE] Support internal load balancers #46663
Conversation
// ServiceAnnotationLoadBalancerInternal is the annotation used on a service with type LoadBalancer | ||
// to signify that an Internal LB should be assembled instead of an External LB. | ||
// Value should be set to "true" (string) to enable. | ||
ServiceAnnotationLoadBalancerInternal = "cloud.google.com/load-balancer-internal" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth making this be cloud.google.com/load-balancer-type: (internal | external)
and leave room for the other LB types that we don't currently represent at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue against having an option named "external" as one would be confused as to how it's different from not having the annotation at all. However, if we have different types of "external" LBs supported in the future, having this annotation would be a nice spot to surface them.
I'll make the change tomorrow; the only supported option will be "internal" or no annotation set. Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, we are trying to keep all API related annotations in https://github.com/kubernetes/kubernetes/blob/master/pkg/api/annotation_key_constants.go and https://github.com/kubernetes/kubernetes/blob/master/pkg/api/v1/annotation_key_constants.go. Is there any concern for moving it to the same place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum...I think the concern here is that ILB is GCE specific. May be we could move this out when other cloud providers would like to support ILB as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other cloud providers already have their "internal" lb's created and use cloud-specific annotations. There is an issue open discussing consolidating the annotations - let's not jump the gun on that effort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
} | ||
|
||
// Delete forwarding rule if any settings are different | ||
fwdRuleDeleted := false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to move this closer to where it is recreated, to minimize disruption?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I'll move instance group and health check creation above here. Thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of code - not so much tests... Are there any parts of this that could be serviced by unit tests?
Overall looks great. would like an extra set of eyes, if possible.
mc := newTargetPoolMetricContext("delete", region) | ||
op, err := gce.service.TargetPools.Delete(gce.projectID, region, name).Do() | ||
|
||
func (gce *GCECloud) DeleteExternalTargetPoolAndChecks(name, region string, hcNames ...string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand why some of these are no public, but this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was public before - I just renamed it and merged it with the logic of the non-public func. https://github.com/kubernetes/kubernetes/pull/46663/files/b836aa75b780046cb290d3ab01f303ffb21ba316..10e59b429409a59c26f985f8a441626e169e37a0#diff-4cae6102def67324f04d6988b5aab0f6L527
Unfortunately, it's public because it's being used in resource cleanup in test/e2e/framework/utils.go
.
|
||
func init() { | ||
var err error | ||
lbSrcRngsFlag.ipn, err = netsets.ParseIPNets([]string{"130.211.0.0/22", "35.191.0.0/16", "209.85.152.0/22", "209.85.204.0/22"}...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment please
/approve |
return defaultZone | ||
} | ||
return zone | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI to reviewers: this logic was taken from the ingress controller.
Agreed, the lack of tests disturb me as well. I don't think we can run any meaningful unit tests without mocking a significant portion of the compute API. This PR is so large partly because I'm separating compute API calls from the load balancer logic in order to support mocking. I'd love to spend a week or two on that effort but would like to hear from other folks who work on the GCE cloudprovider. For the immediate concern of this PR, I think the only unit tests worth considering are a few around resource naming. Would love to hear any other ideas... |
Agree, the mocking/faking/interfacing here will be deep.
Thanks for breaking into many commits. Made it WAY easier to review.
…On Tue, May 30, 2017 at 11:01 PM, Nick Sardo ***@***.***> wrote:
Lots of code - not so much tests... Are there any parts of this that could
be serviced by unit tests?
Agreed, the lack of tests disturb me as well. I don't think we can run any
meaningful unit tests without mocking a significant portion of the compute
API. This PR is so large partly because I'm separating compute API calls
from the load balancer logic in order to support mocking. I'd love to spend
a week or two on that effort but would like to hear from other folks who
work on the GCE cloudprovider.
For the immediate concern of this PR, I think the only unit tests worth
considering are a few around resource naming. Would love to hear any other
ideas...
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#46663 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AFVgVMv6uZ9rYX-r3fMVfRffcw2YKeLiks5r_QI2gaJpZM4NrAni>
.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't gone through all commits...Leave some comments ahead.
// ServiceAnnotationLoadBalancerInternal is the annotation used on a service with type LoadBalancer | ||
// to signify that an Internal LB should be assembled instead of an External LB. | ||
// Value should be set to "true" (string) to enable. | ||
ServiceAnnotationLoadBalancerInternal = "cloud.google.com/load-balancer-internal" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, we are trying to keep all API related annotations in https://github.com/kubernetes/kubernetes/blob/master/pkg/api/annotation_key_constants.go and https://github.com/kubernetes/kubernetes/blob/master/pkg/api/v1/annotation_key_constants.go. Is there any concern for moving it to the same place?
// ServiceAnnotationLoadBalancerInternal is the annotation used on a service with type LoadBalancer | ||
// to signify that an Internal LB should be assembled instead of an External LB. | ||
// Value should be set to "true" (string) to enable. | ||
ServiceAnnotationLoadBalancerInternal = "cloud.google.com/load-balancer-internal" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum...I think the concern here is that ILB is GCE specific. May be we could move this out when other cloud providers would like to support ILB as well.
@@ -35,13 +35,46 @@ import ( | |||
"k8s.io/kubernetes/pkg/cloudprovider" | |||
) | |||
|
|||
const ( | |||
zoneKey = "failure-domain.beta.kubernetes.io/zone" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to import this label from the original place? Like https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/well_known_labels.go#L21.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for finding it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed changing this in first round of changes. Will add this later.
|
||
// MakeHealthCheckFirewallName returns the firewall name used by the GCE load | ||
// balancers (l4) for performing health checks. | ||
func MakeHealthCheckFirewallName(clusterID, hcName string, isNodesHealthCheck bool) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe better to make the function naming consistent (we have getXXX and makeXXX now) between ELB and ILB. I'm guessing you made changes in later commits but leave this comment just in case :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, we also have a mix of exported and private funcs... Those that are exported are used in test/e2e/framework/util.go
. Reckon we should export all these funcs regardless of external use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed all to make...
and kept the same export status as before.
balanceModeCONNECTION lbBalancingMode = "CONNECTION" | ||
) | ||
|
||
type lbBalancingMode string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a link to the public documentations? Obviously I already forgot what those two modes mean :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
ports, protocol := getPortsAndProtocol(svc.Spec.Ports) | ||
scheme := schemeInternal | ||
loadBalancerName := cloudprovider.GetLoadBalancerName(svc) | ||
specialHCPath, specialHCPort := v1_service.GetServiceHealthCheckPathPort(svc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling these specialXXX seems not specific enough...Probably localXXX or localTrafficXXX?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I think checking either one of Path or Port should be enough? Just saw you are only checking Port ==0 in another function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return nil, err | ||
} | ||
|
||
// Get health check settings assuming it's an OnlyLocal service |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment looks a bit confusing, which exact settings is it referring to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return err | ||
} | ||
|
||
func (gce *GCECloud) ensureInternalLoadBalancerDeleted(clusterName, clusterID string, svc *v1.Service) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't see the sharedResourceLock is used, did it turn out that ILB management does not need locking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reminding me. Will add the lock.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, but needs testing.
return ports, protocol | ||
} | ||
|
||
func (gce *GCECloud) getBSLink(name string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably just name it getBackendServiceLink?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this? Java?!?!
Haha. I'll rename it, thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
v, err := gce.service.GlobalAddresses.Get(gce.projectID, name).Do() | ||
return v, mc.Observe(err) | ||
} | ||
|
||
func (gce *GCECloud) ReserveRegionAddress(addr *compute.Address, region string) (*compute.Address, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
// DeleteRegionForwardingRule deletes the RegionalForwardingRule by name & region. | ||
func (gce *GCECloud) DeleteRegionForwardingRule(name, region string) error { | ||
mc := newForwardingRuleMetricContext("delete", "") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set region
in each metric context
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return a | ||
} | ||
return b | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Take this out... Was being used in naming code that didn't make the final cut.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
func (gce *GCECloud) ListZonesInRegion(region string) ([]*compute.Zone, error) { | ||
mc := newZonesMetricContext("list", region) | ||
filter := fmt.Sprintf("region eq https://www.googleapis.com/compute/v1/projects/%v/regions/%v", gce.projectID, region) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Separate region link creation into own func in gce_util.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return gce.GetRegionAddress(addr.Name, region) | ||
} | ||
|
||
// DeleteGlobalStaticIP deletes a global static IP by name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
match comment with func name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return v, mc.Observe(err) | ||
} | ||
|
||
func (gce *GCECloud) ReserveRegionAddress(addr *compute.Address, region string) (*compute.Address, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
func (gce *GCECloud) updateInternalLoadBalancer(clusterName, clusterID string, service *v1.Service, nodes []*v1.Node) error { | ||
igName := getInstanceGroupName(clusterID) | ||
_, err := gce.ensureInstanceGroups(igName, nodes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to update backend service if a new group is created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
return err | ||
} | ||
|
||
if hcInUse { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment explaining this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
if err != nil && !isNotFound(err) { | ||
return err | ||
} | ||
// Create expected firewall |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unnecessary comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
if err != nil { | ||
return err | ||
} | ||
err = gce.ensureFirewall(fwName, fwDesc, sourceRanges.StringSlice(), ports, protocol, nodes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use loadBalancerName
and remove fwName
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
func (gce *GCECloud) ensureHealthCheck(name, path string, port int32) (*compute.HealthCheck, error) { | ||
glog.V(2).Infof("ensureHealthCheck(%v, %v, %v): checking existing health check", name, path, port) | ||
wantedHC := newInternalLBHealthCheck(name, path, port) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename all wantedXXX
to expectedXXX
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
wantedHC := newInternalLBHealthCheck(name, path, port) | ||
|
||
hc, err := gce.GetHealthCheck(name) | ||
if hc == nil || err != nil && isNotFound(err) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was copied logic from loadbalancer_external.
Separate into two code blocks. One checking for non-NotFound errors; another for handling hc == nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
for _, igLink := range igLinks { | ||
backends = append(backends, &compute.Backend{ | ||
Group: igLink, | ||
BalancingMode: string(balancingMode), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment saying that balancing mode settings like MaxConnections
and MaxRate
cannot be used with ILB (currently).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
||
wantedBS := &compute.BackendService{ | ||
Name: name, | ||
Region: gce.region, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove Region
. This is output only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@k8s-bot test this |
@k8s-bot pull-kubernetes-federation-e2e-gce test this |
@k8s-bot pull-kubernetes-e2e-gce-etcd3 test this |
@mikedanese Can you re-lgtm this? I fixed it in the last commit. Thanks |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: MrHohn, bowei, nicksardo, thockin The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
@k8s-bot pull-kubernetes-federation-e2e-gce test this |
@k8s-bot pull-kubernetes-e2e-gce-etcd3 test this Federation e2e seems to be failing consistently. Will re-test that when there's hope. |
@nicksardo: The following test failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
Automatic merge from submit-queue (batch tested with PRs 46550, 46663, 46816, 46820, 46460) |
Is there any documentation how to use this new feature? |
We will be documenting it as part of the 1.7 release |
What this PR does / why we need it:
Allows users to expose K8s services externally of the K8s cluster but within their GCP network.
Fixes #33483
Important User Notes:
loadBalancerIP
field, but it could be lost to another VM or LB if service settings are modified.RATE
- notUTILIZATION
.Reviewer Notes:
Several files were renamed, so github thinks ~2k lines have changed. Review commits one-by-one to see the actual changes.
Release note: