Skip to content

DNS Debugging: Resolution Path and TTL Issues

Tại sao DNS Debugging Quan Trọng

"Cannot resolve hostname" (Không thể phân giải tên miền) thường bị lầm tưởng là sự cố mạng (network issue), nhưng thực chất lại là vấn đề ở tầng ứng dụng (application layer). Quy trình phân giải tên miền (DNS resolution path) trên GCP có sự khác biệt so với các trung tâm dữ liệu truyền thống (traditional datacenter):

  • Compute Engine internal DNS (169.254.169.254)
  • Cloud DNS managed zones
  • Fallback tới external nameservers
  • Caching ở nhiều tầng khác nhau (multiple levels)

Hiểu rõ resolution path là điều bắt buộc vì các sự cố DNS rất khó debug — cơ chế caching che giấu nguyên nhân gốc rễ, TTL tạo ra độ trễ cập nhật, và việc fallback sang external DNS sẽ làm tăng latency.

Quy trình bên trong: DNS Resolution Path

Khi VM gửi một DNS query, resolver sẽ thực hiện theo tuần tự đường dẫn được sắp xếp sẵn (ordered path):

Bước 1: Kiểm tra Local Cache

Resolver của VM (như systemd-resolved, dnsmasq, v.v.) kiểm tra local cache:

$ nslookup app.myservice.local
Name: app.myservice.local
Address: 10.0.1.5  (lấy từ cache, dữ liệu mới)

Tuân thủ TTL: Thời gian cache được quyết định bởi giá trị TTL từ phản hồi DNS. Ví dụ, nếu response TTL=60s, thông tin trong cache sẽ có hiệu lực trong 60 giây.

Bước 2: Truy vấn Compute Engine Metadata Server (169.254.169.254)

