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
Create an Internal Load Balancer if configured #1222
base: main
Are you sure you want to change the base?
Conversation
Hi @bfournie. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. 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. |
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: bfournie 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 |
✅ Deploy Preview for kubernetes-sigs-cluster-api-gcp ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
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.
/ok-to-test
2d101b7
to
e312d9c
Compare
// APIInternalAddress is the IPV4 regional address assigned to the | ||
// internal Load Balancer. | ||
// +optional | ||
APIInternalAddress *string `json:"apiInternalIpAddress,omitempty"` |
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 that this is a breaking change, but should we consider a structure to hold these values? The added values are the same as those for the api server, so a lot of duplicated values appear.
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.
The main reason I didn't do that was because it is a breaking change, I tried to keep the same API for consistency and just add the additional fields.
If the consensus is that its OK to change this API I can make it an array.
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.
make sense as we are adding this to add as a struct
wdyt @damdo
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.
OK, how would we handle the API in this case though? Would the existing fields - APIServerAddress
, APIServerHealthCheck
etc need to be marked as deprecated but still handled for a few releases until the deprecation is complete? It seems like it will add a lot of complexity to this API.
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 tend to agree with @bfournie here.
I'd probably stick with a non-breaking change, and then schedule a full API re-review for a new v1beta2 where we can improve the situation and plan the breaking changes we want to make to the API to clean it up.
cc. @nrb |
e312d9c
to
173c005
Compare
/hold |
6db2752
to
f5670bf
Compare
Remove the configuration of the GCP Internal Load Balancer from the installer as its now being done in the CAPG provider. This allows only the Internal LB to be created to support Private Clusters. This depends on kubernetes-sigs/cluster-api-provider-gcp#1222 which is still under review.
/unhold |
/test ls |
@cpanato: The specified target(s) for
The following commands are available to trigger optional jobs:
Use
In response to this:
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-sigs/prow repository. |
/test pull-cluster-api-provider-gcp-conformance |
Thanks for working on this @bfournie. We would really like this as well! I pulled this down and when running it with When I added stuff like
to
I was then able to reliably get cluster deletion to work without manual intervention or getting stuck. I'm also noticing the Internal Passthrough LB is getting created with
I haven't found the code to change the generated |
// LoadBalancerType defines the type of Load Balancer that should be created. | ||
// If not set, a Global External Proxy Load Balancer will be created by default. | ||
// +optional | ||
LoadBalancerType *LoadBalancerType `json:"loadBalancerType,omitempty"` |
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 had thought about but felt that type of API presents too much ambiguity and potential for error. For example with that type of array you could have the following potential combinations, all of which are in error:
empty
(no LBs defined)INTERNAL/INTERNAL
EXTERNAL/EXTERNAL
Explicitly defining the Load Balancer configuration options seems more useful.
Name *string `json:"name,omitempty"` | ||
|
||
// Subnet is the name of the subnet to use for a regional Load Balancer. | ||
Subnet *string `json:"subnet,omitempty"` |
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.
Can the Internal Load Balancer be created without a subnet? Afaik, it can't. So, omitempty is not a valid value.
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.
Yes, it must be created with a subnet. Currently it uses the first subnet if one is not defined here, so setting it in the API is optional.
https://github.com/kubernetes-sigs/cluster-api-provider-gcp/pull/1222/files#diff-a7274316ed5d60f25cc61e1bcb771a612c3566832a59ecc3a13b279a849c95ebR728-R730
I can change this to require it to be explicitly defined if that seems like the best direction.
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.
Yes, it must be created with a subnet. Currently it uses the first subnet if one is not defined here, so setting it in the API is optional.
https://github.com/kubernetes-sigs/cluster-api-provider-gcp/pull/1222/files#diff-a7274316ed5d60f25cc61e1bcb771a612c3566832a59ecc3a13b279a849c95ebR728-R730
I'd explicitly write this in the comment for this field.
f5670bf
to
b80ab99
Compare
Thank you for testing this! I wasn't seeing an error on deletion but agree that the regional interfaces were not being explicitly called, so I've changed this to do explicit deletions on the regional resources. Regarding the port being used, the ControlPlaneEndpoint should be set to 443 if not overridden by APIServerPort https://github.com/kubernetes-sigs/cluster-api-provider-gcp/blob/main/cloud/scope/cluster.go#L148-L154 and this should be used in the Internal only case here https://github.com/kubernetes-sigs/cluster-api-provider-gcp/pull/1222/files#diff-a7274316ed5d60f25cc61e1bcb771a612c3566832a59ecc3a13b279a849c95ebR235-R240 but perhaps its not. I will investigate this. |
b80ab99
to
a7ea938
Compare
Provide the ability to configure the types of Load Balancers to be created (Internal and/or External). By default, an External Proxy Load Balancer will be created per the current implementation. If set for an Internal Load Balancer, an Internal Passthrough Load Balancer will be created using resources in the specified region.
a7ea938
to
eb4a0ad
Compare
@bfournie: 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-sigs/prow repository. I understand the commands that are listed here. |
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 @bfournie, great effort with this feature!
I left my review, most are nitpicks and some questions.
Also were you planning on writing E2E tests for this?
I think this is a big enough feature that could warrant that.
// ExternalLoadBalancerOnly creates a Global External Proxy Load Balancer | ||
// to manage traffic to backends in multiple regions. This is the default Load | ||
// Balancer and will be created if no LoadBalancerType is defined. | ||
ExternalLoadBalancerOnly = LoadBalancerType("EXTERNAL_ONLY") | ||
|
||
// InternalLoadBalancerOnly creates a Regional Internal Passthrough Load | ||
// Balancer to manage traffic to backends in the configured region. | ||
InternalLoadBalancerOnly = LoadBalancerType("INTERNAL_ONLY") | ||
|
||
// DualLoadBalancer creates both External and Internal Load Balancers to provide | ||
// separate endpoints for managing both external and internal traffic. | ||
DualLoadBalancer = LoadBalancerType("Dual") |
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'd try and stick to values that are following the API Conventions:
values should be PascalCase and should be equivalent to the camelCase field name (json tag)
So I'd drop the _ONLY
(IMO it is already clear without it) and change them to:
External
, Internal
, InternalExternal
(Dual could be ambiguous if we add a third option or different combination in the future),
// will be used. For an Internal Load Balancer service the default | ||
// name is "api-internal". | ||
// +kubebuilder:validation:Optional | ||
// +kubebuilder:validation:MaxLength=32 |
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 this a limitation on the AWS side?
Name *string `json:"name,omitempty"` | ||
|
||
// Subnet is the name of the subnet to use for a regional Load Balancer. | ||
Subnet *string `json:"subnet,omitempty"` |
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.
Yes, it must be created with a subnet. Currently it uses the first subnet if one is not defined here, so setting it in the API is optional.
https://github.com/kubernetes-sigs/cluster-api-provider-gcp/pull/1222/files#diff-a7274316ed5d60f25cc61e1bcb771a612c3566832a59ecc3a13b279a849c95ebR728-R730
I'd explicitly write this in the comment for this field.
|
||
// APIInternalAddress is the IPV4 regional address assigned to the | ||
// internal Load Balancer. | ||
// +optional | ||
APIInternalAddress *string `json:"apiInternalIpAddress,omitempty"` | ||
|
||
// APIInternalHealthCheck is the full reference to the health check | ||
// created for the internal Load Balancer. | ||
// +optional | ||
APIInternalHealthCheck *string `json:"apiInternalHealthCheck,omitempty"` | ||
|
||
// APIInternalBackendService is the full reference to the backend service | ||
// created for the internal Load Balancer. | ||
// +optional | ||
APIInternalBackendService *string `json:"apiInternalBackendService,omitempty"` | ||
|
||
// APIInternalForwardingRule is the full reference to the forwarding rule | ||
// created for the internal Load Balancer. | ||
// +optional | ||
APIInternalForwardingRule *string `json:"apiInternalForwardingRule,omitempty"` |
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.
Are these fields all required when the Internal Load Balancer is set?
If not are they defaulted to something in code?
// loadBalancingMode describes the load balancing mode that the backend performs. | ||
type loadBalancingMode string | ||
|
||
const ( | ||
// Utilization determines how the traffic load is spread based on the | ||
// utilization of instances. | ||
loadBalancingModeUtilization = loadBalancingMode("UTILIZATION") | ||
|
||
// Connection determines how the traffic load is spread based on the | ||
// total number of connections that a backend can handle. This is | ||
// only mode available for passthrough Load Balancers. | ||
loadBalancingModeConnection = loadBalancingMode("CONNECTION") | ||
|
||
loadBalanceTrafficInternal = "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.
Also here let's adhere to the PascalCase conventions
if err := s.deleteForwardingRule(ctx, name); err != nil { | ||
return err | ||
} | ||
s.scope.Network().APIServerForwardingRule = nil | ||
|
||
if err := s.deleteAddress(ctx, name); err != nil { | ||
return err | ||
} | ||
s.scope.Network().APIServerAddress = nil | ||
|
||
if err := s.deleteTargetTCPProxy(ctx); err != nil { | ||
return err | ||
} | ||
s.scope.Network().APIServerTargetProxy = nil | ||
|
||
if err := s.deleteBackendService(ctx, name); err != nil { | ||
return err | ||
} | ||
s.scope.Network().APIServerBackendService = nil | ||
|
||
if err := s.deleteHealthCheck(ctx, name); err != nil { | ||
return err | ||
} | ||
s.scope.Network().APIServerHealthCheck = 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.
I'd add an fmt.Errorf(
wrap for all these errors for easier debugging when following the log error chain
return err | ||
} | ||
s.scope.Network().APIInternalForwardingRule = nil | ||
|
||
if err := s.deleteInternalAddress(ctx, name); err != nil { | ||
return err | ||
} | ||
s.scope.Network().APIInternalAddress = nil | ||
|
||
if err := s.deleteRegionalBackendService(ctx, name); err != nil { | ||
return err | ||
} | ||
s.scope.Network().APIInternalBackendService = nil | ||
|
||
if err := s.deleteRegionalHealthCheck(ctx, name); err != nil { | ||
return err | ||
} | ||
s.scope.Network().APIInternalHealthCheck = 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.
Error wrapping here too
}) | ||
} | ||
if mode == loadBalancingModeConnection { | ||
be.MaxConnections = int64(2 ^ 32) |
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.
Can we add a comment specifying where this value is coming from?
spec.Region = s.scope.Region() | ||
spec.BackendService = backendSvc.SelfLink | ||
// Ports are used instead or PortRange for passthrough Load Balancer | ||
spec.Ports = []string{"6443", "22623"} |
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.
Where are these values coming from?
return nil, err | ||
} | ||
// Return subnet that matches configuration or first one if not configured | ||
if cfgSubnet == "" || strings.HasSuffix(subnet.Name, cfgSubnet) { |
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 the reason for using HasSuffix instead of a full match?
What type of PR is this?
/kind feature
What this PR does / why we need it:
Provide the ability to configure the types of Load Balancers to be created (Internal and/or External). By default, an External Proxy Load Balancer will be created per the current implementation. If set for an Internal Load Balancer, an Internal Passthrough Load Balancer will be created using resources in the specified region.
Which issue(s) this PR fixes :
Fixes #1221
Special notes for your reviewer:
TODOs:
Release note:
-->