DNS — phân giải tên miền và những lỗi nhớ đời
Có một câu meme nội bộ trong giới DevOps: "It's always DNS." Nửa đùa nửa thật — DNS chiếm 30% sự cố production trong sự nghiệp mình. Service không gọi…
Phần 1 — Tại sao bài này quan trọng với DevOps?
Có một câu meme nội bộ trong giới DevOps: "It's always DNS." Nửa đùa nửa thật — DNS chiếm ~30% sự cố production trong sự nghiệp mình. Service không gọi được nhau? DNS. App chậm? DNS lookup chậm. Microservice mới deploy không được khách hàng truy cập? DNS chưa propagate.
Bài này dạy đủ để bạn:
- Đọc và sửa
/etc/resolv.conf,nsswitch.conf— file config DNS trên Linux. - Phân biệt resolver và authoritative server.
- Dùng
digthành thạo — debug DNS issue. - Hiểu DNS trong K8s (CoreDNS) — vì sao pod gọi service.namespace.svc.cluster.local.
Sau bài này, khi gặp Name or service not known, bạn không còn ngơ ngác.
Phần 2 — Bản chất
DNS giải quyết vấn đề: con người nhớ tên (google.com), máy tính dùng IP (142.250.x.x). DNS là "danh bạ" — bạn cho tên, nó trả IP.
Cấu trúc phân tầng từ phải sang trái:
www.example.com.
└────────────┴── root (.)
└───────── TLD (.com)
└──── domain (example)
└── subdomain (www)Quá trình resolve một domain:
Client
│ "IP của www.example.com là gì?"
↓
Resolver (DNS server gần nhất, ví dụ 8.8.8.8)
│ "Hỏi root: TLD .com server ở đâu?"
↓
Root server (a.root-servers.net, ...)
│ "TLD .com ở 192.5.6.30, ..."
↓
TLD server (.com)
│ "Authoritative cho example.com là ns.example.com (1.2.3.4)"
↓
Authoritative server (ns.example.com)
│ "www.example.com là 93.184.216.34"
↓
Trả về Resolver → cache → trả về ClientMỗi bước có TTL (Time-To-Live) — bao lâu thì cache hết hạn, phải hỏi lại.
Phần 3 — Đi sâu kỹ thuật
3.1 Các loại DNS record DevOps phải biết
| Record | Ý nghĩa | Ví dụ |
|---|---|---|
| A | Tên → IPv4 | example.com → 93.184.216.34 |
| AAAA | Tên → IPv6 | example.com → 2606:2800:... |
| CNAME | Alias (tên này = tên kia) | www → example.com |
| MX | Mail server | example.com mail → mail1.example.com |
| TXT | Text bất kỳ (SPF, DKIM, verification) | SPF record |
| SRV | Service location (host + port) | K8s, Active Directory |
| NS | Name server cho domain | example.com NS ns1.example.com |
| PTR | IP → tên (reverse DNS) | 34.216.184.93.in-addr.arpa → example.com |
DevOps đụng nhiều nhất: A, CNAME, TXT (TLS verification), SRV (K8s service discovery).
3.2 Resolver vs Authoritative
- Authoritative server: "Sở hữu" zone, trả lời câu hỏi cuối cùng. Ví dụ
ns1.example.comauthoritative choexample.com. - Resolver (recursive): thay mặt client đi hỏi từ root → TLD → authoritative, cache kết quả.
8.8.8.8,1.1.1.1, hoặc DNS server nội bộ của công ty.
Trong DC on-prem, thường có internal DNS (BIND, dnsmasq, hoặc Active Directory) phân giải cả tên nội bộ (db1.internal) và tên public (forward đến 8.8.8.8).
3.3 /etc/resolv.conf — file quyền lực
# /etc/resolv.conf
nameserver 192.168.1.1 # IP DNS server dùng
nameserver 8.8.8.8 # fallback
search internal.company # tự động thêm khi gõ tên ngắn
options timeout:2 attempts:3search rất quan trọng. Nếu có search internal.company và bạn gõ ping db1, Linux thử:
db1.internal.company(search domain trước)db1.(tên gốc)
Cấu hình sai search domain → cả lookup nội bộ và public bị chậm/lỗi.
Lưu ý Ubuntu modern: /etc/resolv.conf thường là symlink đến file của systemd-resolved. Đừng edit trực tiếp — dùng netplan hoặc disable systemd-resolved.
3.4 nsswitch.conf — thứ tự lookup
# /etc/nsswitch.conf
hosts: files dnsNghĩa là: tra /etc/hosts trước, không có thì tra DNS. Đó là vì sao bạn có thể "fake" DNS cho test bằng cách thêm vào /etc/hosts.
3.5 DNS trong K8s — CoreDNS
K8s có DNS server riêng (CoreDNS), service được resolve qua tên <service>.<namespace>.svc.<cluster-domain>. Ví dụ:
my-app.production.svc.cluster.localPod có /etc/resolv.conf được kubelet tự config:
nameserver 10.96.0.10 # IP của CoreDNS service
search production.svc.cluster.local svc.cluster.local cluster.local
options ndots:5ndots:5 nghĩa là: nếu tên có ít hơn 5 dấu chấm, thử search domain trước. Đây là nguyên nhân của một class bug nổi tiếng — sẽ thấy ở câu chuyện.
3.6 DNS cache
Cache có ở nhiều tầng:
- Browser cache (~1 phút).
- OS resolver cache (
systemd-resolved,nscd). - App cache (Java JVM cache forever nếu không config — bug nổi tiếng).
- Recursive resolver cache (theo TTL).
TTL nhỏ (60s) → propagate nhanh nhưng tải DNS server cao. TTL lớn (3600s) → propagate chậm, nhưng tải nhẹ.
3.7 dig — vũ khí debug DNS
# Query A record
dig example.com
# Query loại record cụ thể
dig MX example.com
dig TXT example.com
# Hỏi DNS server cụ thể (bypass /etc/resolv.conf)
dig @8.8.8.8 example.com
# Trace toàn bộ chain (root → TLD → authoritative)
dig +trace example.com
# Reverse lookup
dig -x 93.184.216.34dig show ra section ANSWER, AUTHORITY, ADDITIONAL — đọc được là debug được.
Phần 4 — Câu chuyện hiện trường
💡 Một lần ở production...
Tháng 11/2023, cluster K8s on-prem. Một service mới (let's call
payment-api) deploy vào namespaceproduction. Service expose qua ClusterIP. Service khác (order-api) cùng namespace gọipayment-apiqua tên ngắnpayment-api.Triệu chứng: lookup chậm. Thay vì <1ms, mỗi DNS query mất ~5 giây. Toàn bộ flow order-to-payment chậm.
SSH vào pod
order-api:cat /etc/resolv.confnameserver 10.96.0.10 search production.svc.cluster.local svc.cluster.local cluster.local options ndots:5Test:
time nslookup payment-api # → 5.012sBật tcpdump trên pod xem DNS query đi đâu:
sudo tcpdump -i any -n port 53Output: pod gửi 5 query DNS liên tiếp:
payment-api.production.svc.cluster.local → A record OK payment-api.production.svc.cluster.local → AAAA (IPv6) — CoreDNS cố lookup → fail timeout payment-api.svc.cluster.local → NXDOMAIN payment-api.cluster.local → NXDOMAIN payment-api. → NXDOMAIN (sau timeout)Lý do:
ndots:5+ glibc resolver mặc định query cả A và AAAA song song. Một số pod app dùng musl libc (Alpine image) query tuần tự → mỗi search domain mất 1s timeout.Fix: pod gọi service bằng FQDN tuyệt đối —
payment-api.production.svc.cluster.local.(chú ý dấu chấm cuối). Khi tên ≥ 5 dấu chấm hoặc kết thúc bằng., glibc skip search domain → 1 query duy nhất → <1ms.Để tránh phải sửa code, có thể đặt
ndots:1trong pod spec, hoặc dùng FQDN trong config.Bài học:
- K8s DNS chậm = thường do
ndots:5+ search domain × số record types.- Tcpdump trên pod là vũ khí — thấy được số query thật.
- Lookup tên ngắn trong K8s nên dùng FQDN tuyệt đối nếu service ở namespace cố định.
Phần 5 — Lab thực hành
Mục tiêu: Dùng dig thành thạo, hiểu DNS resolver chain, cấu hình DNS server riêng.
Bước 1 — Cài tool
sudo apt install -y dnsutils # đã cài từ Bài 01Bước 2 — Cơ bản với dig
# A record
dig example.com
# Đọc output:
# ;; ANSWER SECTION:
# example.com. 3600 IN A 93.184.216.34
# │ │ │ └── value
# │ │ └─ class (IN = Internet)
# │ └── TTL
# └── nameBước 3 — So sánh các DNS server
# Google DNS
dig @8.8.8.8 google.com +short
# Cloudflare
dig @1.1.1.1 google.com +short
# DNS server hiện tại (theo /etc/resolv.conf)
dig google.com +short
# Đo thời gian
dig @8.8.8.8 example.com | grep "Query time"Bước 4 — Query loại record khác
# MX (mail server)
dig MX gmail.com
# TXT (SPF, verification)
dig TXT google.com
# NS (authoritative server)
dig NS google.com
# Reverse DNS
dig -x 8.8.8.8Bước 5 — Trace toàn bộ resolution chain
dig +trace google.comOutput bắt đầu từ root (.), xuống TLD (com.), xuống authoritative (google.com). Đây là cách thấy "đường đi" của DNS lookup.
Bước 6 — Test /etc/hosts override
# Thêm fake entry
echo "1.2.3.4 fake-test.local" | sudo tee -a /etc/hosts
# Resolve
ping -c 1 fake-test.local
# → ping 1.2.3.4
# Cleanup
sudo sed -i '/fake-test.local/d' /etc/hosts/etc/hosts lookup trước DNS — hữu ích cho local testing.
Bước 7 — Setup dnsmasq đơn giản
Cài DNS server local cho lab:
sudo apt install -y dnsmasq
# Cấu hình
sudo tee /etc/dnsmasq.d/lab.conf <<EOF
# Forward query không match đến 8.8.8.8
server=8.8.8.8
# Custom record
address=/db1.lab.local/192.168.100.10
address=/app1.lab.local/192.168.100.20
EOF
sudo systemctl restart dnsmasq
# Test
dig @127.0.0.1 db1.lab.local
# → 192.168.100.10Bạn vừa setup DNS authoritative cho domain lab.local — y chang cách công ty setup internal DNS.
Self-check:
dig +tracecho thấy bao nhiêu hop từ root đến answer?- Vì sao
/etc/hostsđè được DNS? Cấu hình ở đâu? - Trong câu chuyện Phần 4, vì sao FQDN có dấu chấm cuối lại nhanh hơn?
Phần 6 — Best practices
DevOps phải có internal DNS server riêng. Mỗi machine
/etc/hosts→ không scale. dnsmasq, BIND, hoặc tích hợp với Active Directory.Set TTL hợp lý. Production stable: 300-3600s. Trước migration: hạ xuống 60s ~24h trước để propagate nhanh.
Monitor DNS resolver latency. Prometheus + node_exporter có metric. Latency tăng = vấn đề.
K8s pod gọi service: dùng FQDN tuyệt đối nếu service cross-namespace. Tránh
ndots:5waste.JVM app: set
networkaddress.cache.ttl. Mặc định Java cache DNS forever — service IP đổi thì app không cập nhật. Set60hoặc thấp hơn.
Phần 7 — Pitfalls
Edit
/etc/resolv.conftrực tiếp trên Ubuntu modern — bị systemd-resolved override. Phòng tránh: edit netplan hoặc/etc/systemd/resolved.conf.Cache DNS quá hung. App cache DNS forever (Java default), service IP đổi → app gọi sai IP. Phòng tránh: set TTL cache ngắn ở app.
Search domain gây slow lookup (như câu chuyện). Phòng tránh: FQDN hoặc
ndots:1.DNS server đơn lẻ. Một DNS server = single point of failure. Toàn corporate sập DNS = sập everything. Phòng tránh: ≥ 2 DNS server, có failover.
Reverse DNS không khớp. Một số service (mail server, SSH host verification) check PTR record — nếu PTR không khớp với forward, fail/slow. Phòng tránh: setup PTR cho mọi server quan trọng.
Phần 8 — Liên kết DevOps thực tế
- K8s CoreDNS: Bài này là tiền đề để hiểu CoreDNS config.
- Bài 17 (TLS): SAN trong cert phải khớp tên DNS — DNS sai = TLS error.
- Bài 18 (Load Balancing): DNS round-robin là kiểu LB cũ.
- Service Mesh (Istio, Linkerd): dùng DNS extensively cho service discovery.
- CDN, GeoDNS: DNS trả IP khác nhau theo location.
Phần 9 — Dùng AI
Prompt tốt:
Pod K8s base image Alpine, gọi service `redis.cache.svc.cluster.local`
chậm ~3s. Pod cùng cluster image Ubuntu thì <1ms. tcpdump cho thấy Alpine
pod gửi 4 query DNS, Ubuntu gửi 2 query song song. Nguyên nhân và fix?Cảnh báo: AI hay nhầm nscd (legacy) và systemd-resolved (modern). Hỏi rõ Ubuntu version.
Phần 10 — 3 điều khắc cốt
- DNS lookup đi qua chain: client → resolver → root → TLD → authoritative. TTL quyết định cache thời gian.
diglà vũ khí số 1./etc/resolv.confvànsswitch.conflà 2 file phải biết.- K8s
ndots:5+ search domain gây slow lookup. FQDN tuyệt đối hoặcndots:1là fix.
Phần 11 — Câu hỏi tự kiểm tra
- Kể 5 loại DNS record và ý nghĩa.
- Khác biệt giữa resolver (recursive) và authoritative server?
- Trong câu chuyện Phần 4, vì sao Alpine pod chậm hơn Ubuntu pod?
/etc/resolv.confcó dòngsearch company.local— gõping db1thực tế Linux query gì?- TTL DNS = 60s. Bạn vừa update A record. Sau bao lâu thì client trên thế giới biết IP mới?
- JVM app nhớ DNS forever — fix ở đâu, đặt giá trị bao nhiêu?
- Lệnh nào để query DNS server cụ thể, bypass
/etc/resolv.conf?
Bài tiếp theo: Bài 14 — DHCP — cấp IP tự động và pitfall thường gặp.