The ExternalName service type in Kubernetes is a bit of a cheat code, letting you expose external services as if they were internal Kubernetes services without actually creating any network endpoints within your cluster.

Let’s see it in action. Imagine you have an external database service, say my-external-db.example.com, that your applications inside Kubernetes need to talk to. You don’t want to manage its lifecycle within Kubernetes, but you do want to refer to it by a consistent, internal DNS name, like external-db.internal.svc.cluster.local.

Here’s the Service definition:

apiVersion: v1
kind: Service
metadata:
  name: external-db
  namespace: internal
spec:
  type: ExternalName
  externalName: my-external-db.example.com

Now, any pod in the internal namespace (or any other namespace that can resolve external-db.internal.svc.cluster.local) can simply use external-db as the hostname. The Kubernetes DNS service, CoreDNS (or kube-dns), intercepts this query. Instead of returning an IP address for a cluster service, it returns a CNAME record pointing directly to my-external-db.example.com.

# From a pod in the 'internal' namespace
kubectl exec -it <your-pod-name> -- sh
/ # nslookup external-db
Server:         10.43.0.10
Address:        10.43.0.10#53

Name:   external-db.internal.svc.cluster.local
Address: my-external-db.example.com

This CNAME record is then resolved by the underlying DNS resolver on the pod, which will query the cluster’s upstream DNS servers (or directly the internet’s DNS) to find the actual IP address of my-external-db.example.com. Your application gets the IP and connects, none the wiser that it’s not a Kubernetes-managed service.

The primary problem ExternalName solves is simplifying service discovery for external dependencies. Instead of embedding fully qualified domain names (FQDNs) directly into application configurations, which can be brittle and hard to update, you provide a stable, internal Kubernetes service name. This decouples your applications from the specifics of the external service’s DNS, allowing you to change the external service’s FQDN (or its underlying IP addresses, managed by its own DNS) without touching your application deployments.

Internally, it’s a very simple mechanism. When CoreDNS sees a request for a service with type: ExternalName, it doesn’t look for Endpoints objects. It consults the Service definition, finds the externalName field, and constructs a CNAME record pointing to that value. This is handled entirely by the DNS layer; no network traffic is proxied or managed by Kubernetes itself.

The exact levers you control are the name of the service (how it’s referenced internally) and the externalName field (the actual target FQDN). The namespace is crucial for scoping its internal availability. You can create multiple ExternalName services pointing to different external resources, each with its own internal Kubernetes DNS name.

What most people don’t realize is that ExternalName services are resolved before any other service type. If you have a ClusterIP service and an ExternalName service with the same name in the same namespace, the DNS query will resolve to the ExternalName service first because the ExternalName service’s DNS entry is typically configured to be more specific (e.g., my-service.my-namespace.svc.cluster.local for a ClusterIP vs. my-service.my-namespace.svc.cluster.local for ExternalName). This is because the Kubernetes DNS system prioritizes the ExternalName type when a direct match is found in its service records.

The next step in managing external dependencies is often looking into how to secure these connections, which might involve network policies or secrets for authentication.

Want structured learning?

Take the full Kubernetes course →