Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/content/en/docs/documentation/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ This section contains detailed documentation for all Java Operator SDK features

- **[Eventing](eventing/)** - Understanding the event-driven model
- **[Accessing Resources in Caches](working-with-es-caches/)** - How to access resources in caches
- **[Observability](observability/)** - Monitoring and debugging your operators
- **[Operations](operations/)** - Helm chart, metrics, and logging
- **[Other Features](features/)** - Additional capabilities and integrations

Each guide includes practical examples and best practices to help you build robust, production-ready operators.
6 changes: 6 additions & 0 deletions docs/content/en/docs/documentation/operations/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Operations
weight: 85
---

This section covers operations-related features for running and managing operators in production.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Configurations
weight: 55
weight: 89
---

The Java Operator SDK (JOSDK) provides abstractions that work great out of the box. However, we recognize that default behavior isn't always suitable for every use case. Numerous configuration options help you tailor the framework to your specific needs.
Expand Down
116 changes: 116 additions & 0 deletions docs/content/en/docs/documentation/operations/helm-chart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
title: Generic Helm Chart
weight: 86
---

A generic, reusable Helm chart for deploying Java operators built with JOSDK is available at
[`helm/generic-helm-chart`](https://github.com/java-operator-sdk/java-operator-sdk/tree/main/helm/generic-helm-chart).

It is intended as a **template for operator developers** — a starting point that covers common deployment
patterns so you don't have to write a chart from scratch. The chart is maintained on a **best-effort basis**.
Contributions are more than welcome.

The chart is used in the
[`metrics-processing` sample operator E2E test](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/sample-operators/metrics-processing/src/test/java/io/javaoperatorsdk/operator/sample/metrics/MetricsHandlingE2E.java)
to deploy the operator to a cluster via Helm.

## What the Chart Provides

- **Deployment** with security defaults (non-root user, read-only filesystem, no privilege escalation)
- **Dynamic RBAC** (ClusterRole, ClusterRoleBinding, ServiceAccount) — permissions are generated automatically
from the primary and secondary resources you declare in `values.yaml`
- **ConfigMap** for operator configuration (`config.yaml`) and logging (`log4j2.xml`), mounted at `/config`
- **Leader election** support (opt-in)
- **Extensibility** via extra containers, init containers, volumes, and environment variables

## Key Configuration

The most important values to set when adapting the chart for your operator:

```yaml
image:
repository: my-operator-image # required
tag: "latest"

# Custom resources your operator reconciles
primaryResources:
- apiGroup: "sample.javaoperatorsdk"
resources:
- myresources

# Kubernetes resources your operator manages
secondaryResources:
- apiGroup: ""
resources:
- configmaps
- services
```

Primary resources get read/watch/patch permissions and status sub-resource access.
Secondary resources get full CRUD permissions. Default verbs can be overridden per resource entry.

### Operator Environment

The chart injects `OPERATOR_NAMESPACE` automatically. You can optionally set `WATCH_NAMESPACE` to
restrict the operator to a single namespace, and add arbitrary environment variables:

```yaml
operator:
watchNamespace: "" # empty = all namespaces
env:
- name: MY_CUSTOM_VAR
value: "some-value"
```

### Resource Defaults

```yaml
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
```

See the full
[`values.yaml`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/helm/generic-helm-chart/values.yaml)
for all available options.

## Usage Example

A working example of how to use the chart can be found in the metrics-processing sample operator's
[`helm-values.yaml`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/sample-operators/metrics-processing/src/test/resources/helm-values.yaml):

```yaml
image:
repository: metrics-processing-operator
pullPolicy: Never
tag: "latest"

nameOverride: "metrics-processing-operator"

resources: {}

primaryResources:
- apiGroup: "sample.javaoperatorsdk"
resources:
- metricshandlingcustomresource1s
- metricshandlingcustomresource2s
```

Install with:

```shell
helm install my-operator ./helm/generic-helm-chart -f my-values.yaml --namespace my-ns
```

## Testing the Chart

The chart includes unit tests using the [helm-unittest](https://github.com/helm-unittest/helm-unittest) plugin.
Run them with:

```shell
./helm/run-tests.sh
```
51 changes: 51 additions & 0 deletions docs/content/en/docs/documentation/operations/logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: Logging
weight: 88
---

## Contextual Info for Logging with MDC

Logging is enhanced with additional contextual information using
[MDC](http://www.slf4j.org/manual.html#mdc). The following attributes are available in most
parts of reconciliation logic and during the execution of the controller:

| MDC Key | Value added from primary resource |
|:---------------------------|:----------------------------------|
| `resource.apiVersion` | `.apiVersion` |
| `resource.kind` | `.kind` |
| `resource.name` | `.metadata.name` |
| `resource.namespace` | `.metadata.namespace` |
| `resource.resourceVersion` | `.metadata.resourceVersion` |
| `resource.generation` | `.metadata.generation` |
| `resource.uid` | `.metadata.uid` |
Comment on lines +12 to +20
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table rows start with || instead of a single |. Many Markdown renderers (and Hugo Markdown configurations) expect | ... | ... | and may not render this as a table. Use a single leading pipe per row (e.g., | MDC Key | ... |) for consistent rendering.

Copilot uses AI. Check for mistakes.

For more information about MDC see this [link](https://www.baeldung.com/mdc-in-log4j-2-logback).

### MDC entries during event handling

Although, usually users might not require it in their day-to-day workflow, it is worth mentioning that
there are additional MDC entries managed for event handling. Typically, you might be interested in it
in your `SecondaryToPrimaryMapper` related logs.
For `InformerEventSource` and `ControllerEventSource` the following information is present:

| MDC Key | Value from Resource from the Event |
|:-----------------------------------------------|:-------------------------------------------------|
| `eventsource.event.resource.name` | `.metadata.name` |
| `eventsource.event.resource.uid` | `.metadata.uid` |
| `eventsource.event.resource.namespace` | `.metadata.namespace` |
| `eventsource.event.resource.kind` | resource kind |
| `eventsource.event.resource.resourceVersion` | `.metadata.resourceVersion` |
| `eventsource.event.action` | action name (e.g. `ADDED`, `UPDATED`, `DELETED`) |
| `eventsource.name` | name of the event source |
Comment on lines +31 to +39
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as above: || is non-standard for Markdown tables and may break rendering. Switch these rows to start with a single |.

Copilot uses AI. Check for mistakes.

### Note on null values

If a resource doesn't provide values for one of the specified keys, the key will be omitted and not added to the MDC
context. There is, however, one notable exception: the resource's namespace, where, instead of omitting the key, we emit
the `MDCUtils.NO_NAMESPACE` value instead. This allows searching for resources without namespace (notably, clustered
resources) in the logs more easily.

### Disabling MDC support

MDC support is enabled by default. If you want to disable it, you can set the `JAVA_OPERATOR_SDK_USE_MDC` environment
variable to `false` when you start your operator.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Observability
weight: 55
title: Metrics
weight: 87
---

## Runtime Info
Expand All @@ -15,53 +15,6 @@ setting, where this flag usually needs to be set to false, in order to control t
See also an example implementation in the
[WebPage sample](https://github.com/java-operator-sdk/java-operator-sdk/blob/3e2e7c4c834ef1c409d636156b988125744ca911/sample-operators/webpage/src/main/java/io/javaoperatorsdk/operator/sample/WebPageOperator.java#L38-L43)

## Contextual Info for Logging with MDC

Logging is enhanced with additional contextual information using
[MDC](http://www.slf4j.org/manual.html#mdc). The following attributes are available in most
parts of reconciliation logic and during the execution of the controller:

| MDC Key | Value added from primary resource |
|:---------------------------|:----------------------------------|
| `resource.apiVersion` | `.apiVersion` |
| `resource.kind` | `.kind` |
| `resource.name` | `.metadata.name` |
| `resource.namespace` | `.metadata.namespace` |
| `resource.resourceVersion` | `.metadata.resourceVersion` |
| `resource.generation` | `.metadata.generation` |
| `resource.uid` | `.metadata.uid` |

For more information about MDC see this [link](https://www.baeldung.com/mdc-in-log4j-2-logback).

### MDC entries during event handling

Although, usually users might not require it in their day-to-day workflow, it is worth mentioning that
there are additional MDC entries managed for event handling. Typically, you might be interested in it
in your `SecondaryToPrimaryMapper` related logs.
For `InformerEventSource` and `ControllerEventSource` the following information is present:

| MDC Key | Value from Resource from the Event |
|:-----------------------------------------------|:-------------------------------------------------|
| `eventsource.event.resource.name` | `.metadata.name` |
| `eventsource.event.resource.uid` | `.metadata.uid` |
| `eventsource.event.resource.namespace` | `.metadata.namespace` |
| `eventsource.event.resource.kind` | resource kind |
| `eventsource.event.resource.resourceVersion` | `.metadata.resourceVersion` |
| `eventsource.event.action` | action name (e.g. `ADDED`, `UPDATED`, `DELETED`) |
| `eventsource.name` | name of the event source |

### Note on null values

If a resource doesn't provide values for one of the specified keys, the key will be omitted and not added to the MDC
context. There is, however, one notable exception: the resource's namespace, where, instead of omitting the key, we emit
the `MDCUtils.NO_NAMESPACE` value instead. This allows searching for resources without namespace (notably, clustered
resources) in the logs more easily.

### Disabling MDC support

MDC support is enabled by default. If you want to disable it, you can set the `JAVA_OPERATOR_SDK_USE_MDC` environment
variable to `false` when you start your operator.

## Metrics

JOSDK provides built-in support for metrics reporting on what is happening with your reconcilers in the form of
Expand All @@ -77,9 +30,9 @@ Metrics metrics; // initialize your metrics implementation
Operator operator = new Operator(client, o -> o.withMetrics(metrics));
```

### MicrometerMetricsV2
### MicrometerMetricsV2

[`MicrometerMetricsV2`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/micrometer-support/src/main/java/io/javaoperatorsdk/operator/monitoring/micrometer/MicrometerMetricsV2.java)
[`MicrometerMetricsV2`](https://github.com/java-operator-sdk/java-operator-sdk/blob/main/micrometer-support/src/main/java/io/javaoperatorsdk/operator/monitoring/micrometer/MicrometerMetricsV2.java)
is the recommended micrometer-based implementation. It is designed with low cardinality in mind:
all meters are scoped to the controller, not to individual resources. This avoids unbounded cardinality growth as
resources come and go.
Expand Down Expand Up @@ -230,8 +183,8 @@ Metrics loggingMetrics = new LoggingMetrics();

// combine them into a single aggregated instance
Metrics aggregatedMetrics = new AggregatedMetrics(List.of(
micrometerMetrics,
customMetrics,
micrometerMetrics,
customMetrics,
loggingMetrics
));

Expand Down