Summary
The issue arises when provisioning a Linode Load Balancer from a Kubernetes cluster that uses the Linode Cloud Controller Manager (LCCM) on a VPC‑only network. The controller requires node IPs to fall within the 192.168.x.x subnet range, which conflicts with user‑defined VPC subnets such as 10.0.0.0/16. The result is a 400 error telling that node IPs must start with 192.168, and subsequent attempts to force the controller into a VPC‑only context produce a “Nodebalancer is not allowed within a VPC” message. The core missing piece is that Linode Load Balancers cannot be created on custom VPC subnet ranges; they must use the private 192.168 subnet that the LCCM expects.
Root Cause
- Linode Load Balancer IP validation: LCCM enforces that backend node IPs begin with
192.168. - VPC subnet mismatch: User VPC (
10.0.0.0/16) does not satisfy this requirement. - Helm chart misconfiguration: Overriding VPC and subnet values in the chart does not alter the controller’s hardcoded IP validation.
- Documentation ambiguity: Official docs imply VPC support but exclude the fact that load balancers still require the
192.168namespace.
Why This Happens in Real Systems
- Legacy IP handling: Linode historically used
192.168internal addresses for nodebalancers; changing that requires a code change in the controller. - Mixed networking stacks: Many true‑cloud clusters (AWS, GCP) use custom ranges; this litmus test exposes the mismatch.
- Operational simplification: By restricting to
192.168, Linode simplifies backend configuration and security rules.
Real-World Impact
- Services cannot expose external traffic via a LoadBalancer in a VPC‑only setup.
- DevOps teams waste time troubleshooting API errors that are actually network‑policy violations.
- Production workloads become unavailable or rely on costly Workload‑load balancer alternatives.
Example or Code (if necessary and relevant)
apiVersion: v1
kind: Service
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/linode-loadbalancer-backend-ipv4-range: "10.0.1.8/30"
service.beta.kubernetes.io/linode-loadbalancer-backend-vpc-name: "k8s-vpc"
service.beta.kubernetes.io/linode-loadbalancer-backend-subnet-name: "k8s-nodes"
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8080
selector:
app: my-app
The above manifest triggers the 400 error because the IP range is not 192.168.
How Senior Engineers Fix It
- Revert to the default
192.168subnet: Create a new VPC/Subnet with192.168.0.0/16and deploy Linodes into it. - Use External Load Balancers: Offload to a cloud‑native load balancer (e.g., a NodePort exposed via a reverse proxy).
- Patch the Controller: Fork the LCCM source, adjust the IP validation logic, and deploy a custom build.
- Leverage Cilium’s load‑balancer feature: Replace Linode LB with Cilium‑in‑cluster LB, which is VPC‑agnostic.
- Document the limitation: Update internal runbooks to highlight the
192.168requirement.
Why Juniors Miss It
- Assuming full VPC support from Linode documentation leads to overlooking the
192.168constraint. - Misreading error messages: “Must begin with 192.168” is often mistaken as a generic validation error.
- Lack of troubleshooting depth: Junior engineers might triage only by changing annotations or Helm values without examining the controller’s validation logic.
- Ignoring version differences: Newer LCCM releases may still contain legacy checks that older docs hide.