Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5ec6bf5
Backport: Write Lock Lua Extensions (#24)
uw-sc Oct 8, 2026
512e930
rgw: add rate limit for LIST & DELETE ops
mkogan1 Jul 30, 2025
137a8e3
rgw: ops large budget caused by rate limiter was enabled and max_ops …
morphes1995 Dec 4, 2025
b9b783a
rgw: add accurate Retry-After header to rate-limit responses
lumir-sliva Apr 3, 2026
4a41a9b
release: add backport metadata
s0nea Oct 8, 2026
5c3e965
mgr/dashboard: tolerate nodeenv leaving no src directory behind
djgalloway Sep 26, 2026
116222c
Backport: rate limit "retry after" header + "rgw_ratelimit_interval" …
uw-sc Oct 12, 2026
39b8ce4
mon/MonClient: delete MonConnection move assignment
djgalloway Aug 19, 2026
9763e6a
qa/suites/rados/upgrade/cephx: add missing .qa symlinks
djgalloway Aug 19, 2026
8a639d1
mgr/cephadm: skip mgr/mon key rotation when no mon daemons are known
djgalloway Aug 19, 2026
42991c7
common/entity_name: print type names in get_valid_types_as_str()
djgalloway Aug 19, 2026
a9c6f3c
test/cli: update cram expectations for cephx auth changes
djgalloway Aug 19, 2026
52c577e
qa/tasks: fix flake8 findings in ceph.py and radosbench.py
djgalloway Aug 19, 2026
bfabf7e
cephadm: black-format OSD key rotation code in daemons/ceph.py
djgalloway Aug 19, 2026
b57c661
tentacle: test/osd: add missing stringify.h include for TestOSDMap.cc
djgalloway Aug 20, 2026
78090b2
github: run custom test workflow on tentacle and clear stale container
uw-sc Oct 12, 2026
c150a81
release: record backport metadata
uw-sc Oct 12, 2026
fea0f40
tentacle: mgr/cephadm: drop orphaned noautoscale cleanup in _mark_upg…
djgalloway Aug 20, 2026
a9c3027
tentacle: qa/tasks/radosgw_admin_rest: fix undefined admin_conn in ra…
uw-sc Oct 13, 2026
fa77b46
Backport: Fix Existing Build Errors (#26)
uw-sc Oct 14, 2026
a739f66
rgw: Inject keystone roles into IAM policy
supriti Feb 26, 2026
626b232
rgw: Inject keystone userid into IAM policy
supriti Mar 19, 2026
4676721
backport: rgw keystone roles and userid in IAM policy
supriti Oct 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/workflows/test-ceph-custom.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ on:
workflow_dispatch:
inputs:
base_branch:
description: 'Base branch to test (e.g. squid-19.2.4-cobaltcore-storage)'
description: 'Base branch to test (e.g. tentacle-20.2.4-cobaltcore-storage)'
required: true
type: string
pull_request:
branches:
- 'squid-*-cobaltcore-storage'
- 'tentacle-*-cobaltcore-storage'

jobs:
test-ceph:
Expand Down Expand Up @@ -49,6 +49,13 @@ jobs:
git submodule foreach --recursive git clean -fdx
git submodule update --init --recursive

# A job that dies mid-build (e.g. lost runner) leaves its container
# behind, and build-with-container.py always names it ceph_build.
- name: Remove leftover build container
run: |
podman ps -a --filter name=ceph_build
podman rm -f ceph_build

# --- 2. COMPUTE PARALLELISM ---
- name: Compute build + test parallelism
run: |
Expand Down
7 changes: 7 additions & 0 deletions PendingReleaseNotes
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,13 @@ CephFS: Disallow delegating preallocated inode ranges to clients. Config
* RGW: The serialized format of notification and topics has changed, so that
new/updated topics will be unreadable by old RGWs. We recommend completing
the RGW upgrades before creating or modifying any notification topics.
* RGW: New rate limiting options have been added to control the number of
bucket listing requests (`radosgw-admin ratelimit set ... --max-list-ops=`)
and delete operations (`radosgw-admin ratelimit set ... --max-delete-ops=`)
per accumulation interval, along with the ability to configure the
accumulation interval duration (`rgw_ratelimit_interval`).
Their default value is `0`, which keeps backward compatibility to the
previous behavior of READ and WRITE operations rate limiting.
* RBD: Trailing newline in passphrase files (`<passphrase-file>` argument in
`rbd encryption format` command and `--encryption-passphrase-file` option
in other commands) is no longer stripped.
Expand Down
58 changes: 43 additions & 15 deletions doc/radosgw/admin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -629,9 +629,21 @@ Rate Limit Management
=====================

Quotas can be set for The Ceph Object Gateway on users and buckets. The "rate
limit" includes the maximum number of read operations (read ops) and write
operations (write ops) per minute as well as the number of bytes per minute
that can be written or read per user or per bucket.
limit" includes the maximum number of read operations and write operations
per accumulation interval as well as the number of bytes per accumulation interval
that can be written or read per user or per bucket. It also includes the maximum
number of list requests and delete operations per accumulation interval.
The accumulation interval is configured by the :confval:`rgw_ratelimit_interval` option.
The default value is 60 seconds.
(Note: S3 Multi-Object Delete operation are currently not supported by rate limiting)

The configured limits should be divided by the number of active object gateways. For example,
if "user A" is to be be limited to 10 ops per minute and there are two object gateways in the cluster,
then the limit on "user A" should be 5 (10 ops per minute / 2 RGWs).
If the requests are not balanced between RGWs, the rate limit might be underutilized.
For example: if the ops limit is 5 and there are two RGWs,
but the Load Balancer sends load to only one of those RGWs,
the effective limit is 5 ops, because this limit is enforced per RGW.

Read Requests and Write Requests
--------------------------------
Expand All @@ -643,8 +655,8 @@ How Metrics Work
Each object gateway tracks per-user metrics separately from bucket metrics.
These metrics are not shared with other gateways. The configured limits should
be divided by the number of active object gateways. For example, if "user A" is
to be be limited to 10 ops per minute and there are two object gateways in the
cluster, then the limit on "user A" should be ``5`` (10 ops per minute / 2
to be be limited to 10 ops per accumulation interval and there are two object gateways in the
cluster, then the limit on "user A" should be ``5`` (10 ops per accumulation interval / 2
RGWs). If the requests are **not** balanced between RGWs, the rate limit might
be underutilized. For example: if the ops limit is ``5`` and there are two
RGWs, **but** the Load Balancer sends load to only one of those RGWs, the
Expand All @@ -661,12 +673,18 @@ rate limit is reached during the execution of the request. The RGW keeps track
of a "debt" consisting of bytes used in excess of the configured value; users
or buckets that incur this kind of debt are prevented from sending more
requests until the "debt" has been repaid. The maximum size of the "debt" is
twice the max-read/write-bytes per minute. If "user A" is subject to a 1-byte
read limit per minute and they attempt to ``GET`` an object that is 1 GB in size,
twice the max-read/write-bytes per accumulation interval. If "user A" is subject to a 1-byte
read limit per accumulation interval and they attempt to ``GET`` an object that is 1 GB in size,
then the ``GET`` action will fail. After "user A" has completed this 1 GB
operation, RGW blocks the user's requests for up to two minutes. After this
operation, RGW blocks the user's requests for up to two accumulation intervals. After this
time has elapsed, "user A" will be able to send ``GET`` requests again.

Rate-limited requests receive an HTTP ``503`` response with the S3 error code
``SlowDown``, matching the AWS S3 behavior. The response includes a
``Retry-After`` header with the estimated number of seconds until the rate-limit
window allows the next request through, computed from the current token-bucket
state. Load balancers or reverse proxies can be configured to map the ``503``
with ``Retry-After`` to ``429 Too Many Requests`` if clients require it.

- **Bucket:** The ``--bucket`` option allows you to specify a rate limit for a
bucket.
Expand All @@ -675,19 +693,27 @@ time has elapsed, "user A" will be able to send ``GET`` requests again.
user.

- **Maximum Read Ops:** The ``--max-read-ops`` setting allows you to limit read
bytes per minute per RGW instance. A ``0`` value disables throttling.
bytes per accumulation interval per RGW instance. A ``0`` value disables throttling.

- **Maximum Read Bytes:** The ``--max-read-bytes`` setting allows you to limit
read bytes per minute per RGW instance. A ``0`` value disables throttling.
read bytes per accumulation interval per RGW instance. A ``0`` value disables throttling.

- **Maximum Write Ops:** The ``--max-write-ops`` setting allows you to specify
the maximum number of write ops per minute per RGW instance. A ``0`` value
the maximum number of write ops per accumulation interval per RGW instance. A ``0`` value
disables throttling.

- **Maximum Write Bytes:** The ``--max-write-bytes`` setting allows you to
specify the maximum number of write bytes per minute per RGW instance. A
specify the maximum number of write bytes per accumulation interval per RGW instance. A
``0`` value disables throttling.


- **Maximum List Ops:** The ``--max-list-ops`` setting allows you to
specify the maximum number of bucket listing requests per accumulation interval per RGW instance.
A ``0`` value disables throttling.

- **Maximum Delete Ops:** The ``--max-delete-ops`` setting allows you to
specify the maximum number of delete operations per accumulation interval per RGW instance.
A ``0`` value disables throttling.

- **Rate Limit Scope:** The ``--ratelimit-scope`` option sets the scope for the
rate limit. The options are ``bucket`` , ``user`` and ``anonymous``. Bucket
rate limit apply to buckets. The user rate limit applies to a user. The
Expand All @@ -706,7 +732,8 @@ parameters:

radosgw-admin ratelimit set --ratelimit-scope=user --uid=<uid> \
<[--max-read-ops=<num ops>] [--max-read-bytes=<num bytes>] \
[--max-write-ops=<num ops>] [--max-write-bytes=<num bytes>]>
[--max-write-ops=<num ops>] [--max-write-bytes=<num bytes>] \
[--max-list-ops=<num ops>] [--max-delete-ops=<num ops>]>

An example of using ``radosgw-admin ratelimit set`` to set a rate limit might
look like this:
Expand Down Expand Up @@ -771,7 +798,8 @@ The following is the general form of commands that set rate limit parameters:

radosgw-admin ratelimit set --ratelimit-scope=bucket --bucket=<bucket> \
<[--max-read-ops=<num ops>] [--max-read-bytes=<num bytes>] \
[--max-write-ops=<num ops>] [--max-write-bytes=<num bytes>]>
[--max-write-ops=<num ops>] [--max-write-bytes=<num bytes>] \
[--max-list-ops=<num ops>] [--max-delete-ops=<num ops>]>

An example of using ``radosgw-admin ratelimit set`` to set a rate limit for a
bucket might look like this:
Expand Down
29 changes: 18 additions & 11 deletions doc/radosgw/adminops.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2788,8 +2788,9 @@ permission. ::
Rate Limit
==========

The Admin Operations API enables you to set and get ratelimit configurations on users and on bucket and global rate limit configurations. See `Rate Limit Management`_ for additional details.
Rate Limit includes the maximum number of operations and/or bytes per minute, separated by read and/or write, to a bucket and/or by a user and the maximum storage size in megabytes.
The Admin Operations API enables you to set and get ratelimit configurations on users and on bucket and global rate limit configurations. See `Rate Limit Management`_ for additional details.
Rate Limit includes the maximum number of operations and/or bytes per accumulation interval, separated by read and/or write (Additionally list and get operations),
to a bucket and/or by a user and the maximum storage size in megabytes.

To view rate limit, the user must have a ``ratelimit=read`` capability. To set,
modify or disable a ratelimit, the user must have ``ratelimit=write`` capability.
Expand All @@ -2803,16 +2804,22 @@ Valid parameters for quotas include:
- **User:** The ``uid`` option allows you to specify a rate limit for a user.

- **Maximum Read Bytes:** The ``max-read-bytes`` setting allows you to specify
the maximum number of read bytes per minute. A 0 value disables this setting.
the maximum number of read bytes per accumulation interval. A 0 value disables this setting.

- **Maximum Write Bytes:** The ``max-write-bytes`` setting allows you to specify
the maximum number of write bytes per minute. A 0 value disables this setting.
the maximum number of write bytes per accumulation interval. A 0 value disables this setting.

- **Maximum Read Ops:** The ``max-read-ops`` setting allows you to specify
the maximum number of read ops per minute. A 0 value disables this setting.
the maximum number of read ops per accumulation interval. A 0 value disables this setting.

- **Maximum Write Ops:** The ``max-write-ops`` setting allows you to specify
the maximum number of write ops per minute. A 0 value disables this setting.
the maximum number of write ops per accumulation interval. A 0 value disables this setting.

- **Maximum List Ops:** The ``max-list-ops`` setting allows you to specify
the maximum number of bucket listing requests per accumulation interval. A 0 value disables this setting.

- **Maximum Delete Ops:** The ``max-delete-ops`` setting allows you to specify
the maximum number of delete operations per accumulation interval. A 0 value disables throttling.

- **Global:** The ``global`` option allows you to specify a global rate limit.
The value should be either 'True' or 'False'.
Expand All @@ -2839,7 +2846,7 @@ Set User Rate Limit
To set a rate limit, the user must have ``ratelimit`` capability set with ``write``
permission. ::

POST /{admin}/ratelimit?ratelimit-scope=user&uid=<uid><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][enabled=<True|False>]>
POST /{admin}/ratelimit?ratelimit-scope=user&uid=<uid><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][&max-list-ops=<ops>][&max-delete-ops=<ops>][&enabled=<True|False>]>



Expand All @@ -2859,7 +2866,7 @@ Set Rate Limit for an Individual Bucket
To set a rate limit, the user must have ``ratelimit`` capability set with ``write``
permission. ::

POST /{admin}/ratelimit?bucket=<bucket-name>&ratelimit-scope=bucket<[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>]>
POST /{admin}/ratelimit?bucket=<bucket-name>&ratelimit-scope=bucket<[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][&max-list-ops=<ops>][&max-delete-ops=<ops>][&enabled=<True|False>]>



Expand All @@ -2879,7 +2886,7 @@ Set Global User Rate Limit
To set a rate limit, the user must have ``ratelimit`` capability set with ``write``
permission. ::

POST /{admin}/ratelimit?ratelimit-scope=user&global=<True|False><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][enabled=<True|False>]>
POST /{admin}/ratelimit?ratelimit-scope=user&global=<True|False><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][&max-list-ops=<ops>][&max-delete-ops=<ops>][&enabled=<True|False>]>



