✦ For everyone, free.

Practical knowledge for real and everyday life

Home

Kubernetes CRD Scope Management

Kubernetes CRD Scope Management defines how CRDs are scoped, ensuring isolation and governance across namespaces and environments.

Kubernetes CRD Scope Management is the practice of deliberately choosing and enforcing whether a custom resource type exists per-namespace or once cluster-wide, and of managing the downstream RBAC, multi-tenancy, and operational consequences that follow from that fixed, unchangeable choice made at CRD creation time.


The Scope Field Itself

A Binary, Immutable Choice

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: postgresclusters.databases.example.com
spec:
  scope: Namespaced

spec.scope accepts only Namespaced or Cluster, and unlike most other CRD fields, it cannot be changed after the CRD is created; converting a namespaced resource type to cluster-scoped, or vice versa, requires deleting and recreating the CRD, which in turn deletes every existing instance of that resource, making this the single most consequential and least reversible decision in a CRD's design.

Namespaced Scope

A Namespaced custom resource is created within a specific namespace, inherits that namespace's ResourceQuota and LimitRange constraints, and is subject to namespace-scoped RBAC Role/RoleBinding pairs, making it the natural choice for resources representing tenant-owned application state, such as a PostgresCluster belonging to a specific team's namespace.

kubectl get postgresclusters -n production

Cluster Scope

A Cluster-scoped custom resource exists exactly once across the entire cluster regardless of namespace, similar to built-in resources like Node or StorageClass, and can only be governed by ClusterRole/ClusterRoleBinding, making it appropriate for resources representing shared, cluster-wide policy or infrastructure rather than tenant-specific application data.

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: clusterpolicies.security.example.com
spec:
  scope: Cluster

Choosing Scope Based on Resource Semantics

Tenant-Owned vs. Platform-Owned Resources

The primary heuristic for scope selection is ownership semantics: if the resource represents something a single team or application owns and manages independently (a database cluster, a scheduled job, an ingress route), Namespaced scope aligns its lifecycle and access control with the namespace boundary that already separates tenants; if the resource represents a cluster-wide policy, a shared infrastructure binding, or configuration that by definition has no single owning tenant (an admission policy applied cluster-wide, a global network policy default), Cluster scope is the only coherent choice.

Scope = { Namespaced, if tenant-owned ; Cluster, otherwise }

Cluster-Scoped References from Namespaced Resources

A common intermediate pattern has a Namespaced custom resource reference a Cluster-scoped one by name, such as a namespaced PostgresCluster referencing a cluster-scoped StorageClass or a cluster-scoped BackupPolicy, cleanly separating tenant-specific state from shared platform configuration without forcing either resource into the wrong scope.

apiVersion: databases.example.com/v1
kind: PostgresCluster
metadata:
  name: orders-db
  namespace: production
spec:
  backupPolicyRef:
    name: standard-daily-backup

RBAC Implications of Scope

Namespaced Scope RBAC

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: postgrescluster-editor
  namespace: production
rules:
  - apiGroups: ["databases.example.com"]
    resources: ["postgresclusters"]
    verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

A Role scoped to a single namespace can grant full control over a namespaced custom resource without touching that resource type in any other namespace, giving fine-grained, per-tenant delegation.

Cluster Scope RBAC

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: clusterpolicy-viewer
rules:
  - apiGroups: ["security.example.com"]
    resources: ["clusterpolicies"]
    verbs: ["get", "list", "watch"]

Because a cluster-scoped resource has no namespace to bind a Role against, granting any access to it necessarily requires a ClusterRole, even if that ClusterRole is bound only to a single user via a namespace-restricted RoleBinding referencing it, which restricts who can act but not the fact that the resource itself remains globally visible to anyone with list access.


Operational Consequences of Scope Choice

Multi-Tenancy Isolation Failures

Choosing Cluster scope for a resource that should have been tenant-isolated means every tenant with any access to that resource type can see, and potentially list, every other tenant's instances, since there is no namespace boundary to enforce visibility separation; this is a common and serious multi-tenancy design mistake discovered only after the CRD has been widely adopted and is difficult to correct without an immutable-scope migration.

Quota and Limit Applicability

ResourceQuota and LimitRange objects apply only within a namespace and therefore only constrain Namespaced custom resources; a Cluster-scoped resource has no quota mechanism available to it beyond what a validating admission policy or webhook explicitly implements, which must be accounted for when a cluster-scoped resource type could otherwise be created without bound by any authorized user.


Relationship to CRD Naming and Management

Scope management sits alongside naming management as one of the two foundational, effectively permanent decisions made at CRD design time, and it directly shapes how the broader CRD lifecycle management practices — versioning, RBAC design, and Operator authority boundaries — must be structured, since every subsequent access-control and multi-tenancy decision for a custom resource type is downstream of whether that resource was declared namespaced or cluster-scoped from the outset.

namespace: production PostgresCluster ClusterPolicy (global)