In Kubernetes, how do a plain Pod's spec.hostname and spec.subdomain fields give it its own DNS name, and what else must exist?
answer
- two pod spec naming fields
- subdomain equals a Service name
- headless, same namespace, selector matches
- hostname copied onto the endpoint
- hostname.subdomain.namespace.svc.zone
basics
~20 sSet spec.hostname to a DNS label and spec.subdomain to the name of a headless Service in the same namespace that selects the pod. Once the pod is ready, cluster DNS answers <hostname>.<subdomain>.<namespace>.svc.<cluster-domain> with its IP.
solid answer
~40 s`spec.hostname` sets the pod's short hostname and `spec.subdomain` names a domain under it, so the pod's FQDN becomes `<hostname>.<subdomain>.<namespace>.svc.<cluster-domain>`. The fields alone publish nothing: the record appears only when a **headless Service** whose name equals the subdomain, in the same namespace, selects the pod. The EndpointSlice controller then copies the hostname onto the pod's endpoint, and cluster DNS serves the name once the pod is ready. If `hostname` is empty, no hostname is copied, so there is no such name to rely on. The name is stable, but the IP behind it changes whenever the pod is recreated. A StatefulSet sets both fields for you: hostname is the pod name, subdomain is `spec.serviceName`.
code
yaml · 26 linesapiVersion: v1
kind: Service
metadata:
name: rec-peers
namespace: ranking
spec:
clusterIP: None
selector:
app: rec-infer-dev
ports:
- name: grpc
port: 8471
---
apiVersion: v1
kind: Pod
metadata:
name: rec-infer-dev
namespace: ranking
labels:
app: rec-infer-dev
spec:
hostname: shard-a
subdomain: rec-peers
containers:
- name: server
image: registry.example.internal/rec-infer:2.14.3go deeper
Recall the two pod fields, the exact FQDN shape, and that a headless Service with the same name as the subdomain has to select the pod.
Explain that the EndpointSlice controller copies the hostname onto the endpoint only when hostname is set, the subdomain matches and the namespace matches, and that DNS reads it from there.
Point out that the name is stable while the IP is not, that readiness gates the record, and that client DNS caches can briefly point at a recreated pod's old address.
Weigh hand-set pod names against a StatefulSet: the fields give identity, but not recreation, ordering or storage, so plain pods with names suit tests rather than production members.
## What the two fields do A Kubernetes **Pod** carries two optional naming fields in its spec: - **`spec.hostname`** sets the pod's short hostname. It must be a valid DNS label (lowercase, at most 63 characters). If you leave it empty, the kubelet uses the pod's name as the hostname inside the container. - **`spec.subdomain`** names a subdomain. When it is set, the kubelet treats the pod's fully qualified name as `<hostname>.<subdomain>.<namespace>.svc.<cluster-domain>`. When it is empty, the pod has no domain name at all. Those two fields only describe a *name*. On their own they publish nothing to cluster DNS, because the kubelet does not talk to the DNS server. The record comes from somewhere else. ## The headless Service that makes the record real Cluster DNS builds its answers from **EndpointSlices**, the objects that list which pods back a Service. The EndpointSlice controller copies a pod's hostname into the endpoint it writes, but only when **all** of these hold: 1. `spec.hostname` is non-empty. 2. `spec.subdomain` equals the Service's name. 3. The pod and the Service are in the same namespace. On top of that, the Service has to **select** the pod through its label selector; otherwise the pod never appears in the Service's EndpointSlices. The Service should be **headless** (`clusterIP: None`): per-pod names are published for headless Services, because a headless Service's DNS answers are the pod addresses themselves rather than one virtual IP. ## Worked example on a laptop cluster Say you run a recommendation-model inference server as a single plain pod on a single-node development cluster on your laptop, and a second tool needs to reach *that* pod by a fixed name: ```yaml apiVersion: v1 kind: Service metadata: name: rec-peers namespace: ranking spec: clusterIP: None selector: app: rec-infer-dev ports: - name: grpc port: 8471 --- apiVersion: v1 kind: Pod metadata: name: rec-infer-dev namespace: ranking labels: app: rec-infer-dev spec: hostname: shard-a subdomain: rec-peers containers: - name: server image: registry.example.internal/rec-infer:2.14.3 ``` Once the pod is Ready, `shard-a.rec-peers.ranking.svc.cluster.local` (assuming the default `cluster.local` domain) resolves to the pod's IP. The pod loads a 4.2 GB model shard before its readiness probe passes, so the name does not resolve until that load finishes. ## When the name does not appear | Situation | Result | |---|---| | `subdomain` set, `hostname` empty | The endpoint carries no hostname, so there is no `<hostname>.<subdomain>` name to rely on | | Service selector does not match the pod's labels | The pod is not in the Service's EndpointSlices, so no record | | Service in another namespace | A Service only selects pods in its own namespace, so the pod is never its endpoint | | Pod not yet Ready | The endpoint is not ready, so DNS leaves it out, unless the Service sets `publishNotReadyAddresses` | | Pod has no IP yet | No endpoint is written at all | ## Stable name, not stable address The name is stable because it is built from fields *you* chose, not from the pod's IP. If you delete the pod and create it again with the same `hostname` and `subdomain`, the name comes back, now pointing at a **new IP**. Clients that cached the old answer can still hit the dead address for a while. A plain pod is also not recreated by any controller if it dies, which is why this pattern is mostly seen in small setups and tests. If two pods set the same hostname under the same Service, the EndpointSlice API treats those endpoints as interchangeable, and the name resolves to both addresses. ## The same mechanism inside StatefulSets A **StatefulSet** uses exactly these two fields. When its controller creates a pod, it sets `hostname` to the pod name (for example `rec-infer-0`) and `subdomain` to the StatefulSet's `spec.serviceName`. That is where a StatefulSet replica's per-pod name comes from. The Service named there is one you create yourself, and it must be headless and select the pods. ## What the container itself sees - The kubelet writes an `/etc/hosts` entry mapping the pod IP to both the FQDN and the short hostname, so the pod can resolve its own full name even without DNS. - **`spec.setHostnameAsFQDN: true`** makes the kernel hostname inside a Linux container the full FQDN instead of the short name. The kubelet refuses to build a sandbox if that FQDN is longer than 64 characters, so an over-long name leaves the pod stuck in creation.
- How does a StatefulSet reuse this mechanism for its replicas?When the StatefulSet controller creates a pod, it sets `hostname` to the pod name, such as `rec-infer-0`, and `subdomain` to the set's `spec.serviceName`. The replica is therefore reachable as `rec-infer-0.<serviceName>.<namespace>.svc.<cluster-domain>`. The Service named there is not created for you: it must exist, be headless and select the pods, or the per-pod names never appear.
- Two plain pods set the same hostname and subdomain under one headless Service. What does the name resolve to?The EndpointSlice API treats endpoints that share a hostname as interchangeable, so the name resolves to both pod addresses, like several A records for one name. You lose the one-name-one-pod property, which is usually the reason you set a hostname at all. Nothing in the API rejects the duplicate, so keep hostnames unique per Service yourself.
It is like writing a room number on your own door: nobody can find you by it until the building directory, which is the headless Service, lists that room under your name.
saying these in an interview costs you the question
- Setting spec.subdomain alone creates the DNS record, no Service needed
- The kubelet registers the pod's name directly with the cluster DNS server
- A stable DNS name means the pod keeps the same IP address
- The per-pod record exists as soon as the pod is scheduled
- A normal ClusterIP Service named in subdomain gives the same per-pod records