How to Convert a LoadBalancer Service Into a NodePort Service

Transforming Kubernetes Service YAML with ytt

Kubernetes Ingress Controllers often include LoadBalancer type Services as part of their default installation config. If your IaaS supports them, LoadBalancer services are super convenient since they’ll work with the IaaS to automatically provision a load balancer and external IP (and typically firewall rules) to make your service reachable to the world. Load balancers are seldom free, however, and for development clusters they’re often either unsupported or just plain overkill.

Fortunately, a LoadBalancer Service is basically just a NodePort Service and we can use ytt to programmatically convert one into the other.

Below is a ytt overlay that can be used for this purpose:

#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.subset({"kind": "Service", "spec":{"type":"LoadBalancer"}}),expects=1
---
spec:
  #@overlay/replace
  type: NodePort

This defines a ytt overlay that looks for YAML where on kind matches Service and spec.type matches LoadBalancer. It instructs ytt to replace the spec.type of a match with NodePort.

Imagine that the above overlay YAML is in a file verbosely named convert-loadbalancer-service-to-nodeport.yaml and that we have a LoadBalancer Service declared in a file called my-loadbalancer-service.yaml. We can use ytt to apply the overlay like this:

ytt -f my-loadbalancer-service.yaml -f convert-loadbalancer-service-to-nodeport.yaml

Why wouldn’t you just edit my-loadbalancer-service.yaml in a text editor to be a NodePort Service and be done with it? Well this way you can programmatically change Kubernetes config on the fly that you might not control. When those source YAML files are updated by their owners, you don’t have to recopy and update them yourself.

Below is a real world example where we use ytt to convert1 the LoadBalancer Service in the NGINX Ingress Controller’s deployment config and immediately kubectl apply it.

ytt -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.32.0/deploy/static/provider/cloud/deploy.yaml \
-f convert-loadbalancer-service-to-nodeport.yaml --ignore-unknown-comments=true \
| kubectl apply -f -

1 - The --ignore-unknown-comments=true flag is to keep ytt from complaining about the comments in the source YAML.