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
Debug transcript: service resolve được nhưng không connect
DNS đúng không có nghĩa traffic đi được. Mình thường tách DNS và TCP như sau:
kubectl -n app run dns-debug --rm -it --image=busybox:1.36 -- sh
nslookup api.app.svc.cluster.local
nc -vz api.app.svc.cluster.local 8080
wget -S -O- http://api.app.svc.cluster.local:8080/health
Nếu nslookup OK nhưng nc fail, kiểm tra Service và EndpointSlice:
kubectl -n app get svc api -o wide
kubectl -n app get endpointslice -l kubernetes.io/service-name=api
kubectl -n app describe networkpolicy
DNS chỉ trả lời “tên này là ai”. Nó không đảm bảo port đúng, pod ready, hay NetworkPolicy cho phép kết nối.
Điều cần giữ khi vận hành Kubernetes
- 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.