Skip to content

What is KubePattern? ​

KubePattern is an open-source analyzer, written in Go, that finds relational smells in Kubernetes: defects that live not in any single manifest, but in the relations between resources.

Valid in isolation, wrong together

A Page that no menu lists, a Composition for a kind that nothing defines, a database Cluster with no backup schedule. Every one of these manifests is valid on its own. The defect shows up only in the presence or the absence of a relation, which is exactly what KubePattern looks at.

Extensibility makes this matter more every year. Custom resource definitions let operators register new kinds, and entire platforms are now built out of custom resources that refer to each other by name. A growing part of a deployment's architecture is expressed through those relations (ownership, label selectors, references by name), and few tools check them.

Relational smells ​

KubePattern groups what it finds into four families.

FamilyWhat it isExample
Unused / orphanA definition exists, but nothing refers to it.A ClusterIssuer that no Certificate uses
Dangling referenceA resource points at something that does not exist.A Composition for a kind that no XRD defines
Missing companionA resource lacks the sibling that should accompany it.A PostgreSQL Cluster with no ScheduledBackup
MisconfigurationA relation exists that should not.A Pooler named like a Cluster in the same namespace

The Pattern reference shows how a pattern describes each family, and the Registry has ready-made patterns for real platforms.

How a scan works ​

How a KubePattern run moves data Patterns and live resources are read from the cluster. The engine lints the patterns, fetches the kinds they name, builds a graph, evaluates the relationships and writes Smell resources back to the same cluster. Kubernetes clusterPatternskind: PatternLive resourcesany kind, CRDs includedKubePattern engine · runs as a CronJob1Lint patternsa malformed pattern is skipped2Fetch kindsdiscovery + dynamic client3Build the graphonce per run, read-only4Evaluaterelationships as queries5Write smellscreate, update, pruneSmellskind: Smellreadlistwrite
  1. Read the patterns. Patterns are custom resources in your cluster. Each one is checked by a linter before use: a malformed pattern is logged and skipped.
  2. Fetch what they need. Kinds are resolved at run time through API discovery and the dynamic client, so custom resources unknown at build time are reachable. Only the kinds the patterns name are listed, together with the owner kinds reachable from them. A pattern can also name a set of kinds, such as every kind of an API group or of a discovery category.
  3. Build the graph. The fetched resources become the vertices of a graph that is built once per run and never modified by the analysis.
  4. Evaluate. For each pattern, the engine selects the candidate targets and checks the relationships declared in the pattern against the graph.
  5. Write the smells. Each target that matches becomes a Smell, a custom resource that carries the severity, category and message of the pattern.
  6. Self-heal. When the condition stops holding, the Smell is deleted on the next run. Nothing needs to be cleaned up by hand.

The scan runs as a Kubernetes CronJob, hourly by default. Between scans, nothing is running.

Pattern-as-Code ​

A Pattern describes a defect, not a rule: it states the condition that a defective resource satisfies, so every match is a finding. Patterns are built from a small set of relational primitives and contain no expression language, which keeps them readable and checkable. The primitives follow the ways resources refer to one another: references by name, ownership, and label selectors.

The resource a smell is reported on, the target, is fixed by the pattern. A smell may arise from the interaction of several resources, but it is always attributed to one.

yaml
target:
  kind: ClusterIssuer
  apiVersion: cert-manager.io/v1
  plural: clusterissuers
dependencies:
  - id: certificate
    kind: Certificate
    apiVersion: cert-manager.io/v1
    plural: certificates
relationships:
  matchNone:            # no Certificate refers to the issuer: it is unused
    - with: certificate
      type: custom
      criteria:
        - targetPath: "metadata.name"
          dependencyPath: "spec.issuerRef.name"
          operator: EQUALS

Stateful, Kubernetes-native findings ​

Patterns and Smells are both custom resources. You query them with kubectl, protect them with RBAC, and manage them with GitOps.

  • Stable identity. A Smell is named after its pattern and the UID of its target, so the same finding is updated in place from run to run.
  • First observation. Each Smell records when it was first seen (spec.since).
  • Minimum duration. A pattern can require its condition to hold for a minimum time (for) before the finding turns from Pending to Active. This hides transient states, such as a resource that looks unused for a few minutes while a GitOps tool re-creates its only referrer. See Lifecycle.
  • Suppression. Mark a false positive once and it stays suppressed on later runs.

What KubePattern is not ​

  • Not a policy engine. KubePattern does not sit in the admission path and does not block anything. It complements engines such as Kyverno, which are the right tool for enforcement and for rich per-field rules.
  • Not a cleaner. KubePattern never deletes your resources. Its service account reads the cluster and writes only its own Smells.
  • Not a per-resource linter. It does not check one manifest against best practices. It checks how resources relate.

Where next ​