mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +00:00
Merge pull request #92109 from kishorj/nlb_udp_support
Allow UDP for AWS NLB
This commit is contained in:
commit
c5b3dba02d
@ -3691,9 +3691,10 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
|
|||||||
|
|
||||||
sslPorts := getPortSets(annotations[ServiceAnnotationLoadBalancerSSLPorts])
|
sslPorts := getPortSets(annotations[ServiceAnnotationLoadBalancerSSLPorts])
|
||||||
for _, port := range apiService.Spec.Ports {
|
for _, port := range apiService.Spec.Ports {
|
||||||
if port.Protocol != v1.ProtocolTCP {
|
if err := checkProtocol(port, annotations); err != nil {
|
||||||
return nil, fmt.Errorf("Only TCP LoadBalancer is supported for AWS ELB")
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if port.NodePort == 0 {
|
if port.NodePort == 0 {
|
||||||
klog.Errorf("Ignoring port without NodePort defined: %v", port)
|
klog.Errorf("Ignoring port without NodePort defined: %v", port)
|
||||||
continue
|
continue
|
||||||
@ -3713,7 +3714,7 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
|
|||||||
}
|
}
|
||||||
|
|
||||||
certificateARN := annotations[ServiceAnnotationLoadBalancerCertificate]
|
certificateARN := annotations[ServiceAnnotationLoadBalancerCertificate]
|
||||||
if certificateARN != "" && (sslPorts == nil || sslPorts.numbers.Has(int64(port.Port)) || sslPorts.names.Has(port.Name)) {
|
if port.Protocol != v1.ProtocolUDP && certificateARN != "" && (sslPorts == nil || sslPorts.numbers.Has(int64(port.Port)) || sslPorts.names.Has(port.Name)) {
|
||||||
portMapping.FrontendProtocol = elbv2.ProtocolEnumTls
|
portMapping.FrontendProtocol = elbv2.ProtocolEnumTls
|
||||||
portMapping.SSLCertificateARN = certificateARN
|
portMapping.SSLCertificateARN = certificateARN
|
||||||
portMapping.SSLPolicy = annotations[ServiceAnnotationLoadBalancerSSLNegotiationPolicy]
|
portMapping.SSLPolicy = annotations[ServiceAnnotationLoadBalancerSSLNegotiationPolicy]
|
||||||
@ -3724,13 +3725,14 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
|
|||||||
}
|
}
|
||||||
|
|
||||||
v2Mappings = append(v2Mappings, portMapping)
|
v2Mappings = append(v2Mappings, portMapping)
|
||||||
}
|
} else {
|
||||||
listener, err := buildListener(port, annotations, sslPorts)
|
listener, err := buildListener(port, annotations, sslPorts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
listeners = append(listeners, listener)
|
listeners = append(listeners, listener)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if apiService.Spec.LoadBalancerIP != "" {
|
if apiService.Spec.LoadBalancerIP != "" {
|
||||||
return nil, fmt.Errorf("LoadBalancerIP cannot be specified for AWS ELB")
|
return nil, fmt.Errorf("LoadBalancerIP cannot be specified for AWS ELB")
|
||||||
@ -4762,6 +4764,18 @@ func (c *Cloud) nodeNameToProviderID(nodeName types.NodeName) (InstanceID, error
|
|||||||
return KubernetesInstanceID(node.Spec.ProviderID).MapToAWSInstanceID()
|
return KubernetesInstanceID(node.Spec.ProviderID).MapToAWSInstanceID()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkProtocol(port v1.ServicePort, annotations map[string]string) error {
|
||||||
|
// nlb supports tcp, udp
|
||||||
|
if isNLB(annotations) && (port.Protocol == v1.ProtocolTCP || port.Protocol == v1.ProtocolUDP) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// elb only supports tcp
|
||||||
|
if !isNLB(annotations) && port.Protocol == v1.ProtocolTCP {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return fmt.Errorf("Protocol %s not supported by LoadBalancer", port.Protocol)
|
||||||
|
}
|
||||||
|
|
||||||
func setNodeDisk(
|
func setNodeDisk(
|
||||||
nodeDiskMap map[types.NodeName]map[KubernetesVolumeID]bool,
|
nodeDiskMap map[types.NodeName]map[KubernetesVolumeID]bool,
|
||||||
volumeID KubernetesVolumeID,
|
volumeID KubernetesVolumeID,
|
||||||
|
@ -185,9 +185,12 @@ func (c *Cloud) ensureLoadBalancerv2(namespacedName types.NamespacedName, loadBa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// actual maps FrontendPort to an elbv2.Listener
|
// actual maps FrontendPort to an elbv2.Listener
|
||||||
actual := map[int64]*elbv2.Listener{}
|
actual := map[int64]map[string]*elbv2.Listener{}
|
||||||
for _, listener := range listenerDescriptions.Listeners {
|
for _, listener := range listenerDescriptions.Listeners {
|
||||||
actual[*listener.Port] = listener
|
if actual[*listener.Port] == nil {
|
||||||
|
actual[*listener.Port] = map[string]*elbv2.Listener{}
|
||||||
|
}
|
||||||
|
actual[*listener.Port][*listener.Protocol] = listener
|
||||||
}
|
}
|
||||||
|
|
||||||
actualTargetGroups, err := c.elbv2.DescribeTargetGroups(
|
actualTargetGroups, err := c.elbv2.DescribeTargetGroups(
|
||||||
@ -207,10 +210,11 @@ func (c *Cloud) ensureLoadBalancerv2(namespacedName types.NamespacedName, loadBa
|
|||||||
// Handle additions/modifications
|
// Handle additions/modifications
|
||||||
for _, mapping := range mappings {
|
for _, mapping := range mappings {
|
||||||
frontendPort := mapping.FrontendPort
|
frontendPort := mapping.FrontendPort
|
||||||
|
frontendProtocol := mapping.FrontendProtocol
|
||||||
nodePort := mapping.TrafficPort
|
nodePort := mapping.TrafficPort
|
||||||
|
|
||||||
// modifications
|
// modifications
|
||||||
if listener, ok := actual[frontendPort]; ok {
|
if listener, ok := actual[frontendPort][frontendProtocol]; ok {
|
||||||
listenerNeedsModification := false
|
listenerNeedsModification := false
|
||||||
|
|
||||||
if aws.StringValue(listener.Protocol) != mapping.FrontendProtocol {
|
if aws.StringValue(listener.Protocol) != mapping.FrontendProtocol {
|
||||||
@ -315,15 +319,19 @@ func (c *Cloud) ensureLoadBalancerv2(namespacedName types.NamespacedName, loadBa
|
|||||||
dirty = true
|
dirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
frontEndPorts := map[int64]bool{}
|
frontEndPorts := map[int64]map[string]bool{}
|
||||||
for i := range mappings {
|
for i := range mappings {
|
||||||
frontEndPorts[mappings[i].FrontendPort] = true
|
if frontEndPorts[mappings[i].FrontendPort] == nil {
|
||||||
|
frontEndPorts[mappings[i].FrontendPort] = map[string]bool{}
|
||||||
|
}
|
||||||
|
frontEndPorts[mappings[i].FrontendPort][mappings[i].FrontendProtocol] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle deletions
|
// handle deletions
|
||||||
for port, listener := range actual {
|
for port := range actual {
|
||||||
if _, ok := frontEndPorts[port]; !ok {
|
for protocol := range actual[port] {
|
||||||
err := c.deleteListenerV2(listener)
|
if _, ok := frontEndPorts[port][protocol]; !ok {
|
||||||
|
err := c.deleteListenerV2(actual[port][protocol])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -331,7 +339,7 @@ func (c *Cloud) ensureLoadBalancerv2(namespacedName types.NamespacedName, loadBa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if err := c.reconcileLBAttributes(aws.StringValue(loadBalancer.LoadBalancerArn), annotations); err != nil {
|
if err := c.reconcileLBAttributes(aws.StringValue(loadBalancer.LoadBalancerArn), annotations); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -768,10 +776,14 @@ func (c *Cloud) updateInstanceSecurityGroupsForNLB(lbName string, instances map[
|
|||||||
|
|
||||||
{
|
{
|
||||||
clientPorts := sets.Int64{}
|
clientPorts := sets.Int64{}
|
||||||
|
clientProtocol := "tcp"
|
||||||
healthCheckPorts := sets.Int64{}
|
healthCheckPorts := sets.Int64{}
|
||||||
for _, port := range portMappings {
|
for _, port := range portMappings {
|
||||||
clientPorts.Insert(port.TrafficPort)
|
clientPorts.Insert(port.TrafficPort)
|
||||||
healthCheckPorts.Insert(port.HealthCheckPort)
|
healthCheckPorts.Insert(port.HealthCheckPort)
|
||||||
|
if port.TrafficProtocol == string(v1.ProtocolUDP) {
|
||||||
|
clientProtocol = "udp"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
clientRuleAnnotation := fmt.Sprintf("%s=%s", NLBClientRuleDescription, lbName)
|
clientRuleAnnotation := fmt.Sprintf("%s=%s", NLBClientRuleDescription, lbName)
|
||||||
healthRuleAnnotation := fmt.Sprintf("%s=%s", NLBHealthCheckRuleDescription, lbName)
|
healthRuleAnnotation := fmt.Sprintf("%s=%s", NLBHealthCheckRuleDescription, lbName)
|
||||||
@ -785,14 +797,14 @@ func (c *Cloud) updateInstanceSecurityGroupsForNLB(lbName string, instances map[
|
|||||||
if err := c.updateInstanceSecurityGroupForNLBTraffic(sgID, sgPerms, healthRuleAnnotation, "tcp", healthCheckPorts, vpcCIDRs); err != nil {
|
if err := c.updateInstanceSecurityGroupForNLBTraffic(sgID, sgPerms, healthRuleAnnotation, "tcp", healthCheckPorts, vpcCIDRs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := c.updateInstanceSecurityGroupForNLBTraffic(sgID, sgPerms, clientRuleAnnotation, "tcp", clientPorts, clientCIDRs); err != nil {
|
if err := c.updateInstanceSecurityGroupForNLBTraffic(sgID, sgPerms, clientRuleAnnotation, clientProtocol, clientPorts, clientCIDRs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := c.updateInstanceSecurityGroupForNLBTraffic(sgID, sgPerms, healthRuleAnnotation, "tcp", nil, nil); err != nil {
|
if err := c.updateInstanceSecurityGroupForNLBTraffic(sgID, sgPerms, healthRuleAnnotation, "tcp", nil, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := c.updateInstanceSecurityGroupForNLBTraffic(sgID, sgPerms, clientRuleAnnotation, "tcp", nil, nil); err != nil {
|
if err := c.updateInstanceSecurityGroupForNLBTraffic(sgID, sgPerms, clientRuleAnnotation, clientProtocol, nil, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1371,6 +1371,53 @@ func TestDescribeLoadBalancerOnEnsure(t *testing.T) {
|
|||||||
c.EnsureLoadBalancer(context.TODO(), TestClusterName, &v1.Service{ObjectMeta: metav1.ObjectMeta{Name: "myservice", UID: "id"}}, []*v1.Node{})
|
c.EnsureLoadBalancer(context.TODO(), TestClusterName, &v1.Service{ObjectMeta: metav1.ObjectMeta{Name: "myservice", UID: "id"}}, []*v1.Node{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckProtocol(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
annotations map[string]string
|
||||||
|
port v1.ServicePort
|
||||||
|
wantErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "TCP with ELB",
|
||||||
|
annotations: make(map[string]string),
|
||||||
|
port: v1.ServicePort{Protocol: v1.ProtocolTCP, Port: int32(8080)},
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TCP with NLB",
|
||||||
|
annotations: map[string]string{ServiceAnnotationLoadBalancerType: "nlb"},
|
||||||
|
port: v1.ServicePort{Protocol: v1.ProtocolTCP, Port: int32(8080)},
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UDP with ELB",
|
||||||
|
annotations: make(map[string]string),
|
||||||
|
port: v1.ServicePort{Protocol: v1.ProtocolUDP, Port: int32(8080)},
|
||||||
|
wantErr: fmt.Errorf("Protocol UDP not supported by load balancer"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UDP with NLB",
|
||||||
|
annotations: map[string]string{ServiceAnnotationLoadBalancerType: "nlb"},
|
||||||
|
port: v1.ServicePort{Protocol: v1.ProtocolUDP, Port: int32(8080)},
|
||||||
|
wantErr: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
tt := test
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
err := checkProtocol(tt.port, tt.annotations)
|
||||||
|
if tt.wantErr != nil && err == nil {
|
||||||
|
t.Errorf("Expected error: want=%s got =%s", tt.wantErr, err)
|
||||||
|
}
|
||||||
|
if tt.wantErr == nil && err != nil {
|
||||||
|
t.Errorf("Unexpected error: want=%s got =%s", tt.wantErr, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuildListener(t *testing.T) {
|
func TestBuildListener(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
Loading…
Reference in New Issue
Block a user