Skip to content

Comments

rgw: add multisite configuration for cross-zonegroup replication#61862

Closed
cbodley wants to merge 4 commits intoceph:mainfrom
cbodley:wip-rgw-cross-zonegroup-config
Closed

rgw: add multisite configuration for cross-zonegroup replication#61862
cbodley wants to merge 4 commits intoceph:mainfrom
cbodley:wip-rgw-cross-zonegroup-config

Conversation

@cbodley
Copy link
Contributor

@cbodley cbodley commented Feb 17, 2025

realm default and zonegroup overrides

defines the configuration for cross-zonegroup replication at the realm and zonegroup level. the default behavior is set by the realm, and individual zonegroups can override this to enable/disable cross-zonegroup replication to/from other zonegroups

opt-in vs opt-out

the realm configuration supports three models:

  • opt-out model where cross-zonegroup replication is "enabled" in the realm but "forbidden" for specific zonegroup pairs
  • opt-in model where replication is "allowed" in the realm but only "enabled" for specific zonegroup pairs
  • no cross-zonegroup replication when "forbidden" by the realm

the realm uses a tristate enum CanSync to represent the default, while the zonegroup uses two sets ("enable" and "forbid") to represent the overrides

import vs export

zonegroups can override the realm behavior both for import and export. while this can duplicate information (that is, disabling A's import from B is the same as disabling B's export to A), one form will generally be simpler than the other. for example, consider a realm with zonegroups A, B, C with cross-zonegroup replication disabled to/from C. to represent this with imports only:

realm:
  "cross_zonegroup": "enabled"
zonegroup A:
  "cross_zonegroup_import": { "forbid": {"C"} }
zonegroup B:
  "cross_zonegroup_import": { "forbid": {"C"} }
zonegroup C:
  "cross_zonegroup_import": { "forbid": {"A", "B"} }

using both imports and exports, the configuration can be localized to zonegroup C:

realm:
  "cross_zonegroup": "enabled"
zonegroup C:
  "cross_zonegroup_export": { "forbid": {"A", "B"} },
  "cross_zonegroup_import": { "forbid": {"A", "B"} }

wildcards

the wildcard string "*" can be used to match all peers, allowing the example above to be simplified as "forbid": {"*"}. but more importantly, wildcards adapt as zonegroups are added/removed from the realm. so if another zonegroup D is added to the realm above, that use of wildcards would automatically disable its replication to/from C

TODO:

  • add similar configuration for same_zonegroup replication policy
  • radosgw-admin commands to modify this configuration
Show available Jenkins commands
  • jenkins retest this please
  • jenkins test classic perf
  • jenkins test crimson perf
  • jenkins test signed
  • jenkins test make check
  • jenkins test make check arm64
  • jenkins test submodules
  • jenkins test dashboard
  • jenkins test dashboard cephadm
  • jenkins test api
  • jenkins test docs
  • jenkins render docs
  • jenkins test ceph-volume all
  • jenkins test ceph-volume tox
  • jenkins test windows
  • jenkins test rook e2e

@github-actions github-actions bot added the rgw label Feb 17, 2025
@cbodley cbodley requested review from clwluvw and smanjara February 18, 2025 19:42
Copy link
Member

@clwluvw clwluvw left a comment

Choose a reason for hiding this comment

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

Looks Great, Thanks Casey! 😍

const RGWZoneGroup& source);

