Skip to content

feat(dashboard): show tenant quota remaining in burstable and dedicated CPU views #2440

Open

Description

@kvaps

Context

Tenant resourceQuotas are rendered into Kubernetes ResourceQuota with limits.cpu = input and requests.cpu = input / cpuAllocationRatio (default ratio: 10). This correctly reflects the platform's overcommit policy for regular (burstable) VMs and containers.

KubeVirt instance types with dedicatedCPUPlacement: true (the cx* series and other Guaranteed-QoS workloads) pin physical cores and have pod requests == limits, bypassing the ratio. A single dedicated-CPU VM therefore consumes requests.cpu quota ~N× faster than limits.cpu. This is mathematically correct — a pinned core is ~N× more expensive to the platform — but it confuses tenants, who see "limits still has headroom" while VM creation is already blocked by requests.

Context: #2435 tried to fix this on the quota side (new dedicatedCPU key) and was closed. Agreement: the quota math is correct; the problem is presentation.

Proposal

Surface remaining CPU quota in the tenant dashboard (and any tenant-info API) as two complementary views derived from the same live ResourceQuota:

Remaining: ≈10 vCPU of burstable workload OR ≈1 physical core of dedicated-CPU workload

Both numbers compute from the same limits.cpu/requests.cpu and the current cpuAllocationRatio; they just frame the remainder from each side.

Acceptance criteria

  • Tenant dashboard shows remaining CPU in both burstable and dedicated views
  • Values derive from live ResourceQuota status and the active cpuAllocationRatio
  • Existing users with only burstable workloads see no regression

Related

Activity

  1. SerjioTT commented on May 5, 2026

    @SerjioTT
    Contributor

    This issue covers just a part of the broader problem I would like to show.

    Hidden consumption of quotas by components of other managed app

    Most managed apps deploy auxiliary processes that consume quota but are invisible to the tenant. There are couple examples here that I found in the charts:

    Redis (packages/apps/redis/templates/redisfailover.yaml) — the worst case. Sentinel pods (rfs-*) receive the same resource profile as data pods (rfr-*), because the template passes the same (resourcesPreset, resources) tuple to both:

    # redisfailover.yaml lines ~30-34
    sentinel:
        replicas: 3
        resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) }}
    redis:
        resources: {{- include "cozy-lib.resources.defaultingSanitize" (list .Values.resourcesPreset .Values.resources $) }}
        replicas: {{ .Values.replicas }}

    A tenant ordering 3 Redis replicas × 2 CPU / 2Gi expects 6 CPU / 6Gi in limits. Actual consumption: 12 CPU / 12Gi (3 data + 3 sentinel, each 2 CPU / 2Gi). Sentinel is a lightweight monitoring process — I suppose nano preset (250m / 128Mi) would be sufficient.

    The values schema (packages/apps/redis/values.schema.json) has a single resources/resourcesPreset — no separate sentinel configuration is exposed to the user.

    Kafka (packages/apps/kafka/templates/kafka.yaml) — a Kafka deployment has three components that consume quota:

    1. Kafka brokers — resources fully configurable via kafka.resourcesPreset / kafka.resources ✅
    2. ZooKeeper — resources fully configurable via zookeeper.resourcesPreset / zookeeper.resources ✅ (defined in packages/apps/kafka/values.yaml, default preset small, 3 replicas)
    3. Entity Operator (topicOperator + userOperator) — no resource configuration at all ❌:
    # kafka.yaml — entityOperator has no resources block
      entityOperator:
        topicOperator: {}
        userOperator: {}

    Entity Operator pods get resources only via LimitRange defaults. This is the least severe of the issues (just 1 extra pod), but still invisible to quota planning. The bigger tenant-facing problem with Kafka is that even though ZooKeeper is configurable, a tenant ordering "3 Kafka replicas" may not realize they also need to budget for 3 ZooKeeper replicas at small preset (1 CPU / 512Mi each) — the total quota impact is ~2× what a naive "3 brokers × 1 CPU" calculation suggests.

    What the tenant actually sees

    Today the dashboard shows per-application WorkloadMonitors (which track replica health per component — e.g., separate monitors for redis and sentinel in redisfailover.yaml But there is no tenant-level view of aggregate ResourceQuota consumption. A tenant has no way to answer "how much of my quota is used and by what?" without running kubectl describe resourcequota — which they may not have access (or knowledge) to.

    The Kubernetes ResourceQuota object already has .status.used vs .status.hard — the data exists, it's just not surfaced.

    Proposal: show ResourceQuota usage in the tenant dashboard

    Rather than (or in addition to) the burstable-vs-dedicated CPU view from the original proposal, I'd suggest a more general solution:

    Show the live ResourceQuota status (used / hard) for the tenant namespace directly in the dashboard. This would cover:

    1. The original dedicated-CPU problem — the tenant sees requests.cpu: 5/10 and limits.cpu: 5/100 and understands that requests are the bottleneck
    2. The hidden auxiliary component problem — the tenant sees that deploying a "3-replica Redis" actually consumed 12 CPU in limits, not 6
    3. Memory, ephemeral-storage, storage, pod count — all quota dimensions become visible, not just CPU
    4. Any future resource type — no special-casing needed per workload type
      Concretely, the dashboard could show something like:
    Tenant quota usage:
      CPU (limits):             18.25 / 20
      CPU (requests):            1.83 / 2       ← bottleneck visible
      Memory (limits):          12 Gi / 16 Gi
      Memory (requests):        12 Gi / 16 Gi
      Ephemeral storage (lim):  14 Gi / 40 Gi
      Pods:                     12 / 50
    

    Relation to existing infrastructure

    The WorkloadMonitor CRD already tracks per-component replica counts and resource presets (label workloads.cozystack.io/resource-preset). The quota view is complementary: WorkloadMonitor answers "is my Redis healthy?", while ResourceQuota status answers "how much capacity do I have left?"


    Summary: The core user problem is "I don't understand my resource consumption." Showing live ResourceQuota status (used/hard) in the tenant dashboard solves both the dedicated-CPU confusion from this issue and the hidden-auxiliary-component problem across all managed apps, without adding new quota keys or chart-level sugar.

  2. dosubot commented on Aug 4, 2026

    @dosubot

    Hi, Andrei Kvapil (@kvaps). I'm Dosu, and I'm helping the cozystack team manage their backlog and am marking this issue as stale.

    Issue Summary

    • You opened this issue to make tenant CPU quota usage clearer in the dashboard/API, especially the remaining quota for both burstable and dedicated-CPU workloads.
    • The discussion expanded to include hidden quota consumption from auxiliary components in managed apps like Redis and Kafka.
    • A broader approach was suggested: surface the live Kubernetes ResourceQuota used/hard status directly in the tenant dashboard so all quota dimensions are visible.
    • No resolution has been implemented yet, so the issue remains open-ended.

    Next Steps

    • Please confirm whether this is still relevant on the latest version of the cozystack repository; if so, you can keep the discussion open by commenting here.
    • Otherwise, this issue will be automatically closed in 7 days.

    Thanks for your understanding and contribution.

  3. added
    lifecycle/staleDenotes an issue or PR has remained open with no activity and has become stale
    triage/needs-triageIndicates an issue needs triage by a maintainer
    and removed on Aug 10, 2026
  4. added
    area/dashboardIssues or PRs related to the dashboard / UI
    triage/acceptedIndicates an issue is ready to be actively worked on
    priority/backlogGeneral backlog priority. Lower than priority/important-longterm
    lifecycle/frozenIndicates that an issue or PR should not be auto-closed due to staleness
    and removed
    lifecycle/staleDenotes an issue or PR has remained open with no activity and has become stale
    triage/needs-triageIndicates an issue needs triage by a maintainer
    on Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/dashboardIssues or PRs related to the dashboard / UIkind/featureCategorizes issue or PR as related to a new featurelifecycle/frozenIndicates that an issue or PR should not be auto-closed due to stalenesspriority/backlogGeneral backlog priority. Lower than priority/important-longtermquality-of-lifeQoL improvementstriage/acceptedIndicates an issue is ready to be actively worked on

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions