mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-08 21:14:56 +09:00
## What this PR does Adds **hierarchical (recursive) resource quotas** for tenants so a tenant can no longer escalate its allocation by creating sub-tenants. Today `tenant.spec.resourceQuotas` becomes a plain per-namespace `ResourceQuota`, which ignores the tenant tree: a super-admin inside a quota'd tenant can create a sub-tenant with a larger quota — or no quota at all — and consume more than was allocated. A tenant's declared quota is now treated as the budget for its **whole sub-tree**: - A child that declares its own quota **carves a fixed slice** out of the parent's remaining budget (parent 10 CPU → child 4 CPU → parent has 6 left). - A child **without** a quota **shares** the parent's remaining pool rather than being unbounded. - A child quota that exceeds the parent's remaining budget is **rejected**. Two cooperating layers, mirroring OpenShift's ClusterResourceQuota split (admission + reconciliation): 1. **Declaration-time gate** in the aggregated apiserver (`apps.cozystack.io` Tenant create/update): deterministically rejects a sub-tenant whose declared quota exceeds the parent's remaining budget. 2. **Runtime enforcer** in `cozystack-controller`: maintains a per-namespace `tenant-quota-allocated` ResourceQuota that clamps each pool member to its share of the parent budget, aggregating sub-tree usage so members collectively stay within the budget. Kubernetes enforces the most restrictive ResourceQuota in a namespace, so this binds without fighting Flux over the chart-rendered `tenant-quota`. Overcommitted pools (a parent quota lowered below the sum of its children) emit a `QuotaOvercommitted` event. A `--tenant-quota-buffer-percent` flag temporarily inflates pool budgets during rollout so workloads already over a freshly-introduced quota keep running. The model and the selector-spans-namespaces / aggregated-usage approach are adapted from OpenShift's ClusterResourceQuota controllers (`openshift/api`, `library-go`, `cluster-policy-controller`, `apiserver-library-go`), Apache-2.0, Copyright Red Hat, Inc. and the OpenShift Authors; attribution is preserved in the source. The per-namespace quota arithmetic reuses the upstream Kubernetes quota helpers (`k8s.io/apiserver/pkg/quota/v1`). No API types or the tenant chart change; the feature works with the existing `tenant.spec.resourceQuotas` field. ### Screenshots N/A — no UI changes. ### Release note ```release-note feat(tenant): tenant resource quotas are now hierarchical — a sub-tenant's quota is carved out of its parent's remaining budget and can no longer exceed it; sub-tenants without a quota share the parent's pool. Set `--tenant-quota-buffer-percent` on cozystack-controller for a temporary grace buffer during upgrades. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added hierarchical tenant quota enforcement across tenant namespaces, including shared pool handling and configurable quota buffer support. * Tenant quota changes are now validated on create and update to prevent over-allocation. * **Bug Fixes** * Improved quota calculations so usage, carve-outs, and nested tenant limits are applied more consistently. * Stale quota allocations are now cleaned up when namespaces no longer belong to an active tenant pool. <!-- end of auto-generated comment: release notes by coderabbit.ai -->