Expand All @@ -2889,7 +2896,7 @@ Set Global Rate Limit Bucket
To set a rate limit, the user must have ``ratelimit`` capability set with ``write``
permission. ::

POST /{admin}/ratelimit?ratelimit-scope=bucket&global=<True|False><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>]>
POST /{admin}/ratelimit?ratelimit-scope=bucket&global=<True|False><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][&max-list-ops=<ops>][&max-delete-ops=<ops>][&enabled=<True|False>]>



Expand All @@ -2899,7 +2906,7 @@ Set Global Anonymous User Rate Limit
To set a rate limit, the user must have ``ratelimit`` capability set with ``write``
permission. ::

POST /{admin}/ratelimit?ratelimit-scope=anon&global=<True|False><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][enabled=<True|False>]>
POST /{admin}/ratelimit?ratelimit-scope=anon&global=<True|False><[&max-read-bytes=<bytes>][&max-write-bytes=<bytes>][&max-read-ops=<ops>][&max-write-ops=<ops>][&max-list-ops=<ops>][&max-delete-ops=<ops>][&enabled=<True|False>]>



Expand Down
5 changes: 5 additions & 0 deletions doc/radosgw/bucketpolicy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ For all requests, condition keys we support are:
- aws:UserAgent
- aws:username

Request that authenticate with Keystone also include:

