v1alpha1

ResourceCanary API

The practical reference for recommendation, rollout, safety, analysis, persistence, lifecycle, and status fields.

Target reference

targetRef:
  apiVersion: apps/v1
  kind: Deployment
  name: checkout
API versionKinds
apps/v1Deployment, StatefulSet
argoproj.io/v1alpha1Rollout

Recommendation

recommendation:
  source: Manual | VPA
  manual:
    containers:
      - name: app
        resources:
          requests: { cpu: 500m, memory: 768Mi }
          limits: { cpu: "1", memory: 1Gi }
  vpa:
    name: checkout-vpa
    selection: Target | LowerBound | UpperBound

Manual resources are partial overlays. You can specify only requests, only limits, or individual CPU or memory keys. Explicit keys replace the captured live baseline; omitted keys inherit it and never mean removal. Kapr stores and validates the complete merged candidate in status.

If live Pods have inconsistent resources, Kapr blocks a partial Manual recommendation with reason PartialManualRecommendationRequiresConsistentBaseline. Make the fleet consistent or provide complete CPU and memory requests and limits. Requests must not exceed their effective limits after merging.

VPA recommendations provide requests; their refresh policy controls limit handling independently.

VPA refresh and limit policy

refreshPolicy:
  mode: ManualCapture | ThresholdBased
  minimumCpuDeltaPercent: 10
  minimumMemoryDeltaPercent: 10
  minimumTimeSinceLastValidation: 168h
  vpaCpuLimitPolicy: Omit | Derive
  defaultCpuLimitPercentageBump: 0
  defaultMemoryLimitPercentageBump: 20
  forceLimitResizing: false

ThresholdBased requires the minimum time to have elapsed and at least one container's CPU or memory delta to meet its threshold. Deltas may increase or decrease.

vpaCpuLimitPolicy defaults to Omit. When the original workload container has no CPU limit, Kapr keeps the VPA CPU request but omits its CPU limit, even if defaultCpuLimitPercentageBump is configured. Set the policy to Derive to apply that bump to CPU.

Kapr never removes an original CPU limit because Kubernetes does not support removing it through in-place resize. An existing sufficient CPU limit is retained; one below the new CPU request is raised to the request. Memory-limit derivation remains independent.

For derived limits, a bump of 0 makes limit equal request; 20 makes it 120% of request. With forceLimitResizing: false, an existing limit is preserved whenever it already accommodates the new request. These rules only apply to VPA recommendations; Manual recommendations use their explicit resources.

Rollout

rollout:
  initialDelay: 5m
  maxConcurrentResizes: 2
  podSelection: { strategy: StableHash }
  steps:
    - { percent: 10, pause: 10m }
    - { percent: 50, pause: 30m }
    - { percent: 100, pause: 1h }

Steps must be strictly increasing and end at exactly 100%. initialDelay measures pod age since its latest Ready transition.

Safety

safety:
  minReadyPods: 3
  requireAllTargetPodsReadyBeforeStarting: true
  stopIfTargetWorkloadUpdating: true
  allowSingleReplicaWorkload: false

CPU throttling analysis

analysis:
  cpuThrottling:
    enabled: true
    thresholdFraction: 0.05
    window: 5m
    mode: AnyPod | PercentageOfPods | Average
    percentageOfPodsThreshold: 30
    onMetricsUnavailable: Pass | Fail
    prometheus:
      url: http://prometheus.monitoring.svc:9090

The configured pause is a minimum. Analysis waits until every selected pod has spent at least one full analysis window at its resized target.

Persistence

persistence:
  mode: AdmissionOnNextPodTemplateChange | Disabled
  gitOps:
    enabled: false

Disabled validates live pods but never propagates the result to the workload template. The terminal phase is ValidatedWithoutPersistence.

Lifecycle and manual revalidation

lifecycle:
  onRecommendationChange: Revalidate
  revalidationToken: "retry-1"

revalidationToken is an optional opaque string. Each new non-empty value starts one fresh validation attempt using the currently resolved recommendation. It can be a timestamp, deployment ID, Git commit, or operator-generated nonce; Kapr does not parse it as a date.

Reusing the last observed value or clearing the field is a no-op. An explicit token can retry a failed revision once and, for VPA recommendations, captures the latest recommendation without waiting for configured refresh thresholds.

A retrigger restarts an active validation from step zero and cancels pending persistence. Use a unique, non-sensitive value for each requested attempt.

Selected status fields

FieldPurpose
status.phaseHigh-level lifecycle state.
recommendation.currentRevisionHash of the current candidate.
recommendation.validatedRevisionRevision proven across the fleet.
validation.baselineResourcesResources being changed from.
validation.candidateResourcesResources being validated.
validation.observedRevalidationTokenLast manual retrigger token processed.
validation.podsPer-pod resize lifecycle.
recommendation.failedRevisionsSticky deny-list of failed hashes.
conditionsKubernetes-style decision details.

For every field and metric, see the repository's full source reference.