Skip to content

Comments

rgw: check for location constraint on master zonegroup#52791

Merged
cbodley merged 2 commits intoceph:mainfrom
clwluvw:location-constraint
Jan 9, 2025
Merged

rgw: check for location constraint on master zonegroup#52791
cbodley merged 2 commits intoceph:mainfrom
clwluvw:location-constraint

Conversation

@clwluvw
Copy link
Member

@clwluvw clwluvw commented Aug 3, 2023

Check the location constraint of the request when the zonegroup is master

Fixes: https://tracker.ceph.com/issues/62309

@clwluvw clwluvw requested a review from a team as a code owner August 3, 2023 16:49
@github-actions github-actions bot added the rgw label Aug 3, 2023
@clwluvw clwluvw force-pushed the location-constraint branch 4 times, most recently from 807cfa7 to 9e042f3 Compare August 5, 2023 10:11
@cbodley
Copy link
Contributor

cbodley commented Aug 7, 2023

Limit the bucket creation with empty location constraint to master zonegroup (basically defaulting the location to the master zonegroup)

is this really what we want? i tend to think it should default to the zonegroup that issued the CreateBucket request. if the master zonegroup owns it instead, then the issuing zone/zonegroup would have to forward all object operations to the master zonegroup. in that case, the client would lose any benefits of locality with its local zone/zonegroup

cc @smanjara @mattbenjamin

@cbodley
Copy link
Contributor

cbodley commented Aug 7, 2023

p.s. i reworked some of the forward_request_to_master logic in #50599. just a heads-up that we'll likely see conflicts in RGWCreateBucket::execute

@clwluvw
Copy link
Member Author

clwluvw commented Aug 7, 2023

@cbodley With the definition of AWS for the default region, this would make sense to have a default region and if the LocationConstraint was empty - pick the default one for it.
The same applies to GetBucketLocation API when the location is the default region (https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketLocation.html#AmazonS3-GetBucketLocation-response-LocationConstraint).

I would say this would make sure to the clients that they are asking for the right location rather than picking the location that they are requesting as an endpoint (maybe by fault?).

@clwluvw
Copy link
Member Author

clwluvw commented Aug 7, 2023

@cbodley I couldn't follow what you meant by forwarding the request to the master. The main idea of this from my PoV was the thing I mentioned in my comment above (bucket creation and...). Are you talking about any more corners here?

@cbodley
Copy link
Contributor

cbodley commented Aug 8, 2023

With the definition of AWS for the default region, this would make sense to have a default region and if the LocationConstraint was empty - pick the default one for it.

@clwluvw in rgw multisite, the master zonegroup is authoritative for bucket/user metadata, but failover may change which zonegroup is the master. i'm not sure it makes sense to think about the master zonegroup the same way you think about a default region in aws

s3 clients/applications don't need to be aware of rgw's zonegroups at all, they just need to know the address of an http endpoint. generally they'll run some workload that creates a bucket and operates on objects in it. i think it would be unexpected if that whole workload gets redirected to a remote zonegroup instead

clients that do know about the rgw zonegroups have full control over the placement of their buckets via LocationConstraint. but in the absence of a location, making the local zonegroup the bucket owner seems like the obvious choice

@cbodley
Copy link
Contributor

cbodley commented Aug 8, 2023

I couldn't follow what you meant by forwarding the request to the master.

@clwluvw i was only pointing out that another PR moved around some of the same code that you're touching here

@clwluvw clwluvw force-pushed the location-constraint branch from 9e042f3 to b7c934a Compare August 8, 2023 16:22
@clwluvw
Copy link
Member Author

clwluvw commented Aug 8, 2023

@cbodley That pretty much makes sense - Also I was worried about if we want to follow the same concept then how are we going to deal with null in the API I mentioned cause the SDKs are forced eu-east-1 for that so it wouldn't make sense if the "default" is something else. I dropped the change for that.

Regarding the PR you mentioned, I guess the conflict point in the implementation I proposed is still there:

  // validate the LocationConstraint
  if (!location_constraint.empty() && !relaxed_region_enforcement) {
    // on the master zonegroup, allow any valid api_name. otherwise it has to
    // match the bucket's zonegroup

Basically, I think it's better to check the LocationConstraint if the zonegroup is master as well otherwise the user might though it requested another zonegroup on the wrong HTTP endpoint and it gets 200 as a result and so the thought would be the bucket was placed in the zonegroup in bucket create request but the actual is not. What do you think?

@clwluvw
Copy link
Member Author

clwluvw commented Sep 4, 2023

ping @cbodley

@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 can no longer be automatically merged: a rebase is needed and changes have to be manually resolved

@clwluvw
Copy link
Member Author

clwluvw commented Oct 27, 2023

Reproduction:

  1. Have two zonegroups (assuming A as a master zonegroup and B as a secondary zonegroup)
  2. Send a CreateBucket Request to the "zonegroup A endpoint" with the following payload:
<CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
    <LocationConstraint>B</LocationConstraint> 
</CreateBucketConfiguration >

Results in bucket creation in zonegroup A without any error.

This is a client error as the user is asking to create the bucket in zone B but requesting to zonegorup A.
Doing that in the opposite way (request to zonegroup B with <LocationConstraint>A</LocationConstraint>) would result in 4xx as the endpoint would not match the requested LocationConstraint. But in the way I said - it results in 2xx and bucket creation in the master zonegroup (zone A - requested - but not asked) because of the if clause here: https://github.com/ceph/ceph/pull/52791/files#diff-319900fb50bdb02677039fb81949243b9c0e7d98690f6fddf35e6ca5d5d52b2cL3314

The PR will fix the if clause and check whether the zonegroup is master or not so the above example would result in 4xx as well.

@github-actions
Copy link

github-actions bot commented Nov 8, 2023

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

@github-actions
Copy link

github-actions bot commented Jan 7, 2024

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 7, 2024
@github-actions
Copy link

github-actions bot commented Feb 6, 2024

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 6, 2024
@clwluvw clwluvw force-pushed the location-constraint branch 2 times, most recently from a897498 to c274c9a Compare August 19, 2024 20:49
@adamemerson
Copy link
Contributor

jenkins test make check

@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 21, 2024
@clwluvw clwluvw removed the stale label Oct 21, 2024
@clwluvw clwluvw force-pushed the location-constraint branch from c274c9a to 3049af1 Compare November 14, 2024 20:50
@clwluvw
Copy link
Member Author

clwluvw commented Dec 9, 2024

jenkins test submodules

@clwluvw
Copy link
Member Author

clwluvw commented Dec 9, 2024

jenkins test windows

@cbodley
Copy link
Contributor

cbodley commented Dec 9, 2024

<CreateBucketConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
    <LocationConstraint>B</LocationConstraint> 
</CreateBucketConfiguration >

Results in bucket creation in zonegroup A without any error.

i would hope that #59960 will cause this bucket's creation to set the correct RGWBucketInfo::zonegroup to zonegroup B, even though it was created on zonegroup A

@clwluvw
Copy link
Member Author

clwluvw commented Dec 9, 2024

i would hope that #59960 will cause this bucket's creation to set the correct RGWBucketInfo::zonegroup to zonegroup B, even though it was created on zonegroup A

I don't think so as when you are master you will ignore the location_constraint in the body but the rgwx-zonegroup is playing the role now and letting the bucket be created for the correct zonegroup. so if you request directly to the master zonegroup to create a bucket for zonegroup B it won't work as it is still ignoring the body.

@cbodley
Copy link
Contributor

cbodley commented Dec 9, 2024

i would hope that #59960 will cause this bucket's creation to set the correct RGWBucketInfo::zonegroup to zonegroup B, even though it was created on zonegroup A

I don't think so as when you are master you will ignore the location_constraint in the body but the rgwx-zonegroup is playing the role now and letting the bucket be created for the correct zonegroup. so if you request directly to the master zonegroup to create a bucket for zonegroup B it won't work as it is still ignoring the body.

thanks. would something like this be reasonable?

if (location_constraint) {
  bucket.zonegroup = api_name_to_zonegroup_id(location_constrant);
} else if (rgwx_zonegroup) {
  bucket.zonegroup = rgwx_zonegroup; // default to requesting zonegroup
} else {
  bucket.zonegroup = local_zonegroup_id; // default to local zonegroup
}

@clwluvw clwluvw force-pushed the location-constraint branch 2 times, most recently from 0171282 to 4a22bfa Compare December 10, 2024 07:39
@clwluvw
Copy link
Member Author

clwluvw commented Dec 10, 2024

jenkins test make check arm64

Comment on lines 3606 to 3611
// For non-master zonegroups, enforce location constraint match
const bool enforce_location_match = !period || !my_zonegroup.is_master;
if (enforce_location_match && !my_zonegroup.equals(bucket_zonegroup->get_id())) {
Copy link
Contributor

Choose a reason for hiding this comment

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

is there a reason that other zonegroups shouldn't also support creation of remote buckets?

in aws, it looks like you can send a CreateBucket request to any region, naming any other valid region in the LocationConstraint

Copy link
Member Author

Choose a reason for hiding this comment

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

No you will get IllegalLocationConstraintException is response. and tbh I would still be voting for master to also not create bucket for other zonegroups when the request is initiated by the user - not forwarded.
This would make some races easier to solve deleting the condition that we need to cover.

Copy link
Contributor

Choose a reason for hiding this comment

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

No you will get IllegalLocationConstraintException is response.

ah, ok. sorry for the confusion

and tbh I would still be voting for master to also not create bucket for other zonegroups when the request is initiated by the user - not forwarded.

+1

Copy link
Member Author

Choose a reason for hiding this comment

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

+1

🥹

I just drafted a test case for this as well, will try to verify on my local asap.

Copy link
Member Author

Choose a reason for hiding this comment

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

The tests have passed on my local, but we will need #59960.

Copy link
Member Author

Choose a reason for hiding this comment

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

ok this is actually weird - api_name is empty.

2024-12-19T18:15:53.211 INFO:teuthology.orchestra.run.smithi043.stdout:{"id":"8987fccd-6980-4682-9cce-cf39a4aa6b34","epoch":12,"predecessor_uuid":"5276a8ed-77a4-4898-9669-84e295758977","sync_status":[],"period_map":{"id":"8987fccd-6980-4682-9cce-cf39a4aa6b34","zonegroups":[{"id":"a","name":"a","api_name":"","is_master":true,"endpoints":["http://smithi043.front.sepia.ceph.com:8000"],"hostnames":[],"hostnames_s3website":[],"master_zone":"6a93f239-7b93-4dfe-94b1-baf12183eb58","zones":[{"id":"250dd5e0-4049-46ca-bf5b-e7e54b3b29b4","name":"a2","endpoints":["http://smithi104.front.sepia.ceph.com:8001"],"log_meta":false,"log_data":true,"bucket_index_max_shards":11,"read_only":false,"tier_type":"","sync_from_all":true,"sync_from":[],"redirect_zone":"","supported_features":["compress-encrypted","notification_v2","resharding"]},{"id":"6a93f239-7b93-4dfe-94b1-baf12183eb58","name":"a1","endpoints":["http://smithi043.front.sepia.ceph.com:8000"],"log_meta":false,"log_data":true,"bucket_index_max_shards":11,"read_only":false,"tier_type":"","sync_from_all":true,"sync_from":[],"redirect_zone":"","supported_features":["compress-encrypted","notification_v2","resharding"]}],"placement_targets":[{"name":"default-placement","tags":[],"storage_classes":["STANDARD"]}],"default_placement":"default-placement","realm_id":"a54451a6-0f7f-48fa-b6c0-a34c0eb1ea9d","sync_policy":{"groups":[]},"enabled_features":["notification_v2","resharding"]},{"id":"b","name":"b","api_name":"","is_master":false,"endpoints":["http://smithi160.front.sepia.ceph.com:8000"],"hostnames":[],"hostnames_s3website":[],"master_zone":"b3be8bac-85cd-4275-8c15-00f60f318a67","zones":[{"id":"b3be8bac-85cd-4275-8c15-00f60f318a67","name":"b1","endpoints":["http://smithi160.front.sepia.ceph.com:8000"],"log_meta":false,"log_data":true,"bucket_index_max_shards":11,"read_only":false,"tier_type":"","sync_from_all":true,"sync_from":[],"redirect_zone":"","supported_features":["compress-encrypted","notification_v2","resharding"]},{"id":"e868f7a7-a7b3-4202-8e6f-86642035ca92","name":"b2","endpoints":["http://smithi187.front.sepia.ceph.com:8001"],"log_meta":false,"log_data":true,"bucket_index_max_shards":11,"read_only":false,"tier_type":"","sync_from_all":true,"sync_from":[],"redirect_zone":"","supported_features":["compress-encrypted","notification_v2","resharding"]}],"placement_targets":[{"name":"default-placement","tags":[],"storage_classes":["STANDARD"]}],"default_placement":"default-placement","realm_id":"a54451a6-0f7f-48fa-b6c0-a34c0eb1ea9d","sync_policy":{"groups":[]},"enabled_features":["notification_v2","resharding"]}],"short_zone_ids":[{"key":"250dd5e0-4049-46ca-bf5b-e7e54b3b29b4","val":104308217},{"key":"6a93f239-7b93-4dfe-94b1-baf12183eb58","val":2854171449},{"key":"b3be8bac-85cd-4275-8c15-00f60f318a67","val":1981456006},{"key":"e868f7a7-a7b3-4202-8e6f-86642035ca92","val":3492425437}]},"master_zonegroup":"a","master_zone":"6a93f239-7b93-4dfe-94b1-baf12183eb58","period_config":{"bucket_quota":{"enabled":false,"check_on_raw":false,"max_size":-1,"max_size_kb":0,"max_objects":-1},"user_quota":{"enabled":false,"check_on_raw":false,"max_size":-1,"max_size_kb":0,"max_objects":-1},"user_ratelimit":{"max_read_ops":0,"max_write_ops":0,"max_read_bytes":0,"max_write_bytes":0,"enabled":false},"bucket_ratelimit":{"max_read_ops":0,"max_write_ops":0,"max_read_bytes":0,"max_write_bytes":0,"enabled":false},"anonymous_ratelimit":{"max_read_ops":0,"max_write_ops":0,"max_read_bytes":0,"max_write_bytes":0,"enabled":false}},"realm_id":"a54451a6-0f7f-48fa-b6c0-a34c0eb1ea9d","realm_epoch":2}

Copy link
Member Author

Choose a reason for hiding this comment

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

hmm.. I'm not sure why we create zonegroups via zonegroup set but that might explain why api_name is created empty

def create_zonegroup(cluster, gateways, period, config):
""" pass the zonegroup configuration to `zonegroup set` """
config.pop('zones', None) # remove 'zones' from input to `zonegroup set`
endpoints = config.get('endpoints')
if endpoints:
# replace client names with their gateway endpoints
config['endpoints'] = extract_gateway_endpoints(gateways, endpoints)
zonegroup = multisite.ZoneGroup(config['name'], period)
# `zonegroup set` needs --default on command line, and 'is_master' in json
args = is_default_arg(config)
zonegroup.set(cluster, config, args)
period.zonegroups.append(zonegroup)
return zonegroup

Copy link
Member Author

@clwluvw clwluvw Dec 19, 2024

Choose a reason for hiding this comment

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

@cbodley I pushed a fix (c21b5f7), can you please try again?

Copy link
Contributor

Choose a reason for hiding this comment

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

When creating a bucket with a location constraint specified by the
user, this constraint is not included in createparams. Therefore,
to create the bucket in the requested location, createparams and
bucket_zonegroup must be replaced with the user-provided values.

Fixes: https://tracker.ceph.com/issues/62309
Signed-off-by: Seena Fallah <[email protected]>
If api_name is not set in the config, use name as the api_name,
otherwise on RGW it will be set to an empty string.

Signed-off-by: Seena Fallah <[email protected]>
@cbodley
Copy link
Contributor

cbodley commented Jan 9, 2025

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