Optimize workloads owned by custom operators using CRDs
3 minute read
Use this guide if your organization manages workloads with custom operators and you want greater control over owner identification and patch application.
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
- Workload discovery: The StormForge Agent monitors for workloads (like Deployments) and checks their owner references.
- Owner traversal: If an owner is found, the agent traverses up the ownership chain until reaching the root owner or a
stopTraversaltype. - Validate owner type: If
ignoreOwneris configured, StormForge treats the child workload as independent of the owner. - 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-pathlive.stormforge.io/containers.cpu.limits.patch-pathlive.stormforge.io/containers.memory.requests.patch-pathlive.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.”