Optimizing Workloads Owned by Custom Operators (CRDs)
In Kubernetes, many workloads are managed by “Operators” or custom controllers. For example, a Deployment might be owned and managed by an in-house custom resource. StormForge automatically detects these ownership relationships.
When a workload is owned by another resource (an “Operator”), StormForge typically targets the Owner for patching, rather than the workload itself. This ensures that your changes persist and aren’t overwritten by the operator’s reconciliation loop.
You can configure how StormForge interacts with these custom operators using the ownerResourceTypes Helm parameter.
Configuration
The ownerResourceTypes parameter allows you to:
- Define Patch Paths for custom operators (so StormForge knows how to update them).
- Ignore Owners, telling StormForge to patch the underlying workload instead.
- Stop Traversal, used to control owner identification in complex ownership chains.
Helm Parameter: ownerResourceTypes
The ownerResourceTypes parameter is a list of objects with the following fields:
| Field | Description | Required |
|---|---|---|
group |
The API group of the Operator (e.g., opentelemetry.io). |
Yes |
kind |
The Kind of the Operator (e.g., OpenTelemetryCollector). |
Yes |
ignoreOwner |
(Boolean) If true, StormForge ignores this operator and treats the child workload as independent. |
No |
stopTraversal |
(Boolean) If true, StormForge stops looking for further owners beyond this one. |
No |
patchTargetTypeDefaults |
(Map) Default patch paths. Required if you want to patch this operator type. | Conditional |
Patch Target Type Defaults
StormForge uses “Patch Paths” to know which fields in your Operator’s YAML to update when performing various 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
Patch path values are Go templates that will be resolved to JSON pointers, with some extensions. For information on how to define Patch Path settings for your Operator, please contact StormForge support.
Scenario 1: Patching the Operator
If you use a custom operator like the OpenTelemetryCollector, you likely manage your configuration in the OpenTelemetryCollector CRD, not in the underlying Deployment. To optimize this, you might choose to tell StormForge how to write CPU and Memory settings back to that CRD.
Example: OpenTelemetry Collector
You want StormForge to optimize your collectors. The OpenTelemetryCollector resource owns the Deployment. You configure StormForge to target the Collector CRD.
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 will patch the OpenTelemetryCollector operator owner, instead of the Deployment.
Scenario 2: Ignoring the Operator
Sometimes, an operator creates a workload but does not expose resource configuration in its own spec, or acts merely as a deployment trigger. In this case, patching the operator is impossible or useless.
You can use ignoreOwner: true to tell StormForge to skip this operator and patch the underlying workload (e.g., Deployment) directly.
Example: “Fire-and-Forget” Builder
Imagine an in-house builder, AppBuilder, that creates Deployments but stops managing them afterwards.
ownerResourceTypes:
- group: internal.example.com
kind: AppBuilder
ignoreOwner: true
Result: StormForge sees the Deployment owned by AppBuilder, but ignores that relationship. It treats the Deployment as the patch target.
Scenario 3: Stopping Traversal
In deep ownership chains (e.g., AppPlatform -> AppInstance -> Deployment), you might want to patch the AppInstance but not the top-level AppPlatform.
Setting stopTraversal: true on AppInstance tells StormForge: “Stop looking for owners here. Treat AppInstance as the owner.”
How It Works
- Workload Discovery: The StormForge Agent watches for workloads (like Deployments) and checks their owner references.
- Owner Traversal: If an owner is found, the agent traverses up the ownership chain until it finds the root owner or stops due to reaching a type for which
stopTraversalis configured. - Validate Owner Type: If the owner type is configured with
ignoreOwner, StormForge will ignore the operator and treat the child workload as independent. Otherwise, the owner will be used as the workload’s patch target. - Patching: When a recommendation is generated for the workload, some kinds of patches may target and be applied to the Owner resource.