-
Notifications
You must be signed in to change notification settings - Fork 738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nodeInit() unnecessarily calls DescribeNetworkInterfaces() IMDS more than once #808
Comments
Actually, it's even less efficient than that... We already call GetVPCIPv4CIDRs() on line 305 and throw away the result :( https:/aws/amazon-vpc-cni-k8s/blob/master/ipamd/ipamd.go#L305 |
nodeInit() is making all these calls to DescribeNetworkInterfaces(), but it's not actually the GetVPCIPv4CIDRs() call that is doing it. It's all the callers of IPAMContext.getENIAddresses(): amazon-vpc-cni-k8s/ipamd/ipamd.go Line 792 in 4bf10a0
IPAMContext.getENIAddresses() calls the awsClient.DescribeENI() method, which bypasses the "cache" and calls the IMDS's DescribeNetworkInterfaces() API call. In short, the solution here is to call DescribeNetworkInterfaces() once at the start of nodeInit() and pass the results of that call along to subroutines like setupENI() and tryAssignIPs(). |
Even though the call to IPAMContext.awsClient.GetVPCIPv4CIDRs() simply returns the cached list of CIDRs for the node, IPAMContext.nodeInit() was unnecessarily calling it N+1 times, where N = #pods on the instance. This patch changes nodeInit() to call GetVPCIPv4CIDRs() once and then pass the CIDRs into the inner loops. Issue aws#808
In IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile(), the IPAMContext.setupENI() method was being called, passing in an ENIMetadata struct that contained the "local" IPv4 addresses that had been queried from IMDS. IPAMContext.setupENI() called the IPAMContext.getENIAddresses() method, however, which in turn calls the AWS EC2 DescribeNetworkInterfaces API. The DescribeNetworkInterfaces API call is expensive and throttled, and so we need to be careful how often we call it. In the case of IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile(), they were both calling IPAMContext.setupENI() and passing along an ENIMetadata struct that both methods had previously constructed using the EC2InstanceMetadataCache.GetAttachedENIs() method, which in turn called EC2InstanceMetadataCache.getENIMetadata(). EC2InstanceMetadataCache.getENIMetadata() itself ended up calling the DescribeNetworkInterfaces EC2 API for each ENI on the host machine. So, the slice of ENIMetadata structs returned from EC2InstanceMetadataCache.GetAttachedENIs() -- which was being called by IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile() *already had the most up-to-date information from the DescribeNetworkInterfaces EC2 API call*. Therefore, what this patch does is simply modify the ENIMetadata struct to store the slice of pointer to ec2.NetworkInterfacePrivateIpAddress structs that is returned from the DescribeNetworkInterfaces EC2 API call. That way, for methods like IPAMContext.setupENI(), which passes in an ENIMetadata struct, we can remove the call to IPAMContext.getENIAddresses() which cuts down on the number of duplicate calls to DescribeNetworkInterfaces EC2 API. Issue aws#808
Even though the call to IPAMContext.awsClient.GetVPCIPv4CIDRs() simply returns the cached list of CIDRs for the node, IPAMContext.nodeInit() was unnecessarily calling it N+1 times, where N = #pods on the instance. This patch changes nodeInit() to call GetVPCIPv4CIDRs() once and then pass the CIDRs into the inner loops. Issue #808
In IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile(), the IPAMContext.setupENI() method was being called, passing in an ENIMetadata struct that contained the "local" IPv4 addresses that had been queried from IMDS. IPAMContext.setupENI() called the IPAMContext.getENIAddresses() method, however, which in turn calls the AWS EC2 DescribeNetworkInterfaces API. The DescribeNetworkInterfaces API call is expensive and throttled, and so we need to be careful how often we call it. In the case of IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile(), they were both calling IPAMContext.setupENI() and passing along an ENIMetadata struct that both methods had previously constructed using the EC2InstanceMetadataCache.GetAttachedENIs() method, which in turn called EC2InstanceMetadataCache.getENIMetadata(). EC2InstanceMetadataCache.getENIMetadata() itself ended up calling the DescribeNetworkInterfaces EC2 API for each ENI on the host machine. So, the slice of ENIMetadata structs returned from EC2InstanceMetadataCache.GetAttachedENIs() -- which was being called by IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile() *already had the most up-to-date information from the DescribeNetworkInterfaces EC2 API call*. Therefore, what this patch does is simply modify the ENIMetadata struct to store the slice of pointer to ec2.NetworkInterfacePrivateIpAddress structs that is returned from the DescribeNetworkInterfaces EC2 API call. That way, for methods like IPAMContext.setupENI(), which passes in an ENIMetadata struct, we can remove the call to IPAMContext.getENIAddresses() which cuts down on the number of duplicate calls to DescribeNetworkInterfaces EC2 API. Issue #808
Even though the call to IPAMContext.awsClient.GetVPCIPv4CIDRs() simply returns the cached list of CIDRs for the node, IPAMContext.nodeInit() was unnecessarily calling it N+1 times, where N = #pods on the instance. This patch changes nodeInit() to call GetVPCIPv4CIDRs() once and then pass the CIDRs into the inner loops. Issue aws#808 (cherry picked from commit fb00d8b)
In IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile(), the IPAMContext.setupENI() method was being called, passing in an ENIMetadata struct that contained the "local" IPv4 addresses that had been queried from IMDS. IPAMContext.setupENI() called the IPAMContext.getENIAddresses() method, however, which in turn calls the AWS EC2 DescribeNetworkInterfaces API. The DescribeNetworkInterfaces API call is expensive and throttled, and so we need to be careful how often we call it. In the case of IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile(), they were both calling IPAMContext.setupENI() and passing along an ENIMetadata struct that both methods had previously constructed using the EC2InstanceMetadataCache.GetAttachedENIs() method, which in turn called EC2InstanceMetadataCache.getENIMetadata(). EC2InstanceMetadataCache.getENIMetadata() itself ended up calling the DescribeNetworkInterfaces EC2 API for each ENI on the host machine. So, the slice of ENIMetadata structs returned from EC2InstanceMetadataCache.GetAttachedENIs() -- which was being called by IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile() *already had the most up-to-date information from the DescribeNetworkInterfaces EC2 API call*. Therefore, what this patch does is simply modify the ENIMetadata struct to store the slice of pointer to ec2.NetworkInterfacePrivateIpAddress structs that is returned from the DescribeNetworkInterfaces EC2 API call. That way, for methods like IPAMContext.setupENI(), which passes in an ENIMetadata struct, we can remove the call to IPAMContext.getENIAddresses() which cuts down on the number of duplicate calls to DescribeNetworkInterfaces EC2 API. Issue aws#808 (cherry picked from commit 30d63c6)
Even though the call to IPAMContext.awsClient.GetVPCIPv4CIDRs() simply returns the cached list of CIDRs for the node, IPAMContext.nodeInit() was unnecessarily calling it N+1 times, where N = #pods on the instance. This patch changes nodeInit() to call GetVPCIPv4CIDRs() once and then pass the CIDRs into the inner loops. Issue #808 (cherry picked from commit fb00d8b)
In IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile(), the IPAMContext.setupENI() method was being called, passing in an ENIMetadata struct that contained the "local" IPv4 addresses that had been queried from IMDS. IPAMContext.setupENI() called the IPAMContext.getENIAddresses() method, however, which in turn calls the AWS EC2 DescribeNetworkInterfaces API. The DescribeNetworkInterfaces API call is expensive and throttled, and so we need to be careful how often we call it. In the case of IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile(), they were both calling IPAMContext.setupENI() and passing along an ENIMetadata struct that both methods had previously constructed using the EC2InstanceMetadataCache.GetAttachedENIs() method, which in turn called EC2InstanceMetadataCache.getENIMetadata(). EC2InstanceMetadataCache.getENIMetadata() itself ended up calling the DescribeNetworkInterfaces EC2 API for each ENI on the host machine. So, the slice of ENIMetadata structs returned from EC2InstanceMetadataCache.GetAttachedENIs() -- which was being called by IPAMContext.nodeInit() and IPAMContext.nodeIPPoolReconcile() *already had the most up-to-date information from the DescribeNetworkInterfaces EC2 API call*. Therefore, what this patch does is simply modify the ENIMetadata struct to store the slice of pointer to ec2.NetworkInterfacePrivateIpAddress structs that is returned from the DescribeNetworkInterfaces EC2 API call. That way, for methods like IPAMContext.setupENI(), which passes in an ENIMetadata struct, we can remove the call to IPAMContext.getENIAddresses() which cuts down on the number of duplicate calls to DescribeNetworkInterfaces EC2 API. Issue #808 (cherry picked from commit 30d63c6)
nodeInit() - https:/aws/amazon-vpc-cni-k8s/blob/master/ipamd/ipamd.go#L271) function grabs all the ENIs for the worker node, then grabs all pods on the worker node and loops through all the pods setting up iptables rules.
This piece of code: https:/aws/amazon-vpc-cni-k8s/blob/master/ipamd/ipamd.go#L373-L378
can and should be pulled out of that loop since it's not dependent on the contents of the loop iteration. This would eliminate N-1 calls to IMDS to get the subnets associated with the node, where N == #pods
The text was updated successfully, but these errors were encountered: