When a cluster on an isolated network is scaled, the SSH rules on the
source NAT IP are rebuilt for the new node count, but the rules of the
external nodes (added with addNodesToKubernetesCluster) were left in
place. On scale-up the new SSH port range overlapped the firewall rule
of an external node and the scale failed after the rules of the other
nodes had been removed; on scale-down the old rules of the external
nodes stayed on their old ports.
Revoke the SSH port forwarding rules of the external nodes and the
firewall rules for their ports before the rules are rebuilt; they are
recreated after the new range as before. Pass the node VMs to the
rebuild in the order of their SSH ports on scale-down as well, the
external nodes last, as on scale-up.
Reject external nodes in the nodeids of scaleKubernetesCluster: scaling
never removed them but lowered the node count. External nodes are
removed with removeNodesFromKubernetesCluster.
The node order and the nodeids check apply to all network types.
Fixes apache#12633
Description
This PR fixes scaling a CKS cluster on an isolated network that has external nodes (VMs added with addNodesToKubernetesCluster).
When the cluster is scaled, scaleKubernetesClusterIsolatedNetworkRules rebuilds the SSH rules on the source NAT IP: it revokes the firewall rule of the SSH port range (removeSshFirewallRule), removes the port forwarding rules in that range and calls setupKubernetesClusterIsolatedNetworkRules. That creates the range for the control and worker nodes that CKS deploys, 2222 to 2222+n-1 for n such nodes, and after it a single-port firewall rule and a port forwarding rule for each external node. The existing rules of the external nodes were not removed first:
Changes:
As a result the SSH port of an external node moves with the range on every scale, as the existing code intends, and its old port is closed.
Clusters without external nodes get the same rules as before. The VPC tier path is only affected by the order of the node VMs on scale-down: with external nodes, their port forwarding rules now get the ports after the other nodes, as on scale-up. Shared networks are not affected.
Fixes: #12633
#14673 describes the same problem and is a duplicate of #12633.
This targets 4.22, where the bug exists (#12633 is on the 4.22.3 milestone). The commit merges forward to main without conflicts.
Scaling with nodeids that include an external node, which is what the node list in the UI does (#12641), failed with the same error: the range stays the same, and the recreated rule of the external node conflicts with its existing rule. Scaling never removes external nodes (scaleDownKubernetesClusterSize filters them out), but the node count was still lowered by the number of nodeids. With the conflict fixed, such a request would succeed without removing anything, so scaleKubernetesCluster now rejects external nodes in nodeids up front (validateKubernetesClusterScaleNodesToRemove); they are removed with removeNodesFromKubernetesCluster. The UI still offers the delete action for external nodes in the node list, which now gets this error; changing the UI to use removeNodesFromKubernetesCluster there (#12641) is left for a separate change.
#14670 (open, against main) adds the same SSH firewall rules on VPC tiers whose VPC has the Firewall service and rebuilds them the same way on scale. Once this change is merged forward, I'll call the new method in that path as well.
Types of changes
Feature/Enhancement Scale or Bug Severity
Feature/Enhancement Scale
Bug Severity
Screenshots (if appropriate):
How Has This Been Tested?
New unit tests in KubernetesClusterScaleWorkerTest and KubernetesClusterManagerImplTest. Three of them run scaleKubernetesClusterIsolatedNetworkRules with the actual removeSshFirewallRule, removePortForwardingRules, addFirewallRulesForNodes and provisionSshPortForwardingRules. The rules are kept in lists; a new firewall rule that overlaps an existing one is rejected, which models what detectRulesConflict does for these rules.
Without the new call in scaleKubernetesClusterIsolatedNetworkRules, the two scale tests with external nodes fail with "Failed to provision firewall rules for SSH access": the new range 2222-2224 overlaps the old rule of an external node on 2224. When the scale-down passes the node VMs in VM map order, as before, it gives the external node port 2223 and the worker port 2224, while the single-port firewall rule on 2224 is the one created for the external node; the following scale-up then fails with the same error. If the external node rules are removed after removeSshFirewallRule instead of before, the scale-up test fails as well.
mvn -pl plugins/integrations/kubernetes-service -am test -Dtest='**/kubernetes/**/*Test' \ -Dsurefire.failIfNoSpecifiedTests=false -DfailIfNoTests=falseResult with this change on top of 4.22 (b56bbc2), JDK 11 / Maven 3.10: BUILD SUCCESS, 87 tests in the kubernetes-service module, 0 failures, 0 errors; checkstyle 0 violations. The commit also applies on top of main (1881dc6): 137 tests, 0 failures, 0 errors; checkstyle 0 violations.
Live, on 4.23.0.0 without this change (KVM, isolated network created by CKS, v1.35.4, 1 control node, 1 worker and an external node from the CKS-ready Ubuntu 22.04 template; the code paths involved are the same as on 4.22):
The patched build itself has not been deployed to a live management server.
How did you try to break this feature and the system with this change?