DNS Record Types That Matter
You need to set up DNS for a new microservice. The domain is
api.devopsbeast.com. Should you create an A record? A CNAME? Does it matter? Your colleague says "just use a CNAME, it's more flexible." Your load balancer vendor says "use an A record, CNAMEs don't work at the zone apex." Your email deliverability consultant says "add SPF and DKIM TXT records or your emails go to spam."DNS record types are not interchangeable. Each serves a specific purpose, and using the wrong one creates subtle bugs that are painful to debug. Let us walk through every record type that matters for DevOps work.
A Record: The Foundation
The A record maps a hostname to an IPv4 address. This is the most fundamental DNS record — it is the answer to the question "what IP address is this hostname?"
# Query an A record
dig devopsbeast.com A +short
# 104.21.45.67
# A record with full details
dig devopsbeast.com A +noall +answer
# devopsbeast.com. 300 IN A 104.21.45.67
You can have multiple A records for the same hostname. This is called round-robin DNS — the resolver returns all IPs, and the client picks one (usually the first). This provides basic load distribution but not true load balancing.
# Multiple A records for load distribution
dig google.com A +short
# 142.250.80.46
# 142.250.80.78
# 142.250.80.110
When to use A records:
- Pointing a domain to a specific server IP
- Zone apex (naked domain like
devopsbeast.com) — you cannot use CNAME here - When you need multiple IPs for the same hostname
A records point to IP addresses. If the IP changes (server migration, failover), you must update the A record. This is why many engineers prefer CNAME for services behind load balancers — the CNAME points to the load balancer hostname, and the load balancer handles IP changes internally.
AAAA Record: IPv6 Addresses
The AAAA record (pronounced "quad-A") is identical to an A record but maps to an IPv6 address instead of IPv4.
# Query AAAA record
dig devopsbeast.com AAAA +short
# 2606:4700:3034::6815:2d43
# Both A and AAAA
dig devopsbeast.com ANY +short
# 104.21.45.67 (A)
# 2606:4700:3034::6815:2d43 (AAAA)
Modern clients prefer IPv6 when available (Happy Eyeballs algorithm). If you have both A and AAAA records, IPv6-capable clients will connect via IPv6.
If your infrastructure does not support IPv6, do not add AAAA records. A client that receives both A and AAAA may try IPv6 first, experience a connection timeout (because your server does not actually listen on IPv6), and then fall back to IPv4 — adding unnecessary latency. Only publish AAAA records when your stack is fully IPv6-ready.
CNAME Record: Aliases
A CNAME (Canonical Name) record maps one hostname to another hostname. It is an alias. When a resolver encounters a CNAME, it follows the chain to find the final A/AAAA record.
# CNAME example
dig www.devopsbeast.com +noall +answer
# www.devopsbeast.com. 300 IN CNAME devopsbeast.com.
# devopsbeast.com. 300 IN A 104.21.45.67
# The resolver followed the chain:
# www.devopsbeast.com → CNAME → devopsbeast.com → A → 104.21.45.67
When to use CNAME:
- Pointing a subdomain to a load balancer hostname (e.g.,
api.devopsbeast.com → my-alb-1234.us-east-1.elb.amazonaws.com) - Creating aliases (
wwwpointing to the naked domain) - Pointing to SaaS services (
status.devopsbeast.com → statuspage.io)
The CNAME Restriction
This is the most important rule about CNAMEs, and violating it causes subtle, hard-to-debug issues:
A CNAME record cannot coexist with any other record at the same name.
If api.devopsbeast.com has a CNAME, you cannot also have an A record, MX record, TXT record, or any other record at api.devopsbeast.com. The CNAME must be the only record at that name.
# This is INVALID — CNAME and TXT at the same name
api.devopsbeast.com. CNAME my-alb.amazonaws.com.
api.devopsbeast.com. TXT "v=spf1 ..."
# Many DNS providers will let you create this but behavior is undefined
# This is VALID — CNAME is the only record
api.devopsbeast.com. CNAME my-alb.amazonaws.com.
The CNAME restriction means you cannot use a CNAME at the zone apex (naked domain). devopsbeast.com must have NS and SOA records (they are mandatory), so it cannot have a CNAME. This is why most DNS providers offer "ALIAS" or "ANAME" records — they work like CNAME at the apex but are resolved server-side before returning the answer. Cloudflare calls this "CNAME flattening."
A Record vs CNAME Record
A Record
Direct hostname to IP mapping
CNAME Record
Hostname to hostname alias
SRV Record: Service Discovery with Ports
SRV (Service) records provide service discovery. They return not just an IP but also a port number, priority, and weight. This enables client-side load balancing and failover.
The format: _service._protocol.name TTL IN SRV priority weight port target
# SRV record example
dig _http._tcp.devopsbeast.com SRV +short
# 10 60 8080 app1.devopsbeast.com.
# 10 40 8080 app2.devopsbeast.com.
# 20 100 8080 app3.devopsbeast.com.
# Fields: priority weight port target
# Priority 10 is preferred over priority 20
# Within priority 10: 60% traffic to app1, 40% to app2
# Priority 20 (app3) is only used if priority 10 targets are down
Where SRV records matter in Kubernetes:
Kubernetes creates SRV records for headless services (services with clusterIP: None). These allow clients to discover individual pod IPs and ports.
# Headless service in Kubernetes
kubectl exec debug-pod -- dig _http._tcp.my-headless-svc.default.svc.cluster.local SRV +short
# 0 33 8080 10-244-0-5.my-headless-svc.default.svc.cluster.local.
# 0 33 8080 10-244-1-8.my-headless-svc.default.svc.cluster.local.
# 0 33 8080 10-244-2-3.my-headless-svc.default.svc.cluster.local.
SRV records are how StatefulSet pods are individually addressable in Kubernetes. A StatefulSet with a headless service creates SRV records like my-pod-0.my-headless-svc.namespace.svc.cluster.local. This is essential for databases (PostgreSQL, MySQL) and distributed systems (Kafka, Elasticsearch) that need to address specific replicas.
TXT Record: The Swiss Army Knife
TXT records store arbitrary text strings. They were designed for human-readable notes but have become critical infrastructure for email authentication, domain verification, and certificate issuance.
# Query TXT records
dig devopsbeast.com TXT +short
# "v=spf1 include:_spf.google.com ~all"
# "google-site-verification=abc123..."
Common TXT record uses:
| Purpose | Record Name | Value Example |
|---|---|---|
| SPF (email auth) | devopsbeast.com | v=spf1 include:_spf.google.com ~all |
| DKIM (email signing) | selector._domainkey.devopsbeast.com | v=DKIM1; k=rsa; p=MIGfMA0... |
| DMARC (email policy) | _dmarc.devopsbeast.com | v=DMARC1; p=reject; rua=mailto:... |
| Domain verification | devopsbeast.com | google-site-verification=abc123 |
| ACME DNS-01 challenge | _acme-challenge.devopsbeast.com | gfj9Xq...Rg85nM (Let's Encrypt) |
If you manage infrastructure that sends email (alert notifications, CI/CD reports, user-facing transactional email), you must have SPF, DKIM, and DMARC records correctly configured. Without them, your emails go straight to spam. Use dmarcian.com or mxtoolbox.com to validate your email DNS configuration.
ACME DNS-01 Challenges
The DNS-01 challenge is how Let's Encrypt verifies you control a domain before issuing a wildcard certificate. It requires creating a TXT record at _acme-challenge.yourdomain.com with a specific value.
# cert-manager in Kubernetes automates this:
# 1. cert-manager requests a certificate from Let's Encrypt
# 2. Let's Encrypt returns a challenge token
# 3. cert-manager creates a TXT record via your DNS provider API
# 4. Let's Encrypt queries the TXT record to verify ownership
# 5. Certificate is issued
# Check if the challenge record exists
dig _acme-challenge.devopsbeast.com TXT +short
# "gfj9Xq...Rg85nM"
A team automated certificate renewal with cert-manager and Cloudflare DNS. It worked for months. Then one day, renewals started failing. The Cloudflare API token had expired after 90 days, and cert-manager could no longer create TXT records for DNS-01 challenges. Certificates expired silently. The site went down. Lesson: monitor certificate expiry dates (Prometheus has exporters for this) and set alerts at 14 days before expiry.
MX Record: Mail Routing
MX (Mail Exchange) records specify which mail servers accept email for a domain. They include a priority number — lower is preferred.
dig devopsbeast.com MX +short
# 1 aspmx.l.google.com.
# 5 alt1.aspmx.l.google.com.
# 10 alt2.aspmx.l.google.com.
# Priority 1 is tried first, then 5, then 10
MX records must point to A/AAAA records, never to CNAMEs. This is an RFC requirement (RFC 2181). While some mail servers tolerate MX records pointing to CNAMEs, it can cause delivery failures with strict implementations. Always point MX records directly to hostnames that have A records.
NS Record: Nameserver Delegation
NS (Nameserver) records delegate authority for a zone to specific nameservers. They tell the DNS hierarchy: "for this domain, ask these servers."
# Check nameservers for a domain
dig devopsbeast.com NS +short
# ns1.cloudflare.com.
# ns2.cloudflare.com.
# Check nameservers for a subdomain delegation
dig staging.devopsbeast.com NS +short
# ns-1234.awsdns-56.co.uk.
# ns-789.awsdns-01.net.
You can delegate subdomains to different DNS providers. For example, devopsbeast.com is on Cloudflare, but staging.devopsbeast.com is delegated to AWS Route 53. This is useful when different teams manage different environments.
SOA Record: Zone Authority
SOA (Start of Authority) records contain administrative information about a DNS zone. Every zone must have exactly one SOA record.
dig devopsbeast.com SOA +short
# ns1.cloudflare.com. dns.cloudflare.com. 2024010101 3600 600 604800 1800
# ^ ^ ^ ^ ^ ^ ^
# Primary NS Admin email Serial Refresh Retry Expire Minimum(neg TTL)
The minimum TTL field in the SOA record is the negative cache TTL — how long NXDOMAIN responses are cached. This is the number that bites you when you create a new record and people still get NXDOMAIN (as we discussed in the previous lesson).
PTR Record: Reverse DNS
PTR (Pointer) records map IP addresses back to hostnames — the reverse of an A record. They use a special domain: in-addr.arpa for IPv4.
# Reverse DNS lookup
dig -x 8.8.8.8 +short
# dns.google.
# This actually queries:
dig 8.8.8.in-addr.arpa. PTR +short
# dns.google.
PTR records are important for email deliverability (receiving mail servers check that the sending IP has a valid PTR record) and for debugging (tcpdump and netstat use reverse DNS to show hostnames).
In cloud environments, PTR records for your public IPs are managed by the cloud provider. In AWS, you can set reverse DNS for Elastic IPs through the console or API. If your outbound email is being rejected, check that your sending IP has a valid PTR record that matches your SPF and DKIM configuration.
CAA Record: Certificate Authority Authorization
CAA (Certificate Authority Authorization) records specify which CAs are allowed to issue certificates for your domain. This is a security measure to prevent unauthorized certificate issuance.
dig devopsbeast.com CAA +short
# 0 issue "letsencrypt.org"
# 0 issuewild "letsencrypt.org"
# 0 iodef "mailto:security@devopsbeast.com"
# issue: which CAs can issue regular certificates
# issuewild: which CAs can issue wildcard certificates
# iodef: where to report policy violations
If you set CAA records restricting certificate issuance to Let's Encrypt and then try to get a certificate from a different CA (like DigiCert or ZeroSSL), the issuance will fail. Before adding CAA records, inventory all certificate sources across your organization. Forgetting about a CDN or SaaS provider that issues certificates on your behalf is a common mistake.
DNS Records in Kubernetes
Kubernetes uses several DNS record types internally:
| K8s Resource | DNS Record Type | Example |
|---|---|---|
| ClusterIP Service | A | my-svc.ns.svc.cluster.local resolves to ClusterIP |
| Headless Service | A (multiple) | Returns all pod IPs directly |
| Headless Service | SRV | _port-name._protocol.my-svc.ns.svc.cluster.local |
| ExternalName Service | CNAME | ext-svc.ns.svc.cluster.local resolves to external hostname |
| StatefulSet Pod | A | pod-0.my-svc.ns.svc.cluster.local resolves to pod IP |
# ClusterIP service — returns a single ClusterIP
kubectl exec debug -- dig my-service.default.svc.cluster.local A +short
# 10.96.0.42
# Headless service — returns all pod IPs
kubectl exec debug -- dig my-headless.default.svc.cluster.local A +short
# 10.244.0.5
# 10.244.1.8
# 10.244.2.3
# ExternalName service — returns a CNAME
kubectl exec debug -- dig ext-service.default.svc.cluster.local +short
# external-api.provider.com.
# 203.0.113.50
DNS Records: External DNS vs Kubernetes DNS
External DNS Records
Managed by your DNS provider
Kubernetes DNS Records
Managed by CoreDNS automatically
Key Concepts Summary
- A records map hostnames to IPv4 addresses — the most fundamental record type
- AAAA records map hostnames to IPv6 addresses — only use if your stack supports IPv6
- CNAME records alias one hostname to another — cannot coexist with other records at the same name, and cannot be used at the zone apex
- SRV records provide service discovery with port, priority, and weight — used by Kubernetes headless services and StatefulSets
- TXT records store arbitrary text — critical for SPF, DKIM, DMARC (email auth), ACME challenges (certificates), and domain verification
- MX records route email — must point to A records, never CNAMEs
- NS records delegate authority to nameservers — used for subdomain delegation
- SOA records define zone authority and the negative cache TTL
- PTR records provide reverse DNS (IP to hostname) — important for email deliverability
- CAA records restrict which CAs can issue certificates for your domain
Common Mistakes
- Using CNAME at the zone apex (
devopsbeast.com) — this violates DNS standards and breaks NS/SOA record coexistence - Creating a CNAME alongside other records at the same name — undefined behavior that different resolvers handle differently
- Pointing MX records to CNAMEs instead of A records — causes mail delivery failures with strict mail servers
- Forgetting to add SPF, DKIM, and DMARC TXT records — your email goes to spam
- Setting CAA records without checking all certificate issuers — blocks legitimate certificate renewals
- Not understanding that Kubernetes ExternalName services create CNAME records — subject to the same CNAME restrictions
You want to point api.devopsbeast.com to an AWS Application Load Balancer (ALB). The ALB hostname is my-alb-1234.us-east-1.elb.amazonaws.com. You also need a TXT record at api.devopsbeast.com for domain verification. What record type should you use for the ALB?