- keystone:role
- keystone:userid

We support certain s3 condition keys for bucket and object requests.

*Support for the following bucket-related operations was added in the Mimic
Expand Down
13 changes: 13 additions & 0 deletions doc/radosgw/keystone.rst
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,19 @@ S3 API (with AWS-like access and secret keys), if the ``rgw s3 auth
use keystone`` option is set. For details, see
:doc:`s3/authentication`.

Requests authenticated via Keystone (Swift tokens or S3 with Keystone-managed
credentials) expose the Keystone idenitity in the IAM policy environment
as the condition keys: ``keystone:role`` (role names) and
``keystone:userid`` (user UUID). These conditions can be used in bucket
policies and idenitity policies with ``StringEquals``, ``StringNotEquals`` etc.

- **keystone:role** - Allow or deny by *role* (e.g only users with role
``reader`` get read access). Use for RBAC.
- **keystone:userid** - Restrict to specific *user*. Use when policy
depends on a specific user, not just their role.

See :doc:`bucketpolicy` for list of supported condition keys.

Service token support
---------------------

Expand Down
1 change: 1 addition & 0 deletions qa/suites/rados/upgrade/cephx/X/ms_bind/.qa
1 change: 1 addition & 0 deletions qa/suites/rados/upgrade/cephx/release-X/ms_bind/.qa
5 changes: 0 additions & 5 deletions qa/tasks/ceph.py
Original file line number Diff line number Diff line change
Expand Up @@ -1725,8 +1725,6 @@ def key_prune(ctx, config):
elif isinstance(config, list):
config = {'keys': config}

