Skip to content

CKS: open the cluster public IP on VPC tiers when the VPC has the Firewall service - #14670

Open
adestis-mf wants to merge 1 commit into
apache:mainfrom
adestis-mf:cks-vpc-firewall-rules
Open

adestis-mf wants to merge 1 commit into
apache:mainfrom
adestis-mf:cks-vpc-firewall-rules

Conversation

@adestis-mf

Copy link
Copy Markdown

Description

This PR fixes CKS clusters on VPC tiers whose VPC uses the Firewall service for public IPs
(added in #12706). In such a VPC the VPC virtual router drops ingress traffic to a public IP
unless a firewall rule allows it. CKS only created network ACL items, port forwarding and the
API load balancer rule on VPC tiers. The management server could not reach the nodes (SSH 2222+,
API 6443), the control node could not reach its own API through the public IP
(controlPlaneEndpoint), and cluster creation failed after the start timeout.

When the VPC virtual router provides the Firewall service of the cluster's VPC, CKS now creates
the same ingress firewall rules as on isolated networks:

  • create: SSH range and 6443 on the cluster public IP (setupKubernetesClusterVpcTierRules),
    and the etcd SSH ports (setupKubernetesEtcdNetworkRules);
  • scale: the SSH firewall rule is replaced to match the new node count
    (scaleKubernetesClusterVpcTierRules), as for isolated networks;
  • add/remove node: the per-node SSH firewall rule is created and revoked
    (KubernetesClusterAddWorker, KubernetesClusterRemoveWorker).

In a VPC the firewall rules are created after the load balancing and port forwarding
rules. Applying firewall rules on a VPC public IP does not associate the IP with the VR
(IpAddressManagerImpl.applyRules skips it when the rule has no network). If the firewall rules
come first, the later LB/PF rules do not associate it either and the IP never reaches the VR
(#14669). On isolated networks the order stays as it was.

Firewall rules on VPC public IPs are stored with vpc_id and without network_id, so the
per-node lookup now goes by public IP and ports for VPC tiers
(findIngressFirewallRuleForPorts); isolated networks keep using findByNetworkIdAndPorts.
On cluster deletion the rules are revoked together with the release of the cluster public IP
(cleanupIpResources → revokeFirewallRulesForIp), so the destroy worker is unchanged.

The check (isVpcFirewallEnabled) is the one that sets vpc_firewall_enabled on the VR:
VpcServiceMapDao.canProviderSupportServiceInVpc(vpcId, Firewall, VPCVirtualRouter). VPCs
without the Firewall service, isolated networks and the NSX/Netris paths behave as before.

FirewallRulesDao is now injected once in KubernetesClusterActionWorker instead of separately
in three subclasses, so that the shared lookup can use it.

This targets main: the Firewall service for VPC public IPs is not in 4.22, and there is no
4.23 branch. The commit also applies cleanly on top of the 4.23.0.0 tag.

Fixes: #14668

Types of changes

  • Breaking change (fix or feature that would cause existing functionality to change)
  • New feature (non-breaking change which adds functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • Enhancement (improves an existing feature and functionality)
  • Cleanup (Code refactoring and cleanup, that may add test cases)
  • Build/CI
  • Test (unit or integration test code)

Feature/Enhancement Scale or Bug Severity

Feature/Enhancement Scale

  • Major
  • Minor

Bug Severity

  • BLOCKER
  • Critical
  • Major
  • Minor
  • Trivial

Screenshots (if appropriate):

How Has This Been Tested?

Unit tests (new): KubernetesClusterActionWorkerTest covers isVpcFirewallEnabled,
isPublicIpFirewallRequired and findIngressFirewallRuleForPorts for isolated networks and VPC
tiers with and without the Firewall service; KubernetesClusterResourceModifierActionWorkerTest
checks that setupKubernetesClusterVpcTierRules creates the firewall rules only when the VPC
firewall is enabled, and only after the LB and SSH port forwarding rules.

mvn -pl plugins/integrations/kubernetes-service -am test -Dtest='**/kubernetes/**/*Test' \
    -Dsurefire.failIfNoSpecifiedTests=false -DfailIfNoTests=false

Result on JDK 11 / Maven 3.10: BUILD SUCCESS, 141 tests in the kubernetes-service module,
0 failures, 0 errors; checkstyle 0 violations.

Live, on 4.23.0.0 (KVM) without the patch, adding by hand the firewall rules the patch creates
(same VPC with the Firewall service, same tier, v1.35.4, 1 control + 1 worker):

Run Firewall rules Result
1 none, then added after 30 min Error after 3600 s: first kubeadm init had failed, control node never recovers
2 within 7 s of the IP, before LB/PF Error: IP never configured on the VR (#14669)
3 about 10 s after CKS created LB and PF Running in under 3 min; scale-up to 2 workers Running

Deleting each cluster released the public IP and left no firewall rule behind. The patched
build itself was not deployed to a live management server.

How did you try to break this feature and the system with this change?

…ewall service

Since apache#12706 a VPC offering can provide the Firewall service for public
IPs. The VPC virtual router then drops ingress traffic to a public IP
that has no firewall rule. CKS only created network ACL items, port
forwarding and the API load balancer rule on VPC tiers, so the
management server could not reach the nodes (SSH 2222+, API 6443), the
control node could not reach its own API through the public IP, and
cluster creation failed after the start timeout.

When the VPC virtual router provides the Firewall service of the
cluster's VPC (the check that sets vpc_firewall_enabled on the VR), CKS
now creates the same ingress firewall rules as on isolated networks on
create (including etcd nodes), scale and node add/remove. In a VPC the
firewall rules are created after the load balancing and port forwarding
rules: applying firewall rules on a VPC public IP does not associate the
IP with the VR, and if they come first the IP is never associated.
Firewall rules on VPC public IPs have no network_id, so per-node rules
are looked up by public IP and ports. On delete the rules go with the
release of the cluster public IP.

Isolated networks, VPCs without the Firewall service and the NSX/Netris
paths are unchanged.
Copilot AI balanced review requested due to automatic review settings November 10, 2026 22:46
@boring-cyborg

boring-cyborg Bot commented Nov 10, 2026

Copy link
Copy Markdown

Congratulations on your first Pull Request and welcome to the Apache CloudStack community! If you have any issues or are unsure about any anything please check our Contribution Guide (https://github.com/apache/cloudstack/blob/main/CONTRIBUTING.md)
Here are some useful points:

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Scaling a firewall-enabled VPC cluster after importing a worker can fail because unreconciled per-node SSH rules conflict with the replacement port range.

1 open issue
What changed in this PR

This PR fixes CKS connectivity on VPC tiers whose virtual router provides the Firewall service, extending public-IP firewall handling across cluster lifecycle operations.

Changes:

  • Opens API and node SSH ports after load-balancing and port-forwarding rules establish VPC IP association.
  • Updates scaling and node add/remove paths, with shared firewall lookup by public IP for VPC tiers.
  • Adds tests for firewall-service detection, rule lookup, and provisioning order.
File Description
plugins/​integrations/​kubernetes-service/​src/​test/​java/​com/​cloud/​kubernetes/​cluster/​actionworkers/​KubernetesClusterResourceModifierActionWorkerTest.java Tests conditional VPC firewall creation and rule ordering.
plugins/​integrations/​kubernetes-service/​src/​test/​java/​com/​cloud/​kubernetes/​cluster/​actionworkers/​KubernetesClusterActionWorkerTest.java Tests firewall detection and network/public-IP lookups.
plugins/​integrations/​kubernetes-service/​src/​main/​java/​com/​cloud/​kubernetes/​cluster/​actionworkers/​KubernetesClusterStartWorker.java Opens etcd SSH ports after VPC port forwarding.
plugins/​integrations/​kubernetes-service/​src/​main/​java/​com/​cloud/​kubernetes/​cluster/​actionworkers/​KubernetesClusterScaleWorker.java Rebuilds VPC SSH firewall rules during scaling.
plugins/​integrations/​kubernetes-service/​src/​main/​java/​com/​cloud/​kubernetes/​cluster/​actionworkers/​KubernetesClusterResourceModifierActionWorker.java Adds API and SSH firewall rules during VPC setup.
plugins/​integrations/​kubernetes-service/​src/​main/​java/​com/​cloud/​kubernetes/​cluster/​actionworkers/​KubernetesClusterRemoveWorker.java Revokes per-node VPC firewall rules with missing-rule handling.
plugins/​integrations/​kubernetes-service/​src/​main/​java/​com/​cloud/​kubernetes/​cluster/​actionworkers/​KubernetesClusterAddWorker.java Creates and rolls back per-node VPC firewall rules.
plugins/​integrations/​kubernetes-service/​src/​main/​java/​com/​cloud/​kubernetes/​cluster/​actionworkers/​KubernetesClusterActionWorker.java Centralizes firewall DAO injection, detection, and lookup helpers.

Review effort: Balanced

}
if (vpcFirewallEnabled) {
// After the port forwarding rules, as when the cluster is created
addFirewallRulesForNodes(publicIp, clusterVMIds.size());

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, the scenario is valid: the imported node's single-port SSH rule overlaps the rebuilt
range, and detectRulesConflict rejects it (same protocol and source CIDR).

Reading the code, isolated networks on main behave the same way: the add-node path creates the
same per-node rule
(KubernetesClusterAddWorker.java#L229),
and the isolated scale path also revokes a single rule before recreating the range
(KubernetesClusterScaleWorker.java#L135-L149).
This PR mirrors that handling for VPC tiers, so the case is not new, it just becomes reachable on
VPC tiers with the Firewall service.

I'd prefer to keep this PR to the missing rules and fix the import-then-scale case for both
network types in #14673, since it also touches removeSshFirewallRule, which
#14165 is changing. If you'd rather have it here, I'll add it to this PR.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CKS: cluster on a VPC tier fails when the VPC has the Firewall service (#12706)

3 participants