How to Migrate from Service ExternalIPs in Kubernetes v1.36+
Introduction
Kubernetes v1.36 marks the formal deprecation of the .spec.externalIPs field for Services. This feature was originally designed to provide load-balancer-like functionality for non-cloud clusters, but it carries serious security risks—most notably those outlined in CVE-2020-8554, where any cluster user can hijack traffic by setting arbitrary external IPs. Since Kubernetes 1.21, the project has recommended disabling this field, and now v1.36 takes the next step: deprecation with plans to remove support entirely in a future release. This guide will walk you through the steps to migrate away from externalIPs, secure your cluster, and adopt safer alternatives.
What You Need
- A Kubernetes cluster running v1.36 or later (or an earlier version if you plan to upgrade).
- Cluster administrator access to modify admission controllers and RBAC settings.
- kubectl installed and configured to interact with your cluster.
- Basic familiarity with Kubernetes Services and YAML manifests.
- Optional: A tool like
jqto parse JSON output from kubectl.
Step 1: Audit Your Cluster for ExternalIP Usage
Before making any changes, identify which Services currently use the .spec.externalIPs field. Run the following command:
kubectl get services --all-namespaces -o json | jq '.items[] | select(.spec.externalIPs != null) | {namespace: .metadata.namespace, name: .metadata.name, externalIPs: .spec.externalIPs}'
This will list every Service that has externalIPs set. Make a note of these Services, as you will need to migrate them individually.
Step 2: Understand the Security Implications
The externalIPs field assumes all users are fully trusted. In a multi-tenant cluster or one with untrusted users, an attacker can set a Service’s externalIPs to any IP, potentially hijacking traffic meant for that IP. This is why the DenyServiceExternalIPs admission controller exists since v1.21. Even if you don’t currently use externalIPs, enabling this controller is a good proactive measure.
Step 3: Enable the DenyServiceExternalIPs Admission Controller
To block any future use of externalIPs, enable the admission controller. Edit your API server configuration (e.g., /etc/kubernetes/manifests/kube-apiserver.yaml in kubeadm) and add DenyServiceExternalIPs to the --enable-admission-plugins flag. For example:
--enable-admission-plugins=NodeRestriction,DenyServiceExternalIPs
Then restart the API server. Verify that new Service creations with externalIPs are now rejected:
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: test-external
spec:
externalIPs: ["1.2.3.4"]
ports:
- port: 80
EOF
You should see an error message like "externalIPs has been denied by admission".
Step 4: Evaluate Alternative Solutions
For each Service currently using externalIPs, choose an alternative. The simplest—but least secure—alternative is to switch to a type: LoadBalancer Service and assign the IP manually to the .status.loadBalancer.ingress field. However, this still relies on trust; the key difference is that RBAC can restrict who can modify .status fields. Better alternatives include:
- MetalLB for bare-metal load balancers.
- ExternalDNS to manage DNS records pointing to node IPs.
- NodePort or HostPort with careful IP management.
- Use a cloud load balancer (if available) to take advantage of native integration.
Step 5: Migrate ExternalIPs to Manual LoadBalancer (Example)
If you choose the manual LoadBalancer route, here’s how to migrate a Service:
- Record the existing
externalIPsvalue(s). For example,192.0.2.4. - Change the Service type from
ClusterIPtoLoadBalancer. Remove theexternalIPsfield. - After the change, the Service will remain pending because there’s no actual load balancer. Now patch the
statuswith the desired IP:
kubectl patch svc my-example-service -p '{"status":{"loadBalancer":{"ingress":[{"ip":"192.0.2.4"}]}}}' --type merge
Note: If RBAC prevents patching status, you may need elevated permissions. This manual assignment is not ideal for production but works as a temporary measure.
Step 6: Test the Migrated Services
After migrating, verify that traffic reaches the Service correctly. For a LoadBalancer Service with a manually assigned IP, you can use curl or kubectl port-forward to test. Ensure the Service responds on the intended IP and port. Also check that other network policies or firewalls are updated if needed.
Step 7: Plan for Future Removal
The Kubernetes project plans to remove the implementation of externalIPs from kube-proxy in a future minor release. After that, even if a Service has the field set, it will not work. The conformance criteria will also require that implementations do not support externalIPs. Therefore, it is critical to complete migration before the feature is removed entirely. Stay updated by watching the Kubernetes changelog and release notes.
Tips
- Do not delay: Even though v1.36 only deprecates
externalIPs, enable the admission controller now to prevent accidental future use. - Use RBAC to protect
statusupdates: If you switch to manual LoadBalancer, restrict who can patch Service statuses. By default, only cluster admins can do this. - Consider dedicated load balancer controllers: Tools like MetalLB, Cilium, or kube-vip offer robust, secure, and automated alternatives for bare-metal clusters.
- Audit existing tools: If you use automation or GitOps tools that set
externalIPs, update their configurations to use the new approach. - Monitor Kubernetes security announcements: The deprecation path may accelerate; subscribe to the kubernetes-announce mailing list.
- Test in a non-production environment first: Validate migration steps on a staging cluster before rolling out to production.
Related Articles
- How Zero-Day Supply Chain Attacks Are Redefining Cybersecurity Defenses
- BleepingComputer Retracts False Instructure Data Breach Report, Citing Outdated Information
- Securing Windows Access: Eliminating Static Credentials and VPN Over-Privilege with Boundary and Vault
- Session Timeouts and Disability: Why Authentication Design Must Be Inclusive
- Massive OAuth Token Harvesting Campaign by Russian GRU Hackers Exposed: 18,000 Routers Hijacked
- Safeguarding Your Organization from Modern Cyber Threats: A Step-by-Step Guide
- Canvas Halt Nationwide as Ransomware Defacement Paralyzes Schools During Finals
- Emergency Kernel Vulnerability Mitigation: The Killswitch Approach