# CustomResourceDefinition

> CustomResourceDefinitions add new API types, and their inventory reads like a manifest of installed operators. ZopNight records group, kind, scope, and served versions for each CRD, marks definitions established once the API serves them, and uses the keda.sh group to report whether KEDA is installed; namespace scheduling does not depend on it.

Source: https://zop.dev/integrations/kubernetes/crd
Updated: 2026-08-19

---

A CustomResourceDefinition teaches the Kubernetes API a new object type. CRDs are how operators extend a cluster. Install cert-manager, KEDA, or a service mesh and each arrives as a set of definitions, so the CRD list reads as a manifest of what else is running and making decisions in the cluster.

## An inventory of operators, read from the API

Discovery records each CRD's `group`, `kind`, `scope`, and served versions. The group alone identifies most operators at a glance: `keda.sh` means event-driven autoscaling is installed, `cert-manager.io` means certificates are automated, `monitoring.coreos.com` means Prometheus. Since every controller behind those groups runs pods, holds leases, and sometimes provisions cloud resources, the CRD inventory is the cheapest available answer to what software has authority here.

## Established, or defined but not served

A CRD that the API server has validated and begun serving carries the Established condition, and discovery promotes that to the resource's status; definitions still settling report as merely active. The distinction is a useful health check after operator installs: a chart that applied its CRDs but whose definitions never established leaves every dependent custom resource unservable.

## Scope: the field that decides where instances live

Each definition declares whether its instances are Namespaced or Cluster scoped, and discovery keeps that field verbatim. Scope determines cleanup semantics (namespaced custom resources die with their namespace, cluster-scoped ones need explicit deletion), and it determines who can create instances under a given RBAC setup, which is why the field matters to more than taxonomists.

## The KEDA check, and what it does not switch

ZopNight checks for the `keda.sh` definitions to report whether KEDA is installed and whether its scaling rules can be listed. Namespace scheduling does not wait on that check: at stop it lists the namespace's KEDA ScaledObjects directly (an empty list when KEDA is absent), saves and deletes them first so KEDA cannot scale workloads back up, and recreates them at start.

```bash
kubectl get crds -o custom-columns=NAME:.metadata.name,GROUP:.spec.group,KIND:.spec.names.kind,SCOPE:.spec.scope,VERSIONS:.spec.versions[*].name
```

Reviewing the list occasionally pays: CRDs from uninstalled operators linger indefinitely, and orphaned definitions with live instances are configuration that no controller reconciles anymore.
