KubeHerodocs · v0.3.3

CRD reference

BudgetPolicy, CeilingPolicy and RightsizingPolicy — every field, every default, the arming annotation and the status each one reports.

Three CRDs in the kubehero.kubehero.io/v1 API group, reconciled by the operator. All three are conservative by default: nothing mutates a workload until a human arms the policy.

Arming

humanArm defaults to true on every policy. An armed policy carries the annotation:

metadata:
  annotations:
    kubehero.kubehero.io/armed: "true"

It's set by a human — from the dashboard, with kubehero cap --arm, or with kubectl annotate — never by the operator or the advisor. Each policy reports an Armed condition. Setting humanArm: false removes the gate for that policy; don't, in production.

BudgetPolicy

Declarative spending intent for a scope.

apiVersion: kubehero.kubehero.io/v1
kind: BudgetPolicy
metadata:
  name: prod-monthly
  namespace: kubehero-system
spec:
  scope:
    clusterSelector:
      matchLabels: { env: prod }
  ceiling: "$100000/mo"
  hardStop: true
  humanArm: true
  escalation:
    - action: alert
      channels: ["slack://ops-oncall"]
      waitAfter: "2m"
    - action: hpa.cap
      ratioPercent: 50
      waitAfter: "3m"
  alertChannels:
    - "slack://ops"
    - "pagerduty://prod-p1"
FieldTypeDefaultNotes
scope.clusterSelectorLabelSelectorallclusters the policy applies to
scope.namespaceSelectorLabelSelectorallnamespaces within those clusters
ceilingstringrequiredhuman-readable limit: $100000/mo, $300/hr
hardStopboolfalsewhen false the policy is alert-only; the escalation plan never runs
humanArmbooltrueescalation needs the arming annotation
escalation[]EscalationStepordered steps, see below
alertChannels[]stringnotified at threshold crossings (50 / 80 / 95 / 100% by default)

EscalationStep

FieldNotes
actionalert · hpa.cap · pod.evict · nodepool.cordon
ratioPercent1–100, for scaling actions (e.g. cap HPA max replicas at 50%)
waitAfterdelay before the next step, e.g. 2m
channels[]for alert: channel URLs as in Alerting

Evictions respect PodDisruptionBudgets. Every action records the prior state so kubehero undo can restore it within the cooldown.

CeilingPolicy

Burn-rate triggered enforcement for a BudgetPolicy.

apiVersion: kubehero.kubehero.io/v1
kind: CeilingPolicy
metadata:
  name: prod-burn-2x
  namespace: kubehero-system
spec:
  budgetRef: prod-monthly
  trigger:
    burnRateMilli: 2000   # 2.0× the budgeted rate
    window: "5m"          # sustained this long
  escalation:
    - action: hpa.cap
      ratioPercent: 40
      waitAfter: "2m"
  cooldown: "10m"
  humanArm: true
FieldTypeDefaultNotes
budgetRefstringrequiredthe BudgetPolicy this ceiling protects
trigger.burnRateMilliint ≥ 1000requiredburn-rate multiple × 1000 (1500 = 1.5×)
trigger.windowdurationrequiredhow long the burn rate must hold
escalation[]EscalationStepas for BudgetPolicy
cooldowndurationminimum time between escalations; also the undo window
humanArmbooltrue

The operator reads the live burn rate from the control plane. If it can't reach the control plane it reads zero, so ceilings can never trip.

RightsizingPolicy

How to recommend, shadow or apply rightsizing. Full behaviour: Rightsizing.

apiVersion: kubehero.kubehero.io/v1
kind: RightsizingPolicy
metadata:
  name: payments-rightsize
  namespace: kubehero-system
spec:
  scope:
    namespaceSelector:
      matchLabels: { team: payments }
  mode: shadow
  humanArm: true
  minConfidence: medium
  adjustLimits: false
  targetUtilization: 70
  exclude: ["payments-db-migrator"]
  safety:
    observationWindow: 7d
    p95HeadroomPct: 15
    maxChangePerDay: 1
    minReplicas: 2
FieldTypeDefaultNotes
scopeScoperequiredclusterSelector / namespaceSelector
modeenumrequiredrecommend · shadow · apply
humanArmbooltrueapply mode needs the arming annotation
minConfidenceenummediumlow · medium · high — lowest confidence apply acts on
adjustLimitsboolfalsealso scale limits, keeping the limit:request ratio
targetUtilizationint 1–100alternative to headroom: headroom = 100 / target − 1
exclude[]stringworkload names to skip
safety.observationWindowduration7d1h – 90d
safety.p95HeadroomPctint15headroom over the sized percentile
safety.maxChangePerDayint1per workload per UTC day; 0 blocks all changes
safety.minReplicasint1skip workloads with fewer replicas

Workloads annotated kubehero.io/rightsizing: "disabled" are always skipped.

Status

FieldMeaning
conditionsReady, Armed, …
workloadsInScopeworkloads the scope matched
recommendations[]namespace, workload, kind, container, currentCpuRequest, recommendedCpuRequest, currentMemoryRequest, recommendedMemoryRequest, savingsUsdMonth, confidence, reason, oomKills
totalSavingsUsdMonthsum of savings
plannedChanges[]cpuRequest / memoryRequest / cpuLimit / memoryLimit as from → to, outcome (planned · applied · blocked · failed), reason, changeId
lastEvaluated, lastAppliedtimestamps

Samples

Ready-to-apply samples live in config/samples in the platform repo. kubectl apply -f and kubehero apply -f both work; the operator reconciles within seconds and re-evaluates rightsizing every 10 minutes.

On this page