Optimize workloads owned by custom operators using CRDs

Configure how workloads managed by custom operators are optimized with Custom Resource Definitions

In Kubernetes, operators—or custom controllers—can manage workloads. For example, a custom resource might own and manage a Deployment workload. StormForge automatically detects these ownership relationships.

When another resource (an operator) owns a workload, StormForge typically targets this owner for patching rather than the workload. This way, changes persist and aren’t overwritten by the operator’s reconciliation loop.

You can configure how StormForge interacts with custom operators using the ownerResourceTypes Helm parameter.

How Optimize Live handles custom operators

  1. Workload discovery: The StormForge Agent monitors for workloads (like Deployments) and checks their owner references.
  2. Owner traversal: If an owner is found, the agent traverses up the ownership chain until reaching the root owner or a stopTraversal type.
  3. Validate owner type: If ignoreOwner is configured, StormForge treats the child workload as independent of the owner.
  4. Patching: When a workload recommendation is generated, some patches may target (and be applied to) the owner.

Define a custom operator

Define custom operators using the Helm parameter ownerResourceTypes in the StormForge Agent’s Helm configuration.

Use the ownerResourceTypes Helm parameter to:

  • Ignore owners and patch the underlying workload directly.
  • Stop traversal and control owner identification in complex ownership chains.
  • Define patch paths for custom operators, so StormForge knows how to update them.

Helm parameter: ownerResourceTypes

The ownerResourceTypes parameter is a list of objects with the following fields:

Field Description Required
group The operator API group (for example, opentelemetry.io). Yes
kind The operator Kind (for example, OpenTelemetryCollector). Yes
ignoreOwner (Boolean) If true, StormForge ignores the operator and treats the child workload as independent. No
stopTraversal (Boolean) If true, StormForge stops looking for owners beyond this one. No
patchTargetTypeDefaults (Map) Default patch paths. Required for patching. Conditional

Patch target type defaults

StormForge uses patch paths to determine which operator fields to update when performing optimization operations.

Common keys for patchTargetTypeDefaults:

  • live.stormforge.io/containers.cpu.requests.patch-path
  • live.stormforge.io/containers.cpu.limits.patch-path
  • live.stormforge.io/containers.memory.requests.patch-path
  • live.stormforge.io/containers.memory.limits.patch-path

Contact StormForge support for information on how to define patch path settings for your operator.

Configuration use cases

Patch the operator

If you use a custom operator, you likely manage your configuration in the operator CRD rather than the underlying workload. You can tell StormForge to write CPU and memory settings back to the operator CRD.

Example: OpenTelemetry Collector

To configure StormForge to target your OpenTelemetryCollector resource CRD, which owns your Deployment workload, your values.yaml may resemble the following:

ownerResourceTypes:
- group: opentelemetry.io
  kind: OpenTelemetryCollector
  resource: opentelemetrycollectors
  patchTargetTypeDefaults:
    # These paths define where resource settings live in the OpenTelemetryCollector CRD
    live.stormforge.io/pod-template.metadata.patch-path: >
      /spec/podAnnotations
    live.stormforge.io/pod-template.metadata.patch-format: >
      { "stormforge.io/recommendation-url": "{{ .RecommendationURL }}" }
    live.stormforge.io/containers.cpu.requests.patch-path: >
      /spec/resources/requests/cpu
    live.stormforge.io/containers.cpu.limits.patch-path: >
      /spec/resources/limits/cpu
    live.stormforge.io/containers.memory.requests.patch-path: >
      /spec/resources/requests/memory
    live.stormforge.io/containers.memory.limits.patch-path: >
      /spec/resources/limits/memory

With this configuration, when StormForge optimizes the collector’s Deployment, it patches the OpenTelemetryCollector operator owner rather than the Deployment.

Ignore the operator

Operators can create a workload without exposing resource configuration in its own spec, or act merely as a deployment trigger. When this happens, patching the operator is impossible or useless.

Use ignoreOwner: true to tell StormForge to skip the operator and patch the underlying workload (for example, Deployment) directly.

Example: “Fire-and-forget” builder

Imagine an in-house builder, AppBuilder, that creates Deployments but then stops managing them.

ownerResourceTypes:
- group: internal.example.com
  kind: AppBuilder
  ignoreOwner: true

With ignoreOwner: true, while StormForge sees that AppBuilder owns the Deployment, it ignores that relationship and treats the Deployment as the patch target.

Stop traversal

In deep ownership chains (for example, AppPlatform -> AppInstance -> Deployment), you might want to patch AppInstance but not AppPlatform.

Set stopTraversal: true on AppInstance to tell StormForge: “Stop looking for owners here. Treat AppInstance as the owner.”

Last modified February 5, 2026