Skip to content
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

Unassign IPs over warm IP target #412

Closed

Conversation

nckturner
Copy link
Contributor

@nckturner nckturner commented Apr 25, 2019

This is a change to the behavior of WARM_IP_TARGET. When the plugin's IP address pool goes beyond WARM_IP_TARGET, it will unassign excess IP addresses in order to reduce the total number of allocated IP addresses.

The way it does this is when the number of available IPs is short of WARM_IP_TARGET, we allocate the remaining IPs on the ENI. Every 30 seconds, if IPs remain ununsed, the decreaseIPPool function will deallocate IPs left over on ENIs down to WARM_IP_TARGET.

Issue #, if available:
Helps with concerns like #314 where total IP usage in a VPC is a problem

Description of changes:

  • Moved IP allocation and retry logic into increaseIPPool(),
  • Removed retryAllocENIIP().
  • Modified c.decreaseIPPool() to be c.decreaseIPPool(decreaseIPPoolInterval), so that it does not run as frequently (now every 30 seconds) to allow for IPs to be used by kubelet before being unassigned and removed from the pool.
  • Additionally renamed a number of functions and variables to better reflect their function.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@nckturner nckturner requested a review from mogren April 25, 2019 15:32
@@ -883,6 +886,34 @@ func (cache *EC2InstanceMetadataCache) AllocIPAddresses(eniID string, numIPs int
return nil
}

// DeallocIPAddresses allocates numIPs of IP address on an ENI
func (cache *EC2InstanceMetadataCache) DeallocIPAddresses(eniID string, ips []string) error {
ctx := context.Background()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently just using a dummy context, but in a future change we should pipe context from higher up so that we can take advantage of cancellation.

@@ -348,177 +352,254 @@ func (c *IPAMContext) StartNodeIPPoolManager() {
}

func (c *IPAMContext) updateIPPoolIfRequired() {
c.retryAllocENIIP()
Copy link
Contributor Author

@nckturner nckturner Apr 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic was moved into increaseIPPool, since that's what its doing, and if WARM_IP_TARGET is set, then its not always a retry.

log.Debugf("Found ENI %s that has less than the maximum number of IP addresses allocated: cur=%d, max=%d",
eni.ID, len(eni.IPv4Addresses), maxIPPerENI)

err = c.awsClient.AllocIPAddresses(eni.ID, maxIPPerENI-int64(len(eni.IPv4Addresses)))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is the IP allocation logic for each ENI. We attempt to allocate the remaining IPs on the ENI, keep them around until the next decreaseIPPool (which is called if we are over WARM_IP_TARGET), and then they will be unassigned if they are still not used. We only get here if we have less than WARM_IP_TARGET, so this doesn't continuously assign and unassign IPs.

if eni != nil {
log.Debugf("Attempt again to allocate IP address for ENI :%s", eni.ID)
var err error
if warmIPTargetDefined {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See line 587 to see where the IP allocation logic moved for cases where ENIs should have more assigned IPs than they currently have.

@@ -850,17 +929,25 @@ func getWarmIPTarget() int {
return noWarmIPTarget
}

func (c *IPAMContext) getCurWarmIPTarget() (int64, bool) {
func (c *IPAMContext) ipTargetState() (short int, over int, enabled bool) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This now returns short (the number of IPs that we are short of the target), over (the number of IPs that we are over the target) and enabled. I thought it made more sense than using a negative number to represent short, but maybe its more confusing. Appreciate feedback.

When the plugin's IP address pool goes beyond WARM_IP_TARGET,
it will unassign excess IP addresses in order to reduce the total
number of allocated IP addresses.
@nckturner nckturner force-pushed the remove-ips-over-warm-ip-target branch from 9084865 to 935e26d Compare April 25, 2019 15:50
total, used := c.dataStore.GetStats()
log.Debugf("Successfully decreased IP pool")
logPoolStats(int64(total), int64(used), c.currentMaxAddrsPerENI, c.maxAddrsPerENI)
}

// findFreeableIPs finds and returns IPs that are not assigned to Pods but are attached
// to ENIs on the node.
func (c *IPAMContext) findFreeableIPs(eni string) ([]string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice with a unit test for this one.


// Deallocate IPs from the instance if they aren't used by pods.
if err := c.awsClient.DeallocIPAddresses(eniID, ips); err != nil {
log.Debugf(fmt.Sprintf("Failed to decrease IP pool by removing IPs %v from ENI %s: %s", ips, eniID, err))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we try to free 5 IPs and the call fails. Could 3 have been freed? Might be handled by the reconcile loop.

@@ -3,58 +3,63 @@ module github.com/aws/amazon-vpc-cni-k8s
go 1.12

require (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the actual dependency change? How easy is this PR to cherry pick over to the release-1.4 branch?

github.com/davecgh/go-spew v1.1.1
github.com/docker/distribution v2.6.2+incompatible
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.7.1
Copy link
Contributor Author

@nckturner nckturner Apr 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

golang-set is the only dependency I know of that actually changed (was added).

@jqmichael
Copy link

Not sure what happened. But I couldn't find any references to c.decreaseIPPool(decreaseIPPoolInterval) in the latest commit.

@mogren
Copy link
Contributor

mogren commented May 10, 2019

Superseded by #461

@mogren mogren closed this May 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants