Conversation
This was referenced Sep 29, 2026
A service changed from LoadBalancer to another type was skipped, so its Hetzner balancer kept running and its finalizer stayed. The API server clears loadBalancerClass with the type, so ownership is now decided by the finalizer: a service robotlb no longer serves has its balancer deleted and the finalizer removed, the same path a deleted service takes. The balancer to delete is found by the Hetzner ID robotlb now records on the service, since the name annotation may be gone by then. The ID is bound to the service UID, so a manifest exported and applied under another name cannot release the original's balancer. Without a recorded ID, or when no balancer has it, the balancer is looked up by name as before. A service with no TCP port that has a nodePort used to lose its external IP while the balancer behind it stayed. The balancer and the address are now kept, and the service gets a warning event instead, since a missing nodePort is more likely a mistake than a request to delete the balancer. Assisted-by: LLM Signed-off-by: Aleksei Sviridkin <f@lex.la>
lexfrei
force-pushed
the
fix/release-balancer
branch
from
September 29, 2026 15:15
76182d6 to
d6c6ee0
Compare
This was referenced Sep 29, 2026
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.
When a Service stops being a robotlb load balancer, its Hetzner balancer is now deleted and the finalizer removed. Until now such a Service was skipped, so the balancer stayed billed and the finalizer stayed.
The API server clears
loadBalancerClasstogether with the type, so robotlb decides ownership by its finalizer. A Service that carries it but is no longer a robotlbLoadBalancer, after a type change or a change back with another class, goes through the same release path as a deleted Service. The status is left alone, since the API server clears it on the type change.This adds a new annotation,
robotlb/balancer-id, which robotlb records after a successful reconcile as<uid>/<id>. Release deletes the balancer by that ID, because the name annotation may be removed in the same change as the type. The UID keeps a copied manifest from releasing the original's balancer. Without a recorded ID, or when Hetzner has no balancer with it, the balancer is looked up by name as before.A Service with no TCP port that has a node port now keeps its balancer and external IP and gets a warning event. Before, it lost the IP while the balancer stayed.
On upgrade, Services changed from
LoadBalancerbefore this release still carry the finalizer, and their balancer is deleted on the first start. The README has a command to list them. Such a Service has no recorded ID, so its balancer is found by name, and a same-named Service in another namespace may share it, see #41.This is stacked on #37 and targets its branch.
Closes #38