What does the cloud-controller-manager's service controller do with a Kubernetes type=LoadBalancer Service, and what role do the NodePorts underneath play?
answer
- finalizer before the cloud call
- Ensure, Update, EnsureDeleted
- status.loadBalancer.ingress
- node list, not pod list
- allocateLoadBalancerNodePorts defaults true
basics
~20 sThe service controller adds a cleanup finalizer, has the provider build a balancer for the eligible nodes, writes the address into status, and updates or deletes the balancer as things change. Classic balancers forward to each node's NodePort.
solid answer
~40 sThe service controller runs in the cloud-controller-manager. For each `type: LoadBalancer` Service without a `loadBalancerClass`, it: 1. adds the finalizer `service.kubernetes.io/load-balancer-cleanup` 2. calls the provider's `EnsureLoadBalancer` with the current eligible nodes 3. patches `status.loadBalancer.ingress` with the balancer's IP or hostname When nodes change it calls `UpdateLoadBalancer`. When the Service is deleted it calls `EnsureLoadBalancerDeleted` and only then removes the finalizer. In the classic model the balancer sends traffic to every node on the Service's **NodePort**, and kube-proxy forwards it to a pod. That is why a LoadBalancer Service gets NodePorts by default. `spec.allocateLoadBalancerNodePorts: false` turns off that automatic allocation for balancers that route straight to pod IPs.
code
yaml · 15 linesapiVersion: v1
kind: Service
metadata:
name: invoice-renderer
namespace: billing-invoices
spec:
type: LoadBalancer
selector:
app: invoice-renderer
ports:
- name: https
port: 443
targetPort: 8443
nodePort: 31742
allocateLoadBalancerNodePorts: truego deeper
Recall that a LoadBalancer Service builds on a NodePort, which builds on a ClusterIP, and that a controller in the cloud-controller-manager creates the balancer and writes its address.
Walk through the loop: finalizer, EnsureLoadBalancer with the eligible nodes, status patch, UpdateLoadBalancer on node changes, EnsureLoadBalancerDeleted before the finalizer is removed. Explain why the balancer targets NodePorts.
Discuss node exclusion on large clusters, what a stuck finalizer means, and when allocateLoadBalancerNodePorts false is safe, including that it does not free NodePorts that are already allocated.
Weigh node-targeting against pod-targeting balancers for a platform: backend-set size, NodePort range use, the extra hop, and how that choice shapes the defaults you give tenants.
## Where the service controller lives The **cloud-controller-manager (CCM)** is the control-plane binary that holds provider-specific logic. One of its controllers is the **service controller** (registered as `service-lb-controller`). It uses the cloud-provider interface's `LoadBalancer` methods: `GetLoadBalancer`, `EnsureLoadBalancer`, `UpdateLoadBalancer` and `EnsureLoadBalancerDeleted`. The provider supplies the code behind those methods. Kubernetes supplies the loop around them. ## The reconcile loop The controller only acts on a Service with `spec.type: LoadBalancer` and **no** `spec.loadBalancerClass`. For each such Service: 1. **Finalizer first.** It adds `service.kubernetes.io/load-balancer-cleanup` to `metadata.finalizers`, so the Service object cannot disappear while a cloud balancer still exists. 2. **Ensure.** It records an `EnsuringLoadBalancer` event and calls `EnsureLoadBalancer(ctx, clusterName, service, nodes)`. The provider reads the Service's ports, annotations and other fields and creates or reconciles the balancer. 3. **Publish.** It patches `status.loadBalancer.ingress` with the returned `ip` or `hostname` and records `EnsuredLoadBalancer`. That status is what `kubectl get svc` prints as EXTERNAL-IP. 4. **Track nodes.** When the eligible node set changes, it calls `UpdateLoadBalancer` for affected Services and records `UpdatedLoadBalancer`. 5. **Delete.** When the Service is deleted, or changed to a type other than LoadBalancer, it records `DeletingLoadBalancer`, calls `EnsureLoadBalancerDeleted`, and only then removes the finalizer. 6. **Fail loudly.** Any error becomes a Warning event, `SyncLoadBalancerFailed`, and the Service is retried with backoff. ## Which nodes become backends The controller passes the provider a filtered node list. A node is left out if it carries the label `node.kubernetes.io/exclude-from-external-load-balancers` set to true, or the `ToBeDeletedByClusterAutoscaler` taint. There are other filters too, and the controller also reacts when nodes are deleted. If nothing is left, it records `UnAvailableLoadBalancer`. On a 210-node multi-tenant platform cluster, that means the default backend set is potentially 210 targets for every balancer. The exclusion label is the in-tree lever for trimming it. ## The NodePort underneath In the classic, node-targeting model, the path for the PDF-invoice renderer looks like this: | Hop | Address | Who handles it | |---|---|---| | Client → balancer | balancer address, port 443 | cloud provider | | Balancer → node | `nodeIP:31742` (the Service's `nodePort`) | node's network stack | | Node → pod | `podIP:8443` (the `targetPort`) | kube-proxy's rules | - The balancer does not need to know about pods, which come and go. It only needs a stable list of nodes and one port. - kube-proxy on each node already translates the NodePort into a pod endpoint. - The source-IP and extra-hop consequences of this path belong to `externalTrafficPolicy`, which is a separate subject. Some balancers instead **target pod IPs directly**, when pods have addresses that can be routed from the balancer's network. For them the NodePort is unused, but it still takes up a port in the 30000-32767 range on every node. ## allocateLoadBalancerNodePorts - `spec.allocateLoadBalancerNodePorts` defaults to `true`, which gives today's behaviour. - Setting it to `false` tells the API server **not to auto-assign** `nodePort` values for this LoadBalancer Service. - A `nodePort` you set explicitly is still honoured. - The field is only valid on `type: LoadBalancer` and is cleared if the type changes. - Flipping it to `false` on an existing Service does **not** release ports that were already allocated. To free them, remove the `nodePort` values explicitly. - Only turn it off when you know your implementation does not use NodePorts (pod-IP-targeting balancers, or MetalLB, which draws traffic addressed to the balancer IP straight onto a node). ## ipMode in the status Each ingress entry can carry `ipMode`. `VIP` means traffic reaches the node still addressed to the balancer IP. `Proxy` means the balancer rewrites the destination. With `VIP`, kube-proxy also handles the balancer IP locally, so in-cluster callers using the external IP skip the balancer. With `Proxy`, kube-proxy leaves that traffic to go through the balancer, which keeps its TLS termination or PROXY-protocol behaviour. The field is GA since Kubernetes 1.32.
- What happens if you delete a Kubernetes LoadBalancer Service while the cloud-controller-manager is down?The API server sets the deletion timestamp, but the `service.kubernetes.io/load-balancer-cleanup` finalizer keeps the object in place. When the controller comes back, it calls `EnsureLoadBalancerDeleted`, then removes the finalizer, and the Service disappears. Without the finalizer, the Service would vanish and the cloud balancer would be orphaned, still billing. Removing the finalizer by hand causes exactly that leak.
- Why would you set allocateLoadBalancerNodePorts: false on a busy multi-tenant cluster?Every auto-allocated NodePort uses up one of roughly 2,768 ports in the default 30000-32767 range, is opened on every node, and widens the attack surface. If the balancer targets pod IPs or the implementation does not use NodePorts, those ports do nothing. Turning allocation off saves the range and closes unused listeners. Check the implementation first, or traffic stops.
saying these in an interview costs you the question
- The balancer is given the list of pod IPs by the service controller
- kube-proxy calls the cloud API when a Service changes
- Deleting the Service leaves the cloud balancer for manual cleanup
- allocateLoadBalancerNodePorts false also releases existing NodePorts
- A LoadBalancer Service has no ClusterIP or NodePort