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

Create IP to hostname mapping for Medusa restores #524

Conversation

Miles-Garnsey
Copy link
Member

What this PR does:

Creates a mapping from the hosts in a given remote Medusa backup (on a cloud bucket) to targets derived from a K8ssandraCluster's projected hostnames.

Which issue(s) this PR fixes:
Fixes #486

Checklist

  • Changes manually tested
  • Automated Tests added/updated
  • Documentation added/updated
  • CHANGELOG.md updated (not required for documentation PRs)
  • CLA Signed: DataStax CLA

@Miles-Garnsey Miles-Garnsey requested a review from a team as a code owner April 14, 2022 05:40
@Miles-Garnsey Miles-Garnsey force-pushed the feature/create-medusa-mapping branch 3 times, most recently from c3ea7ac to 667eed6 Compare April 20, 2022 07:13
Copy link
Contributor

@adejanovski adejanovski left a comment

Choose a reason for hiding this comment

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

Great stuff so far @Miles-Garnsey !

I left a few minor comments, but this is clearly headed in the right direction.

ToTargetSourceMap() map[HostName]HostDNSOrIP
}

// Transform HostMappingSlide into a map with source IPs as keys and Target IPs as values.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// Transform HostMappingSlide into a map with source IPs as keys and Target IPs as values.
// Transform HostMappingSlice into a map with source IPs as keys and Target IPs as values.

pkg/medusa/hostmap.go Outdated Show resolved Hide resolved
pkg/medusa/hostmap.go Outdated Show resolved Hide resolved
pkg/medusa/hostmap.go Outdated Show resolved Hide resolved
pkg/medusa/hostmap.go Outdated Show resolved Hide resolved
pkg/medusa/hostmap.go Show resolved Hide resolved
pkg/medusa/hostmap.go Outdated Show resolved Hide resolved
pkg/medusa/hostmap.go Outdated Show resolved Hide resolved
return nil, err
}
out := HostMappingSlice{}
for sourceRackLocation, sourceRackNodes := range sourceRacks {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we could relax the need to have matching rack names straight away by:

  • checking that we have the same number of racks
  • picking the dest rack based on the source rack position in a sorted key list instead of its name. This way "rack1" could be matched with "r1" for example.

The racks would have to be sorted alphabetically on both sides so we can have the right assignments.
wdyt?

Copy link
Member Author

@Miles-Garnsey Miles-Garnsey Apr 21, 2022

Choose a reason for hiding this comment

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

There are three solutions to this problem.

Solution 1

In the current solution, rack names must match, and the racks must be the same size between the source and destination topologies, but they do not need to be balanced (i.e. all racks the same size). Additionally, users can control the mapping with precision.

Solution 2

Under your proposal, rack names may differ, but the racks must be balanced and users cannot control the placements with precision (except by manipulating the alphabetical ordering which is OK, but a bit hacky).

Solution 3

If we don't care about being able to control placement, we can eliminate requirements on both balance and naming via the following:

  1. Add a function which takes a map[nodeLocation]string and returns map[len(nodes)]nodeLocation.
  2. Put sources and targets though that function.
  3. Do a "join" on the two maps via a for loop using len(nodes) as the key.

This has the advantage that racks may be unbalanced AND names need not match. But users still cannot control placement since (in the standard case where all racks are the same size) the source-destination mapping will be randomised.

In some ways, I'd rather force the rack names to match as it gives more control. But I'm not committed to any particular solution here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Discussion we had offline (with thanks to @adejanovski for the info):

  • Network topology strategy actually allocates replicas based on rack names (replicas go to the racks alphabetically close to the primary replica).
  • The EC2 aware snitch will actually modify rack names.

As a result of these two facts, it isn't appropriate to (a) force users to use the same rack names between source and destination clusters or (b) allow customers to change the token ordering relative to the rack-name alphabetical ordering.

Further changes to account for this logic incoming.

Copy link
Contributor

Choose a reason for hiding this comment

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

The EC2 aware snitch will actually modify rack names

Does it matter that we always use GossipingPropertyFileSnitch?

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure @jsanda but it is a worthwhile callout. Based on conversation with Alexander, it sounded like he was also concerned about the replicas being allocated into the same racks (which happens based on the alphabetical ordering of their names). I didn't quite follow that part 100%.

@adejanovski your thoughts are welcome. I have to be honest, the most recent round of changes has left me less than happy with this code as I feel that the data structures etc. that I originally wrote (when I was going to force rack names to match) are now poorly suited to the new requirements around alphabetical ordering.

Copy link
Contributor

Choose a reason for hiding this comment

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

Does it matter that we always use GossipingPropertyFileSnitch?

No, it's fine. It's just worth mentioning the EC2Snitch because the source cluster could be using it.

@adejanovski
Copy link
Contributor

It all looks very good to me @Miles-Garnsey 👍

One last thing is missing if you check #486, which is the in_place setting.
If the mapping shows exactly matching pod names between the source and the target cluster, then you're performing an in place restore (and in_place should then be true), otherwise it's a remote restore (in this case we don't restore the system.local table which contain the cluster name and tokens) .

@Miles-Garnsey
Copy link
Member Author

Miles-Garnsey commented May 3, 2022

@adejanovski my latest commit adds a function IsInPlace() to check for the condition you've described. Let me know if it is what you need.

Thanks for the kind words on the code too, I'm not personally that happy with it, but if it meets your needs that's great.

@Miles-Garnsey
Copy link
Member Author

Final unit tests finished/added. I also noticed that there is no way that we can actually restore a cluster with unbalanced racks, because we don't allow for setting rack size anywhere at the cass-operator level here so I guess all of those considerations weren't actually worth worrying about too much (or would be part of a different ticket anyway).

I think this is ready to merge if there isn't anything else to consider.

Copy link
Contributor

@adejanovski adejanovski left a comment

Choose a reason for hiding this comment

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

Just a tiny request for one or two additional unit tests, but otherwise it all looks very good to me 👍

Let's hold off from merging at the moment as this PR relies on another one that's yet to be approved.
This work may need some rebasing if the solution for spinning up the standalone medusa pod turns out to be different than what's currently implemented.

return out, nil
}

func (s HostMappingSlice) IsInPlace() (bool, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

LGTM 👍

It looks like that function is not tested. Would it be possible to add a test for both outcomes?

Copy link
Member Author

Choose a reason for hiding this comment

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

Gah, sorry, I did have these written, I just hadn't committed/pushed. Don't know how I missed that. Check again now.

adejanovski and others added 2 commits July 25, 2022 18:57
Allows the operator to communicate with the Medusa storage backend without requiring a Cassandra pod to be up.
@Miles-Garnsey Miles-Garnsey force-pushed the feature/create-medusa-mapping branch from 8e15c6e to 6b331fa Compare July 25, 2022 08:58
@adejanovski
Copy link
Contributor

Closing in favor or #980

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
No open projects
Archived in project
Development

Successfully merging this pull request may close these issues.

K8SSAND-1357 ⁃ Create Medusa restore mapping in the operator
3 participants