How to Migrate from Service ExternalIPs in Kubernetes v1.36+

By ✦ min read

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.

How to Migrate from Service ExternalIPs in Kubernetes v1.36+

What You Need

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:

Step 5: Migrate ExternalIPs to Manual LoadBalancer (Example)

If you choose the manual LoadBalancer route, here’s how to migrate a Service:

  1. Record the existing externalIPs value(s). For example, 192.0.2.4.
  2. Change the Service type from ClusterIP to LoadBalancer. Remove the externalIPs field.
  3. After the change, the Service will remain pending because there’s no actual load balancer. Now patch the status with 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

Tags:

Recommended

Discover More

Breaking: Man Pages for dig and tcpdump Get Major Update with Beginner-Friendly ExamplesHow to Shield Your Supply Chain from Cyber-Enabled Cargo TheftReMarkable Paper Pure: A $399 E Ink Tablet Designed for Distraction-Free WritingByteDance's Astra: A Dual-Model System Revolutionizing Autonomous Robot NavigationCoding at Warp Speed: New AI Guide Reveals Verification Is Now the Only Competitive Advantage