From 7767535426b29fc14461083528b0d15493a3262e Mon Sep 17 00:00:00 2001 From: Brooks Garrett Date: Fri, 28 Sep 2018 23:25:04 -0400 Subject: [PATCH] Respect Allocation IDs --- .../k8s.io/legacy-cloud-providers/aws/aws.go | 19 ++++++++++++++--- .../aws/aws_loadbalancer.go | 21 ++++++++++++++----- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go b/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go index 07f0bc064cb..59b21bffe6e 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go +++ b/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go @@ -23,6 +23,7 @@ import ( "io" "net" "path" + "sort" "strconv" "strings" "sync" @@ -44,9 +45,9 @@ import ( "github.com/aws/aws-sdk-go/service/kms" "github.com/aws/aws-sdk-go/service/sts" "gopkg.in/gcfg.v1" + "k8s.io/api/core/v1" "k8s.io/klog" - "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -199,6 +200,11 @@ const ServiceAnnotationLoadBalancerHCTimeout = "service.beta.kubernetes.io/aws-l // service to specify, in seconds, the interval between health checks. const ServiceAnnotationLoadBalancerHCInterval = "service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval" +// ServiceAnnotationLoadBalancerEIPAllocations is the annotation used on the +// service to specify a comma separated list of EIP allocations to use as +// static IP addresses for the NLB. Only supported on elbv2 (NLB) +const ServiceAnnotationLoadBalancerEIPAllocations = "service.beta.kubernetes.io/aws-load-balancer-eip-allocations" + // Event key when a volume is stuck on attaching state when being attached to a volume const volumeAttachmentStuck = "VolumeAttachmentStuck" @@ -3281,9 +3287,16 @@ func (c *Cloud) findELBSubnets(internalELB bool) ([]string, error) { continue } + var azNames []string + for key := range subnetsByAZ { + azNames = append(azNames, key) + } + + sort.Strings(azNames) + var subnetIDs []string - for _, subnet := range subnetsByAZ { - subnetIDs = append(subnetIDs, aws.StringValue(subnet.SubnetId)) + for _, key := range azNames { + subnetIDs = append(subnetIDs, aws.StringValue(subnetsByAZ[key].SubnetId)) } return subnetIDs, nil diff --git a/staging/src/k8s.io/legacy-cloud-providers/aws/aws_loadbalancer.go b/staging/src/k8s.io/legacy-cloud-providers/aws/aws_loadbalancer.go index 3d6b50840d7..349e5a05de9 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/aws/aws_loadbalancer.go +++ b/staging/src/k8s.io/legacy-cloud-providers/aws/aws_loadbalancer.go @@ -132,9 +132,17 @@ func (c *Cloud) ensureLoadBalancerv2(namespacedName types.NamespacedName, loadBa createRequest.Scheme = aws.String("internal") } + var allocationIDs []string + if eipList, present := annotations[ServiceAnnotationLoadBalancerEIPAllocations]; present { + allocationIDs = strings.Split(eipList, ",") + if len(allocationIDs) != len(subnetIDs) { + return nil, fmt.Errorf("Error creating load balancer: Must have same number of EIP AllocationIDs (%d) and SubnetIDs (%d)", len(allocationIDs), len(subnetIDs)) + } + } + // We are supposed to specify one subnet per AZ. // TODO: What happens if we have more than one subnet per AZ? - createRequest.SubnetMappings = createSubnetMappings(subnetIDs) + createRequest.SubnetMappings = createSubnetMappings(subnetIDs, allocationIDs) for k, v := range tags { createRequest.Tags = append(createRequest.Tags, &elbv2.Tag{ @@ -1347,12 +1355,15 @@ func elbListenersAreEqual(actual, expected *elb.Listener) bool { return true } -func createSubnetMappings(subnetIDs []string) []*elbv2.SubnetMapping { +func createSubnetMappings(subnetIDs []string, allocationIDs []string) []*elbv2.SubnetMapping { response := []*elbv2.SubnetMapping{} - for _, id := range subnetIDs { - // Ignore AllocationId for now - response = append(response, &elbv2.SubnetMapping{SubnetId: aws.String(id)}) + for index, id := range subnetIDs { + sm := &elbv2.SubnetMapping{SubnetId: aws.String(id)} + if len(allocationIDs) > 0 { + sm.AllocationId = aws.String(allocationIDs[index]) + } + response = append(response, sm) } return response