testdir = teuthology.get_testdir(ctx)

cluster_name = config.setdefault('cluster', 'ceph')
manager = ctx.managers[cluster_name]

Expand Down Expand Up @@ -1789,7 +1787,6 @@ def key_rotate(ctx, config):
]

daemons = ctx.daemons.resolve_role_list(config.get('daemons', None), CEPH_ROLE_TYPES, True)
clusters = set()

new_mon_key = None
for role in daemons:
Expand Down Expand Up @@ -1831,7 +1828,6 @@ def key_rotate(ctx, config):
daemon.restart()

clients = config.get('clients', [])
firstmon = teuthology.get_first_mon(ctx, config, cluster_name)
keyring = ctx.ceph[cluster_name].keyring
for client in clients:
if client == 'all':
Expand Down Expand Up @@ -2272,7 +2268,6 @@ def task(ctx, config):

# stop logging health to clog during shutdown, or else we generate
# a bunch of scary messages unrelated to our actual run.
firstmon = teuthology.get_first_mon(ctx, config, cluster_name)
ctx.ceph[cluster_name].admin.run(
args=[
'sudo',
Expand Down
4 changes: 2 additions & 2 deletions qa/tasks/radosbench.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def task(ctx, config):
extra_args.append(f'--auth_exit_on_failure={auth_exit_on_failure}')

bench_args = [
f'bench',
'bench',
f'--concurrent-ios={concurrency}',
]

Expand Down Expand Up @@ -163,7 +163,7 @@ def task(ctx, config):
log.info('joining radosbench (timing out after %ss)', timeout)
try:
run.wait(radosbench.values(), timeout=timeout)
except CommandFailedError as e:
except CommandFailedError:
for p in radosbench.values():
if p.exitstatus == expected_rc:
pass
Expand Down
Loading
Loading