Sửa lỗi DNS Kubernetes: dial tcp lookup on 10.96.0.10:53 no such host

intermediate☸️ Kubernetes2026-04-01| Kubernetes (EKS, GKE, AKS hoặc Bare Metal), CoreDNS, Linux Nodes

Error Message

dial tcp: lookup <service-name> on 10.96.0.10:53: no such host
#kubernetes#dns#coredns#khắc phục sự cố

Tình huống lỗi

Vừa mới đây các microservices của bạn vẫn đang giao tiếp hoàn hảo; thì ngay sau đó, log đã tràn ngập các lỗi kết nối. Điều này thường xảy ra khi một Pod cố gắng truy cập vào một dịch vụ khác nhưng gặp vật cản. Thay vì một cái bắt tay (handshake) thành công, bạn sẽ thấy lỗi này:

dial tcp: lookup my-api-service on 10.96.0.10:53: no such host

Thông báo này cho chúng ta biết hai điều. Thứ nhất, Pod của bạn đang cố gắng sử dụng dịch vụ DNS của Kubernetes một cách chính xác (thường được gán cho địa chỉ 10.96.0.10). Thứ hai, máy chủ DNS đã không phản hồi hoặc không thể tìm thấy địa chỉ cho my-api-service.

Tại sao DNS thất bại trong Kubernetes

Trong các cụm (cluster) được xây dựng bằng kubeadm, 10.96.0.10 là ClusterIP tiêu chuẩn cho dịch vụ kube-dns. Khi việc tra cứu (lookup) thất bại, nguyên nhân gốc rễ thường xuất phát từ một trong bốn lĩnh vực sau:

  • Sự không ổn định của CoreDNS: Các Pod DNS đang bị crash, kẹt trong trạng thái CrashLoopBackOff, hoặc bị quá tải.
  • Phạm vi Namespace: Bạn đang cố gắng truy cập một dịch vụ ở namespace khác mà không sử dụng tên đầy đủ của nó.
  • Chặn bởi Network Policy: Một chính sách đang ngăn chặn Pod của bạn gửi lưu lượng truy cập đến namespace kube-system qua cổng 53.
  • Sai lệch cấu hình: Tệp resolv.conf bên trong container của bạn không trỏ đến đúng IP của dịch vụ DNS.

Cách khắc phục nhanh: Khởi động lại CoreDNS

Bắt đầu với những bước cơ bản. Nếu CoreDNS gặp phải một lỗi tạm thời hoặc rò rỉ bộ nhớ, một lệnh rollout restart nhanh chóng thường sẽ giải quyết được vấn đề. Trước tiên, hãy kiểm tra trạng thái các Pod DNS của bạn.

# Check if CoreDNS pods are running (you should see at least 2 for HA)
kubectl get pods -n kube-system -l k8s-app=kube-dns

# Trigger a fresh rollout
kubectl rollout restart deployment coredns -n kube-system

Phân tích và khắc phục sự cố chuyên sâu

1. Sử dụng Tên miền Đầy đủ (FQDN)

Việc phân giải DNS trong Kubernetes dựa trên một hệ thống phân cấp cụ thể: <service>.<namespace>.svc.cluster.local. Nếu ứng dụng của bạn nằm trong namespace-a và muốn giao tiếp với my-api trong namespace-b, một yêu cầu đơn giản tới http://my-api sẽ thất bại vì đường dẫn tìm kiếm cục bộ chỉ tra cứu bên trong namespace-a.

Cách khắc phục: Luôn sử dụng địa chỉ nội bộ đầy đủ cho lưu lượng truy cập giữa các namespace:

# Change this:
my-api-service

# To this:
my-api-service.target-namespace.svc.cluster.local

2. Gỡ lỗi bằng công cụ mạng chuyên dụng

Nếu bạn không chắc vấn đề nằm ở mã nguồn của mình hay ở cluster, hãy khởi tạo một Pod gỡ lỗi. Đặc biệt hãy sử dụng image busybox:1.28. Các phiên bản BusyBox mới hơn chứa một lỗi tìm kiếm DNS đã được xác nhận, có thể đưa ra kết quả sai lệch trong quá trình kiểm tra.

kubectl run dns-test --rm -it --image=busybox:1.28 -- /bin/sh

# Test internal cluster resolution
nslookup kubernetes.default

# Test your specific service
nslookup my-api-service.my-namespace.svc.cluster.local

Nếu nslookup kubernetes.default thất bại, có khả năng toàn bộ hệ thống DNS của bạn đã bị sập. Nếu nó hoạt động nhưng dịch vụ cụ thể của bạn thất bại, hãy kiểm tra các label và selector của Service.

3. Kiểm tra tệp resolv.conf của Pod

Mỗi Pod có một tệp /etc/resolv.conf quy định nơi gửi các truy vấn DNS. Nếu tệp này bị cấu hình sai, Pod sẽ không bao giờ tìm thấy máy chủ DNS. Chạy lệnh sau để xem cấu hình bên trong Pod:

kubectl exec <pod-name> -- cat /etc/resolv.conf

Một cấu hình chuẩn sẽ trông như thế này:

nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

Nếu IP của nameserver không khớp với IP của Service kube-dns (kiểm tra bằng lệnh kubectl get svc -n kube-system), thì cấu hình Kubelet của bạn đang không đồng bộ.

4. Kiểm tra các Network Policy gây hạn chế

Các cụm cluster được thắt chặt bảo mật thường sử dụng NetworkPolicies để hạn chế lưu lượng. Nếu bạn sử dụng Calico hoặc Cilium, hãy đảm bảo các Pod ứng dụng của bạn được phép gửi lưu lượng egress tới namespace kube-system qua Cổng 53 (UDP và TCP). Nếu không có quyền này, truy vấn DNS sẽ không bao giờ rời khỏi Pod.

# Example egress rule for DNS access
egress:
  - to:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: kube-system
    ports:
    - protocol: UDP
      port: 53
    - protocol: TCP
      port: 53

Phòng ngừa: Tránh xung đột CIDR

Một cái bẫy phổ biến khi thiết lập cluster là các dải IP bị chồng lấn. Nếu Service CIDR của bạn (ví dụ: 10.96.0.0/12) chồng lấn với VPN của công ty hoặc mạng trung tâm dữ liệu cục bộ, các gói tin DNS có thể bị định tuyến ra ngoài cluster thay vì đến CoreDNS. Tôi khuyên bạn nên sử dụng một IP Subnet Calculator trong giai đoạn lập kế hoạch để đảm bảo dải 10.96.0.0 của bạn hoàn toàn tách biệt với hạ tầng vật lý.

Xác minh cuối cùng

Sau khi bạn đã áp dụng bản sửa lỗi, hãy xác minh bằng cách truy vấn dịch vụ trực tiếp từ container ứng dụng. Bạn sẽ muốn thấy một ClusterIP hợp lệ được trả về trong phản hồi:

kubectl exec <pod-name> -- nslookup my-api-service

# Success looks like this:
Server:    10.96.0.10
Address:   10.96.0.10:53

Name:      my-api-service.default.svc.cluster.local
Address:   10.105.22.45

Ngay khi dòng Address đó xuất hiện, các lỗi dial tcp sẽ chấm dứt và các dịch vụ của bạn sẽ tiếp tục giao tiếp bình thường.

Related Error Notes