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

ayushtkn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 6d4ff6d0f43 HIVE-30091: Fix K8s operator LLAP/TezAM replica resolution 
when autoscaling is disabled (#6814)
6d4ff6d0f43 is described below

commit 6d4ff6d0f4389472ca116145f8e1faf007782692
Author: Tanishq Chugh <[email protected]>
AuthorDate: Fri Sep 25 04:05:07 2026 +0530

    HIVE-30091: Fix K8s operator LLAP/TezAM replica resolution when autoscaling 
is disabled (#6814)
    
    * HIVE-30091: Fix K8s operator LLAP/TezAM replica resolution when 
autoscaling is disabled
    
    * Address copilot comments
    
    * Rename method to clearAutoscalingState to avoid shadowing
---
 .../autoscaling/HiveClusterAutoscaler.java         |  19 ++++
 .../operator/reconciler/HiveClusterReconciler.java | 112 ++++++++++++++-------
 2 files changed, 92 insertions(+), 39 deletions(-)

diff --git 
a/packaging/src/kubernetes/src/java/org/apache/hive/kubernetes/operator/autoscaling/HiveClusterAutoscaler.java
 
b/packaging/src/kubernetes/src/java/org/apache/hive/kubernetes/operator/autoscaling/HiveClusterAutoscaler.java
index f6016043fc6..5be325e4085 100644
--- 
a/packaging/src/kubernetes/src/java/org/apache/hive/kubernetes/operator/autoscaling/HiveClusterAutoscaler.java
+++ 
b/packaging/src/kubernetes/src/java/org/apache/hive/kubernetes/operator/autoscaling/HiveClusterAutoscaler.java
@@ -81,6 +81,25 @@ public static void setManagedReplicas(String namespace, 
String clusterName,
     MANAGED_REPLICAS.put(cacheKey(namespace, clusterName, component), 
replicas);
   }
 
+  /**
+   * Removes the autoscaler-managed replica count for a component. Used when 
autoscaling is disabled so
+   * a pre-existing in-memory scale decision if any is cleared up.
+   */
+  public static void cleanupManagedReplicas(String namespace, String 
clusterName, String component) {
+    MANAGED_REPLICAS.remove(cacheKey(namespace, clusterName, component));
+  }
+
+  /**
+   * Clears all in-memory autoscaling state for a component when autoscaling 
is disabled.
+   */
+  public void resetComponentAutoscalingState(String namespace, String 
clusterName, String component) {
+    String key = cacheKey(namespace, clusterName, component);
+    MANAGED_REPLICAS.remove(key);
+    pendingScaleDowns.remove(key);
+    autoscalers.remove(key);
+    lastScaleTimes.remove(key);
+  }
+
   private record PendingScaleDown(int targetReplicas, Instant annotatedAt, 
List<String> podsToDeregister) {}
 
   private final BackgroundMetricsScraper bgScraper;
diff --git 
a/packaging/src/kubernetes/src/java/org/apache/hive/kubernetes/operator/reconciler/HiveClusterReconciler.java
 
b/packaging/src/kubernetes/src/java/org/apache/hive/kubernetes/operator/reconciler/HiveClusterReconciler.java
index 557ebe99d54..ccb1390c90b 100644
--- 
a/packaging/src/kubernetes/src/java/org/apache/hive/kubernetes/operator/reconciler/HiveClusterReconciler.java
+++ 
b/packaging/src/kubernetes/src/java/org/apache/hive/kubernetes/operator/reconciler/HiveClusterReconciler.java
@@ -162,6 +162,15 @@ public UpdateControl<HiveCluster> reconcile(HiveCluster 
resource, Context<HiveCl
       break;
     }
 
+    boolean canEvaluateAutoscaling = (rescheduleSeconds == 0 && 
anyAutoscalingEnabled(resource.getSpec()));
+    
+    HiveClusterAutoscaler scaler = autoscaler;
+    if (scaler == null && canEvaluateAutoscaling) {
+      scaler = getOrCreateAutoscaler(client);
+    }
+    
+    resetAutoscalingStateForDisabledComponents(resource, scaler);
+
     // --- Imperative LLAP cluster management ---
     // Must also run while suspended: resolve*ReplicaCount() return 0 when
     // spec.suspend() is set, and skipping the call would leave LLAP/TezAM
@@ -169,8 +178,7 @@ public UpdateControl<HiveCluster> reconcile(HiveCluster 
resource, Context<HiveCl
     reconcileLlapClusters(resource, client);
 
     // --- Autoscaling evaluation (only when enabled and not suspended) ---
-    if (rescheduleSeconds == 0 && anyAutoscalingEnabled(resource.getSpec())) {
-      HiveClusterAutoscaler scaler = getOrCreateAutoscaler(client);
+    if (canEvaluateAutoscaling) {
       HiveClusterAutoscaler.AutoscalingEvaluation eval = 
scaler.evaluate(resource, client);
       for (Map.Entry<String, Integer> entry : eval.patches().entrySet()) {
         patchReplicas(client, resource, entry.getKey(), entry.getValue());
@@ -553,6 +561,42 @@ private HiveClusterAutoscaler 
getOrCreateAutoscaler(KubernetesClient client) {
     return autoscaler;
   }
 
+  /**
+   * Clears autoscaling state for components with autoscaling disabled in spec.
+   */
+  private static void resetAutoscalingStateForDisabledComponents(HiveCluster 
resource, HiveClusterAutoscaler scaler) {
+    HiveClusterSpec spec = resource.getSpec();
+    String ns = resource.getMetadata().getNamespace();
+    String clusterName = resource.getMetadata().getName();
+
+    if (!spec.hiveServer2().autoscaling().isEnabled()) {
+      clearAutoscalingState(scaler, ns, clusterName, 
ConfigUtils.COMPONENT_HIVESERVER2);
+    }
+    if (spec.metastore().isEnabled() && 
!spec.metastore().autoscaling().isEnabled()) {
+      clearAutoscalingState(scaler, ns, clusterName, 
ConfigUtils.COMPONENT_METASTORE);
+    }
+    for (var llap : spec.llapClusters()) {
+      if (!llap.isEnabled()) {
+        continue;
+      }
+      if (!llap.autoscaling().isEnabled()) {
+        clearAutoscalingState(scaler, ns, clusterName, 
ConfigUtils.llapComponentKey(llap.name()));
+      }
+      if (spec.tezAm().isEnabled() && !llap.tezAm().autoscaling().isEnabled()) 
{
+        clearAutoscalingState(scaler, ns, clusterName, 
ConfigUtils.tezAmComponentKey(llap.name()));
+      }
+    }
+  }
+
+  private static void clearAutoscalingState(HiveClusterAutoscaler scaler,
+      String namespace, String clusterName, String component) {
+    if (scaler != null) {
+      scaler.resetComponentAutoscalingState(namespace, clusterName, component);
+    } else {
+      HiveClusterAutoscaler.cleanupManagedReplicas(namespace, clusterName, 
component);
+    }
+  }
+
   private static boolean anyAutoscalingEnabled(HiveClusterSpec spec) {
     if (spec.hiveServer2().autoscaling().isEnabled()) {
       return true;
@@ -713,12 +757,12 @@ private int resolveLlapReplicaCount(HiveCluster resource,
       return 0;
     }
     String componentKey = ConfigUtils.llapComponentKey(llapSpec.name());
-    Integer managed = HiveClusterAutoscaler.getManagedReplicas(ns, 
clusterName, componentKey);
-    if (managed != null) {
-      return managed;
-    }
-    // First reconcile before autoscaler runs: start at minReplicas if 
autoscaling enabled
     if (llapSpec.autoscaling().isEnabled()) {
+      Integer managed = HiveClusterAutoscaler.getManagedReplicas(ns, 
clusterName, componentKey);
+      if (managed != null) {
+        return managed;
+      }
+      // First reconcile before autoscaler runs: start at minReplicas if 
autoscaling enabled
       return llapSpec.autoscaling().minReplicas();
     }
     return llapSpec.replicas();
@@ -734,21 +778,17 @@ private int resolveTezAmReplicaCount(HiveCluster resource,
       return 0;
     }
     LlapSpec.LlapTezAmSpec tezAmSpec = llapSpec.tezAm();
-    // Check if autoscaler has a managed value for this specific TezAM
     String tezAmComponentKey = ConfigUtils.tezAmComponentKey(llapSpec.name());
-    Integer tezAmManaged = HiveClusterAutoscaler.getManagedReplicas(ns, 
clusterName, tezAmComponentKey);
-    if (tezAmManaged != null) {
-      return tezAmManaged;
-    }
-    // TezAM follows LLAP's autoscaling gate: only run if LLAP is running.
-    String llapComponentKey = ConfigUtils.llapComponentKey(llapSpec.name());
-    Integer llapManaged = HiveClusterAutoscaler.getManagedReplicas(ns, 
clusterName, llapComponentKey);
-    if (llapManaged != null && llapManaged == 0) {
-      return 0;
+    // Check if autoscaler has a managed value for this specific TezAM
+    if (tezAmSpec.autoscaling().isEnabled()) {
+      Integer tezAmManaged = HiveClusterAutoscaler.getManagedReplicas(ns, 
clusterName, tezAmComponentKey);
+      if (tezAmManaged != null) {
+        return tezAmManaged;
+      }
     }
-    if (llapSpec.autoscaling().isEnabled() && llapManaged == null
-        && llapSpec.autoscaling().minReplicas() == 0) {
-      // First reconcile before autoscaler runs: LLAP starts at 0, so TezAM 
stays down too.
+
+    int llapDesired = resolveLlapReplicaCount(resource, llapSpec, ns, 
clusterName);
+    if (llapDesired == 0) {
       return 0;
     }
     if (tezAmSpec.autoscaling().isEnabled()) {
@@ -1012,35 +1052,29 @@ private void wakeCluster(HiveCluster resource) {
     // the dependent resources (Deployments/StatefulSets) on the next reconcile
     // and use these values for spec.replicas. We don't call patchReplicas()
     // because the workloads may have been garbage-collected while suspended.
-    // With autoscaling disabled the wake value is the spec's static replica
-    // count — using minReplicas (0 by default) would pin the component to 0.
-    int hs2Wake = spec.hiveServer2().autoscaling().isEnabled()
-        ? Math.max(1, spec.hiveServer2().autoscaling().minReplicas())
-        : spec.hiveServer2().replicas();
-    HiveClusterAutoscaler.setManagedReplicas(ns, name, 
ConfigUtils.COMPONENT_HIVESERVER2, hs2Wake);
+    if (spec.hiveServer2().autoscaling().isEnabled()) {
+      HiveClusterAutoscaler.setManagedReplicas(ns, name, 
ConfigUtils.COMPONENT_HIVESERVER2,
+          Math.max(1, spec.hiveServer2().autoscaling().minReplicas()));
+    }
 
-    if (spec.metastore().isEnabled() && spec.autoSuspend().includeMetastore()) 
{
-      int hmsWake = spec.metastore().autoscaling().isEnabled()
-          ? Math.max(1, spec.metastore().autoscaling().minReplicas())
-          : spec.metastore().replicas();
-      HiveClusterAutoscaler.setManagedReplicas(ns, name, 
ConfigUtils.COMPONENT_METASTORE, hmsWake);
+    if (spec.metastore().isEnabled() && spec.autoSuspend().includeMetastore()
+        && spec.metastore().autoscaling().isEnabled()) {
+      HiveClusterAutoscaler.setManagedReplicas(ns, name, 
ConfigUtils.COMPONENT_METASTORE,
+          Math.max(1, spec.metastore().autoscaling().minReplicas()));
     }
 
     for (var llap : spec.llapClusters()) {
-      if (llap.isEnabled()) {
-        int llapWake = llap.autoscaling().isEnabled()
-            ? llap.autoscaling().minReplicas() : llap.replicas();
-        HiveClusterAutoscaler.setManagedReplicas(ns, name, 
ConfigUtils.llapComponentKey(llap.name()), llapWake);
+      if (llap.isEnabled() && llap.autoscaling().isEnabled()) {
+        HiveClusterAutoscaler.setManagedReplicas(ns, name, 
ConfigUtils.llapComponentKey(llap.name()),
+            llap.autoscaling().minReplicas());
       }
     }
 
     if (spec.tezAm().isEnabled()) {
       for (var llap : spec.llapClusters()) {
-        if (llap.isEnabled()) {
-          int tezWake = llap.tezAm().autoscaling().isEnabled()
-              ? llap.tezAm().autoscaling().minReplicas() : 
llap.tezAm().replicas();
+        if (llap.isEnabled() && llap.tezAm().autoscaling().isEnabled()) {
           HiveClusterAutoscaler.setManagedReplicas(ns, name,
-              ConfigUtils.tezAmComponentKey(llap.name()), tezWake);
+              ConfigUtils.tezAmComponentKey(llap.name()), 
llap.tezAm().autoscaling().minReplicas());
         }
       }
     }

Reply via email to