Skip to content

Commit 652e97a

Browse files
committed
Add ability to use NLBs as control plane load-balancers
1 parent 9baeadd commit 652e97a

24 files changed

+1590
-78
lines changed

api/v1beta1/awscluster_conversion.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ func (src *AWSCluster) ConvertTo(dstRaw conversion.Hub) error {
4242
restoreControlPlaneLoadBalancer(restored.Spec.ControlPlaneLoadBalancer, dst.Spec.ControlPlaneLoadBalancer)
4343
}
4444

45+
restoreControlPlaneLoadBalancerStatus(&restored.Status.Network, &dst.Status.Network)
46+
4547
dst.Spec.S3Bucket = restored.Spec.S3Bucket
4648

4749
return nil
@@ -52,6 +54,14 @@ func (src *AWSCluster) ConvertTo(dstRaw conversion.Hub) error {
5254
func restoreControlPlaneLoadBalancer(restored, dst *infrav1.AWSLoadBalancerSpec) {
5355
dst.Name = restored.Name
5456
dst.HealthCheckProtocol = restored.HealthCheckProtocol
57+
dst.LoadBalancerType = restored.LoadBalancerType
58+
dst.DisableHostsRewrite = restored.DisableHostsRewrite
59+
}
60+
61+
// restoreControlPlaneLoadBalancerStatus manually restores the control plane loadbalancer status data.
62+
// Assumes restored and dst are non-nil.
63+
func restoreControlPlaneLoadBalancerStatus(restored, dst *infrav1.NetworkStatus) {
64+
dst.APIServerLB = restored.APIServerLB
5565
}
5666

5767
// ConvertFrom converts the v1beta1 AWSCluster receiver to a v1beta1 AWSCluster.

api/v1beta1/conversion.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,15 @@ func Convert_v1beta1_AWSResourceReference_To_v1beta2_AWSResourceReference(in *AW
3232
func Convert_v1beta1_AWSMachineSpec_To_v1beta2_AWSMachineSpec(in *AWSMachineSpec, out *v1beta2.AWSMachineSpec, s conversion.Scope) error {
3333
return autoConvert_v1beta1_AWSMachineSpec_To_v1beta2_AWSMachineSpec(in, out, s)
3434
}
35+
36+
func Convert_v1beta2_AWSLoadBalancerSpec_To_v1beta1_AWSLoadBalancerSpec(in *v1beta2.AWSLoadBalancerSpec, out *AWSLoadBalancerSpec, s conversion.Scope) error {
37+
return autoConvert_v1beta2_AWSLoadBalancerSpec_To_v1beta1_AWSLoadBalancerSpec(in, out, s)
38+
}
39+
40+
func Convert_v1beta1_ClassicELB_To_v1beta2_ClassicELB(in *ClassicELB, out *v1beta2.ClassicELB, s conversion.Scope) error {
41+
return autoConvert_v1beta1_ClassicELB_To_v1beta2_ClassicELB(in, out, s)
42+
}
43+
44+
func Convert_v1beta2_NetworkStatus_To_v1beta1_NetworkStatus(in *v1beta2.NetworkStatus, out *NetworkStatus, s conversion.Scope) error {
45+
return autoConvert_v1beta2_NetworkStatus_To_v1beta1_NetworkStatus(in, out, s)
46+
}

api/v1beta1/zz_generated.conversion.go

Lines changed: 36 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1beta2/awscluster_types.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,15 @@ type Bastion struct {
152152
AMI string `json:"ami,omitempty"`
153153
}
154154

155+
type LoadBalancerType string
156+
157+
var (
158+
LoadBalancerTypeClassic = LoadBalancerType("classic")
159+
LoadBalancerTypeELB = LoadBalancerType("elb")
160+
LoadBalancerTypeALB = LoadBalancerType("alb")
161+
LoadBalancerTypeNLB = LoadBalancerType("nlb")
162+
)
163+
155164
// AWSLoadBalancerSpec defines the desired state of an AWS load balancer.
156165
type AWSLoadBalancerSpec struct {
157166
// Name sets the name of the classic ELB load balancer. As per AWS, the name must be unique
@@ -193,6 +202,14 @@ type AWSLoadBalancerSpec struct {
193202
// This is optional - if not provided new security groups will be created for the load balancer
194203
// +optional
195204
AdditionalSecurityGroups []string `json:"additionalSecurityGroups,omitempty"`
205+
206+
// LoadBalancerType sets the type for a load balancer. The default type is classic.
207+
// +kubebuilder:validation:Enum:=classic;elb;alb;nlb
208+
LoadBalancerType LoadBalancerType `json:"loadBalancerType,omitempty"`
209+
210+
// DisableHostsRewrite disabled the hair pinning issue solution that adds the NLB's address as 127.0.0.1 to the hosts
211+
// file of each instance. This is by default, false.
212+
DisableHostsRewrite bool `json:"disableHostsRewrite,omitempty"`
196213
}
197214

198215
// AWSClusterStatus defines the observed state of AWSCluster.

api/v1beta2/defaults.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16+
1617
package v1beta2
1718

1819
import (
@@ -61,7 +62,10 @@ func SetDefaults_AWSClusterSpec(s *AWSClusterSpec) { //nolint:golint,stylecheck
6162
}
6263
}
6364
if s.ControlPlaneLoadBalancer == nil {
64-
s.ControlPlaneLoadBalancer = &AWSLoadBalancerSpec{Scheme: &ClassicELBSchemeInternetFacing}
65+
s.ControlPlaneLoadBalancer = &AWSLoadBalancerSpec{
66+
Scheme: &ClassicELBSchemeInternetFacing,
67+
LoadBalancerType: LoadBalancerTypeClassic,
68+
}
6569
}
6670
}
6771

api/v1beta2/network_types.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ type NetworkStatus struct {
2929

3030
// APIServerELB is the Kubernetes api server classic load balancer.
3131
APIServerELB ClassicELB `json:"apiServerElb,omitempty"`
32+
33+
// APIServerLB is the Kubernetes api server load balancer.
34+
APIServerLB LBSpec `json:"apiServerLb,omitempty"`
3235
}
3336

3437
// ClassicELBScheme defines the scheme of a classic load balancer.
@@ -44,6 +47,18 @@ var (
4447
ClassicELBSchemeInternal = ClassicELBScheme("internal")
4548
)
4649

50+
// LBScheme defines the scheme of a network load balancer.
51+
type LBScheme string
52+
53+
var (
54+
// LBSchemeInternal defines an internal-only facing
55+
// load balancer internal to an ELB.
56+
LBSchemeInternal = ClassicELBScheme("internal")
57+
58+
// LBSchemeIncorrectInternetFacing was inaccurately used to define an internet-facing LB in v0.6 releases > v0.6.6 and v0.7.0 release.
59+
LBSchemeIncorrectInternetFacing = ClassicELBScheme("Internet-facing")
60+
)
61+
4762
func (e ClassicELBScheme) String() string {
4863
return string(e)
4964
}
@@ -69,6 +84,51 @@ var (
6984
ClassicELBProtocolHTTPS = ClassicELBProtocol("HTTPS")
7085
)
7186

87+
// LBProtocol defines listener protocols for a classic load balancer.
88+
type LBProtocol string
89+
90+
func (e LBProtocol) String() string {
91+
return string(e)
92+
}
93+
94+
var (
95+
// LBProtocolTCP defines the NLB API string representing the TCP protocol.
96+
LBProtocolTCP = LBProtocol("TCP")
97+
// LBProtocolTLS defines the NLB API string representing the TLS protocol.
98+
LBProtocolTLS = LBProtocol("TLS")
99+
// LBProtocolUDP defines the NLB API string representing the UPD protocol.
100+
LBProtocolUDP = LBProtocol("UDP")
101+
)
102+
103+
// TargetGroupHealthCheck defines health check settings for the target group.
104+
// TODO: Create default values for these.
105+
type TargetGroupHealthCheck struct {
106+
HealthCheckProtocol *string `json:"healthCheckProtocol"`
107+
HealthCheckPath *string `json:"healthCheckPath"`
108+
HealthCheckIntervalSeconds *int64 `json:"healthCheckIntervalSeconds"`
109+
HealthCheckTimeoutSeconds *int64 `json:"healthCheckTimeoutSeconds"`
110+
HealthyThresholdCount *int64 `json:"healthyThresholdCount"`
111+
}
112+
113+
// LBTargetGroupSpec specifies target group settings for a given listener.
114+
// This is created first, and the ARN is then passed to the listener.
115+
type LBTargetGroupSpec struct {
116+
Name *string `json:"name"`
117+
Port *int64 `json:"port"`
118+
// +kubebuilder:validation:Enum=tcp;tls;upd
119+
Protocol LBProtocol `json:"protocol"`
120+
VpcID *string `json:"vpcId"`
121+
// HealthCheck is the classic elb health check associated with the load balancer.
122+
HealthCheck *TargetGroupHealthCheck `json:"targetGroupHealthCheck,omitempty"`
123+
}
124+
125+
// LBListener defines an AWS network load balancer listener.
126+
type LBListener struct {
127+
Protocol LBProtocol `json:"protocol"`
128+
Port int64 `json:"port"`
129+
TargetGroup LBTargetGroupSpec `json:"targetGroup"`
130+
}
131+
72132
// ClassicELB defines an AWS classic load balancer.
73133
type ClassicELB struct {
74134
// The name of the load balancer. It must be unique within the set of load balancers
@@ -104,6 +164,41 @@ type ClassicELB struct {
104164
Tags map[string]string `json:"tags,omitempty"`
105165
}
106166

167+
// LBSpec defines an AWS network load balancer.
168+
type LBSpec struct {
169+
// ARN of the load balancer. Unlike the ClassicLB, ARN is used mostly
170+
// to define and get it.
171+
ARN string `json:"arn,omitempty"`
172+
// The name of the load balancer. It must be unique within the set of load balancers
173+
// defined in the region. It also serves as identifier.
174+
// +optional
175+
Name string `json:"name,omitempty"`
176+
177+
// Scheme is the load balancer scheme, either internet-facing or private.
178+
Scheme LBScheme `json:"scheme,omitempty"`
179+
180+
// DNSName is the dns name of the load balancer.
181+
DNSName string `json:"dnsName,omitempty"`
182+
183+
// AvailabilityZones is an array of availability zones in the VPC attached to the load balancer.
184+
AvailabilityZones []string `json:"availabilityZones,omitempty"`
185+
186+
// SubnetIDs is an array of subnets in the VPC attached to the load balancer.
187+
SubnetIDs []string `json:"subnetIds,omitempty"`
188+
189+
// SecurityGroupIDs is an array of security groups assigned to the load balancer.
190+
SecurityGroupIDs []string `json:"securityGroupIds,omitempty"`
191+
192+
// Listeners is an array of classic elb listeners associated with the load balancer. There must be at least one.
193+
Listeners []LBListener `json:"listeners,omitempty"`
194+
195+
// Attributes defines extra attributes associated with the load balancer.
196+
Attributes map[string]*string `json:"attributes,omitempty"`
197+
198+
// Tags is a map of tags associated with the load balancer.
199+
Tags map[string]string `json:"tags,omitempty"`
200+
}
201+
107202
// IsUnmanaged returns true if the Classic ELB is unmanaged.
108203
func (b *ClassicELB) IsUnmanaged(clusterName string) bool {
109204
return b.Name != "" && !Tags(b.Tags).HasOwned(clusterName)
@@ -114,6 +209,16 @@ func (b *ClassicELB) IsManaged(clusterName string) bool {
114209
return !b.IsUnmanaged(clusterName)
115210
}
116211

212+
// IsManaged returns true if LB is managed.
213+
func (lb *LBSpec) IsManaged(clusterName string) bool {
214+
return !lb.IsUnmanaged(clusterName)
215+
}
216+
217+
// IsUnmanaged returns true if the LB is unmanaged.
218+
func (lb *LBSpec) IsUnmanaged(clusterName string) bool {
219+
return lb.Name != "" && !Tags(lb.Tags).HasOwned(clusterName)
220+
}
221+
117222
// ClassicELBAttributes defines extra attributes associated with a classic load balancer.
118223
type ClassicELBAttributes struct {
119224
// IdleTimeout is time that the connection is allowed to be idle (no data

0 commit comments

Comments
 (0)