Repository navigation
CKS: fix scaling a cluster with external nodes - #14683
Open
adestis-mf wants to merge 1 commit into
Open
adestis-mf wants to merge 1 commit into
adestis-mf wants to merge 1 commit into
Conversation
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
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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,
scaleKubernetesClusterIsolatedNetworkRulesrebuilds 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 callssetupKubernetesClusterIsolatedNetworkRules. 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:FirewallManagerImpl.detectRulesConflictrejects it, because the ports overlap and protocol and source CIDR (0.0.0.0/0) are the same, and the scale fails with "unable to update network rules", caused by "Failed to provision firewall rules for SSH access" (CKS: Scaling of Kubernetes Cluster fails if there is external worker node is added #12633). By then the SSH firewall rule and the SSH port forwarding rules of the other nodes are removed, and they are not recreated.Changes:
removeExternalNodeSshRulesruns before the rules are rebuilt. For each external node it revokes the port forwarding rules on the cluster's public IP from a port of the node SSH port range (2222 up to the SSH ports of the etcd nodes,cloud.kubernetes.etcd.node.start.port) to port 22, each together with the firewall rule for that port. The existing code then recreates them after the new range. The firewall rule is revoked first, so that if a revoke fails, a retry still finds it through the port forwarding rule. Both failures are reported asManagementServerException, which the scale worker already handles.getNodeVmIdsForSshRules). That is the order in whichaddFirewallRulesForNodesandprovisionSshPortForwardingRulesassign the SSH ports. Until now scale-down passed the VM map order. Once a scale-up has added a node after an external node, and a node before the external node in the VM map is then removed (bynodeids), that order put the external node before the remaining new node, and the port forwarding rules no longer matched the firewall rules. A later scale then failed on the same conflict.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 tomainwithout conflicts.Scaling with
nodeidsthat 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 (scaleDownKubernetesClusterSizefilters them out), but the node count was still lowered by the number ofnodeids. With the conflict fixed, such a request would succeed without removing anything, soscaleKubernetesClusternow rejects external nodes innodeidsup front (validateKubernetesClusterScaleNodesToRemove); they are removed withremoveNodesFromKubernetesCluster. The UI still offers the delete action for external nodes in the node list, which now gets this error; changing the UI to useremoveNodesFromKubernetesClusterthere (#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
KubernetesClusterScaleWorkerTestandKubernetesClusterManagerImplTest. Three of them runscaleKubernetesClusterIsolatedNetworkRuleswith the actualremoveSshFirewallRule,removePortForwardingRules,addFirewallRulesForNodesandprovisionSshPortForwardingRules. The rules are kept in lists; a new firewall rule that overlaps an existing one is rejected, which models whatdetectRulesConflictdoes for these rules.removeSshFirewallRulewould pick one of them if they were not removed first.getNodeVmIdsForSshRules: the external nodes come last, etcd nodes are left out.removeExternalNodeSshRulesrevokes an old SSH rule of an external node as well, and keeps its other rules: to another private port, from a port below 2222 or in the etcd range, and on another public IP.ManagementServerException, and a second call removes what is left. A firewall revoke that returns false is reported, and the port forwarding rule stays.KubernetesClusterManagerImplTest:validateKubernetesClusterScaleNodesToRemoveaccepts nodes deployed by CKS and rejects a list with an external node.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 afterremoveSshFirewallRuleinstead of before, the scale-up test fails as well.Result 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 ofmain(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):size=3failed with "unable to update network rules": the new range 2222-2224 conflicted with the rule of the external node on 2224. Afterwards only the rules of the external node and 6443 were left, and the cluster was back inRunning.Ready.nodeidsthen forwarded 2223 to the external node and 2224 to the new worker, and left the old rules of the external node on 2225. The next scale-up failed again:removeSshFirewallRulerevoked the old rule of the external node on 2225 instead of the range rule, and the new range conflicted with the old one.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?
KubernetesClusterRemoveWorkerfinds the SSH port of a node in a similar way. A rule that a user created with exactly this pattern for an external node is revoked too; one from a port outside that range, to another port or on another IP is kept.Scaling, and a retry finds the remaining rules.removeSshFirewallRuleis unchanged; kubernetes: prefer the node SSH rule when scaling a cluster with etcd nodes #14165 changes it, and this PR does not touch those lines.nodeidstoscaleKubernetesCluster, such as the delete action in the UI's node list, now gets an error. The request fails with "External nodes can not be removed by scaling a cluster, use removeNodesFromKubernetesCluster", before any change to the cluster. Before, the same request failed later on isolated networks, after the SSH port forwarding rules of the other nodes had been removed, or, on VPC tiers, lowered the node count without removing the node (both from reading the code). Requests with only nodes deployed by CKS are validated as before.scaleKubernetesClusterIsolatedNetworkRulesis nowprotectedfor the unit tests.