/// Test whether a destination bucket should sync from the given source bucket.
bool should_sync_from(const SiteConfig& site,
Copy link
Member

@clwluvw clwluvw Feb 18, 2025

Choose a reason for hiding this comment

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

I’ve been reflecting on where this should be invoked. In #59911, the approach I took was to mark bilog entries with the zones responsible for processing (log_zones), and I initially thought zones should unconditionally process those entries as the criteria (in terms of filters) had already been validated by the source zone when the entry was logged. This would cover most scenarios, aside from two edge cases—bucket deletion during replication or changes in permissions.

That approach was based on zones, as at the moment, sync pipes can only keep zones, not zonegroups. Based on your insights from #61140 (comment), I believe we need to shift focus from zones to zonegroups. The master can change over time, and we want to avoid missing any processing entries.

What I’m envisioning is this: during the logging phase, we still mark the relevant zonegroups based on the matching pipes, rather than individual zones. And if there were no matching pipes, we should log when there is more than one zone per zonegroup with empty log_zonegroups set. Then, during the processing phase, when we fetch entries, we would check if the zonegroup of the requested zone (rgwx-zonegroup) matches ourselves (destination). If it does, we don’t apply any additional filtering on log_zonegroups and return all entries. and if it doesn't we just return the ones having rgwx-zonegroup in the log_zonegroups set.

This would also require modifying the sync pipes to store a bucket’s zonegroup hint, instead of its zone, as constantly looking up the zonegroup for each request wouldn’t be efficient. Buckets don’t frequently move, and in cases of bucket recreation, we can update the policies as needed, maintaining compatibility with AWS—where even if a bucket is moved mid-replication, it still replicates.

So, my question is: do we need to perform this validation on the pull side, or would it be sufficient to handle it during the logging phase, relying on the log_zonegroups field? perhaps just ANDing the case where replication is possible from my zonegorup to the destination bucket's zonegroup. So we change this to should_sync_to rather than from to promote the case on which side this needs to be considered. although if it's on the logging side this would lose the immediate effect if an admin wants to stop replication from zonegroup A to B. So maybe both can be considered anyway.

Copy link
Contributor

Choose a reason for hiding this comment

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

What I’m envisioning is this: during the logging phase, we still mark the relevant zonegroups based on the matching pipes, rather than individual zones. And if there were no matching pipes, we should log when there is more than one zone per zonegroup with empty log_zonegroups set. Then, during the processing phase, when we fetch entries, we would check if the zonegroup of the requested zone (rgwx-zonegroup) matches ourselves (destination). If it does, we don’t apply any additional filtering on log_zonegroups and return all entries. and if it doesn't we just return the ones having rgwx-zonegroup in the log_zonegroups set.

that sounds right to me.

This would also require modifying the sync pipes to store a bucket’s zonegroup hint, instead of its zone, as constantly looking up the zonegroup for each request wouldn’t be efficient. Buckets don’t frequently move, and in cases of bucket recreation, we can update the policies as needed, maintaining compatibility with AWS—where even if a bucket is moved mid-replication, it still replicates.

sorry not clear, could you clarify what moving a bucket mean?

Copy link
Contributor

Choose a reason for hiding this comment

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

looks like we will need to introduce the concept of master zone in data sync.

Copy link
Member

@clwluvw clwluvw Feb 19, 2025

Choose a reason for hiding this comment

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

sorry not clear, could you clarify what moving a bucket mean?

So if you have a policy on your source bucket pointing to a destination bucket in Region A and then you delete the destination bucket and create it in Region B, AWS will continue replicating from the source bucket to the newly created bucket in Region B without any modification needed by the user.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, my question is: do we need to perform this validation on the pull side, or would it be sufficient to handle it during the logging phase, relying on the log_zonegroups field?

for the RGWBucketInfo overload of should_sync_from(), i was thinking we'd only use that on PutBucketReplication to reject any cross-zonegroup policy that's disabled by the admin. though i guess this would open a loophole if the destination bucket was deleted and recreated on a zonegroup that wasn't supposed to be enabled

@cbodley
Copy link
Contributor Author

cbodley commented Mar 12, 2025

this is what i'm thinking for the associated radosgw-admin commands:

radosgw-admin realm cross-zonegroup <enable|allow|forbid> --rgw-realm myrealm
radosgw-admin realm same-zonegroup <enable|allow|forbid> --rgw-realm myrealm
radosgw-admin zonegroup cross-zonegroup <enable|forbid> --rgw-zonegroup myzonegroup --peer-zonegroup-id <uuid>
radosgw-admin zonegroup cross-zonegroup rm <enable|forbid> --rgw-zonegroup myzonegroup --peer-zonegroup-id <uuid>
radosgw-admin zonegroup same-zonegroup <enable|allow|forbid> --rgw-zonegroup myzonegroup

edit: zonegroup needs to track cross-zonegroup imports and exports separately:

radosgw-admin zonegroup import <enable|forbid> --rgw-zonegroup myzonegroup --peer-zonegroup-id <uuid>
radosgw-admin zonegroup import rm <enable|forbid> --rgw-zonegroup myzonegroup --peer-zonegroup-id <uuid>
radosgw-admin zonegroup export <enable|forbid> --rgw-zonegroup myzonegroup --peer-zonegroup-id <uuid>
radosgw-admin zonegroup export rm <enable|forbid> --rgw-zonegroup myzonegroup --peer-zonegroup-id <uuid>

@github-actions github-actions bot added the tests label Mar 12, 2025
@cbodley cbodley force-pushed the wip-rgw-cross-zonegroup-config branch from 8c740ff to e54323f Compare March 17, 2025 14:14
@github-actions
Copy link

github-actions bot commented May 5, 2025

This pull request can no longer be automatically merged: a rebase is needed and changes have to be manually resolved

@cbodley cbodley force-pushed the wip-rgw-cross-zonegroup-config branch from 59f752f to d1e9c45 Compare May 6, 2025 16:33
@cbodley
Copy link
Contributor Author

cbodley commented May 6, 2025

squashed/rebased over conflicts from #62398

@github-actions
Copy link

This pull request can no longer be automatically merged: a rebase is needed and changes have to be manually resolved

@github-actions
Copy link

This pull request has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs for another 30 days.
If you are a maintainer or core committer, please follow-up on this pull request to identify what steps should be taken by the author to move this proposed change forward.
If you are the author of this pull request, thank you for your proposed contribution. If you believe this change is still appropriate, please ensure that any feedback has been addressed and ask for a code review.

@github-actions github-actions bot added the stale label Aug 17, 2025
@clwluvw clwluvw removed the stale label Aug 18, 2025
@github-actions
Copy link

This pull request has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs for another 30 days.
If you are a maintainer or core committer, please follow-up on this pull request to identify what steps should be taken by the author to move this proposed change forward.
If you are the author of this pull request, thank you for your proposed contribution. If you believe this change is still appropriate, please ensure that any feedback has been addressed and ask for a code review.

@github-actions github-actions bot added the stale label Oct 17, 2025
@github-actions
Copy link

This pull request has been automatically closed because there has been no activity for 90 days. Please feel free to reopen this pull request (or open a new one) if the proposed change is still appropriate. Thank you for your contribution!

@github-actions github-actions bot closed this Nov 16, 2025
@clwluvw clwluvw reopened this Nov 21, 2025
@github-actions github-actions bot removed the stale label Nov 21, 2025
@github-actions
Copy link

This pull request has been automatically marked as stale because it has not had any activity for 60 days. It will be closed if no further activity occurs for another 30 days.
If you are a maintainer or core committer, please follow-up on this pull request to identify what steps should be taken by the author to move this proposed change forward.
If you are the author of this pull request, thank you for your proposed contribution. If you believe this change is still appropriate, please ensure that any feedback has been addressed and ask for a code review.

@github-actions github-actions bot added the stale label Jan 20, 2026
@github-actions
Copy link

This pull request has been automatically closed because there has been no activity for 90 days. Please feel free to reopen this pull request (or open a new one) if the proposed change is still appropriate. Thank you for your contribution!

@github-actions github-actions bot closed this Feb 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants