Dennis-Mircea Ciupitu created FLINK-41035:
---------------------------------------------

             Summary: Operator health probe reports "All informers are 
unhealthy" when a single event source fails with stop-on-informer-error=false
                 Key: FLINK-41035
                 URL: https://issues.apache.org/jira/browse/FLINK-41035
             Project: Flink
          Issue Type: Bug
          Components: Kubernetes Operator
            Reporter: Dennis-Mircea Ciupitu


h1. Problem

With {{{}kubernetes.operator.startup.stop-on-informer-error=false{}}}, the 
operator is supposed to start and keep running even if some informers cannot be 
started, for example because of missing RBAC permissions. The operator health 
probe tolerates informers that were already unhealthy at startup, and only 
reports unhealthy if an informer becomes unhealthy later, or if all informers 
are unhealthy.

The "all informers are unhealthy" check does not actually look at all 
informers. Whether it triggers depends on how many namespaces an event source 
covers, not on the real state of the operator:
 * *One watched namespace, {{Ingress}} cannot be watched:* the probe logs {{All 
informers are unhealthy}} and returns 500, although every other informer 
(FlinkDeployment, Deployment, FlinkSessionJob, FlinkStateSnapshot, ...) is 
healthy. The startup probe then kills the operator, and this repeats on every 
start.
 * *Two watched namespaces, {{Ingress}} cannot be watched in one of them:* the 
probe returns 200, and the failing informers are tolerated as expected.

The failure is the same in both cases (one resource type cannot be watched in 
one namespace), but the outcome is opposite. In the first case 
{{stop-on-informer-error=false}} has no effect, because the operator never 
stays up.
h1. Root cause

{{InformerHealthSummary.fromRuntimeInfo}} computes "is any informer healthy" 
from {{{}RuntimeInfo.unhealthyInformerWrappingEventSourceHealthIndicator(){}}}. 
That JOSDK view only returns the event sources that contain at least one 
unhealthy informer. Fully healthy event sources are filtered out.

As a result, a healthy informer is only seen when it shares an event source 
with an unhealthy one, which in practice means the same resource type in 
another watched namespace. With a single watched namespace (or when watching 
all namespaces), every event source has exactly one informer, so the check only 
ever sees the failing informers and concludes that all informers are unhealthy. 
This check runs before the startup tolerance, so the tolerated informers never 
get a chance to be accepted.
h1. How to reproduce
h2. Setup
 * Operator installed with the Helm chart, watching only the {{default}} 
namespace ({{{}watchNamespaces: [default]{}}}), namespace-scoped RBAC.
 * {{kubernetes.operator.startup.stop-on-informer-error: false}}
 * {{kubernetes.operator.ingress.manage}} left at its default ({{{}true{}}}), 
so the FlinkDeployment and FlinkBlueGreenDeployment controllers register an 
{{Ingress}} informer.

h2. Steps
 # Remove the ingress permission from the operator Role:
{code:bash}
kubectl -n default get role flink-operator -o json \
  | jq 'del(.rules[] | select(.apiGroups == ["networking.k8s.io"]))' \
  | kubectl replace -f -
{code}

 # Restart the operator:
{code:bash}
kubectl rollout restart deploy/flink-kubernetes-operator
{code}

h2. Observed

After the cache sync timeout, the two {{Ingress}} informers are tolerated as 
initially unhealthy, the health endpoint starts, and the first probe already 
fails:
{noformat}
2026-10-19 18:23:12,211 WARN  [ingresses.networking.k8s.io/v1] 
i.j.o.p.e.s.informer.InformerWrapper Informer startup error. Will periodically 
retry. Informer: networking.k8s.io/v1/namespaces/default/ingresses
2026-10-19 18:23:12,213 WARN  [ingresses.networking.k8s.io/v1] 
i.j.o.p.e.s.informer.InformerWrapper Informer startup error. Will periodically 
retry. Informer: networking.k8s.io/v1/namespaces/default/ingresses
2026-10-19 18:23:12,217 INFO  main o.a.f.k.operator.health.HealthProbe 
Initially unhealthy informers: 
[InformerIdentifier(controllerName=flinkbluegreendeploymentcontroller, 
eventSourceName=...InformerEventSource@4893b344, informerName=default), 
InformerIdentifier(controllerName=flinkdeploymentcontroller, 
eventSourceName=...InformerEventSource@20411320, informerName=default)]
2026-10-19 18:23:12,270 INFO  main o.a.f.k.o.h.OperatorHealthService Health 
probe HTTP endpoint started on port 8085
2026-10-19 18:23:20,954 ERROR nioEventLoopGroup-3-1 
o.a.f.k.operator.health.HealthProbe All informers are unhealthy
{noformat}
{noformat}
Warning  Unhealthy  kubelet  Startup probe failed: HTTP probe failed with 
statuscode: 500
{noformat}
The operator container is restarted once the startup probe budget is exhausted, 
and the same sequence repeats on every start.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to