Nếu không có trong local cache, VM sẽ gửi truy vấn tới resolver được tích hợp sẵn của Compute Engine (Compute Engine's built-in resolver):

Query: app.myservice.local
→ Destination: 169.254.169.254:53

Metadata server hoạt động như sau:

  1. Kiểm tra internal zone — Kiểm tra Cloud DNS private zones hoặc internal DNS.
  2. Kiểm tra Compute Engine DNS — Tự động tạo các record cho các instance.
  3. Nếu tìm thấy: Trả về kết quả, bao gồm cả TTL.
  4. Nếu không tìm thấy: Chuyển tiếp sang bước tiếp theo.

Internal Zones:

bash
# Tạo private zone
gcloud dns managed-zones create internal-zone \
  --zone-type=private \
  --networks=default

Bước 3: Cloud DNS Managed Zones

Nếu không thuộc internal zone, hệ thống kiểm tra Cloud DNS managed zones có thể truy cập từ VPC này:

bash
# Tạo public zone (truy cập được từ mọi nơi)
gcloud dns managed-zones create public-zone \
  --zone-type=public

# Tạo private zone (chỉ định riêng cho VPC)
gcloud dns managed-zones create private-zone \
  --zone-type=private \
  --networks=default,other-network  # Chỉ truy cập được trong các VPC này

Metadata server kiểm tra các zone theo thứ tự:

  1. Các private zone liên kết với VPC của VM.
  2. Các public zone.

Bước 4: Fallback sang External Nameservers

Nếu vẫn không thể phân giải, metadata server sẽ chuyển tiếp truy vấn tới các external nameservers (như 8.8.8.8, v.v.):

app.external.com
→ Không có trong internal/Cloud DNS
→ Chuyển tiếp tới 8.8.8.8 (public Google nameserver)
→ Public nameserver phân giải và trả về kết quả

Hệ quả: Các truy vấn đến tên miền bên ngoài sẽ làm tăng latency (do phải đi qua internet tới public DNS).

Bước 5: Không tìm thấy (Not Found)

Nếu tất cả các bước trên đều không phân giải được, hệ thống trả về lỗi NXDOMAIN (tên miền không tồn tại).

Sơ đồ Quy trình Phân giải đầy đủ (Resolution Path)

Query: example.com

1. Kiểm tra local cache
   ├─ HIT: Trả về kết quả trong cache (theo TTL)
   └─ MISS: Tiếp tục
2. Truy vấn metadata server (169.254.169.254)
   ├─ Khớp internal zone?
   │  ├─ HIT: Trả về kết quả + TTL
   │  └─ MISS: Tiếp tục
   ├─ Có record Compute Engine?
   │  ├─ HIT: Trả về kết quả
   │  └─ MISS: Tiếp tục
   └─ Có Cloud DNS zones?
      ├─ HIT: Trả về kết quả + TTL
      └─ MISS: Chuyển tiếp sang external
3. Chuyển tiếp tới external nameserver (8.8.8.8)
   ├─ HIT: Trả về kết quả + TTL
   └─ MISS: Trả về NXDOMAIN

Kết quả: Trả về Answer hoặc lỗi NXDOMAIN

TTL và Caching

TTL = Time To Live, được tính bằng giây. Cơ chế Caching xảy ra ở nhiều tầng khác nhau:

Tầng 1: OS-Level Resolver Cache

Các chương trình như systemd-resolved trên Linux, mDNSResponder trên macOS:

bash
# Xem thống kê cache (Linux)
systemd-resolve --statistics
# Hiển thị tỷ lệ hit cache, các thông tin trong cache

# Xóa cache
sudo systemctl restart systemd-resolved

# Hoặc dùng nscd:
sudo systemctl restart nscd

Đảm bảo tuân thủ TTL: Thông tin trong cache sẽ tồn tại trong đúng số giây quy định của TTL. Sau khi TTL hết hạn, truy vấn tiếp theo sẽ lấy dữ liệu mới.

Tầng 2: Application Library Caching

Các thư viện như java.net.InetAddress, curl có thể tự lưu cache DNS:

java
// Java lưu cache DNS mặc định trong 300 giây
java.security.Security.setProperty("networkaddress.cache.ttl", "60")

// urllib của Python cũng hỗ trợ lưu cache
import socket
socket.setdefaulttimeout(60)

Vấn đề: Cache của ứng dụng có thể ghi đè giá trị TTL. Nếu ứng dụng cấu hình cứng thời gian cache là 300s, thì DNS TTL 60s sẽ không được tuân thủ.

Tầng 3: GCP Metadata Server Caching

Compute Engine metadata server cũng lưu cache (chi tiết cơ chế nội bộ không được công bố công khai).

Hệ quả: Các thay đổi DNS sẽ có độ trễ cập nhật nhất định, cho đến khi TTL cũ hết hạn.

Các lỗi DNS thường gặp khi Debug

Trường hợp 1: Phân giải thành công nhưng kết nối thất bại

Triệu chứng:

$ nslookup app.myservice.local
Name: app.myservice.local
Address: 10.0.1.5

$ ping 10.0.1.5
PING 10.0.1.5 ...
64 bytes from 10.0.1.5: icmp_seq=1 ttl=64 time=1.234 ms

$ curl app.myservice.local:8080
Connection refused

Nguyên nhân gốc rễ: DNS hoạt động bình thường (phân giải đúng IP), nhưng:

  • Ứng dụng không lắng nghe (not listening) trên port đó.
  • Firewall đang chặn port đó.
  • Cấu hình sai thông số port.

Debug:

bash
# Kiểm tra xem ứng dụng có lắng nghe port không
gcloud compute ssh vm-instance
sudo netstat -tlnp | grep 8080
# Nếu trống, ứng dụng chưa được khởi chạy hoặc không lắng nghe port này

# Kiểm tra firewall
gcloud compute firewall-rules list --filter="allow-list:tcp:8080"

Trường hợp 2: Internal DNS không thể phân giải

Triệu chứng:

$ nslookup app.myservice.local
** server can't find app.myservice.local: SERVFAIL

$ nslookup google.com
Name: google.com
Address: 142.251.41.14  (external phân giải bình thường)

Nguyên nhân gốc rễ: Internal DNS zone cấu hình sai hoặc record không tồn tại.

Debug:

bash
# Liệt kê các zone
gcloud dns managed-zones list

# Liệt kê các record trong zone
gcloud dns record-sets list --zone=my-zone

# Kiểm tra xem private zone có thể truy cập được từ VPC của VM không
gcloud dns managed-zones describe my-zone
# Xem field: visibility (phải bao gồm VPC của VM)

# Test trực tiếp
gcloud compute ssh vm-instance
sudo dig app.myservice.local @169.254.169.254
# Sẽ phân giải được nếu zone cấu hình đúng

Cách sửa:

bash
# Tạo/Cập nhật record
gcloud dns record-sets update app.myservice.local \
  --zone=my-zone \
  --type=A \
  --ttl=300 \
  --rrdatas=10.0.1.5

# Hoặc tạo mới
gcloud dns record-sets create app.myservice.local \
  --zone=my-zone \
  --type=A \
  --ttl=300 \
  --rrdatas=10.0.1.5

Trường hợp 3: Lỗi phân giải chập chờn (Intermittent Resolution Failures)

Triệu chứng: Lúc phân giải được, lúc không. Không rõ quy luật.

Nguyên nhân gốc rễ: Thường do sự cố caching hoặc các record không nhất quán.

Nguyên nhân có thể:

  • Cache của ứng dụng bị lỗi thời (outdated).
  • TTL hết hạn giữa lúc kết nối.
  • Sử dụng Round-robin DNS trả về các IP khác nhau.
  • Cơ chế Failover chuyển đổi IP.

Debug:

bash
# Kiểm tra TTL cache của ứng dụng
# (Xem kỹ tài liệu hướng dẫn của ứng dụng)

# Kiểm tra xem có cấu hình round-robin hay không
gcloud dns record-sets list --zone=my-zone \
  --filter="name:app.myservice.local"
# Nếu có nhiều rrdatas, đó là cấu hình round-robin

# Xóa cache ứng dụng
# Khởi động lại ứng dụng hoặc invalidate cache

# Kích hoạt Cloud DNS query logging để theo dõi thêm:
gcloud dns logging create logging-config \
  --managed-zone=my-zone

# Truy vấn logs trong Cloud Logging

Trường hợp 4: Latency DNS cao

Triệu chứng:

$ time nslookup app.myservice.local
real    0m2.345s

Nguyên nhân gốc rễ: Các truy vấn bị chuyển tiếp (fallback) ra external nameserver.

Debug:

bash
# Kiểm tra xem internal zone đã được cấu hình chưa
gcloud dns managed-zones describe my-zone
# Nếu không phải private zone, hoặc không liên kết với VPC của VM, truy vấn sẽ ra ngoài internet

# Test latency từ VM
gcloud compute ssh vm-instance
time nslookup app.myservice.local
time nslookup google.com  # So sánh latency

Cách sửa: Đảm bảo cấu hình đúng internal zones:

bash
gcloud dns managed-zones create internal-zone \
  --zone-type=private \
  --networks=default \
  --dnssecstate=off

Trường hợp 5: Đổi Record DNS nhưng client vẫn nhận IP cũ

Triệu chứng:

# Cập nhật record
gcloud dns record-sets update app.local --zone=my-zone --rrdatas=10.0.2.5

# Nhưng client vẫn kết nối đến IP cũ
ping app.local → 10.0.1.5 (IP cũ)

Nguyên nhân gốc rễ: Bị lưu cache ở một trong các tầng:

  • OS resolver cache (TTL vẫn còn hiệu lực).
  • Cache của ứng dụng.
  • Cache phía client (trình duyệt, OS).

Debug và khắc phục:

bash
# Xóa cache của OS
sudo systemctl restart systemd-resolved

# Xóa cache ứng dụng
# Thường chỉ cần restart lại ứng dụng

# Xác thực record mới
nslookup app.local
# Phải hiển thị IP mới 10.0.2.5

# Chờ TTL cũ hết hạn trên toàn bộ hệ thống
# Giá trị TTL cũ quyết định thời gian chờ — nếu TTL cũ là 3600s, bạn phải chờ tối đa 1 tiếng

Cách phòng tránh:

  • Cấu hình TTL thấp (60s) đối với các record thường xuyên thay đổi IP.
  • Sử dụng TTL=300s mặc định (đây là mức cân bằng tốt).

DNS Query Logging

Kích hoạt Cloud DNS logging để giám sát hành vi phân giải tên miền:

bash
# Tạo cấu hình logging
gcloud dns logging create logging-config \
  --managed-zone=my-zone

# Xem logs trong Cloud Logging
# Logs hiển thị: query name, response code, latency, resolver

Cấu trúc Query Log:

json
{
  "timestamp": "2026-06-26T15:30:45Z",
  "queryName": "app.myservice.local",
  "queryType": "A",
  "responseCode": "NOERROR",  // hoặc NXDOMAIN, SERVFAIL, v.v.
  "queryLatencyMs": 2,
  "clientIp": "10.0.1.2",
  "protocol": "UDP"
}

Các trường hợp sử dụng:

  • Xác định các tên miền được truy vấn nhiều nhất.
  • Phát hiện các lỗi NXDOMAIN.
  • Đo lường latency phân giải tên miền.
  • Debug các mã response code.

DNS Response Codes

Các mã phản hồi phổ biến:

CodeMeaningAction
NOERRORPhân giải thành côngBình thường
NXDOMAINTên miền không tồn tạiKiểm tra lại cấu hình zone
SERVFAILLỗi DNS ServerKiểm tra lại hoạt động của nameserver
FORMERRTruy vấn sai định dạngLỗi client DNS
REFUSEDDNS Server từ chối phản hồiKiểm tra xem firewall có chặn DNS không
TIMEDOUTTruy vấn bị timeoutDo nghẽn mạng hoặc server bị down

Best Practices

1. Sử dụng Private Zones cho các Internal Services

bash
# TỐT: Sử dụng internal zone cấu hình riêng cho VPC
gcloud dns managed-zones create internal \
  --zone-type=private \
  --networks=prod-vpc

# XẤU: Dựa vào public DNS cho các dịch vụ nội bộ
# (làm tăng latency và rủi ro bảo mật)

2. Thiết lập cấu hình TTL hợp lý

bash
# Đặt TTL thấp (60s) cho các record thường xuyên đổi IP
gcloud dns record-sets update service.local \
  --zone=my-zone \
  --type=A \
  --ttl=60 \
  --rrdatas=10.0.1.5

# Đặt TTL cao (3600s) cho các record ổn định, ít thay đổi
gcloud dns record-sets update static.local \
  --zone=my-zone \
  --type=A \
  --ttl=3600 \
  --rrdatas=10.0.1.5

3. Kiểm tra Phân giải DNS từ VM

bash
# Từ phía VM
gcloud compute ssh vm-instance
nslookup -type=A app.myservice.local  # Thực hiện truy vấn DNS
dig +short app.local  # Sử dụng công cụ dig thay thế

# Chỉ định rõ nameserver để kiểm tra
nslookup app.local 169.254.169.254  # Trỏ trực tiếp server

4. Giám sát status hoạt động của DNS

bash
# Kiểm tra cấu hình zone
gcloud dns managed-zones describe my-zone

# Liệt kê các nameserver
gcloud dns managed-zones describe my-zone --format="value(nameServers)"

# Kiểm tra cập nhật của record
dig NS example.com @8.8.8.8

5. Sử dụng cơ chế Health-Check Driven TTL

Kết hợp health checks với DNS:

bash
# Các Cloud Load Balancer health check có thể kích hoạt cơ chế DNS failover
# (thông qua cơ chế health-check-driven routing của Cloud DNS nếu có cấu hình)

References