Dennis-Mircea opened a new pull request, #1249: URL: https://github.com/apache/flink-kubernetes-operator/pull/1249
## What is the purpose of the change This PR adds a fix that marks the JobManager as `READY` only after its REST API responds. To achieve this, the code was restructured to ensure proper layering and separation of concerns. The implementation now has 3 distinct layers of observation: the JM Deployment (including its pods), the Flink Cluster process, and the Job. With this layering in place, the JobManager is now marked as `READY` by the Flink Cluster observation, while the JM Deployment observation can only advance as far as `DEPLOYED_NOT_READY`. For comparison, this is what was in place previously: <img width="389" height="301" alt="observeInternal-before" src="https://github.com/user-attachments/assets/32374258-09cb-40db-94ba-0420c091dfc6" /> The Flink cluster was the white box because it had no observation step of its own. The Kubernetes step decided everything, as once the port accepted a connection, it set `DEPLOYED_NOT_READY`, and on the next observe (10s later by default) it set `READY` without asking Flink anything. The job observer then called the REST API as if the JobManager were up, and when that call timed out, the status was dropped back to `DEPLOYED_NOT_READY`. The cluster info was fetched only after READY was already set, so a failure there changed nothing. This scenario was presented already step by step within the JIRA. Now this is in place: <img width="389" height="301" alt="observeInternal-after" src="https://github.com/user-attachments/assets/c8a61cb5-3a17-458b-9cad-561fca84cc23" /> Concretely (which is now translated 1-1 within the code structure): - The Kubernetes step (blue) looks at the Deployment and the JobManager pod. It can say the JobManager is missing, failed, starting, or started with its port open. It can never say `READY`. - The cluster step (orange) talks to the JobManager process through its REST API. If the call succeeds, the JobManager is `READY` and the version, revision and TaskManager count are stored. If the call fails, the Kubernetes step is asked again, to find out whether the pod is still there. - The job step (red) asks the JobMaster about its job: status, checkpoints, savepoints, state size, health. It runs only after the cluster step succeeded, so it never talks to a JobManager that is not answering. NOTE: The TaskManager pods are never observed on their own. In native mode, Flink's ResourceManager creates and replaces them, in standalone mode, the TaskManager Deployment does, and in both cases the operator only learns about them through the JobManager, as the registered TaskManager count returned by `/taskmanagers`. Two more things fall out of the split: - A session cluster no longer fetches its cluster info twice per loop. Before, `SessionObserver` fetched it once to see whether the REST API was reachable and threw the result away, then `observeClusterInfo` fetched it again to store it. Now the single fetch is the readiness check, and its result is what gets stored. - For application clusters, what belongs to the cluster (version, revision, TaskManager count) and what belongs to the job (status, snapshots, state size, health) are now observed in separate steps. The job status observer no longer needs to know about the Kubernetes Deployment, so its `onTimeout` hook is gone. The same split applied to `getClusterInfo`, which used to fetch the job's checkpoint statistics, without a timeout, as part of the cluster call. ## Brief change log - `AbstractFlinkDeploymentObserver`: `observeInternal` runs the Kubernetes step or the REST step, then the job step when `READY`. `observeJmDeployment` no longer sets `READY`. New `observeFlinkCluster` owns `READY`: REST call succeeds, `READY` plus cluster info; REST call fails, WARN if we were `READY` (job RUNNING moves to RECONCILING), INFO otherwise, then `observeJmDeployment`. TaskManager count, CPU and memory are fetched best-effort after a successful call. - `observeJob` replaces the abstract `observeFlinkCluster`: `ApplicationObserver` observes job status, snapshots, state size and health there, `SessionObserver` marks the spec stable. - `JobStatusObserver`: `onTimeout` hook removed, with the `ApplicationJobObserver` subclass. The RUNNING to RECONCILING move on a lost REST API now happens in `observeFlinkCluster`; `ifRunningMoveToReconciling` stays for a job status call that fails after a successful probe. - `FlinkService`: `getClusterInfo(conf, jobId)` split into `getClusterInfo(conf)`, `getTaskManagerReplicas(conf)` and `getStateSize(conf, jobId)`, the last one with the client timeout it was missing. `ClusterInfo` removed. - `kubernetes.operator.observer.rest-ready.delay` description reworded. ## Verifying this change The stability of this change can be verified by all existing tests that are still passing + new ones that cover the missing cases. Moreover, the change was verified against a local minikube setup and below, the correct log sequencing can be observed: ```log 2026-11-06 16:21:37,921 WARN ecutor-flinkdeploymentcontroller-157 o.a.f.k.o.o.d.ApplicationObserver JobManager REST API stopped answering java.util.concurrent.TimeoutException at java.base/java.util.concurrent.CompletableFuture.timedGet(Unknown Source) at java.base/java.util.concurrent.CompletableFuture.get(Unknown Source) at org.apache.flink.kubernetes.operator.service.AbstractFlinkService.getClusterInfo(AbstractFlinkService.java:814) at org.apache.flink.kubernetes.operator.observer.deployment.AbstractFlinkDeploymentObserver.observeFlinkCluster(AbstractFlinkDeploymentObserver.java:105) at org.apache.flink.kubernetes.operator.observer.deployment.AbstractFlinkDeploymentObserver.observeInternal(AbstractFlinkDeploymentObserver.java:91) at org.apache.flink.kubernetes.operator.observer.AbstractFlinkResourceObserver.observe(AbstractFlinkResourceObserver.java:49) at org.apache.flink.kubernetes.operator.controller.FlinkDeploymentController.reconcile(FlinkDeploymentController.java:145) at org.apache.flink.kubernetes.operator.controller.FlinkDeploymentController.reconcile(FlinkDeploymentController.java:59) at io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:191) at io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:147) at org.apache.flink.kubernetes.operator.metrics.OperatorJosdkMetrics.timeControllerExecution(OperatorJosdkMetrics.java:82) at io.javaoperatorsdk.operator.processing.Controller.reconcile(Controller.java:146) at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.reconcileExecution(ReconciliationDispatcher.java:164) at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleReconcile(ReconciliationDispatcher.java:145) at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleDispatch(ReconciliationDispatcher.java:111) at io.javaoperatorsdk.operator.processing.event.ReconciliationDispatcher.handleExecution(ReconciliationDispatcher.java:76) at io.javaoperatorsdk.operator.processing.event.EventProcessor$ReconcilerExecutor.run(EventProcessor.java:578) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.base/java.lang.Thread.run(Unknown Source) 2026-11-06 16:21:37,922 INFO ecutor-flinkdeploymentcontroller-157 o.a.f.k.o.o.d.ApplicationObserver Observing JobManager deployment. Previous status: READY 2026-11-06 16:21:37,926 INFO ecutor-flinkdeploymentcontroller-157 o.a.f.k.o.o.d.ApplicationObserver JobManager deployment port is ready, waiting for the Flink REST API... 2026-11-06 16:21:37,941 INFO ecutor-flinkdeploymentcontroller-157 .r.d.AbstractFlinkResourceReconciler Resource fully reconciled, nothing to do... 2026-11-06 16:21:57,965 INFO ecutor-flinkdeploymentcontroller-168 o.a.f.k.o.o.d.ApplicationObserver JobManager REST API is not ready yet, no answer within 10 s 2026-11-06 16:21:57,965 INFO ecutor-flinkdeploymentcontroller-168 o.a.f.k.o.o.d.ApplicationObserver Observing JobManager deployment. Previous status: DEPLOYED_NOT_READY 2026-11-06 16:21:57,970 INFO ecutor-flinkdeploymentcontroller-168 o.a.f.k.o.o.d.ApplicationObserver JobManager deployment port is ready, waiting for the Flink REST API... 2026-11-06 16:21:57,972 INFO ecutor-flinkdeploymentcontroller-168 .r.d.AbstractFlinkResourceReconciler Resource fully reconciled, nothing to do... ``` ## Does this pull request potentially affect one of the following parts: - Dependencies (does it add or upgrade a dependency): no - The public API, i.e., is any changes to the `CustomResourceDescriptors`: no - Core observer or reconciler logic that is regularly executed: yes ## Documentation - Does this pull request introduce a new feature? no - If yes, how is the feature documented? not applicable --- ##### Was generative AI tooling used to co-author this PR? <!-- If generative AI tooling has been used in the process of authoring this PR, please change the checkbox below to `[X]` followed by the name of the tool, and uncomment the "Generated-by" line. See the ASF Generative Tooling Guidance for details: https://www.apache.org/legal/generative-tooling.html You are responsible for the quality and correctness of every change in this PR regardless of the tooling used. Low-effort AI-generated PRs will be closed. See AGENTS.md for the full guidance. --> - [ ] Yes (please specify the tool below) <!-- Generated-by: [Tool Name and Version] --> -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
