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

use labels and env vars to set EIP metro or facility, else error #222

Merged
merged 1 commit into from
Jan 24, 2022

Conversation

deitch
Copy link
Contributor

@deitch deitch commented Dec 16, 2021

Fixes #183

Completely eliminates the usage of EQXM metadata in CPEM. Instead, follows similar logic suggested in this comment by @detiber:

  1. If Service.Spec.LoadBalancerIP is set, we use it, nothing more to do; if not...
  2. If Service.Metadata.Annotations["topology.kubernetes.io/region"] is set, get an EIP for the given metro; if not...
  3. If Service.Metadata.Annotations["topology.kubernetes.io/zone"] is set, get an EIP for the given facility; if not...
  4. If the env var / cli flag for metro is set on CCM, get an EIP for the given metro; if not...
  5. If the env var / cli flag for facility is set on CCM, get an EIP for the given facility; if not...
  6. Get no EIP

Does not address the "global EIP" option; we can add it later.

Updated README as well, of course

README.md Show resolved Hide resolved
metal/loadbalancers.go Outdated Show resolved Hide resolved
@deitch
Copy link
Contributor Author

deitch commented Jan 14, 2022

Done. It now determines where to place the EIP as follows:

  1. Global facility set by env var; else
  2. Global metro set by env var; else
  3. Service-specific facility annotation; else
  4. Service-specific metro annotation; else
  5. Fail

The annotation follows the pattern of all other annotations we use: metal.equinix.com/*. In this case, metal.equinix.com/eip-metro and metal.equinix.com/eip-facility. Like all our annotations, that annotation is a default, and is configurable.

Ready for another full review @displague and @detiber

@displague
Copy link
Member

displague commented Jan 18, 2022

I'm in favor of merging this to get the agreed changes in the project.

We have not updated the Helm chart in this PR (https://github.com/equinix/cloud-provider-equinix-metal/tree/master/deploy/chart). Do you think the new location options should be required?

I worry about deploying this change in a release with "Step 5 Fail" because anyone upgrading to this image, via latest or a minor release bump and takes advantage of EIP features will get errors upon update until the new environment variables / command line options are added.

Perhaps we can follow up this PR with one that adds a default behavior to check EM metadata (or API data). This could then be disabled in use-cases where it does not make sense. Upgrades would not break and the Helm chart would not need to require a location parameter. What do you think?

@deitch
Copy link
Contributor Author

deitch commented Jan 18, 2022

We have not updated the Helm chart in this PR (https://github.com/equinix/cloud-provider-equinix-metal/tree/master/deploy/chart). Do you think the new location options should be required?

Yes, but it can afford a separate PR. We should check all of the deployment stuff.

I worry about deploying this change in a release with "Step 5 Fail" because anyone upgrading to this image, via latest or a minor release bump and takes advantage of EIP features will get errors upon update until the new environment variables / command line options are added.

Agreed, but that is what semver is for. Someone who uses latest does so at their own risk.

Perhaps we can follow up this PR with one that adds a default behavior to check EM metadata (or API data). This could then be disabled in use-cases where it does not make sense. Upgrades would not break and the Helm chart would not need to require a location parameter. What do you think?

Location parameter only is required if you do not have it on the service annotations. I am comfortable with it being this way

// 1. if metro is set globally, use it; else
// 2. if facility is set globally, use it; else
// 3. if Service.Metadata.Labels["topology.kubernetes.io/region"] is set, use it; else
// 4. if Service.Metadata.Labels["topology.kubernetes.io/zone"] is set, use it; else
Copy link
Member

@displague displague Jan 20, 2022

Choose a reason for hiding this comment

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

A user is able to offer conflicting annotations vs other settings.
The rules spell out how this will be processed so I can't complain about how conflicts are handled.

When both Region and Zone are set, especially when the zone resides in the region, I think it's reasonable to assume the more granular, Zone, will be used. This is not the case today. Based on how EM EIPs work, I think users supplying both settings will be better served with the Regional EIP (Metro based), so I'm fine with this staying as-is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I agree with you on all of the above. There can be conflicts, so we spell out exactly what the behaviour is.

When both Region and Zone are set, especially when the zone resides in the region, I think it's reasonable to assume the more granular, Zone, will be used. This is not the case today. Based on how EM EIPs work, I think users supplying both settings will be better served with the Regional EIP (Metro based), so I'm fine with this staying as-is.

I agree here as well. The right behaviour should be (everywhere, not just here), if you supplied a more granular request for anything, I will respect that.

The code we actually use shows:

			// create a request
			req := packngo.IPReservationRequest{
				Type:        "public_ipv4",
				Quantity:    1,
				Description: ccmIPDescription,
				Tags: []string{
					emTag,
					svcTag,
					clsTag,
				},
				FailOnApprovalRequired: true,
			}
			if metro != "" {
				req.Metro = &metro
			}
			if facility != "" {
				req.Facility = &facility
			}

So we basically add both if set, and let the API deal with it.

@@ -388,6 +393,12 @@ func (l *loadBalancers) addService(ctx context.Context, svc *v1.Service, ips []p
// if we did not find an IP reserved, create a request
klog.V(2).Infof("no IP assignment found for %s, requesting", svcName)
// create a request
// our logic as to where to create the IP:
// 1. if metro is set globally, use it; else
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps the more granular setting, the service annotation, should be consulted first with the "default" coming from the global settings?

Copy link
Member

Choose a reason for hiding this comment

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

Administrators are more likely to have access to the CPEM runtime parameters.
Users are more likely to have access to the service annotation.

Copy link
Member

@displague displague Jan 20, 2022

Choose a reason for hiding this comment

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

If the annotated locations need to be restricted, we could introduce another global setting to define the permitted values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You mean to use the env var / CLI flag as a fallback rather than override? I can see the use case, but that is not how it has been used in the past. In any case, the only ones ever likely to use env var on the actual CPEM will be administrators. If they set it, they really mean to override.

I don't mind considering having another env var for fallback, but this one historically has been the explicit override; I would like to leave it as is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The flags/env vars really are just meant as controlling overrides for development time. They don't have a good production purpose.

displague
displague previously approved these changes Jan 21, 2022
Signed-off-by: Avi Deitcher <avi@deitcher.net>
@deitch
Copy link
Contributor Author

deitch commented Jan 21, 2022

Rebased, letting CI run

@deitch
Copy link
Contributor Author

deitch commented Jan 22, 2022

Needs a new approval after rebase @displague

@displague displague merged commit 0744cf4 into master Jan 24, 2022
@displague displague deleted the remove-metadata branch January 24, 2022 14:01
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.

Metadata usage may be problematic
3 participants