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 581c67e8a [FLINK-41031] Close operator-owned resources on shutdown and
exit on startup failure (#1224)
581c67e8a is described below
commit 581c67e8aa6946928ad1a3aeee652b26f6c2fa4f
Author: Dennis-Mircea Ciupitu <[email protected]>
AuthorDate: Thu Oct 29 12:59:43 2026 +0200
[FLINK-41031] Close operator-owned resources on shutdown and exit on
startup failure (#1224)
---
.../flink/kubernetes/operator/FlinkOperator.java | 31 +++++++++++++++++++---
.../operator/config/FlinkConfigManager.java | 11 ++++++--
.../operator/health/CanaryResourceManager.java | 12 +++++++--
.../operator/health/OperatorHealthService.java | 11 ++++++--
.../metrics/KubernetesOperatorMetricGroup.java | 12 ++++++++-
.../service/FlinkResourceContextFactory.java | 10 +++++--
.../operator/config/FlinkConfigManagerTest.java | 9 +++++++
.../operator/health/HealthProbeTest.java | 15 ++++++++++-
.../metrics/KubernetesOperatorMetricGroupTest.java | 20 ++++++++++++++
.../service/FlinkResourceContextFactoryTest.java | 14 ++++++++++
.../operator/admission/FlinkOperatorWebhook.java | 26 +++++++++++++++---
.../admission/informer/InformerManager.java | 11 +++++++-
.../admission/informer/InformerManagerTest.java | 14 ++++++++++
13 files changed, 178 insertions(+), 18 deletions(-)
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/FlinkOperator.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/FlinkOperator.java
index 8a5af0e6b..4ee1db6bf 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/FlinkOperator.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/FlinkOperator.java
@@ -57,6 +57,7 @@ import
org.apache.flink.kubernetes.operator.utils.KubernetesClientUtils;
import org.apache.flink.kubernetes.operator.utils.OperatorPluginUtils;
import org.apache.flink.kubernetes.operator.utils.StatusRecorder;
import org.apache.flink.kubernetes.operator.utils.ValidatorUtils;
+import org.apache.flink.util.IOUtils;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.javaoperatorsdk.operator.Operator;
@@ -69,6 +70,7 @@ import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.time.Duration;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
@@ -199,6 +201,7 @@ public class FlinkOperator {
var reconcilerFactory = new ReconcilerFactory(eventRecorder,
statusRecorder, autoscaler);
var observerFactory = new
FlinkDeploymentObserverFactory(eventRecorder);
var canaryResourceManager = new
CanaryResourceManager<FlinkDeployment>(configManager);
+ canaryResourceManagers.add(canaryResourceManager);
HealthProbe.INSTANCE.registerCanaryResourceManager(canaryResourceManager);
canaryResourceManagers.add(canaryResourceManager);
@@ -224,6 +227,7 @@ public class FlinkOperator {
var reconciler = new SessionJobReconciler(eventRecorder,
statusRecorder, autoscaler);
var observer = new FlinkSessionJobObserver(eventRecorder);
var canaryResourceManager = new
CanaryResourceManager<FlinkSessionJob>(configManager);
+ canaryResourceManagers.add(canaryResourceManager);
HealthProbe.INSTANCE.registerCanaryResourceManager(canaryResourceManager);
canaryResourceManagers.add(canaryResourceManager);
@@ -297,22 +301,41 @@ public class FlinkOperator {
registerSessionJobController();
registerSnapshotController();
registerBlueGreenController();
- operator.installShutdownHook(
-
baseConfig.get(KubernetesOperatorConfigOptions.OPERATOR_TERMINATION_TIMEOUT));
+ Runtime.getRuntime().addShutdownHook(new Thread(this::stop));
operator.start();
if (operatorHealthService != null) {
HealthProbe.INSTANCE.setRuntimeInfo(operator.getRuntimeInfo());
- Runtime.getRuntime().addShutdownHook(new
Thread(operatorHealthService::stop));
operatorHealthService.start();
}
}
public void stop() {
+ // in-flight reconciliations are drained first
operator.stop();
+
+ var closeables = new ArrayList<AutoCloseable>();
+ closeables.add(ctxFactory);
+ closeables.addAll(canaryResourceManagers);
+ closeables.add(configManager);
+ closeables.add(metricGroup);
+ if (operatorHealthService != null) {
+ closeables.add(operatorHealthService);
+ }
+ try {
+ IOUtils.closeAll(closeables);
+ } catch (Exception e) {
+ LOG.warn("Failed to close operator components", e);
+ }
}
public static void main(String... args) {
EnvUtils.logEnvironmentInfo(LOG, "Flink Kubernetes Operator", args);
- new FlinkOperator(null).run();
+ try {
+ new FlinkOperator(null).run();
+ } catch (Throwable t) {
+ // Non-daemon threads started before the failure would keep the
JVM alive
+ LOG.error("Failed to start the operator", t);
+ System.exit(1);
+ }
}
}
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/config/FlinkConfigManager.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/config/FlinkConfigManager.java
index 9b9126bc5..ebbd8b557 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/config/FlinkConfigManager.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/config/FlinkConfigManager.java
@@ -74,11 +74,12 @@ import static
org.apache.flink.kubernetes.operator.config.KubernetesOperatorConf
import static
org.apache.flink.kubernetes.operator.config.KubernetesOperatorConfigOptions.VERSION_CONF_PREFIX;
/** Configuration manager for the Flink operator. */
-public class FlinkConfigManager {
+public class FlinkConfigManager implements AutoCloseable {
private static final Logger LOG =
LoggerFactory.getLogger(FlinkConfigManager.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
+ @VisibleForTesting final ScheduledExecutorService executorService;
private volatile Configuration defaultConfig;
private volatile FlinkOperatorConfiguration defaultOperatorConfiguration;
// TODO: From 1.11 release, snapshot CRD should be mandatory and this can
be removed.
@@ -133,7 +134,7 @@ public class FlinkConfigManager {
});
updateDefaultConfig(defaultConfig);
- ScheduledExecutorService executorService =
Executors.newSingleThreadScheduledExecutor();
+ this.executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(
cache::cleanUp,
cacheTimeout.toMillis(),
@@ -149,6 +150,12 @@ public class FlinkConfigManager {
return snapshotCrdInstalled;
}
+ /** Stops the config cache cleanup and the dynamic config watcher. */
+ @Override
+ public void close() {
+ executorService.shutdownNow();
+ }
+
/**
* Update the base configuration for the operator. Newly generated configs
(observe, deploy,
* etc.) will use this as the base.
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/health/CanaryResourceManager.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/health/CanaryResourceManager.java
index e3eccc0b1..bd0d8660b 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/health/CanaryResourceManager.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/health/CanaryResourceManager.java
@@ -46,7 +46,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
* deployed, their reconciliation stops at this class.
*/
@RequiredArgsConstructor
-public class CanaryResourceManager<CR extends AbstractFlinkResource<?, ?>> {
+public class CanaryResourceManager<CR extends AbstractFlinkResource<?, ?>>
+ implements AutoCloseable {
private static final Logger LOG =
LoggerFactory.getLogger(CanaryResourceManager.class);
@@ -57,7 +58,8 @@ public class CanaryResourceManager<CR extends
AbstractFlinkResource<?, ?>> {
private final ConcurrentHashMap<ResourceID, CanaryResourceState>
canaryResources =
new ConcurrentHashMap<>();
- private final ScheduledExecutorService executorService =
Executors.newScheduledThreadPool(3);
+ @VisibleForTesting
+ final ScheduledExecutorService executorService =
Executors.newScheduledThreadPool(3);
private final FlinkConfigManager configManager;
@@ -243,6 +245,12 @@ public class CanaryResourceManager<CR extends
AbstractFlinkResource<?, ?>> {
return "true".equalsIgnoreCase(labels.getOrDefault(CANARY_LABEL,
"false"));
}
+ /** Stops the scheduled canary health checks. */
+ @Override
+ public void close() {
+ executorService.shutdownNow();
+ }
+
private class CanaryResourceState {
CR resource;
long bumpedGeneration;
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/health/OperatorHealthService.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/health/OperatorHealthService.java
index c0e67e8b3..20007fcde 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/health/OperatorHealthService.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/health/OperatorHealthService.java
@@ -24,7 +24,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Health probe service. */
-public class OperatorHealthService {
+public class OperatorHealthService implements AutoCloseable {
private static final Logger LOG =
LoggerFactory.getLogger(OperatorHealthService.class);
private final HealthProbe probe = HealthProbe.INSTANCE;
@@ -52,7 +52,14 @@ public class OperatorHealthService {
}
public void stop() {
- httpBootstrap.stop();
+ if (httpBootstrap != null) {
+ httpBootstrap.stop();
+ }
+ }
+
+ @Override
+ public void close() {
+ stop();
}
public static OperatorHealthService fromConfig(FlinkConfigManager
configManager) {
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/metrics/KubernetesOperatorMetricGroup.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/metrics/KubernetesOperatorMetricGroup.java
index fee905e8b..2f08646a6 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/metrics/KubernetesOperatorMetricGroup.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/metrics/KubernetesOperatorMetricGroup.java
@@ -23,13 +23,15 @@ import org.apache.flink.runtime.metrics.MetricRegistry;
import org.apache.flink.runtime.metrics.dump.QueryScopeInfo;
import org.apache.flink.runtime.metrics.groups.AbstractMetricGroup;
import org.apache.flink.runtime.metrics.scope.ScopeFormat;
+import org.apache.flink.util.AutoCloseableAsync;
import io.fabric8.kubernetes.client.CustomResource;
import java.util.Map;
/** Base metric group for Flink Operator System metrics. */
-public class KubernetesOperatorMetricGroup extends
AbstractMetricGroup<AbstractMetricGroup<?>> {
+public class KubernetesOperatorMetricGroup extends
AbstractMetricGroup<AbstractMetricGroup<?>>
+ implements AutoCloseable {
protected final String namespace;
protected final String name;
@@ -76,6 +78,14 @@ public class KubernetesOperatorMetricGroup extends
AbstractMetricGroup<AbstractM
hostname);
}
+ @Override
+ public void close() {
+ super.close();
+ if (registry instanceof AutoCloseableAsync closeableRegistry) {
+ closeableRegistry.closeAsync();
+ }
+ }
+
@Override
protected final void putVariables(Map<String, String> variables) {
variables.put(KubernetesOperatorScopeFormat.NAMESPACE, namespace);
diff --git
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/service/FlinkResourceContextFactory.java
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/service/FlinkResourceContextFactory.java
index 58be43e21..a3a029397 100644
---
a/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/service/FlinkResourceContextFactory.java
+++
b/flink-kubernetes-operator/src/main/java/org/apache/flink/kubernetes/operator/service/FlinkResourceContextFactory.java
@@ -53,7 +53,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/** Factory for creating the {@link FlinkResourceContext}. */
-public class FlinkResourceContextFactory {
+public class FlinkResourceContextFactory implements AutoCloseable {
private static final Logger LOG =
LoggerFactory.getLogger(FlinkResourceContextFactory.class);
@@ -71,7 +71,7 @@ public class FlinkResourceContextFactory {
private final FlinkConfigManager configManager;
private final ArtifactManager artifactManager;
- private final ExecutorService clientExecutorService;
+ @VisibleForTesting final ExecutorService clientExecutorService;
private final KubernetesOperatorMetricGroup operatorMetricGroup;
private final EventRecorder eventRecorder;
@@ -181,4 +181,10 @@ public class FlinkResourceContextFactory {
lastRecordedExceptionCache.remove(resourceId);
LOG.debug("Removed resource {} from last recorded exception cache",
resourceId);
}
+
+ /** Stops the executor used by the Flink REST cluster clients. */
+ @Override
+ public void close() {
+ clientExecutorService.shutdownNow();
+ }
}
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 715c072b8..e60ad317c 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
@@ -467,4 +467,13 @@ public class FlinkConfigManagerTest {
assertTrue(completed2.get());
assertTrue(completed3.get());
}
+
+ @Test
+ public void testCloseStopsExecutor() {
+ var configManager = new FlinkConfigManager(new Configuration());
+ assertFalse(configManager.executorService.isShutdown());
+
+ configManager.close();
+ assertTrue(configManager.executorService.isShutdown());
+ }
}
diff --git
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/health/HealthProbeTest.java
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/health/HealthProbeTest.java
index 654476b1b..2878bcb18 100644
---
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/health/HealthProbeTest.java
+++
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/health/HealthProbeTest.java
@@ -37,6 +37,7 @@ import
io.javaoperatorsdk.operator.processing.event.ResourceID;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
@@ -47,6 +48,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import static
org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpResponseStatus.OK;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
@@ -81,7 +83,7 @@ public class HealthProbeTest {
assertNotNull(HealthProbe.INSTANCE.getRuntimeInfo());
} finally {
operator.stop();
- assertFalse(callHealthEndpoint(conf));
+ assertThrows(ConnectException.class, () ->
callHealthEndpoint(conf));
}
}
}
@@ -257,4 +259,15 @@ public class HealthProbeTest {
return () -> informers;
}
+
+ @Test
+ public void testCanaryResourceManagerCloseStopsExecutor() {
+ try (var configManager = new FlinkConfigManager(new Configuration())) {
+ var canaryManager = new
CanaryResourceManager<FlinkDeployment>(configManager);
+ assertFalse(canaryManager.executorService.isShutdown());
+
+ canaryManager.close();
+ assertTrue(canaryManager.executorService.isShutdown());
+ }
+ }
}
diff --git
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/metrics/KubernetesOperatorMetricGroupTest.java
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/metrics/KubernetesOperatorMetricGroupTest.java
index 211bb65a4..164f71fd1 100644
---
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/metrics/KubernetesOperatorMetricGroupTest.java
+++
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/metrics/KubernetesOperatorMetricGroupTest.java
@@ -29,6 +29,8 @@ import java.util.Map;
import static
org.apache.flink.kubernetes.operator.metrics.KubernetesOperatorMetricOptions.SCOPE_NAMING_KUBERNETES_OPERATOR;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @link KubernetesOperatorMetricGroup tests.
@@ -150,6 +152,24 @@ public class KubernetesOperatorMetricGroupTest {
registry.close();
}
+ @Test
+ public void testCloseClosesRegistry() {
+ var configuration = new Configuration();
+ var registry = new
MetricRegistryImpl(fromConfiguration(configuration));
+ var group =
+ KubernetesOperatorMetricGroup.create(
+ registry,
+ configuration,
+ "default",
+ "flink-kubernetes-operator",
+ "localhost");
+ assertFalse(registry.isShutdown());
+
+ group.close();
+ assertTrue(group.isClosed());
+ assertTrue(registry.isShutdown());
+ }
+
private static MetricRegistryConfiguration fromConfiguration(Configuration
configuration) {
return MetricRegistryConfiguration.fromConfiguration(configuration,
Long.MAX_VALUE);
}
diff --git
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/service/FlinkResourceContextFactoryTest.java
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/service/FlinkResourceContextFactoryTest.java
index 1eb8fe4b1..ee464d142 100644
---
a/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/service/FlinkResourceContextFactoryTest.java
+++
b/flink-kubernetes-operator/src/test/java/org/apache/flink/kubernetes/operator/service/FlinkResourceContextFactoryTest.java
@@ -25,6 +25,8 @@ import
org.apache.flink.kubernetes.operator.config.KubernetesOperatorConfigOptio
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/** Tests for {@link FlinkResourceContextFactory}. */
public class FlinkResourceContextFactoryTest {
@@ -56,4 +58,16 @@ public class FlinkResourceContextFactoryTest {
TestUtils.createTestMetricGroup(new
Configuration()),
null));
}
+
+ @Test
+ public void testCloseStopsClientExecutor() {
+ try (var configManager = new FlinkConfigManager(new Configuration());
+ var metricGroup = TestUtils.createTestMetricGroup(new
Configuration())) {
+ var contextFactory = new
FlinkResourceContextFactory(configManager, metricGroup, null);
+ assertFalse(contextFactory.clientExecutorService.isShutdown());
+
+ contextFactory.close();
+ assertTrue(contextFactory.clientExecutorService.isShutdown());
+ }
+ }
}
diff --git
a/flink-kubernetes-webhook/src/main/java/org/apache/flink/kubernetes/operator/admission/FlinkOperatorWebhook.java
b/flink-kubernetes-webhook/src/main/java/org/apache/flink/kubernetes/operator/admission/FlinkOperatorWebhook.java
index 673f9c9a8..cde403afb 100644
---
a/flink-kubernetes-webhook/src/main/java/org/apache/flink/kubernetes/operator/admission/FlinkOperatorWebhook.java
+++
b/flink-kubernetes-webhook/src/main/java/org/apache/flink/kubernetes/operator/admission/FlinkOperatorWebhook.java
@@ -32,6 +32,7 @@ import
org.apache.flink.kubernetes.operator.utils.KubernetesClientUtils;
import org.apache.flink.kubernetes.operator.utils.MutatorUtils;
import org.apache.flink.kubernetes.operator.utils.OperatorPluginUtils;
import org.apache.flink.kubernetes.operator.utils.ValidatorUtils;
+import org.apache.flink.util.IOUtils;
import org.apache.flink.shaded.netty4.io.netty.bootstrap.ServerBootstrap;
import org.apache.flink.shaded.netty4.io.netty.channel.Channel;
@@ -53,6 +54,8 @@ import javax.annotation.Nullable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.file.Path;
+import java.util.ArrayDeque;
+import java.util.Deque;
import java.util.Set;
/** Main Class for Flink native k8s operator. */
@@ -67,17 +70,23 @@ public class FlinkOperatorWebhook {
@VisibleForTesting final Set<FlinkResourceMutator> mutators;
@VisibleForTesting final AdmissionHandler admissionHandler;
+ private final Deque<AutoCloseable> ownedResources = new ArrayDeque<>();
+
@VisibleForTesting
FlinkOperatorWebhook(
@Nullable InformerManager informerManager, @Nullable
FlinkConfigManager configManager) {
if (informerManager == null) {
- informerManager = new InformerManager(new
KubernetesClientBuilder().build());
+ var kubernetesClient = new KubernetesClientBuilder().build();
+ ownedResources.push(kubernetesClient);
+ informerManager = new InformerManager(kubernetesClient);
+ ownedResources.push(informerManager);
}
if (configManager == null) {
configManager =
new FlinkConfigManager(
informerManager::setNamespaces,
KubernetesClientUtils.isCrdInstalled(FlinkStateSnapshot.class));
+ ownedResources.push(configManager);
}
var operatorConfig = configManager.getOperatorConfiguration();
@@ -119,12 +128,23 @@ public class FlinkOperatorWebhook {
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
+ try {
+ IOUtils.closeAll(ownedResources);
+ } catch (Exception e) {
+ LOG.warn("Failed to close webhook resources", e);
+ }
}
}
- public static void main(String[] args) throws Exception {
+ public static void main(String[] args) {
EnvUtils.logEnvironmentInfo(LOG, "Flink Kubernetes Webhook", args);
- new FlinkOperatorWebhook(null, null).run();
+ try {
+ new FlinkOperatorWebhook(null, null).run();
+ } catch (Throwable t) {
+ // Non-daemon threads started before the failure would keep the
JVM alive
+ LOG.error("Failed to start the webhook", t);
+ System.exit(1);
+ }
}
private static int getPort() {
diff --git
a/flink-kubernetes-webhook/src/main/java/org/apache/flink/kubernetes/operator/admission/informer/InformerManager.java
b/flink-kubernetes-webhook/src/main/java/org/apache/flink/kubernetes/operator/admission/informer/InformerManager.java
index d2b69d3cf..50b84cbea 100644
---
a/flink-kubernetes-webhook/src/main/java/org/apache/flink/kubernetes/operator/admission/informer/InformerManager.java
+++
b/flink-kubernetes-webhook/src/main/java/org/apache/flink/kubernetes/operator/admission/informer/InformerManager.java
@@ -36,7 +36,7 @@ import java.util.concurrent.ConcurrentHashMap;
import static
io.javaoperatorsdk.operator.api.reconciler.Constants.DEFAULT_NAMESPACES_SET;
/** The manager of the informers. */
-public class InformerManager {
+public class InformerManager implements AutoCloseable {
private static final Logger LOG =
LoggerFactory.getLogger(InformerManager.class);
private final Set<String> watchedNamespaces =
ConcurrentHashMap.newKeySet();
@@ -138,6 +138,15 @@ public class InformerManager {
LOG.info("Setting namespaces to {}", watchedNamespaces);
this.watchedNamespaces.clear();
this.watchedNamespaces.addAll(watchedNamespaces);
+ stopInformers();
+ }
+
+ @Override
+ public void close() {
+ stopInformers();
+ }
+
+ private void stopInformers() {
if (flinkDepInformers != null) {
synchronized (this) {
if (flinkDepInformers != null) {
diff --git
a/flink-kubernetes-webhook/src/test/java/org/apache/flink/kubernetes/operator/admission/informer/InformerManagerTest.java
b/flink-kubernetes-webhook/src/test/java/org/apache/flink/kubernetes/operator/admission/informer/InformerManagerTest.java
index 1f167fe26..591f4a4d2 100644
---
a/flink-kubernetes-webhook/src/test/java/org/apache/flink/kubernetes/operator/admission/informer/InformerManagerTest.java
+++
b/flink-kubernetes-webhook/src/test/java/org/apache/flink/kubernetes/operator/admission/informer/InformerManagerTest.java
@@ -72,6 +72,20 @@ public class InformerManagerTest {
Assertions.assertNotNull(informerManager.getFlinkSessionJobInformer("ns3"));
}
+ @Test
+ public void testCloseStopsInformers() {
+ var informerManager = new InformerManager(kubernetesClient);
+ informerManager.setNamespaces(Set.of("ns1"));
+ var depInformer = informerManager.getFlinkDepInformer("ns1");
+ var sessionJobInformer =
informerManager.getFlinkSessionJobInformer("ns1");
+ Assertions.assertTrue(depInformer.isRunning());
+ Assertions.assertTrue(sessionJobInformer.isRunning());
+
+ informerManager.close();
+ Assertions.assertFalse(depInformer.isRunning());
+ Assertions.assertFalse(sessionJobInformer.isRunning());
+ }
+
@Test
public void testSetNamespacesStopsSessionJobInformers() {
var informerManager = new InformerManager(kubernetesClient);