extract common code and check node-type offering if present during upgrade and scale
diff --git a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java
index e352a69..6220b3a 100644
--- a/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java
+++ b/plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java
@@ -1418,14 +1418,10 @@
                     throw new InvalidParameterValueException("Failed to find service offering ID: " + serviceOfferingId);
                 }
                 checkServiceOfferingForNodesScale(serviceOffering, kubernetesCluster, clusterVersion);
-                Long nodeTypeOfferingId = getExistingServiceOfferingIdForNodeType(key, kubernetesCluster);
-                if (nodeTypeOfferingId == null) {
-                    if (getNodeCountForType(KubernetesClusterNodeType.valueOf(key), kubernetesCluster) <=0) {
-                        continue;
-                    }
-                    nodeTypeOfferingId = kubernetesCluster.getServiceOfferingId();
+                final ServiceOffering existingServiceOffering = getEffectiveServiceOfferingForNodeType(key, kubernetesCluster);
+                if (existingServiceOffering == null) {
+                    continue;
                 }
-                final ServiceOffering existingServiceOffering = serviceOfferingDao.findById(nodeTypeOfferingId);
                 if (KubernetesCluster.State.Running.equals(kubernetesCluster.getState()) && (serviceOffering.getRamSize() < existingServiceOffering.getRamSize() ||
                         serviceOffering.getCpu() * serviceOffering.getSpeed() < existingServiceOffering.getCpu() * existingServiceOffering.getSpeed())) {
                     logAndThrow(Level.WARN, String.format("Kubernetes cluster cannot be scaled down for service offering. Service offering : %s offers lesser resources as compared to service offering : %s of Kubernetes cluster : %s",
@@ -1446,6 +1442,33 @@
         return kubernetesCluster.getServiceOfferingId();
     }
 
+    // Resolves the offering backing a node type, falling back to the legacy cluster-wide offering; null if the cluster has no nodes of this type.
+    protected ServiceOffering getEffectiveServiceOfferingForNodeType(String key, KubernetesClusterVO kubernetesCluster) {
+        if (getNodeCountForType(KubernetesClusterNodeType.valueOf(key), kubernetesCluster) <= 0) {
+            return null;
+        }
+        Long offeringId = getExistingServiceOfferingIdForNodeType(key, kubernetesCluster);
+        if (offeringId == null) {
+            offeringId = kubernetesCluster.getServiceOfferingId();
+        }
+        if (offeringId == null) {
+            return null;
+        }
+        return serviceOfferingDao.findByIdIncludingRemoved(offeringId);
+    }
+
+    // Effective offerings for every node type actually present on the cluster.
+    protected List<ServiceOffering> getEffectiveServiceOfferingsForCluster(KubernetesClusterVO kubernetesCluster) {
+        List<ServiceOffering> offerings = new ArrayList<>();
+        for (String key : CLUSTER_NODES_TYPES_LIST) {
+            ServiceOffering offering = getEffectiveServiceOfferingForNodeType(key, kubernetesCluster);
+            if (offering != null) {
+                offerings.add(offering);
+            }
+        }
+        return offerings;
+    }
+
     protected void checkServiceOfferingForNodesScale(ServiceOffering serviceOffering, KubernetesClusterVO kubernetesCluster, KubernetesSupportedVersion clusterVersion) {
         if (serviceOffering.isDynamic()) {
             throw new InvalidParameterValueException(String.format("Custom service offerings are not supported for Kubernetes clusters. Kubernetes cluster : %s, service offering : %s", kubernetesCluster.getName(), serviceOffering.getName()));
@@ -1510,17 +1533,19 @@
             throw new InvalidParameterValueException(String.format("Invalid Kubernetes version associated with cluster : %s",
                     kubernetesCluster.getName()));
         }
-        final ServiceOffering serviceOffering = serviceOfferingDao.findByIdIncludingRemoved(kubernetesCluster.getServiceOfferingId());
-        if (serviceOffering == null) {
+        final List<ServiceOffering> effectiveServiceOfferings = getEffectiveServiceOfferingsForCluster(kubernetesCluster);
+        if (CollectionUtils.isEmpty(effectiveServiceOfferings)) {
             throw new CloudRuntimeException(String.format("Invalid service offering associated with Kubernetes cluster : %s", kubernetesCluster.getName()));
         }
-        if (serviceOffering.getCpu() < upgradeVersion.getMinimumCpu()) {
-            throw new InvalidParameterValueException(String.format("Kubernetes cluster : %s cannot be upgraded with Kubernetes version : %s which needs minimum %d vCPUs while associated service offering : %s offers only %d vCPUs",
-                    kubernetesCluster.getName(), upgradeVersion.getName(), upgradeVersion.getMinimumCpu(), serviceOffering.getName(), serviceOffering.getCpu()));
-        }
-        if (serviceOffering.getRamSize() < upgradeVersion.getMinimumRamSize()) {
-            throw new InvalidParameterValueException(String.format("Kubernetes cluster : %s cannot be upgraded with Kubernetes version : %s which needs minimum %d MB RAM while associated service offering : %s offers only %d MB RAM",
-                    kubernetesCluster.getName(), upgradeVersion.getName(), upgradeVersion.getMinimumRamSize(), serviceOffering.getName(), serviceOffering.getRamSize()));
+        for (ServiceOffering serviceOffering : effectiveServiceOfferings) {
+            if (serviceOffering.getCpu() < upgradeVersion.getMinimumCpu()) {
+                throw new InvalidParameterValueException(String.format("Kubernetes cluster : %s cannot be upgraded with Kubernetes version : %s which needs minimum %d vCPUs while associated service offering : %s offers only %d vCPUs",
+                        kubernetesCluster.getName(), upgradeVersion.getName(), upgradeVersion.getMinimumCpu(), serviceOffering.getName(), serviceOffering.getCpu()));
+            }
+            if (serviceOffering.getRamSize() < upgradeVersion.getMinimumRamSize()) {
+                throw new InvalidParameterValueException(String.format("Kubernetes cluster : %s cannot be upgraded with Kubernetes version : %s which needs minimum %d MB RAM while associated service offering : %s offers only %d MB RAM",
+                        kubernetesCluster.getName(), upgradeVersion.getName(), upgradeVersion.getMinimumRamSize(), serviceOffering.getName(), serviceOffering.getRamSize()));
+            }
         }
         // Check upgradeVersion is either patch upgrade or immediate minor upgrade
         try {