Skip to content

Smells ​

The results of a KubePattern analysis are Smells: custom resources that each describe one defect on one resource. A Smell is produced by a Pattern, and it is kept up to date by every run until the defect is fixed.

yaml
apiVersion: kubepattern.dev/v1
kind: Smell
metadata:
  name: cnpg-cluster-without-scheduledbackup-9c1e4d2a-5b7f-4c1e-8a3d-2f6b0e91c7a4
  namespace: orders
spec:
  name: cnpg-cluster-without-scheduledbackup
  category: Reliability
  severity: HIGH
  message: "Cluster orders/pg-orders has no ScheduledBackup."
  suppress: false
  pattern:
    name: cnpg-cluster-without-scheduledbackup
    version: kubepattern.dev/v1
  target:
    apiVersion: postgresql.cnpg.io/v1
    kind: Cluster
    name: pg-orders
    namespace: orders
    uid: 9c1e4d2a-5b7f-4c1e-8a3d-2f6b0e91c7a4

Retrieving results ​

Smells are namespaced resources, and smell is also the short name.

bash
# every smell in the cluster
kubectl get smells -A

# one smell in detail
kubectl describe smell <smell-name> -n <namespace>

# as YAML
kubectl get smell <smell-name> -n <namespace> -o yaml

# the smells of one pattern, using its UID
kubectl get smells -A -l kubepattern.dev/pattern-uid=<pattern-uid>

Patterns, in contrast, are cluster-scoped: kubectl get patterns needs no namespace.

Filtering by field

kubectl --field-selector does not work on custom resource fields such as spec.severity. Use labels, or output to JSON and filter with jq:

bash
kubectl get smells -A -o json \
  | jq -r '.items[] | select(.spec.severity=="HIGH") | .metadata.namespace + "/" + .metadata.name'

Columns ​

kubectl get smells shows the following columns. The last three appear with -o wide.

ColumnField
Severityspec.severity
Phase next releasespec.phase
Since next releasespec.sinceshown as an age, such as 3d
Target Kindspec.target.kind
Target Namespec.target.name
Target Namespacespec.target.namespace-o wide
Messagespec.message-o wide
Suppressedspec.suppress-o wide

Where a Smell is stored ​

By default, a Smell is stored in the namespace of the resource it concerns. Smells about cluster-scoped resources, or all Smells if so configured, go to a dedicated namespace. Set analysis.saveInNamespace and analysis.targetNamespace in the chart to choose. See Getting Started.

Naming and identity ​

The name of a Smell is <pattern-name>-<target-uid>. The same finding is therefore updated in place across runs instead of being created again, and kubectl get smells -A always lists the current problems.

A Smell raised by an absence pattern, which has no target resource, is named <pattern-name>-empty.

The Smell resource ​

PropertyDescription
apiVersionkubepattern.dev/v1.
kindAlways Smell.
metadata.name<pattern-name>-<target-uid>.
metadata.namespaceThe namespace of the target, unless configured otherwise.
metadata.labelskubepattern.dev/pattern-uid next release links the Smell to its pattern. kubepattern.dev/phase next release mirrors spec.phase, so a selector can keep only Active smells. lastScan is the id of the run that last wrote it.
spec.nameThe name of the pattern that produced the Smell.
spec.categoryThe category of the pattern.
spec.severityLOW, MEDIUM, HIGH or CRITICAL.
spec.messageThe message of the pattern, with its placeholders filled in.
spec.referenceA link to documentation on how to fix the Smell.
spec.patternThe name of the pattern and its API version.
spec.targetThe apiVersion, kind, name, namespace and uid of the resource the Smell is reported on.
spec.phase next releasePending until the condition has held for the pattern's for, Active afterwards.
spec.since next releaseWhen the condition was first observed.
spec.suppressWhether the Smell has been marked as a false positive.

Suppressing a false positive ​

A pattern can only see the references it describes, so now and then it flags something you know is fine. Mark that Smell as suppressed:

bash
kubectl patch smell <smell-name> -n <namespace> \
  --type merge -p '{"spec":{"suppress":true}}'

KubePattern keeps the flag on the following runs, so the suppression survives. next release Earlier versions reset it on every update. A suppressed Smell is still listed by kubectl get smells, so filter on spec.suppress in your own dashboards and alerts.

When a Smell disappears ​

KubePattern removes a Smell as soon as its target no longer satisfies the pattern. Fix the problem, and the Smell is gone on the next run, with no manual clean-up. A Smell is also removed when its pattern is deleted.

If a pattern is skipped, for example because the analyzer cannot read one of its kinds, its Smells are kept rather than removed. next release Lifecycle has the details.