@@ -1946,12 +1946,16 @@ func (c *Cloud) buildELBSecurityGroupList(serviceName types.NamespacedName, load
1946
1946
// from buildELBSecurityGroupList. The logic is:
1947
1947
// - securityGroups specified by ServiceAnnotationLoadBalancerSecurityGroups appears first in order
1948
1948
// - securityGroups specified by ServiceAnnotationLoadBalancerExtraSecurityGroups appears last in order
1949
- func (c * Cloud ) sortELBSecurityGroupList (securityGroupIDs []string , annotations map [string ]string ) {
1949
+ func (c * Cloud ) sortELBSecurityGroupList (securityGroupIDs []string , annotations map [string ]string , taggedLBSecurityGroups map [ string ] struct {} ) {
1950
1950
annotatedSGList := getSGListFromAnnotation (annotations [ServiceAnnotationLoadBalancerSecurityGroups ])
1951
1951
annotatedExtraSGList := getSGListFromAnnotation (annotations [ServiceAnnotationLoadBalancerExtraSecurityGroups ])
1952
1952
annotatedSGIndex := make (map [string ]int , len (annotatedSGList ))
1953
1953
annotatedExtraSGIndex := make (map [string ]int , len (annotatedExtraSGList ))
1954
1954
1955
+ if taggedLBSecurityGroups == nil {
1956
+ taggedLBSecurityGroups = make (map [string ]struct {})
1957
+ }
1958
+
1955
1959
for i , sgID := range annotatedSGList {
1956
1960
annotatedSGIndex [sgID ] = i
1957
1961
}
@@ -1969,7 +1973,11 @@ func (c *Cloud) sortELBSecurityGroupList(securityGroupIDs []string, annotations
1969
1973
}
1970
1974
}
1971
1975
sort .Slice (securityGroupIDs , func (i , j int ) bool {
1972
- return sgOrderMapping [securityGroupIDs [i ]] < sgOrderMapping [securityGroupIDs [j ]]
1976
+ // If i is tagged but j is not, then i should be before j.
1977
+ _ , iTagged := taggedLBSecurityGroups [securityGroupIDs [i ]]
1978
+ _ , jTagged := taggedLBSecurityGroups [securityGroupIDs [j ]]
1979
+
1980
+ return sgOrderMapping [securityGroupIDs [i ]] < sgOrderMapping [securityGroupIDs [j ]] || iTagged && ! jTagged
1973
1981
})
1974
1982
}
1975
1983
@@ -2498,7 +2506,7 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
2498
2506
}
2499
2507
}
2500
2508
2501
- err = c .updateInstanceSecurityGroupsForLoadBalancer (loadBalancer , instances , annotations )
2509
+ err = c .updateInstanceSecurityGroupsForLoadBalancer (loadBalancer , instances , annotations , false )
2502
2510
if err != nil {
2503
2511
klog .Warningf ("Error opening ingress rules for the load balancer to the instances: %q" , err )
2504
2512
return nil , err
@@ -2659,7 +2667,7 @@ func (c *Cloud) getTaggedSecurityGroups() (map[string]*ec2.SecurityGroup, error)
2659
2667
2660
2668
// Open security group ingress rules on the instances so that the load balancer can talk to them
2661
2669
// Will also remove any security groups ingress rules for the load balancer that are _not_ needed for allInstances
2662
- func (c * Cloud ) updateInstanceSecurityGroupsForLoadBalancer (lb * elb.LoadBalancerDescription , instances map [InstanceID ]* ec2.Instance , annotations map [string ]string ) error {
2670
+ func (c * Cloud ) updateInstanceSecurityGroupsForLoadBalancer (lb * elb.LoadBalancerDescription , instances map [InstanceID ]* ec2.Instance , annotations map [string ]string , isDeleting bool ) error {
2663
2671
if c .cfg .Global .DisableSecurityGroupIngress {
2664
2672
return nil
2665
2673
}
@@ -2669,11 +2677,24 @@ func (c *Cloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancer
2669
2677
if len (lbSecurityGroupIDs ) == 0 {
2670
2678
return fmt .Errorf ("could not determine security group for load balancer: %s" , aws .StringValue (lb .LoadBalancerName ))
2671
2679
}
2672
- c .sortELBSecurityGroupList (lbSecurityGroupIDs , annotations )
2680
+
2681
+ taggedSecurityGroups , err := c .getTaggedSecurityGroups ()
2682
+ if err != nil {
2683
+ return fmt .Errorf ("error querying for tagged security groups: %q" , err )
2684
+ }
2685
+
2686
+ taggedLBSecurityGroups := make (map [string ]struct {})
2687
+ for _ , sg := range lbSecurityGroupIDs {
2688
+ if _ , ok := taggedSecurityGroups [sg ]; ok {
2689
+ taggedLBSecurityGroups [sg ] = struct {}{}
2690
+ }
2691
+ }
2692
+
2693
+ c .sortELBSecurityGroupList (lbSecurityGroupIDs , annotations , taggedLBSecurityGroups )
2673
2694
loadBalancerSecurityGroupID := lbSecurityGroupIDs [0 ]
2674
2695
2675
2696
// Get the actual list of groups that allow ingress from the load-balancer
2676
- var actualGroups [] * ec2.SecurityGroup
2697
+ actualGroups := make ( map [ * ec2.SecurityGroup ] bool )
2677
2698
{
2678
2699
describeRequest := & ec2.DescribeSecurityGroupsInput {}
2679
2700
describeRequest .Filters = []* ec2.Filter {
@@ -2684,18 +2705,10 @@ func (c *Cloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancer
2684
2705
return fmt .Errorf ("error querying security groups for ELB: %q" , err )
2685
2706
}
2686
2707
for _ , sg := range response {
2687
- if ! c .tagging .hasClusterTag (sg .Tags ) {
2688
- continue
2689
- }
2690
- actualGroups = append (actualGroups , sg )
2708
+ actualGroups [sg ] = c .tagging .hasClusterTag (sg .Tags )
2691
2709
}
2692
2710
}
2693
2711
2694
- taggedSecurityGroups , err := c .getTaggedSecurityGroups ()
2695
- if err != nil {
2696
- return fmt .Errorf ("error querying for tagged security groups: %q" , err )
2697
- }
2698
-
2699
2712
// Open the firewall from the load balancer to the instance
2700
2713
// We don't actually have a trivial way to know in advance which security group the instance is in
2701
2714
// (it is probably the node security group, but we don't easily have that).
@@ -2725,7 +2738,7 @@ func (c *Cloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancer
2725
2738
}
2726
2739
2727
2740
// Compare to actual groups
2728
- for _ , actualGroup := range actualGroups {
2741
+ for actualGroup , hasClusterTag := range actualGroups {
2729
2742
actualGroupID := aws .StringValue (actualGroup .GroupId )
2730
2743
if actualGroupID == "" {
2731
2744
klog .Warning ("Ignoring group without ID: " , actualGroup )
@@ -2737,8 +2750,12 @@ func (c *Cloud) updateInstanceSecurityGroupsForLoadBalancer(lb *elb.LoadBalancer
2737
2750
// We don't need to make a change; the permission is already in place
2738
2751
delete (instanceSecurityGroupIds , actualGroupID )
2739
2752
} else {
2740
- // This group is not needed by allInstances; delete it
2741
- instanceSecurityGroupIds [actualGroupID ] = false
2753
+ if hasClusterTag || isDeleting {
2754
+ // If the group is tagged, and we don't need the rule, we should remove it.
2755
+ // If the security group is deleting, we should also remove the rule else
2756
+ // we cannot remove the security group, we wiil get a dependency violation.
2757
+ instanceSecurityGroupIds [actualGroupID ] = false
2758
+ }
2742
2759
}
2743
2760
}
2744
2761
@@ -2847,28 +2864,11 @@ func (c *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName strin
2847
2864
return nil
2848
2865
}
2849
2866
2850
- {
2851
- // De-authorize the load balancer security group from the instances security group
2852
- err = c .updateInstanceSecurityGroupsForLoadBalancer (lb , nil , service .Annotations )
2853
- if err != nil {
2854
- klog .Errorf ("Error deregistering load balancer from instance security groups: %q" , err )
2855
- return err
2856
- }
2857
- }
2858
-
2859
- {
2860
- // Delete the load balancer itself
2861
- request := & elb.DeleteLoadBalancerInput {}
2862
- request .LoadBalancerName = lb .LoadBalancerName
2863
-
2864
- _ , err = c .elb .DeleteLoadBalancer (request )
2865
- if err != nil {
2866
- // TODO: Check if error was because load balancer was concurrently deleted
2867
- klog .Errorf ("Error deleting load balancer: %q" , err )
2868
- return err
2869
- }
2870
- }
2871
-
2867
+ // Collect the security groups to delete.
2868
+ // We need to know this ahead of time so that we can check
2869
+ // if the load balancer security group is being deleted.
2870
+ securityGroupIDs := map [string ]struct {}{}
2871
+ taggedLBSecurityGroups := map [string ]struct {}{}
2872
2872
{
2873
2873
// Delete the security group(s) for the load balancer
2874
2874
// Note that this is annoying: the load balancer disappears from the API immediately, but it is still
@@ -2884,9 +2884,6 @@ func (c *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName strin
2884
2884
if err != nil {
2885
2885
return fmt .Errorf ("error querying security groups for ELB: %q" , err )
2886
2886
}
2887
-
2888
- // Collect the security groups to delete
2889
- securityGroupIDs := map [string ]struct {}{}
2890
2887
annotatedSgSet := map [string ]bool {}
2891
2888
annotatedSgsList := getSGListFromAnnotation (service .Annotations [ServiceAnnotationLoadBalancerSecurityGroups ])
2892
2889
annotatedExtraSgsList := getSGListFromAnnotation (service .Annotations [ServiceAnnotationLoadBalancerExtraSecurityGroups ])
@@ -2911,6 +2908,8 @@ func (c *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName strin
2911
2908
if ! c .tagging .hasClusterTag (sg .Tags ) {
2912
2909
klog .Warningf ("Ignoring security group with no cluster tag in %s" , service .Name )
2913
2910
continue
2911
+ } else {
2912
+ taggedLBSecurityGroups [sgID ] = struct {}{}
2914
2913
}
2915
2914
2916
2915
// This is an extra protection of deletion of non provisioned Security Group which is annotated with `service.beta.kubernetes.io/aws-load-balancer-security-groups`.
@@ -2921,6 +2920,41 @@ func (c *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName strin
2921
2920
2922
2921
securityGroupIDs [sgID ] = struct {}{}
2923
2922
}
2923
+ }
2924
+
2925
+ {
2926
+ // Determine the load balancer security group id
2927
+ lbSecurityGroupIDs := aws .StringValueSlice (lb .SecurityGroups )
2928
+ if len (lbSecurityGroupIDs ) == 0 {
2929
+ return fmt .Errorf ("could not determine security group for load balancer: %s" , aws .StringValue (lb .LoadBalancerName ))
2930
+ }
2931
+ c .sortELBSecurityGroupList (lbSecurityGroupIDs , service .Annotations , taggedLBSecurityGroups )
2932
+ loadBalancerSecurityGroupID := lbSecurityGroupIDs [0 ]
2933
+
2934
+ _ , isDeleteingLBSecurityGroup := securityGroupIDs [loadBalancerSecurityGroupID ]
2935
+
2936
+ // De-authorize the load balancer security group from the instances security group
2937
+ err = c .updateInstanceSecurityGroupsForLoadBalancer (lb , nil , service .Annotations , isDeleteingLBSecurityGroup )
2938
+ if err != nil {
2939
+ klog .Errorf ("Error deregistering load balancer from instance security groups: %q" , err )
2940
+ return err
2941
+ }
2942
+ }
2943
+
2944
+ {
2945
+ // Delete the load balancer itself
2946
+ request := & elb.DeleteLoadBalancerInput {}
2947
+ request .LoadBalancerName = lb .LoadBalancerName
2948
+
2949
+ _ , err = c .elb .DeleteLoadBalancer (request )
2950
+ if err != nil {
2951
+ // TODO: Check if error was because load balancer was concurrently deleted
2952
+ klog .Errorf ("Error deleting load balancer: %q" , err )
2953
+ return err
2954
+ }
2955
+ }
2956
+
2957
+ {
2924
2958
2925
2959
// Loop through and try to delete them
2926
2960
timeoutAt := time .Now ().Add (time .Second * 600 )
@@ -3017,7 +3051,7 @@ func (c *Cloud) UpdateLoadBalancer(ctx context.Context, clusterName string, serv
3017
3051
return err
3018
3052
}
3019
3053
3020
- err = c .updateInstanceSecurityGroupsForLoadBalancer (lb , instances , service .Annotations )
3054
+ err = c .updateInstanceSecurityGroupsForLoadBalancer (lb , instances , service .Annotations , false )
3021
3055
if err != nil {
3022
3056
return err
3023
3057
}
0 commit comments