Network ACL entries are shared per tier but deleted per Service, taking other Services' ports down
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 45/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- go, kubernetes
- Ambito
- backend, cloud, networking
Direzione di ricerca
The issue is in the network ACL management logic of the cloud controller. Start by examining the updateNetworkACL and deleteNetworkACLRule functions, likely in a file like pkg/cloud/cloudstack/loadbalancer.go. Understand how ACL entries are currently matched and deleted. The fix involves adding CloudStack resource tags to track ownership, so review the CloudStack API client for tagging support on NetworkACL resources. 'Done' means each Service's ACL entry is uniquely owned and deleted without affecting others, and operator-created entries are preserved.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Summary
On a VPC tier the controller opens a port with a Network ACL entry matched only on protocol and
port. The entry is shared by every LoadBalancer Service on that tier, and by anything an operator
added by hand, but cleanup deletes it whenever any one Service stops using that port. The other
Services lose ingress on that port until their next reconcile recreates the entry.
Impact
- Two Services on one tier both exposing TCP/443 on their own public IPs share one ACL entry.
Deleting either Service, or moving it off port 443, removes the entry. Traffic to the other
Service on 443 is dropped until its next reconcile. - An entry created by an operator for the same protocol and port is adopted rather than
duplicated, then deleted on the same trigger. If the operator's entry had a restricted CIDR, the
controller recreates it as0.0.0.0/0on the next reconcile, silently widening exposure.
Firewall rules on isolated networks have the same ownership model but are scoped to the
Service's own public IP, so they only affect that Service.
Reproduction
- VPC tier with a custom ACL list attached (not
default_allow/default_deny). - Create Service A,
type: LoadBalancer, port 443. - Create Service B,
type: LoadBalancer, port 443.listNetworkACLsshows a single TCP/443
entry on the tier. - Delete Service A.
- The TCP/443 entry is gone. Service B does not answer on 443 until its next reconcile.
Cause
updateNetworkACL lists the tier's entries and skips creation if any entry matches the IP
protocol and port, so entries are shared and carry no marker of who created them.
deleteNetworkACLRule lists the same way and deletes the first match. It is called from:
EnsureLoadBalancerDeleted, for every rule of the Service being deleted;- the prune path in
EnsureLoadBalancer(pruneNetworkACLRule), for a rule the Service no
longer needs. Since #104 an entry the same Service still claims is kept and the delete is
scoped to the rule's own network, but nothing considers other Services.
This is the design the ACL path shipped with in #69 (July 2024). The cleanup loop it replaced in
#104 deleted the same way, so #104 narrowed the problem without fixing it. Raised by review on
#104: .
Proposed fix
Tag what the controller creates and delete only what it tagged. CloudStack resource tags support
NetworkACL, FirewallRule and PublicIpAddress.
- On create, tag the ACL entry (and firewall rule) with the owning Service, for example
cloudstack-ccm/service=<service UID>. - Stop sharing entries: create one entry per Service even when a matching one exists, so each
entry has exactly one owner. Verify CloudStack accepts same-protocol/port items in one ACL list;
if it does not, fall back to one tag key per Service on the shared entry and delete only when the
last key is removed. - On cleanup, delete only entries tagged with this Service. Untagged entries are left alone, which
also stops the controller from deleting or widening operator-created entries. - Existing untagged entries created by older controller versions need a one-time adoption rule,
for example tag on first match during reconcile.
A cheaper mitigation without tags is to list the tier's load balancer rules before deleting and
skip the delete if any other rule uses the same protocol and port. It closes the cross-Service
case but not the operator-created case, and it races with concurrent reconciles.
Related
The same tagging covers the public IP ownership gaps left over from #105: an IP whose rule was
deleted but whose release failed is never retried, and the pre-release check counts only load
balancer rules so an IP carrying port forwarding or static NAT can be released. Those can be
folded into this issue or filed separately.
- Lingua principale
- Go
- Stelle
- 52
- Fork
- 34
- Merge medio
- 6g 1h
- PR unite (30g)
- 3
Guida per i contributori
Nessuna guida per i contributori indicizzata per questo repository
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di apache/cloudstack-kubernetes-provider
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
apache/cloudstack-kubernetes-provider#75 · 2 commenti ·
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
apache/cloudstack-kubernetes-provider#73 · 2 commenti ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
apache/cloudstack-kubernetes-provider#52 · 4 commenti ·
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 20/100
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 25/100
Tutte le issue di apache/cloudstack-kubernetes-provider
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
prometheus/procfs#872 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
bazel-contrib/rules_go#4726 · 1 commento ·
-
area/auto-scaling area/monitoring area/ops-productivity kind/enhancement
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100