The Namespace Quota Operator is a Kubernetes operator that provides dynamic and flexible management of resource quotas and limit ranges across namespaces. It allows cluster administrators to define quota profiles that can be automatically applied to namespaces based on names or labels.
- Overview
- Description
- Custom Resource Definition (CRD)
- Components
- Getting Started
- Project Distribution
- License
The operator introduces a custom resource called QuotaProfile that enables you to:
- Define multiple ResourceQuota and LimitRange specifications in a single profile
- Target namespaces using either name-based or label-based selector
- Implement precedence-based quota assignment when multiple profiles match a namespace
- Automatically manage the lifecycle of ResourceQuota and LimitRange resources
The Namespace Quota Operator simplifies the management of resource quotas and limit ranges in Kubernetes clusters by providing a centralized and automated approach. Instead of manually creating and managing individual ResourceQuota and LimitRange resources for each namespace, administrators can define reusable QuotaProfiles that are automatically applied based on namespace names or labels.
Key benefits include:
- Centralized Management: Define quota policies once and apply them across multiple namespaces
- Automated Enforcement: Automatically create, update, and delete quota resources as namespaces are created or modified
- Flexible Targeting: Use either namespace names or labels to determine which quotas apply
- Precedence-based Resolution: Clear rules for handling multiple matching profiles through name-based precedence and configurable priority levels
- Protected Resources: Validation webhooks prevent manual modifications to operator-managed resources
- Automatic Cleanup: Finalizers ensure proper cleanup of quota-related resources and labels
sequenceDiagram
participant A as Cluster Admin
participant QP as QuotaProfile
participant QPC as QuotaProfile Controller
participant NS as Namespace
participant NSC as Namespace Controller
participant RQ as ResourceQuota
participant LR as LimitRange
A->>QP: Create/Update QuotaProfile
QPC->>QP: Watch for changes
QPC->>NS: Find matching namespaces
QPC->>NS: Apply labels
NSC->>NS: Watch for label changes
NSC->>RQ: Create/Update/Delete ResourceQuota
NSC->>LR: Create/Update/Delete LimitRange
The QuotaProfile CRD allows you to define resource quotas and limit ranges that should be applied to matching namespaces.
apiVersion: quota.dev.operator/v1alpha1
kind: QuotaProfile
metadata:
name: example-profile
spec:
# Only one of matchLabels or matchName can be specified
namespaceSelector:
matchLabels:
environment: dev
# OR
matchName: "namespace-name"
# Higher precedence values take priority when multiple profiles match
precedence: 10
# List of ResourceQuota specifications
resourceQuotaSpecs:
- hard:
requests.cpu: "1"
requests.memory: "1Gi"
limits.cpu: "2"
limits.memory: "2Gi"
# List of LimitRange specifications
limitRangeSpecs:
- limits:
- type: Container
default:
cpu: 500m
defaultRequest:
cpu: 500m
max:
cpu: "1"
min:
cpu: 100mKey Features:
- Only one selector type (name or labels) can be used per profile
- Name-based selectors have the highest precedence
- For label-based selectors, the
precedencefield determines priority - If profiles have the same precedence, the most recently created profile takes effect
flowchart TD
A[New/Updated Namespace] --> B{Name-based selector match?}
B -->|Yes| C[Apply the matching name-based profile]
B -->|No| D{Label-based selector matches?}
D -->|No matches| E[No profile applied]
D -->|Multiple matches| F{Compare precedence values}
F -->|Highest wins| G[Apply highest precedence profile]
F -->|Equal precedence| H[Apply most recent profile]
D -->|Single match| I[Apply the matching profile]
flowchart TD
subgraph "Operator Components"
QPCRD[QuotaProfile CRD]
QPCT[QuotaProfile Controller]
NSCT[Namespace Controller]
subgraph "Admission Webhooks"
QPV[Validating Webhooks]
NSM[Mutating Webhook]
end
end
subgraph "Kubernetes Resources"
QP[QuotaProfile CRs in various namespaces]
NS[Target Namespaces]
RQ[ResourceQuotas]
LR[LimitRanges]
end
Admin[Cluster Admin] -->|Creates/Updates| QP
%% Main relationships
QPCRD -.->|Defines| QP
QP -->|Watched by| QPCT
QPCT -->|Labels matching| NS
NS -->|Label changes trigger| NSCT
NSCT -->|Creates/Updates| RQ
NSCT -->|Creates/Updates| LR
%% Webhook validations
QPV -->|Validates| QP
NSM -->|Mutates| NS
QPV -->|Protects| RQ
QPV -->|Protects| LR
%% Colors optimized for both light and dark backgrounds
classDef operator fill:#2b9348,stroke:#000000,color:#ffffff
classDef k8sresource fill:#4895ef,stroke:#000000,color:#ffffff
classDef crd fill:#9d4edd,stroke:#000000,color:#ffffff
classDef webhook fill:#ff9e00,stroke:#000000,color:#ffffff
classDef user fill:#ffffff,stroke:#000000,color:#000000
class QPCT,NSCT operator
class QP,NS,RQ,LR k8sresource
class QPCRD crd
class QPV,NSM webhook
class Admin user
- Monitors namespaces and matches them against QuotaProfiles
- Assigns namespace labels for tracking:
quota.dev.operator/profile:<qp-namespace>:<qp-name>quota.dev.operator/profile-last-update-timestamp: RFC3339 timestamp (:replaced with-)
- Implements finalizers to clean up labels from namespaces when profiles are deleted
- Watches for namespace label changes
- Creates, updates, or deletes ResourceQuota and LimitRange resources based on the assigned QuotaProfile
The operator implements four webhooks to ensure proper resource management:
- Ensures only one selector type is specified (name or labels)
- Prevents conflicts with existing QuotaProfiles using the same selector
- Evaluates namespaces against all QuotaProfiles
- Updates namespace labels when matches are found
- Removes quota-related labels when no profiles match
- Prevents manual updates/deletions of operator-managed LimitRange resources
- Prevents manual updates/deletions of operator-managed ResourceQuota resources
- go version v1.23.0+
- docker version 17.03+
- kubectl version v1.11.3+
- Access to a Kubernetes v1.11.3+ cluster
- cert-manager v1.0.0+ installed in the cluster (required for webhook certificates)
Build and push your image to the location specified by IMG:
make docker-build docker-push IMG=<some-registry>/namespace-quota-operator:tagNOTE: This image ought to be published in the personal registry you specified. And it is required to have access to pull the image from the working environment. Make sure you have the proper permission to the registry if the above commands don't work.
Install the CRDs into the cluster:
make installDeploy the Manager to the cluster with the image specified by IMG:
make deploy IMG=<some-registry>/namespace-quota-operator:tagNOTE: If you encounter RBAC errors, you may need to grant yourself cluster-admin privileges or be logged in as admin.
Create instances of your solution You can apply the samples (examples) from the config/sample:
kubectl apply -k config/samples/NOTE: Ensure that the samples has default values to test it out.
Delete the instances (CRs) from the cluster:
kubectl delete -k config/samples/Delete the APIs(CRDs) from the cluster:
make uninstallUnDeploy the controller from the cluster:
make undeployFollowing the options to release and provide this solution to the users.
- Build the installer for the image built and published in the registry:
make build-installer IMG=<some-registry>/namespace-quota-operator:tagNOTE: The makefile target mentioned above generates an 'install.yaml' file in the dist directory. This file contains all the resources built with Kustomize, which are necessary to install this project without its dependencies.
- Using the installer
Users can just run 'kubectl apply -f ' to install the project, i.e.:
kubectl apply -f https://raw.githubusercontent.com/<org>/namespace-quota-operator/<tag or branch>/dist/install.yaml- Build the chart using the optional helm plugin
kubebuilder edit --plugins=helm/v1-alpha- See that a chart was generated under 'dist/chart', and users can obtain this solution from there.
NOTE: If you change the project, you need to update the Helm Chart using the same command above to sync the latest changes. Furthermore, if you create webhooks, you need to use the above command with the '--force' flag and manually ensure that any custom configuration previously added to 'dist/chart/values.yaml' or 'dist/chart/manager/manager.yaml' is manually re-applied afterwards.
NOTE: Run make help for more information on all potential make targets
More information can be found via the Kubebuilder Documentation
Copyright 2025.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.