This is an automated email from the ASF dual-hosted git repository.

gyfora pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/flink-kubernetes-operator.git


The following commit(s) were added to refs/heads/main by this push:
     new a8407c47 [FLINK-39791][helm] Honor defaultConfiguration.config.yaml 
and always mount config.yaml (#1126)
a8407c47 is described below

commit a8407c47a78c29f15a7dd9cc399b93b83d944223
Author: Gerk Elznik <[email protected]>
AuthorDate: Tue Aug 11 04:10:07 2026 -0600

    [FLINK-39791][helm] Honor defaultConfiguration.config.yaml and always mount 
config.yaml (#1126)
---
 .github/workflows/e2e.yaml                         |  4 +-
 docs/content.zh/docs/deployment/compatibility.md   |  2 +-
 docs/content.zh/docs/deployment/configuration.md   | 24 +++++++--
 .../docs/deployment/helm/installation.md           |  4 +-
 docs/content.zh/docs/internals/startup.md          |  8 +--
 docs/content/docs/deployment/compatibility.md      |  2 +-
 docs/content/docs/deployment/configuration.md      | 24 +++++++--
 docs/content/docs/deployment/helm/installation.md  |  4 +-
 docs/content/docs/internals/startup.md             |  8 +--
 e2e-tests/test_dynamic_flink_conf.sh               |  6 ++-
 .../operator/config/FlinkConfigManagerTest.java    | 39 ++++++++++++++
 .../conf/{flink-conf.yaml => config.yaml}          |  4 --
 .../templates/controller/configmap.yaml            | 24 +++------
 .../templates/controller/deployment.yaml           |  5 --
 .../tests/controller/configmap_test.yaml           | 61 ++++++++++++++++++++++
 .../tests/controller/deployment_test.yaml          | 13 +++++
 helm/flink-kubernetes-operator/values.yaml         | 11 +++-
 17 files changed, 192 insertions(+), 51 deletions(-)

diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml
index 197ea985..5d01ceab 100644
--- a/.github/workflows/e2e.yaml
+++ b/.github/workflows/e2e.yaml
@@ -84,8 +84,8 @@ jobs:
       - name: Start the operator
         run: |
           if [[ "${{ inputs.test }}" == "test_flink_operator_ha.sh" ]]; then
-           sed -i "s/# kubernetes.operator.leader-election.enabled: 
false/kubernetes.operator.leader-election.enabled: true/" 
helm/flink-kubernetes-operator/conf/flink-conf.yaml
-           sed -i "s/# kubernetes.operator.leader-election.lease-name: 
flink-operator-lease/kubernetes.operator.leader-election.lease-name: 
flink-operator-lease/" helm/flink-kubernetes-operator/conf/flink-conf.yaml
+           sed -i "s/# kubernetes.operator.leader-election.enabled: 
false/kubernetes.operator.leader-election.enabled: true/" 
helm/flink-kubernetes-operator/conf/config.yaml
+           sed -i "s/# kubernetes.operator.leader-election.lease-name: 
flink-operator-lease/kubernetes.operator.leader-election.lease-name: 
flink-operator-lease/" helm/flink-kubernetes-operator/conf/config.yaml
            sed -i "s/replicas: 1/replicas: 2/" 
helm/flink-kubernetes-operator/values.yaml
           fi
           if [[ "${{ inputs.test }}" == "test_dynamic_config.sh" ]]; then      
    
diff --git a/docs/content.zh/docs/deployment/compatibility.md 
b/docs/content.zh/docs/deployment/compatibility.md
index fe627034..fce7d41d 100644
--- a/docs/content.zh/docs/deployment/compatibility.md
+++ b/docs/content.zh/docs/deployment/compatibility.md
@@ -97,7 +97,7 @@ The operator JVM links against a specific Flink release for 
its own runtime need
 This bundled runtime is used by the operator process for purposes such as:
 
 - Pluggable filesystem access (`org.apache.flink.core.fs.FileSystem`), used to 
fetch `FlinkSessionJob` artifacts from non-HTTP schemes such as `s3://`, 
`gs://`, `hdfs://`.
-- Configuration parsing (`org.apache.flink.configuration.GlobalConfiguration`) 
that reads the operator's own `flink-conf.yaml`.
+- Configuration parsing (`org.apache.flink.configuration.GlobalConfiguration`) 
that reads the operator's own `config.yaml`.
 - Plugin discovery (`org.apache.flink.core.plugin.PluginManager`) that loads 
custom validators, mutators, listeners, and filesystem factories.
 
 ## Kubernetes
diff --git a/docs/content.zh/docs/deployment/configuration.md 
b/docs/content.zh/docs/deployment/configuration.md
index 6d08bc9b..3c66a0c8 100644
--- a/docs/content.zh/docs/deployment/configuration.md
+++ b/docs/content.zh/docs/deployment/configuration.md
@@ -51,10 +51,28 @@ defaultConfiguration:
 
 ### YAML Configuration File Format
 
-Operator configuration is delivered through the 
`defaultConfiguration.flink-conf.yaml` block in the Helm `values.yaml`. The 
operator's runtime loads that file with Flink's legacy configuration parser, 
which accepts only flat key-value pairs written with dot notation and does not 
support nested YAML maps.
+Operator configuration can be delivered in either of Flink's two configuration 
formats, by defining the matching key under `defaultConfiguration` in the Helm 
`values.yaml`:
+
+- `flink-conf.yaml` is the legacy format, which accepts only flat key-value 
pairs written with dot notation and does not support nested YAML maps. This is 
the format the chart ships by default.
+- `config.yaml` is the YAML 1.2 format defined from Flink 1.19 onward and the 
only format Flink 2.0 accepts. It supports nested keys (see the [Flink 
Configuration 
File](https://nightlies.apache.org/flink/flink-docs-master/docs/deployment/config/#flink-configuration-file)
 documentation):
+
+```yaml
+defaultConfiguration:
+  create: true
+  append: true
+  config.yaml: |+
+    kubernetes.operator:
+      metrics.reporter.slf4j:
+        factory.class: org.apache.flink.metrics.slf4j.Slf4jReporterFactory
+        interval: 5 MINUTE
+      reconcile.interval: 15 s
+      observer.progress-check.interval: 5 s
+```
+
+When both keys are set, `config.yaml` takes precedence. Either way the 
resolved configuration is mounted as `config.yaml`, the file name Flink 2.0 
requires.
 
 {{< hint info >}}
-Flink 2.0 onward also defines a `config.yaml` format with YAML 1.2 syntax that 
supports nested keys (see the [Flink Configuration 
File](https://nightlies.apache.org/flink/flink-docs-release-2.2/docs/deployment/config/#flink-configuration-file)
 documentation). The Helm chart's `values.yaml` shows a `config.yaml` example 
block, but with the current chart it is not effectively loadable: the ConfigMap 
template unconditionally renders both `flink-conf.yaml` and `config.yaml` keys, 
and Flink's [...]
+Prefer the nested form shown above. A flat, dotted-key override of a key that 
the chart's default `conf/config.yaml` already ships would be a duplicate key 
under Flink's strict YAML parser and fail at operator startup.
 {{< /hint >}}
 
 ### Flink Version and Namespace Specific Defaults
@@ -101,7 +119,7 @@ Whether dynamic configuration updates are enabled can be 
verified in the `deploy
 o.a.f.k.o.c.FlinkConfigManager [INFO ] Enabled dynamic config updates, 
checking config changes every PT5M
 ```
 
-To change config values dynamically, the ConfigMap can be edited directly with 
`kubectl patch` or `kubectl edit`. For example, the reconcile interval is 
changed by overriding `kubernetes.operator.reconcile.interval`.
+To change config values dynamically, the ConfigMap can be edited directly with 
`kubectl patch` or `kubectl edit`. Edits belong to the `config.yaml` key, which 
is the file the operator mounts. For example, the reconcile interval is changed 
by overriding `kubernetes.operator.reconcile.interval`.
 
 The update, here to 30 seconds, is confirmed in the operator log:
 
diff --git a/docs/content.zh/docs/deployment/helm/installation.md 
b/docs/content.zh/docs/deployment/helm/installation.md
index 0ed010b3..46c6d9ff 100644
--- a/docs/content.zh/docs/deployment/helm/installation.md
+++ b/docs/content.zh/docs/deployment/helm/installation.md
@@ -75,9 +75,9 @@ The configurable parameters of the Helm chart and their 
default values are detai
 | Parameters                                     | Description                 
                                                                                
                                                   | Default Value              
                                                                                
                                                                                
                                                                                
              [...]
 
|------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
 | defaultConfiguration.append                    | Whether to append 
configuration files with configs.                                               
                                                             | true             
                                                                                
                                                                                
                                                                                
                        [...]
-| defaultConfiguration.config.yaml               | The newer configuration 
file format for Flink that will be enforced in Flink 2.0. Note this was 
introduced in Flink 1.19.                                      | 
kubernetes.operator.metrics.reporter.slf4j.factory.class: 
org.apache.flink.metrics.slf4j.Slf4jReporterFactory<br/>kubernetes.operator.metrics.reporter.slf4j.interval:
 5 MINUTE<br/>kubernetes.operator.reconcile.interval: 15 
s<br/>kubernetes.operator.observer.progress-check.interva [...]
+| defaultConfiguration.config.yaml               | Modern YAML 1.2 config 
format (introduced in Flink 1.19, required by Flink 2.0). Takes precedence over 
flink-conf.yaml when set; the resolved config is always mounted as config.yaml. 
                                        | 
kubernetes.operator.metrics.reporter.slf4j.factory.class: 
org.apache.flink.metrics.slf4j.Slf4jReporterFactory<br/>kubernetes.operator.metrics.reporter.slf4j.interval:
 5 MINUTE<br/>kubernetes.operator.reconcile.interv [...]
 | defaultConfiguration.create                    | Whether to enable default 
configuration to create for flink-kubernetes-operator.                          
                                                     | true                     
                                                                                
                                                                                
                                                                                
                [...]
-| defaultConfiguration.flink-conf.yaml           | The default configuration 
of flink-conf.yaml.                                                             
                                                     | 
kubernetes.operator.metrics.reporter.slf4j.factory.class: 
org.apache.flink.metrics.slf4j.Slf4jReporterFactory<br/>kubernetes.operator.metrics.reporter.slf4j.interval:
 5 MINUTE<br/>kubernetes.operator.reconcile.interval: 15 
s<br/>kubernetes.operator.observer.progress-check.interva [...]
+| defaultConfiguration.flink-conf.yaml           | Legacy flat config format. 
Used when config.yaml is not set; the resolved config is always mounted as 
config.yaml.                                                                    
                                              | 
kubernetes.operator.metrics.reporter.slf4j.factory.class: 
org.apache.flink.metrics.slf4j.Slf4jReporterFactory<br/>kubernetes.operator.metrics.reporter.slf4j.interval:
 5 MINUTE<br/>kubernetes.operator.reconcile.i [...]
 | defaultConfiguration.log4j-console.properties  | The default configuration 
of log4j-console.properties.                                                    
                                                     |                          
                                                                                
                                                                                
                                                                                
                [...]
 | defaultConfiguration.log4j-operator.properties | The default configuration 
of log4j-operator.properties.                                                   
                                                     |                          
                                                                                
                                                                                
                                                                                
                [...]
 | defaultConfiguration.logback-operator.xml      | The default configuration 
of logback-operator.xml. Used when `logging.framework` is set to `logback`.     
                                                     |                          
                                                                                
                                                                                
                                                                                
                [...]
diff --git a/docs/content.zh/docs/internals/startup.md 
b/docs/content.zh/docs/internals/startup.md
index f37d4058..2f5f1b1b 100644
--- a/docs/content.zh/docs/internals/startup.md
+++ b/docs/content.zh/docs/internals/startup.md
@@ -91,7 +91,7 @@ helm install -f custom-values.yaml  flink-kubernetes-operator 
 helm/flink-kubern
                                   │
                                   │  flink-kubernetes-operator Deployment is 
created with:
                                   │      ENV: LOG_CONFIG=..., JVM_ARGS=..., 
OPERATOR_NAMESPACE, ...
-                                  │      Volume items: config.yaml (default) 
or flink-conf.yaml,
+                                  │      Volume items: config.yaml,
                                   │                    
log4j-operator.properties or logback-operator.xml,
                                   │                    
log4j-console.properties or logback-console.xml
                                   ▼
@@ -118,10 +118,10 @@ The following notes elaborate on the chart's CRD 
handling, helper-driven labels,
 
  - `crds/` uses Helm's special CRD handling: applied on `helm install` only, 
untouched by `helm upgrade` and `helm uninstall`. Based on this, Helm CRD 
upgrades and deletions are out-of-band today, and they need to be manually 
executed via `kubectl` commands (`kubectl apply -f crds/`, `kubectl delete crd 
...`). See [Upgrading the Operator → Upgrading the CRDs]({{< ref 
"docs/operations/upgrade#2-upgrading-the-crds" >}}) for the supported procedure.
  - `_helpers.tpl` defines a common label set applied to every chart-rendered 
resource: `app.kubernetes.io/name`, `app.kubernetes.io/version`, 
`app.kubernetes.io/managed-by`, and `helm.sh/chart`. The same 
`app.kubernetes.io/name` label is the operator Deployment's 
`selector.matchLabels`, so a single `kubectl get all -l 
app.kubernetes.io/name=<release-name>` reaches every chart-created object.
- - The `flink-operator-config` ConfigMap is created only when 
`defaultConfiguration.create` is set to `true`, and it carries six data keys 
(`config.yaml`, `flink-conf.yaml`, `log4j-operator.properties`, 
`log4j-console.properties`, `logback-operator.xml`, `logback-console.xml`) 
populated with two different strategies:
-   - Append: chart's `conf/flink-conf.yaml`, `conf/log4j-operator.properties`, 
and `conf/log4j-console.properties` baselines (when 
`defaultConfiguration.append=true`), followed by user-supplied 
`defaultConfiguration."config.yaml"` / `"flink-conf.yaml"` / 
`"log4j-operator.properties"` / `"log4j-console.properties"` overrides 
concatenated on top.
+ - The `flink-operator-config` ConfigMap is created only when 
`defaultConfiguration.create` is set to `true`, and it carries five data keys 
(`config.yaml`, `log4j-operator.properties`, `log4j-console.properties`, 
`logback-operator.xml`, `logback-console.xml`) populated with two different 
strategies:
+   - Append: chart's `conf/config.yaml`, `conf/log4j-operator.properties`, and 
`conf/log4j-console.properties` baselines (when 
`defaultConfiguration.append=true`), followed by user-supplied 
`defaultConfiguration."config.yaml"` / `"log4j-operator.properties"` / 
`"log4j-console.properties"` overrides concatenated on top. The single 
`config.yaml` entry resolves `defaultConfiguration."config.yaml"` when set, 
otherwise `defaultConfiguration."flink-conf.yaml"`.
    - Replace: user-supplied `defaultConfiguration."logback-operator.xml"` / 
`"logback-console.xml"` if set, otherwise the chart's `conf/logback-*.xml` 
baseline when `defaultConfiguration.append=true`. The two sources are mutually 
exclusive, not concatenated.
-   - For the two top-level YAML keys (`config.yaml`, `flink-conf.yaml`), 
`kubernetes.operator.watched.namespaces` and 
`kubernetes.operator.health.probe.*` are auto-injected when the matching 
`values.yaml` fields are set.
+   - In the `config.yaml` entry, `kubernetes.operator.watched.namespaces` and 
`kubernetes.operator.health.probe.*` are auto-injected when the matching 
`values.yaml` fields are set.
  - The operator `Deployment` is a standard Pod-spec passthrough configured via 
`operatorPod.*` and related keys in `values.yaml`:
    - container `name`, `image`, `command`, `ports` (metrics, health-probe), 
`volumeMounts` (config, artifacts, TLS cert), `env`, `envFrom`, 
`livenessProbe`, `startupProbe`, `lifecycle.postStart`, and `securityContext`.
    - pod-level scheduling fields `nodeSelector`, `affinity`, `tolerations`, 
`topologySpreadConstraints`, `priorityClassName`, `serviceAccountName`, 
`imagePullSecrets`, and optional `initContainers` / `sidecarContainers`.
diff --git a/docs/content/docs/deployment/compatibility.md 
b/docs/content/docs/deployment/compatibility.md
index fe627034..fce7d41d 100644
--- a/docs/content/docs/deployment/compatibility.md
+++ b/docs/content/docs/deployment/compatibility.md
@@ -97,7 +97,7 @@ The operator JVM links against a specific Flink release for 
its own runtime need
 This bundled runtime is used by the operator process for purposes such as:
 
 - Pluggable filesystem access (`org.apache.flink.core.fs.FileSystem`), used to 
fetch `FlinkSessionJob` artifacts from non-HTTP schemes such as `s3://`, 
`gs://`, `hdfs://`.
-- Configuration parsing (`org.apache.flink.configuration.GlobalConfiguration`) 
that reads the operator's own `flink-conf.yaml`.
+- Configuration parsing (`org.apache.flink.configuration.GlobalConfiguration`) 
that reads the operator's own `config.yaml`.
 - Plugin discovery (`org.apache.flink.core.plugin.PluginManager`) that loads 
custom validators, mutators, listeners, and filesystem factories.
 
 ## Kubernetes
diff --git a/docs/content/docs/deployment/configuration.md 
b/docs/content/docs/deployment/configuration.md
index 6d08bc9b..3c66a0c8 100644
--- a/docs/content/docs/deployment/configuration.md
+++ b/docs/content/docs/deployment/configuration.md
@@ -51,10 +51,28 @@ defaultConfiguration:
 
 ### YAML Configuration File Format
 
-Operator configuration is delivered through the 
`defaultConfiguration.flink-conf.yaml` block in the Helm `values.yaml`. The 
operator's runtime loads that file with Flink's legacy configuration parser, 
which accepts only flat key-value pairs written with dot notation and does not 
support nested YAML maps.
+Operator configuration can be delivered in either of Flink's two configuration 
formats, by defining the matching key under `defaultConfiguration` in the Helm 
`values.yaml`:
+
+- `flink-conf.yaml` is the legacy format, which accepts only flat key-value 
pairs written with dot notation and does not support nested YAML maps. This is 
the format the chart ships by default.
+- `config.yaml` is the YAML 1.2 format defined from Flink 1.19 onward and the 
only format Flink 2.0 accepts. It supports nested keys (see the [Flink 
Configuration 
File](https://nightlies.apache.org/flink/flink-docs-master/docs/deployment/config/#flink-configuration-file)
 documentation):
+
+```yaml
+defaultConfiguration:
+  create: true
+  append: true
+  config.yaml: |+
+    kubernetes.operator:
+      metrics.reporter.slf4j:
+        factory.class: org.apache.flink.metrics.slf4j.Slf4jReporterFactory
+        interval: 5 MINUTE
+      reconcile.interval: 15 s
+      observer.progress-check.interval: 5 s
+```
+
+When both keys are set, `config.yaml` takes precedence. Either way the 
resolved configuration is mounted as `config.yaml`, the file name Flink 2.0 
requires.
 
 {{< hint info >}}
-Flink 2.0 onward also defines a `config.yaml` format with YAML 1.2 syntax that 
supports nested keys (see the [Flink Configuration 
File](https://nightlies.apache.org/flink/flink-docs-release-2.2/docs/deployment/config/#flink-configuration-file)
 documentation). The Helm chart's `values.yaml` shows a `config.yaml` example 
block, but with the current chart it is not effectively loadable: the ConfigMap 
template unconditionally renders both `flink-conf.yaml` and `config.yaml` keys, 
and Flink's [...]
+Prefer the nested form shown above. A flat, dotted-key override of a key that 
the chart's default `conf/config.yaml` already ships would be a duplicate key 
under Flink's strict YAML parser and fail at operator startup.
 {{< /hint >}}
 
 ### Flink Version and Namespace Specific Defaults
@@ -101,7 +119,7 @@ Whether dynamic configuration updates are enabled can be 
verified in the `deploy
 o.a.f.k.o.c.FlinkConfigManager [INFO ] Enabled dynamic config updates, 
checking config changes every PT5M
 ```
 
-To change config values dynamically, the ConfigMap can be edited directly with 
`kubectl patch` or `kubectl edit`. For example, the reconcile interval is 
changed by overriding `kubernetes.operator.reconcile.interval`.
+To change config values dynamically, the ConfigMap can be edited directly with 
`kubectl patch` or `kubectl edit`. Edits belong to the `config.yaml` key, which 
is the file the operator mounts. For example, the reconcile interval is changed 
by overriding `kubernetes.operator.reconcile.interval`.
 
 The update, here to 30 seconds, is confirmed in the operator log:
 
diff --git a/docs/content/docs/deployment/helm/installation.md 
b/docs/content/docs/deployment/helm/installation.md
index 0ed010b3..46c6d9ff 100644
--- a/docs/content/docs/deployment/helm/installation.md
+++ b/docs/content/docs/deployment/helm/installation.md
@@ -75,9 +75,9 @@ The configurable parameters of the Helm chart and their 
default values are detai
 | Parameters                                     | Description                 
                                                                                
                                                   | Default Value              
                                                                                
                                                                                
                                                                                
              [...]
 
|------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
 | defaultConfiguration.append                    | Whether to append 
configuration files with configs.                                               
                                                             | true             
                                                                                
                                                                                
                                                                                
                        [...]
-| defaultConfiguration.config.yaml               | The newer configuration 
file format for Flink that will be enforced in Flink 2.0. Note this was 
introduced in Flink 1.19.                                      | 
kubernetes.operator.metrics.reporter.slf4j.factory.class: 
org.apache.flink.metrics.slf4j.Slf4jReporterFactory<br/>kubernetes.operator.metrics.reporter.slf4j.interval:
 5 MINUTE<br/>kubernetes.operator.reconcile.interval: 15 
s<br/>kubernetes.operator.observer.progress-check.interva [...]
+| defaultConfiguration.config.yaml               | Modern YAML 1.2 config 
format (introduced in Flink 1.19, required by Flink 2.0). Takes precedence over 
flink-conf.yaml when set; the resolved config is always mounted as config.yaml. 
                                        | 
kubernetes.operator.metrics.reporter.slf4j.factory.class: 
org.apache.flink.metrics.slf4j.Slf4jReporterFactory<br/>kubernetes.operator.metrics.reporter.slf4j.interval:
 5 MINUTE<br/>kubernetes.operator.reconcile.interv [...]
 | defaultConfiguration.create                    | Whether to enable default 
configuration to create for flink-kubernetes-operator.                          
                                                     | true                     
                                                                                
                                                                                
                                                                                
                [...]
-| defaultConfiguration.flink-conf.yaml           | The default configuration 
of flink-conf.yaml.                                                             
                                                     | 
kubernetes.operator.metrics.reporter.slf4j.factory.class: 
org.apache.flink.metrics.slf4j.Slf4jReporterFactory<br/>kubernetes.operator.metrics.reporter.slf4j.interval:
 5 MINUTE<br/>kubernetes.operator.reconcile.interval: 15 
s<br/>kubernetes.operator.observer.progress-check.interva [...]
+| defaultConfiguration.flink-conf.yaml           | Legacy flat config format. 
Used when config.yaml is not set; the resolved config is always mounted as 
config.yaml.                                                                    
                                              | 
kubernetes.operator.metrics.reporter.slf4j.factory.class: 
org.apache.flink.metrics.slf4j.Slf4jReporterFactory<br/>kubernetes.operator.metrics.reporter.slf4j.interval:
 5 MINUTE<br/>kubernetes.operator.reconcile.i [...]
 | defaultConfiguration.log4j-console.properties  | The default configuration 
of log4j-console.properties.                                                    
                                                     |                          
                                                                                
                                                                                
                                                                                
                [...]
 | defaultConfiguration.log4j-operator.properties | The default configuration 
of log4j-operator.properties.                                                   
                                                     |                          
                                                                                
                                                                                
                                                                                
                [...]
 | defaultConfiguration.logback-operator.xml      | The default configuration 
of logback-operator.xml. Used when `logging.framework` is set to `logback`.     
                                                     |                          
                                                                                
                                                                                
                                                                                
                [...]
diff --git a/docs/content/docs/internals/startup.md 
b/docs/content/docs/internals/startup.md
index f37d4058..2f5f1b1b 100644
--- a/docs/content/docs/internals/startup.md
+++ b/docs/content/docs/internals/startup.md
@@ -91,7 +91,7 @@ helm install -f custom-values.yaml  flink-kubernetes-operator 
 helm/flink-kubern
                                   │
                                   │  flink-kubernetes-operator Deployment is 
created with:
                                   │      ENV: LOG_CONFIG=..., JVM_ARGS=..., 
OPERATOR_NAMESPACE, ...
-                                  │      Volume items: config.yaml (default) 
or flink-conf.yaml,
+                                  │      Volume items: config.yaml,
                                   │                    
log4j-operator.properties or logback-operator.xml,
                                   │                    
log4j-console.properties or logback-console.xml
                                   ▼
@@ -118,10 +118,10 @@ The following notes elaborate on the chart's CRD 
handling, helper-driven labels,
 
  - `crds/` uses Helm's special CRD handling: applied on `helm install` only, 
untouched by `helm upgrade` and `helm uninstall`. Based on this, Helm CRD 
upgrades and deletions are out-of-band today, and they need to be manually 
executed via `kubectl` commands (`kubectl apply -f crds/`, `kubectl delete crd 
...`). See [Upgrading the Operator → Upgrading the CRDs]({{< ref 
"docs/operations/upgrade#2-upgrading-the-crds" >}}) for the supported procedure.
  - `_helpers.tpl` defines a common label set applied to every chart-rendered 
resource: `app.kubernetes.io/name`, `app.kubernetes.io/version`, 
`app.kubernetes.io/managed-by`, and `helm.sh/chart`. The same 
`app.kubernetes.io/name` label is the operator Deployment's 
`selector.matchLabels`, so a single `kubectl get all -l 
app.kubernetes.io/name=<release-name>` reaches every chart-created object.
- - The `flink-operator-config` ConfigMap is created only when 
`defaultConfiguration.create` is set to `true`, and it carries six data keys 
(`config.yaml`, `flink-conf.yaml`, `log4j-operator.properties`, 
`log4j-console.properties`, `logback-operator.xml`, `logback-console.xml`) 
populated with two different strategies:
-   - Append: chart's `conf/flink-conf.yaml`, `conf/log4j-operator.properties`, 
and `conf/log4j-console.properties` baselines (when 
`defaultConfiguration.append=true`), followed by user-supplied 
`defaultConfiguration."config.yaml"` / `"flink-conf.yaml"` / 
`"log4j-operator.properties"` / `"log4j-console.properties"` overrides 
concatenated on top.
+ - The `flink-operator-config` ConfigMap is created only when 
`defaultConfiguration.create` is set to `true`, and it carries five data keys 
(`config.yaml`, `log4j-operator.properties`, `log4j-console.properties`, 
`logback-operator.xml`, `logback-console.xml`) populated with two different 
strategies:
+   - Append: chart's `conf/config.yaml`, `conf/log4j-operator.properties`, and 
`conf/log4j-console.properties` baselines (when 
`defaultConfiguration.append=true`), followed by user-supplied 
`defaultConfiguration."config.yaml"` / `"log4j-operator.properties"` / 
`"log4j-console.properties"` overrides concatenated on top. The single 
`config.yaml` entry resolves `defaultConfiguration."config.yaml"` when set, 
otherwise `defaultConfiguration."flink-conf.yaml"`.
    - Replace: user-supplied `defaultConfiguration."logback-operator.xml"` / 
`"logback-console.xml"` if set, otherwise the chart's `conf/logback-*.xml` 
baseline when `defaultConfiguration.append=true`. The two sources are mutually 
exclusive, not concatenated.
-   - For the two top-level YAML keys (`config.yaml`, `flink-conf.yaml`), 
`kubernetes.operator.watched.namespaces` and 
`kubernetes.operator.health.probe.*` are auto-injected when the matching 
`values.yaml` fields are set.
+   - In the `config.yaml` entry, `kubernetes.operator.watched.namespaces` and 
`kubernetes.operator.health.probe.*` are auto-injected when the matching 
`values.yaml` fields are set.
  - The operator `Deployment` is a standard Pod-spec passthrough configured via 
`operatorPod.*` and related keys in `values.yaml`:
    - container `name`, `image`, `command`, `ports` (metrics, health-probe), 
`volumeMounts` (config, artifacts, TLS cert), `env`, `envFrom`, 
`livenessProbe`, `startupProbe`, `lifecycle.postStart`, and `securityContext`.
    - pod-level scheduling fields `nodeSelector`, `affinity`, `tolerations`, 
`topologySpreadConstraints`, `priorityClassName`, `serviceAccountName`, 
`imagePullSecrets`, and optional `initContainers` / `sidecarContainers`.
diff --git a/e2e-tests/test_dynamic_flink_conf.sh 
b/e2e-tests/test_dynamic_flink_conf.sh
index 3569d2c3..1552804f 100755
--- a/e2e-tests/test_dynamic_flink_conf.sh
+++ b/e2e-tests/test_dynamic_flink_conf.sh
@@ -17,7 +17,9 @@
 # limitations under the License.
 
################################################################################
 
-# This script tests the operator dynamic config on watched namespace:
+# This script tests the operator dynamic config on watched namespace, with the 
chart configured
+# through the legacy defaultConfiguration.flink-conf.yaml key, which the chart 
resolves into the
+# config.yaml the operator mounts:
 # 1. Create a new namespace
 # 2. Change the watched namespaces by patching on the flink-config-override
 # 3. Monitor the operator log to find the watched namespace changed info
@@ -34,7 +36,7 @@ echo "Current operator pod is ${operator_pod}"
 create_namespace dynamic
 
 kubectl config set-context --current --namespace="${operator_namespace}"
-patch_flink_config '{"data": {"flink-conf.yaml": 
"kubernetes.operator.watched.namespaces: default,flink,dynamic"}}'
+patch_flink_config '{"data": {"config.yaml": 
"kubernetes.operator.watched.namespaces: default,flink,dynamic"}}'
 wait_for_operator_logs "${operator_pod}" "Setting default configuration to 
{kubernetes.operator.watched.namespaces=default,flink,dynamic}" ${TIMEOUT} || 
exit 1
 
 echo "Successfully run the dynamic property test"
diff --git 
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/config/FlinkConfigManagerTest.java
 
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/config/FlinkConfigManagerTest.java
index 39414af4..715c072b 100644
--- 
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/config/FlinkConfigManagerTest.java
+++ 
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/config/FlinkConfigManagerTest.java
@@ -18,6 +18,7 @@
 package org.apache.flink.kubernetes.operator.config;
 
 import org.apache.flink.autoscaler.config.AutoScalerOptions;
+import org.apache.flink.configuration.ConfigConstants;
 import org.apache.flink.configuration.ConfigOption;
 import org.apache.flink.configuration.ConfigOptions;
 import org.apache.flink.configuration.Configuration;
@@ -210,6 +211,44 @@ public class FlinkConfigManagerTest {
         assertEquals(Map.of("foo", "1", "bar", "2"), conf.toMap());
     }
 
+    /**
+     * The operator configuration uses the config.yaml format while an 
external override directory
+     * may still be mounted in the legacy flink-conf.yaml format.
+     */
+    @Test
+    public void testLegacyFormatConfigOverrides(
+            @TempDir Path confDir, @TempDir Path confOverrideDir) throws 
IOException {
+        Map<String, String> originalEnv = System.getenv();
+        try {
+            Files.write(
+                    confDir.resolve(GlobalConfiguration.FLINK_CONF_FILENAME),
+                    List.of("kubernetes.operator.reconcile.interval: 15 s", 
"foo: 1"));
+            Files.write(
+                    
confOverrideDir.resolve(GlobalConfiguration.LEGACY_FLINK_CONF_FILENAME),
+                    List.of("kubernetes.operator.reconcile.interval: 30 s", 
"bar: 2"));
+
+            Map<String, String> systemEnv = new HashMap<>(originalEnv);
+            systemEnv.put(ConfigConstants.ENV_FLINK_CONF_DIR, 
confDir.toString());
+            TestUtils.setEnv(systemEnv);
+
+            var conf =
+                    FlinkConfigManager.loadGlobalConfiguration(
+                            Optional.of(confOverrideDir.toString()));
+
+            // Overrides in the legacy format are loaded and take precedence
+            assertEquals(
+                    Duration.ofSeconds(30),
+                    
conf.get(KubernetesOperatorConfigOptions.OPERATOR_RECONCILE_INTERVAL));
+            assertEquals("2", conf.toMap().get("bar"));
+            // Settings only present in the operator configuration are kept
+            assertEquals("1", conf.toMap().get("foo"));
+            // The operator configuration is loaded last, so its format 
decides how values parse
+            assertTrue(GlobalConfiguration.isStandardYaml());
+        } finally {
+            TestUtils.setEnv(originalEnv);
+        }
+    }
+
     @Test
     public void testWatchNamespaceOverride() {
         Map<String, String> originalEnv = System.getenv();
diff --git a/helm/flink-kubernetes-operator/conf/flink-conf.yaml 
b/helm/flink-kubernetes-operator/conf/config.yaml
similarity index 98%
rename from helm/flink-kubernetes-operator/conf/flink-conf.yaml
rename to helm/flink-kubernetes-operator/conf/config.yaml
index 0f6cd746..a04a8237 100644
--- a/helm/flink-kubernetes-operator/conf/flink-conf.yaml
+++ b/helm/flink-kubernetes-operator/conf/config.yaml
@@ -16,10 +16,6 @@
 # limitations under the License.
 
################################################################################
 
-# Flink job/cluster related configs
-taskmanager.numberOfTaskSlots: 1
-parallelism.default: 1
-
 # These parameters are required for Java 17 support.
 # Flink 1.18 uses env.java.opts.all, if a user supplies their own version of 
these opts in their FlinkDeployment the options below will be overridden.
 # env.java.default-opts.all is used for 1.19 onwards so users can supply their 
own opts.all in their Job deployments and have these appended.
diff --git a/helm/flink-kubernetes-operator/templates/controller/configmap.yaml 
b/helm/flink-kubernetes-operator/templates/controller/configmap.yaml
index 5ab29cd8..18f61e9b 100644
--- a/helm/flink-kubernetes-operator/templates/controller/configmap.yaml
+++ b/helm/flink-kubernetes-operator/templates/controller/configmap.yaml
@@ -25,24 +25,14 @@ metadata:
 data:
   config.yaml: |+
 {{- if .Values.defaultConfiguration.append }}
-  {{- $.Files.Get "conf/flink-conf.yaml"  | nindent 4 -}}
+  {{- $.Files.Get "conf/config.yaml"  | nindent 4 -}}
 {{- end }}
-{{- if hasKey (.Values.defaultConfiguration) "config.yaml" }}
-  {{- index (.Values.defaultConfiguration) "config.yaml" | nindent 4 -}}
-{{- end }}
-{{- if .Values.watchNamespaces }}
-    kubernetes.operator.watched.namespaces: {{ join "," 
.Values.watchNamespaces  }}
-{{- end }}
-{{- if index .Values "operatorHealth" }}
-    kubernetes.operator.health.probe.enabled: true
-    kubernetes.operator.health.probe.port: {{ .Values.operatorHealth.port }}
-{{- end }}
-  flink-conf.yaml: |+
-{{- if .Values.defaultConfiguration.append }}
-  {{- $.Files.Get "conf/flink-conf.yaml"  | nindent 4 -}}
-{{- end }}
-{{- if hasKey (.Values.defaultConfiguration) "flink-conf.yaml" }}
-  {{- index (.Values.defaultConfiguration) "flink-conf.yaml" | nindent 4 -}}
+{{- with (index .Values.defaultConfiguration "config.yaml") }}
+  {{- . | nindent 4 -}}
+{{- else }}
+  {{- with (index .Values.defaultConfiguration "flink-conf.yaml") }}
+  {{- . | nindent 4 -}}
+  {{- end }}
 {{- end }}
 {{- if .Values.watchNamespaces }}
     kubernetes.operator.watched.namespaces: {{ join "," 
.Values.watchNamespaces  }}
diff --git 
a/helm/flink-kubernetes-operator/templates/controller/deployment.yaml 
b/helm/flink-kubernetes-operator/templates/controller/deployment.yaml
index a31175c9..036e2716 100644
--- a/helm/flink-kubernetes-operator/templates/controller/deployment.yaml
+++ b/helm/flink-kubernetes-operator/templates/controller/deployment.yaml
@@ -244,13 +244,8 @@ spec:
           configMap:
             name: flink-operator-config
             items:
-            {{- if hasKey .Values.defaultConfiguration "flink-conf.yaml" }}
-              - key: flink-conf.yaml
-                path: flink-conf.yaml
-            {{- else }}
               - key: config.yaml
                 path: config.yaml
-            {{- end }}
             {{- if eq .Values.logging.framework "logback" }}
               - key: logback-operator.xml
                 path: logback-operator.xml
diff --git 
a/helm/flink-kubernetes-operator/tests/controller/configmap_test.yaml 
b/helm/flink-kubernetes-operator/tests/controller/configmap_test.yaml
index 90476695..74ec6111 100644
--- a/helm/flink-kubernetes-operator/tests/controller/configmap_test.yaml
+++ b/helm/flink-kubernetes-operator/tests/controller/configmap_test.yaml
@@ -68,3 +68,64 @@ tests:
     asserts:
       - isNotNull:
           path: data["log4j-console.properties"]
+
+  - it: Emits a single config.yaml key with today's effective defaults and no 
redundant seed keys
+    asserts:
+      - isNotNull:
+          path: data["config.yaml"]
+      - notExists:
+          path: data["flink-conf.yaml"]
+      - matchRegex:
+          path: data["config.yaml"]
+          pattern: 
"(?m)^\\s*kubernetes.operator.metrics.reporter.slf4j.factory.class:"
+      - matchRegex:
+          path: data["config.yaml"]
+          pattern: "(?m)^\\s*kubernetes.operator.reconcile.interval: 15 s"
+      - matchRegex:
+          path: data["config.yaml"]
+          pattern: "(?m)^\\s*kubernetes.operator.health.probe.enabled: true"
+      - notMatchRegex:
+          path: data["config.yaml"]
+          pattern: "(?m)^\\s*taskmanager.numberOfTaskSlots:"
+      - notMatchRegex:
+          path: data["config.yaml"]
+          pattern: "(?m)^\\s*parallelism.default:"
+
+  - it: A user flink-conf.yaml override flows into config.yaml when 
config.yaml is unset
+    set:
+      defaultConfiguration:
+        flink-conf.yaml: |+
+          kubernetes.operator.reconcile.interval: 99 s
+    asserts:
+      - matchRegex:
+          path: data["config.yaml"]
+          pattern: "reconcile.interval: 99 s"
+
+  - it: When both are set, config.yaml wins and flink-conf.yaml is ignored
+    set:
+      defaultConfiguration:
+        config.yaml: |+
+          kubernetes.operator:
+            reconcile.interval: 30 s
+        flink-conf.yaml: |+
+          kubernetes.operator.reconcile.interval: 99 s
+    asserts:
+      - matchRegex:
+          path: data["config.yaml"]
+          pattern: "reconcile.interval: 30 s"
+      - notMatchRegex:
+          path: data["config.yaml"]
+          pattern: "reconcile.interval: 99 s"
+
+  - it: A flat config.yaml override of a former seed key is not duplicated 
(relies on dropping it from the seed)
+    set:
+      defaultConfiguration:
+        config.yaml: |+
+          taskmanager.numberOfTaskSlots: 2
+    asserts:
+      - matchRegex:
+          path: data["config.yaml"]
+          pattern: "taskmanager.numberOfTaskSlots: 2"
+      - notMatchRegex:
+          path: data["config.yaml"]
+          pattern: "taskmanager.numberOfTaskSlots: 1"
diff --git 
a/helm/flink-kubernetes-operator/tests/controller/deployment_test.yaml 
b/helm/flink-kubernetes-operator/tests/controller/deployment_test.yaml
index e6333d76..08dda10d 100644
--- a/helm/flink-kubernetes-operator/tests/controller/deployment_test.yaml
+++ b/helm/flink-kubernetes-operator/tests/controller/deployment_test.yaml
@@ -383,3 +383,16 @@ tests:
         key: log4j-operator.properties
         path: log4j-operator.properties
 
+- it: Should mount the operator config as config.yaml by default
+  asserts:
+  - contains:
+      path: spec.template.spec.volumes[0].configMap.items
+      content:
+        key: config.yaml
+        path: config.yaml
+  - notContains:
+      path: spec.template.spec.volumes[0].configMap.items
+      content:
+        key: flink-conf.yaml
+        path: flink-conf.yaml
+
diff --git a/helm/flink-kubernetes-operator/values.yaml 
b/helm/flink-kubernetes-operator/values.yaml
index 8eaa936e..aecf1d01 100644
--- a/helm/flink-kubernetes-operator/values.yaml
+++ b/helm/flink-kubernetes-operator/values.yaml
@@ -174,7 +174,16 @@ defaultConfiguration:
   # This option has not effect, if create is equal to false.
   append: true
 
-#  Uncomment to use the new config.yaml format, but also comment out the 
flink-config.yaml key.
+# Operator configuration overrides go under ONE of the two keys below. If both 
are set,
+# config.yaml wins; either way the operator mounts the result as config.yaml.
+#
+#   config.yaml      - modern YAML 1.2 format (Flink 1.19+, required by Flink 
2.0). Recommended.
+#   flink-conf.yaml  - legacy flat "key: value" format (shipped as the default 
below).
+#
+# Prefer the nested config.yaml form: a flat, dotted-key override of a key the 
chart already
+# ships (e.g. the Java 17 opts in conf/config.yaml) would be a duplicate key 
under Flink's
+# strict YAML parser and fail at operator startup. Example, equivalent to the 
default below:
+#
 #  config.yaml: |+
 #    kubernetes.operator:
 #      metrics.reporter.slf4j:

Reply via email to