CKA — Service DNS

4 minute read

CKA Exam Domain

Domain Weight
Services & Networking 20%

DNS is how Pods discover and communicate with Services. Knowing the FQDN format and how to debug DNS issues is essential for the CKA exam.

Kubernetes DNS Overview

Every Kubernetes cluster runs a DNS server — CoreDNS — as Pods in the kube-system namespace. CoreDNS watches the Kubernetes API for new Services and automatically creates DNS records for them.

When a Pod makes a DNS query (e.g., curl web-svc), it gets routed to CoreDNS, which resolves the name to the Service’s ClusterIP.

# Check CoreDNS is running
kubectl get pods -n kube-system -l k8s-app=kube-dns

# View CoreDNS configuration
kubectl get configmap coredns -n kube-system -o yaml

Every Pod in the cluster is configured to use CoreDNS as its DNS resolver (check /etc/resolv.conf inside any Pod).

Service DNS Format

Every Service gets a DNS record in the following format:

<service-name>.<namespace>.svc.cluster.local
Component Description Example
<service-name> Name of the Service web-svc
<namespace> Namespace the Service lives in default
svc Indicates it’s a Service svc
cluster.local Default cluster domain cluster.local

Full example:

web-svc.default.svc.cluster.local

This resolves to the ClusterIP of the Service.

Same Namespace vs Cross-Namespace

When a Pod communicates with a Service, the DNS name you need depends on whether they’re in the same namespace.

Same namespace — just use the Service name:

curl web-svc
# Resolves to web-svc.default.svc.cluster.local (if Pod is in default namespace)

Cross-namespace — you need at least <service>.<namespace>:

curl web-svc.other-namespace
# Resolves to web-svc.other-namespace.svc.cluster.local

You can always use the full FQDN regardless:

curl web-svc.other-namespace.svc.cluster.local

CKA tip: If the exam asks you to call a Service in a different namespace, use <service>.<namespace> or the full FQDN.

Pod DNS Policies

Each Pod has a DNS policy that controls how DNS queries are resolved. You can set this in spec.dnsPolicy:

Policy Behavior
ClusterFirst (default) Queries go to CoreDNS first. If not resolved, forwarded to upstream DNS.
Default Inherits DNS config from the node where the Pod runs.
ClusterFirstWithHostNet Same as ClusterFirst, but for Pods using hostNetwork: true.
None No DNS config from Kubernetes. You must provide spec.dnsConfig.

For the CKA exam, ClusterFirst is the one you’ll almost always see. It ensures Pods can resolve Service names via CoreDNS.

apiVersion: v1
kind: Pod
metadata:
  name: custom-dns-pod
spec:
  dnsPolicy: "None"
  dnsConfig:
    nameservers:
      - 8.8.8.8
    searches:
      - custom.local
  containers:
    - name: app
      image: nginx

DNS Resolution Examples

Test DNS resolution from inside a Pod:

# From within a Pod — same namespace
nslookup web-svc
# Returns: web-svc.default.svc.cluster.local -> 10.96.0.100

# Full FQDN — same namespace
nslookup web-svc.default.svc.cluster.local
# Returns: 10.96.0.100

# Cross-namespace
nslookup web-svc.other-namespace.svc.cluster.local
# Returns: 10.96.0.200

# Kubernetes API service (always exists)
nslookup kubernetes.default.svc.cluster.local
# Returns: 10.96.0.1

Headless Service DNS

For a Headless Service (clusterIP: None), DNS behaves differently:

  • A DNS query for the Service name returns A records for each individual Pod instead of a single ClusterIP
  • Each Pod also gets its own DNS record if the Pod has a hostname and subdomain set (common with StatefulSets)
# Headless service DNS query
nslookup web-headless.default.svc.cluster.local

# Returns multiple A records:
# 10.244.1.5
# 10.244.2.8
# 10.244.3.3

For StatefulSets, each Pod gets a predictable DNS name:

<pod-name>.<service-name>.<namespace>.svc.cluster.local

Example:

mysql-0.mysql-headless.default.svc.cluster.local
mysql-1.mysql-headless.default.svc.cluster.local

Debugging DNS

DNS issues are a common troubleshooting scenario on the CKA exam. Here’s a reliable debugging workflow:

Step 1: Launch a debugging Pod with DNS tools:

kubectl run dnsutils --image=gcr.io/kubernetes-e2e-test-images/dnsutils:1.3 --command -- sleep 3600

Step 2: Test DNS resolution:

# Test the kubernetes service (should always work)
kubectl exec -it dnsutils -- nslookup kubernetes

# Test a specific service
kubectl exec -it dnsutils -- nslookup web-svc.default.svc.cluster.local

# Test cross-namespace resolution
kubectl exec -it dnsutils -- nslookup web-svc.other-namespace.svc.cluster.local

Step 3: Check CoreDNS health:

# Are CoreDNS Pods running?
kubectl get pods -n kube-system -l k8s-app=kube-dns

# Check CoreDNS logs
kubectl logs -n kube-system -l k8s-app=kube-dns

# Check if the kube-dns Service exists
kubectl get svc -n kube-system kube-dns

Step 4: Check Pod’s DNS config:

kubectl exec -it dnsutils -- cat /etc/resolv.conf
# Should show: nameserver 10.96.0.10 (kube-dns ClusterIP)

Practice Questions

Q1. What is the full DNS name for a Service named api-svc in the production namespace?

Show Answer
api-svc.production.svc.cluster.local

Q2. A Pod in the staging namespace needs to reach a Service named cache in the shared namespace. What DNS name should it use?

Show Answer
cache.shared

Or the full FQDN:

cache.shared.svc.cluster.local

The short name cache alone won’t work because the Pod is in a different namespace than the Service.

Q3. Create a temporary Pod to test DNS resolution of the kubernetes service.

Show Answer
kubectl run dns-test --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes

Expected output should show the ClusterIP of the kubernetes Service (typically 10.96.0.1).

Q4. What DNS policy should a Pod with hostNetwork: true use to resolve cluster Service names?

Show Answer

ClusterFirstWithHostNet

Pods using hostNetwork: true inherit the node’s DNS config by default. Setting dnsPolicy: ClusterFirstWithHostNet ensures they still use CoreDNS for cluster DNS resolution.

Q5. How does DNS resolution differ for a Headless Service compared to a regular ClusterIP Service?

Show Answer
  • ClusterIP Service: DNS returns a single A record pointing to the Service’s ClusterIP. kube-proxy handles load balancing to individual Pods.
  • Headless Service: DNS returns multiple A records — one for each Pod backing the Service. The client receives Pod IPs directly and can implement its own selection logic.

This makes Headless Services ideal for StatefulSets where each Pod needs to be individually addressable.

Updated: