[
https://issues.apache.org/jira/browse/FLINK-41375?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
ASF GitHub Bot updated FLINK-41375:
-----------------------------------
Labels: pull-request-available (was: )
> JobManager crash loops are detected only in the back-off phase and reported
> without the termination reason
> ----------------------------------------------------------------------------------------------------------
>
> Key: FLINK-41375
> URL: https://issues.apache.org/jira/browse/FLINK-41375
> Project: Flink
> Issue Type: Bug
> Components: Kubernetes Operator
> Reporter: Dennis-Mircea Ciupitu
> Priority: Major
> Labels: pull-request-available
>
> h1. Problem
> When the JobManager container keeps dying (for example, OOMKilled reason),
> what the operator reports depends on the moment it happens to look at the
> pod, and it never says why the container died.
> The observer only recognises a crash loop while the kubelet is backing off
> ({{{}state.waiting.reason=CrashLoopBackOff{}}}). Between 2 kills, while the
> container is {{running}} again, it reports {{DEPLOYING}} as if everything
> were fine, even though the pod already says
> {{{}lastState.terminated.reason=OOMKilled{}}}, {{exitCode=137}} and counts
> the restarts.
> The actual problem is that the {{OOMKilled}} entry in
> {{CONTAINER_ERROR_REASONS}} never matches on the current observation logic.
> Kubernetes puts that reason under {{{}terminated{}}}, not under
> {{{}waiting{}}}. The longer the JobManager runs before each kill, the more
> often the operator says {{{}DEPLOYING{}}}.
> When it does detect the loop, the error and the event are a copy of the
> kubelet's back-off sentence with the pod name. The reason and the exit code
> are nowhere in the resource. And because that sentence changes with every
> back-off step and every pod, each detection produces a new event instead of
> counting up the existing one.
> On a deployment that was already stable, the {{DEPLOYING}} sample also wipes
> {{{}status.error{}}}, so the resource alternates between an error and no
> error at all.
> h1. Reproduction
> {{examples/basic.yaml}} with the below extra line + "1024m" as JM spec
> resource memory:
> {code:yaml}
> flinkConfiguration:
> env.java.opts.jobmanager: "-Xms1200m -Xmx1200m -XX:+AlwaysPreTouch"
> {code}
> {code:java}
> kubectl get pods
> NAME READY STATUS RESTARTS
> AGE
> basic-example-65774988d7-tzv74 0/1 OOMKilled 0 3s
> kubectl get pods
> NAME READY STATUS
> RESTARTS AGE
> basic-example-65774988d7-tzv74 0/1 CrashLoopBackOff 2 (3s
> ago) 20s
> {code}
> Operator log:
> {code:java}
> 2026-11-07 09:59:52,330 INFO ecutor-flinkdeploymentcontroller-350
> .r.d.AbstractFlinkResourceReconciler Deploying for the first time
> 2026-11-07 09:59:52,335 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.operator.listener.AuditUtils >>> Status[Job] | Info |
> UPGRADING | The resource is being upgraded
> 2026-11-07 09:59:52,336 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.o.r.d.ApplicationReconciler Assigning JobId override to
> 5efdcfec84cb50f1fca3c5aecd224f0b
> 2026-11-07 09:59:52,343 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.operator.listener.AuditUtils >>> Event[Job] | Info | SUBMIT
> | Starting deployment
> 2026-11-07 09:59:52,343 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.o.s.AbstractFlinkService Deploying application cluster
> 2026-11-07 09:59:52,343 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.o.service.NativeFlinkService Deploying application cluster
> 2026-11-07 09:59:52,343 INFO ecutor-flinkdeploymentcontroller-350
> f.c.d.a.c.ApplicationClusterDeployer Submitting application in 'Application
> Mode'.
> 2026-11-07 09:59:52,346 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.r.u.c.m.ProcessMemoryUtils The derived from fraction jvm overhead
> memory (102.400mb (107374184 bytes)) is less than its min value 192.000mb
> (201326592 bytes), min value will be used instead
> 2026-11-07 09:59:52,392 INFO ecutor-flinkdeploymentcontroller-350
> .a.DefaultKubernetesArtifactUploader Local artifact uploading is disabled.
> Set 'kubernetes.artifacts.local-upload-enabled' to enable.
> 2026-11-07 09:59:52,392 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.utils.KubernetesUtils Kubernetes deployment requires a fixed port.
> Configuration blob.server.port will be set to 6124
> 2026-11-07 09:59:52,393 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.utils.KubernetesUtils Kubernetes deployment requires a fixed port.
> Configuration taskmanager.rpc.port will be set to 6122
> 2026-11-07 09:59:52,401 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.configuration.Configuration Config uses fallback configuration key
> 'kubernetes.service-account' instead of key
> 'kubernetes.jobmanager.service-account'
> 2026-11-07 09:59:52,479 WARN ecutor-flinkdeploymentcontroller-350
> o.a.f.k.KubernetesClusterDescriptor Please note that Flink client
> operations(e.g. cancel, list, stop, savepoint, etc.) won't work from outside
> the Kubernetes cluster since 'kubernetes.rest-service.exposed.type' has been
> set to ClusterIP.
> 2026-11-07 09:59:52,480 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.KubernetesClusterDescriptor Create flink application cluster
> basic-example successfully, JobManager Web Interface:
> http://basic-example-rest.default:8081
> 2026-11-07 09:59:52,480 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.o.service.NativeFlinkService Application cluster successfully deployed
> 2026-11-07 09:59:52,486 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.operator.listener.AuditUtils >>> Status[Job] | Info |
> DEPLOYED | The resource is deployed/submitted to Kubernetes, but it’s
> not yet considered to be stable and might be rolled back in the future
> 2026-11-07 09:59:52,486 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.o.o.d.ApplicationObserver Observing JobManager deployment. Previous
> status: DEPLOYING
> 2026-11-07 09:59:52,489 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.o.o.d.ApplicationObserver JobManager is being deployed
> 2026-11-07 09:59:52,491 INFO ecutor-flinkdeploymentcontroller-350
> o.a.f.k.o.a.state.ConfigMapView Creating ConfigMap autoscaler-basic-example
> 2026-11-07 09:59:52,492 INFO ecutor-flinkdeploymentcontroller-350
> .r.d.AbstractFlinkResourceReconciler Resource fully reconciled, nothing to
> do...
> 2026-11-07 10:00:02,495 INFO ecutor-flinkdeploymentcontroller-369
> o.a.f.k.o.o.d.ApplicationObserver Observing JobManager deployment. Previous
> status: DEPLOYING
> 2026-11-07 10:00:02,508 INFO ecutor-flinkdeploymentcontroller-369
> o.a.f.k.operator.listener.AuditUtils >>> Event[Job] | Warning |
> CRASHLOOPBACKOFF | [flink-main-container] back-off 10s restarting failed
> container=flink-main-container
> pod=basic-example-65774988d7-tzv74_default(b57eb99c-a3cf-4fad-8db0-d7b144669a0d)
> {code}
> This is the error the resource keeps reporting. Nothing in it says why the
> container died:
> {code:java}
> kubectl get flinkdep basic-example -o jsonpath='{.status.error}'
> {"type":"org.apache.flink.kubernetes.operator.exception.DeploymentFailedException","message":"[flink-main-container]
> back-off 10s restarting failed container=flink-main-container
> pod=basic-example-65774988d7-q8x7d_default(deccff18-576e-4a16-aeb4-6efaf894eb9a)","stackTrace":"org.apache.flink.kubernetes.operator.exception.DeploymentFailedException:
> [flink-main-container] back-off 10s restarting failed
> container=flink-main-container
> pod=basic-example-65774988d7-q8x7d_default(deccff18-576e-4a16-aeb4-6efaf894eb9a)\n\tat
>
> org.apache.flink.kubernetes.operator.exception.DeploymentFailedException.forContainerStatus(DeploymentFailedException.java:74)\n\tat
>
> org.apache.flink.kubernetes.operator.observer.deployment.AbstractFlinkDeploymentObserver.checkContainerError(AbstractFlinkDeploymentObserver.java:251)\n\tat
> java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(Unknown
> Source)\n\tat
> java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Unknown
> Source)\n\tat
> java.base/java.util.stream.ReferencePipeline$Head.forEach(Unknown
> Source)\n\tat
> org.apache.flink.kubernetes.operator.observer.deployment.AbstractFlinkDeploymentObserver.checkContainerErrors(AbstractFlinkDeploymentObserver.java:238)\n\tat
>
> org.apache.flink.kubernetes.operator.observer.deployment.AbstractFlinkDeploymentObserver.observeJmDeployment(AbstractFlinkDeploymentObserver.java:193)\n\tat
>
> org.apache.flink.kubernetes.operator.observer.deployment.AbstractFlinkDeploymentObserver.observeInternal(AbstractFlinkDeploymentObserver.java:89)\n\tat
>
> org.apache.flink.kubernetes.operator.observer.AbstractFlinkResourceObserver.observe(AbstractFlinkResourceObserver.java:49)\n\tat
>
> org.apache.flink.kubernetes.operator.controller.FlinkDeploymentController.reconcile(FlinkDeploymentController.java:145)\n\tat
>
> org.apache.flink.kubernetes.operator.controller.FlinkDeploymentController.reconcile(FlinkDeploymentController.java:59)\n\tat
>
> io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:191)\n\tat
>
> io.javaoperatorsdk.operator.processing.Controller$1.execute(Controller.java:147)\n\tat
>
> org.apache.flink.kubernetes.operator.metrics.OperatorJosdkMetrics.timeControllerExecution(OperatorJosdkMetrics.java:82)\n\tat
>
> io.javaoperatorsdk.operator.processing.Controller.reconcile(Controller.java:146)\n\tat
>
> io.javaoperatorsdk.operator.processing.event.Rec","additionalMetadata":{"reason":"CrashLoopBackOff"},"throwableList":[]}
> {code}
> Sampled every 5 s over two runs (first deployment, and a stable deployment
> whose JobManager starts crash-looping): every observe that lands in the
> {{running}} window reports {{DEPLOYING}} with
> {{{}lastState.terminated.reason=OOMKilled{}}}; on the stable deployment it
> also wipes {{status.error}} for one progress-check interval; two
> {{CrashLoopBackOff}} events in six minutes per run, one per back-off step.
> h1. Expected
> * A JobManager container that has already died with a non-zero exit code and
> been restarted is reported as crash-looping whenever the operator looks at
> it, whether the kubelet is currently backing off or the container is up again
> between two kills.
> * {{status.error}} and the event name the termination reason and exit code,
> and the text does not change with the back-off timer or the pod name, so one
> event is counted up instead of a new one per step.
> * The error is not cleared until the JobManager is actually {{{}READY{}}}.
--
This message was sent by Atlassian Jira
(v10.3.26#10030026)