Sau bài này bạn làm được: hiểu DNS naming convention trong K8s; debug “service không resolve” đúng chỗ; biết ndots ảnh hưởng performance thế nào.
Service discovery bằng DNS
Kubernetes chạy CoreDNS trong cluster (namespace kube-system). Mỗi Service tự động có DNS record:
<service-name>.<namespace>.svc.cluster.local
Ví dụ:
my-api.default.svc.cluster.local → ClusterIP 10.96.0.15
postgres.production.svc.cluster.local → ClusterIP 10.96.3.42
Pod gọi service cùng namespace → chỉ cần tên ngắn:
# Cùng namespace
curl http://my-api:80
# Khác namespace
curl http://my-api.staging:80
# FQDN đầy đủ (chậm nhất do skip search)
curl http://my-api.staging.svc.cluster.local:80
DNS records cho Service
ClusterIP Service
my-api.default.svc.cluster.local. → A record → 10.96.0.15
Headless Service (clusterIP: None)
my-db.default.svc.cluster.local. → A records → 10.244.0.5
10.244.1.3
10.244.2.7
Mỗi pod backend có record riêng. Client nhận danh sách IP, chọn pod.
StatefulSet + Headless Service
Mỗi pod có DNS name riêng:
my-db-0.my-db.default.svc.cluster.local → 10.244.0.5
my-db-1.my-db.default.svc.cluster.local → 10.244.1.3
my-db-2.my-db.default.svc.cluster.local → 10.244.2.7
SRV records
Service có port name → có SRV record:
_http._tcp.my-api.default.svc.cluster.local → SRV → port 80
resolv.conf trong Pod
Kubelet cấu hình DNS cho mỗi pod:
kubectl exec my-app -- cat /etc/resolv.conf
# nameserver 10.96.0.10 ← CoreDNS ClusterIP
# search default.svc.cluster.local svc.cluster.local cluster.local
# options ndots:5
Search domains
Khi bạn gọi my-api, resolver thử:
my-api.default.svc.cluster.local(search domain 1)my-api.svc.cluster.local(search domain 2)my-api.cluster.local(search domain 3)my-api.(absolute name)
Tên ngắn my-api resolve qua search domain đầu tiên → nhanh (1 query).
ndots:5 và hiệu ứng
ndots:5 nghĩa là: nếu tên có ít hơn 5 dấu chấm, thử search domains trước, rồi mới thử absolute.
Hậu quả: gọi api.example.com (2 dots < 5) → resolver thử:
api.example.com.default.svc.cluster.local(fail)api.example.com.svc.cluster.local(fail)api.example.com.cluster.local(fail)api.example.com.(thành công)
→ 4 DNS queries thay vì 1. Với external domain gọi nhiều → gấp 4 lần DNS traffic.
Giải pháp:
# Option 1: FQDN có dấu chấm cuối
# Trong code: gọi "api.example.com." (trailing dot) → skip search
# Hoặc thiết lập ở pod spec:
spec:
dnsConfig:
options:
- name: ndots
value: "2" # Giảm ndots cho pod gọi nhiều external
CoreDNS
Kiến trúc
CoreDNS chạy như Deployment trong kube-system, thường 2 replicas. Config qua ConfigMap coredns:
kubectl -n kube-system get cm coredns -o yaml
Corefile mặc định
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
kubernetesplugin: resolve service/pod names.forward: external domains forward tới upstream DNS (node’s resolv.conf).cache 30: cache DNS 30 giây.
Stub domain (custom DNS zone)
Nếu internal domain corp.example.com dùng DNS server riêng:
corp.example.com:53 {
errors
cache 30
forward . 10.0.0.53 # Corporate DNS server
}
Debug DNS trong Pod
Bước 1: Tạo debug pod
kubectl run dns-debug --image=busybox:1.36 --restart=Never -- sleep 3600
kubectl exec -it dns-debug -- sh
Bước 2: Kiểm tra resolve
# nslookup
nslookup my-api
nslookup my-api.default.svc.cluster.local
nslookup google.com
# Hoặc dùng image có dig
kubectl run dns-debug --image=tutum/dnsutils --restart=Never -- sleep 3600
kubectl exec -it dns-debug -- dig my-api.default.svc.cluster.local
Bước 3: Kiểm tra CoreDNS
# CoreDNS pods chạy?
kubectl -n kube-system get pods -l k8s-app=kube-dns
# CoreDNS logs
kubectl -n kube-system logs -l k8s-app=kube-dns
# CoreDNS Service (DNS ClusterIP)
kubectl -n kube-system get svc kube-dns
Lỗi thường gặp
| Triệu chứng | Nguyên nhân |
|---|---|
nslookup: can't resolve | CoreDNS pod crash, Service selector sai, hoặc service không tồn tại |
| Resolve chậm (> 5s) | ndots:5 + external domain → nhiều query. Giảm ndots hoặc dùng FQDN |
| Resolve OK nhưng connect fail | DNS đúng nhưng port/targetPort sai, hoặc NetworkPolicy chặn |
NXDOMAIN cho service cùng namespace | Namespace sai, hoặc tên service viết sai |
dnsPolicy
spec:
dnsPolicy: ClusterFirst # Mặc định: dùng CoreDNS cluster
# Các option khác:
# Default: dùng DNS của node
# ClusterFirstWithHostNet: ClusterFirst khi hostNetwork=true
# None: tự configure hoàn toàn qua dnsConfig
Tóm tắt
- Kubernetes DNS:
<svc>.<ns>.svc.cluster.local. Cùng namespace → tên ngắn. - CoreDNS chạy trong cluster, forward external domain ra upstream.
ndots:5gây nhiều query cho external domain → giảm ndots hoặc dùng FQDN trailing dot.- Debug:
nslookup/digtrong pod → check CoreDNS pod → check Service/Endpoints. - Headless Service → DNS trả pod IP trực tiếp. StatefulSet → mỗi pod có DNS name riêng.
Câu hỏi hay gặp
Tại sao dùng tên ngắn my-api mà resolve được?
Trả lời: /etc/resolv.conf trong pod có search default.svc.cluster.local svc.cluster.local cluster.local. Resolver tự append search domain vào tên ngắn. my-api → my-api.default.svc.cluster.local → resolve.
Pod ở namespace A gọi Service ở namespace B bằng cách nào?
Trả lời: Dùng <service-name>.<namespace>: my-api.production. DNS resolve qua search domain thành my-api.production.svc.cluster.local. Hoặc dùng FQDN đầy đủ.
DNS cache ảnh hưởng khi Service endpoint thay đổi?
Trả lời: CoreDNS cache mặc định 30s. Service thay đổi endpoint (pod mới) → client có thể giữ IP cũ tối đa 30s. Với headless Service, app nên re-resolve DNS thường xuyên (connection pool TTL < 30s). Xem thêm Mạng bài 04 — DNS thực dụng.
Bài tiếp theo (Giai đoạn III): Ingress, Gateway API và TLS — route HTTP traffic từ ngoài vào cluster.