@@ -223,8 +223,14 @@ type APIs interface {
223
223
224
224
IsPrefixDelegationSupported () bool
225
225
226
- // IsPrimarySubnetExcluded returns if the primary subnet is excluded for pod IPs
227
- IsPrimarySubnetExcluded (ctx context.Context ) (bool , error )
226
+ // GetENISubnetID gets the subnet ID for an ENI from AWS
227
+ GetENISubnetID (ctx context.Context , eniID string ) (string , error )
228
+
229
+ // GetVpcSubnets returns all subnets in the VPC
230
+ GetVpcSubnets (ctx context.Context ) ([]ec2types.Subnet , error )
231
+
232
+ // IsSubnetExcluded returns if a subnet is excluded for pod IPs based on its tags
233
+ IsSubnetExcluded (ctx context.Context , subnetID string ) (bool , error )
228
234
}
229
235
230
236
// EC2InstanceMetadataCache caches instance metadata
@@ -554,8 +560,8 @@ func (cache *EC2InstanceMetadataCache) discoverCustomSecurityGroups(ctx context.
554
560
return sgIDs , nil
555
561
}
556
562
557
- // getENISubnetID gets the subnet ID for an ENI from AWS
558
- func (cache * EC2InstanceMetadataCache ) getENISubnetID (ctx context.Context , eniID string ) (string , error ) {
563
+ // GetENISubnetID gets the subnet ID for an ENI from AWS
564
+ func (cache * EC2InstanceMetadataCache ) GetENISubnetID (ctx context.Context , eniID string ) (string , error ) {
559
565
describeInput := & ec2.DescribeNetworkInterfacesInput {
560
566
NetworkInterfaceIds : []string {eniID },
561
567
}
@@ -574,7 +580,7 @@ func (cache *EC2InstanceMetadataCache) getENISubnetID(ctx context.Context, eniID
574
580
575
581
// Helper function to check if an ENI is in a secondary subnet
576
582
func (cache * EC2InstanceMetadataCache ) isENIInSecondarySubnet (ctx context.Context , eniID string ) bool {
577
- eniSubnetID , err := cache .getENISubnetID (ctx , eniID )
583
+ eniSubnetID , err := cache .GetENISubnetID (ctx , eniID )
578
584
return err == nil && eniSubnetID != cache .subnetID
579
585
}
580
586
@@ -1175,13 +1181,13 @@ func (cache *EC2InstanceMetadataCache) createENI(ctx context.Context, sg []*stri
1175
1181
}
1176
1182
} else {
1177
1183
if cache .useSubnetDiscovery {
1178
- subnetResult , vpcErr := cache .getVpcSubnets (ctx )
1184
+ subnetResult , vpcErr := cache .GetVpcSubnets (ctx )
1179
1185
if vpcErr != nil {
1180
1186
log .Warnf ("Failed to call ec2:DescribeSubnets: %v" , vpcErr )
1181
1187
log .Info ("Defaulting to same subnet as the primary interface for the new ENI" )
1182
1188
1183
1189
// Even in fallback, check if primary subnet is excluded
1184
- excluded , checkErr := cache .IsPrimarySubnetExcluded (ctx )
1190
+ excluded , checkErr := cache .IsSubnetExcluded (ctx , cache . subnetID )
1185
1191
if checkErr != nil {
1186
1192
log .Warnf ("Failed to check if primary subnet is excluded: %v. Proceeding with ENI creation attempt." , checkErr )
1187
1193
} else if excluded {
@@ -1232,7 +1238,7 @@ func (cache *EC2InstanceMetadataCache) createENI(ctx context.Context, sg []*stri
1232
1238
} else {
1233
1239
log .Info ("Using same security group config as the primary interface for the new ENI" )
1234
1240
// When subnet discovery is disabled, check if primary subnet is excluded
1235
- excluded , checkErr := cache .IsPrimarySubnetExcluded (ctx )
1241
+ excluded , checkErr := cache .IsSubnetExcluded (ctx , cache . subnetID )
1236
1242
if checkErr != nil {
1237
1243
// If we can't determine exclusion status, log warning and proceed
1238
1244
log .Warnf ("Failed to check if primary subnet is excluded: %v. Proceeding with ENI creation attempt." , checkErr )
@@ -1250,7 +1256,7 @@ func (cache *EC2InstanceMetadataCache) createENI(ctx context.Context, sg []*stri
1250
1256
return "" , errors .Wrap (err , "failed to create network interface" )
1251
1257
}
1252
1258
1253
- func (cache * EC2InstanceMetadataCache ) getVpcSubnets (ctx context.Context ) ([]ec2types.Subnet , error ) {
1259
+ func (cache * EC2InstanceMetadataCache ) GetVpcSubnets (ctx context.Context ) ([]ec2types.Subnet , error ) {
1254
1260
describeSubnetInput := & ec2.DescribeSubnetsInput {
1255
1261
Filters : []ec2types.Filter {
1256
1262
{
@@ -2576,31 +2582,34 @@ func checkAPIErrorAndBroadcastEvent(err error, api string) {
2576
2582
}
2577
2583
}
2578
2584
2579
- // isPrimarySubnetExcluded checks if the primary subnet has the kubernetes.io/role/cni=0 tag
2580
- func (cache * EC2InstanceMetadataCache ) IsPrimarySubnetExcluded (ctx context.Context ) (bool , error ) {
2581
- // Get the primary subnet information
2582
- describeSubnetInput := & ec2.DescribeSubnetsInput {
2583
- SubnetIds : []string {cache .subnetID },
2584
- }
2585
-
2586
- start := time .Now ()
2587
- subnetResult , err := cache .ec2SVC .DescribeSubnets (ctx , describeSubnetInput )
2588
- prometheusmetrics .Ec2ApiReq .WithLabelValues ("DescribeSubnets" ).Inc ()
2589
- prometheusmetrics .AwsAPILatency .WithLabelValues ("DescribeSubnets" , fmt .Sprint (err != nil ), awsReqStatus (err )).Observe (msSince (start ))
2585
+ // IsSubnetExcluded checks if a subnet is excluded by examining its kubernetes.io/role/cni tag
2586
+ func (cache * EC2InstanceMetadataCache ) IsSubnetExcluded (ctx context.Context , subnetID string ) (bool , error ) {
2587
+ // Get all VPC subnets with their tags
2588
+ subnets , err := cache .GetVpcSubnets (ctx )
2590
2589
if err != nil {
2591
- checkAPIErrorAndBroadcastEvent (err , "ec2:DescribeSubnets" )
2592
- awsAPIErrInc ("DescribeSubnets" , err )
2593
- prometheusmetrics .Ec2ApiErr .WithLabelValues ("DescribeSubnets" ).Inc ()
2594
- log .Errorf ("Failed to describe primary subnet %s: %v" , cache .subnetID , err )
2595
- return false , fmt .Errorf ("isPrimarySubnetExcluded: unable to describe primary subnet: %v" , err )
2596
- }
2590
+ return false , fmt .Errorf ("failed to get VPC subnets: %v" , err )
2591
+ }
2592
+
2593
+ // Find the specific subnet and check its tags
2594
+ for _ , subnet := range subnets {
2595
+ if * subnet .SubnetId == subnetID {
2596
+ // Check if the subnet has the exclusion tag kubernetes.io/role/cni=0
2597
+ for _ , tag := range subnet .Tags {
2598
+ if * tag .Key == "kubernetes.io/role/cni" {
2599
+ tagValue := * tag .Value
2600
+ excluded := tagValue == "0"
2601
+ log .Debugf ("IsSubnetExcluded: subnet %s has tag kubernetes.io/role/cni=%s, excluded=%t" , subnetID , tagValue , excluded )
2602
+ return excluded , nil
2603
+ }
2604
+ }
2597
2605
2598
- if len (subnetResult .Subnets ) == 0 {
2599
- log .Errorf ("Primary subnet %s not found in DescribeSubnets response" , cache .subnetID )
2600
- return false , fmt .Errorf ("isPrimarySubnetExcluded: primary subnet not found" )
2606
+ // If no kubernetes.io/role/cni tag found, subnet is not explicitly excluded
2607
+ log .Debugf ("IsSubnetExcluded: subnet %s has no kubernetes.io/role/cni tag, not excluded" , subnetID )
2608
+ return false , nil
2609
+ }
2601
2610
}
2602
2611
2603
- subnet := subnetResult . Subnets [ 0 ]
2604
- // Check if the subnet has the exclusion tag
2605
- return ! validTag ( subnet , true ), nil
2612
+ // Subnet not found in VPC
2613
+ log . Warnf ( "IsSubnetExcluded: subnet %s not found in VPC" , subnetID )
2614
+ return false , fmt . Errorf ( " subnet %s not found in VPC" , subnetID )
2606
2615
}
0 commit comments