อาการ
Service ใน namespace frontend พยายามเรียก service ใน backend:
$ kubectl exec -it -n frontend webapp -- curl http://api:8080
curl: (6) Could not resolve host: api
หรือ:
$ curl http://api:8080
curl: (28) Connection timed out
แต่ถ้าอยู่ namespace เดียวกัน — เรียกได้ปกติ
ความเข้าใจผิดอันดับ 1: Service Name ไม่ resolve ข้าม namespace
ใน K8s — service name ที่สั้น (api) จะ resolve เฉพาะ namespace ปัจจุบัน
ต้องใช้ FQDN ข้าม namespace:
<service>.<namespace>.svc.cluster.local
หรือสั้นๆ:
<service>.<namespace>
แก้:
# ❌ ไม่ทำงานข้าม namespace
curl http://api:8080
# ✅ ทำงาน
curl http://api.backend:8080
curl http://api.backend.svc.cluster.local:8080
ดู /etc/resolv.conf ใน Pod
kubectl exec -it -n frontend webapp -- cat /etc/resolv.conf
nameserver 10.96.0.10
search frontend.svc.cluster.local svc.cluster.local cluster.local
options ndots:5
อ่าน:
- search = list ของ suffix ที่ DNS ลองต่อท้าย
api→api.frontend.svc.cluster.local(ลองอันแรก)api→api.svc.cluster.local(ลองถัดไป)api→api.cluster.local
ดังนั้น api ใน namespace frontend resolve เป็น service api ใน frontend เท่านั้น
ใช้ FQDN — ขั้น search ถูก skip:
api.backend → api.backend.svc.cluster.local (เพราะเริ่ม resolve จาก root)
สาเหตุอื่นที่เป็นไปได้
1. NetworkPolicy block
ถ้ามี NetworkPolicy ใน backend ที่ default deny:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: backend
spec:
podSelector: {}
policyTypes: [Ingress]
→ traffic จาก frontend ถูก drop
ตรวจ:
kubectl get networkpolicy -n backend
kubectl describe networkpolicy -n backend
แก้: เพิ่ม policy อนุญาตจาก namespace frontend:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-from-frontend
namespace: backend
spec:
podSelector:
matchLabels:
app: api
policyTypes: [Ingress]
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: frontend
ports:
- protocol: TCP
port: 8080
หมายเหตุ: K8s 1.22+ มี label kubernetes.io/metadata.name ใน namespace อัตโนมัติ — version เก่ากว่าต้อง label เอง
2. Service ไม่มี endpoint
kubectl get endpoints api -n backend
ถ้า:
NAME ENDPOINTS
api <none>
→ ไม่มี pod ที่ match selector
kubectl get svc api -n backend -o yaml | grep -A 3 selector
kubectl get pods -n backend --show-labels
ตรวจ label ของ pod ตรงกับ selector มั้ย
3. CoreDNS ไม่ทำงาน
kubectl get pods -n kube-system -l k8s-app=kube-dns
kubectl logs -n kube-system -l k8s-app=kube-dns --tail=100
ถ้า CoreDNS down — ทุก DNS query ใน cluster พัง
ทดสอบ:
kubectl run -it --rm dns-test --image=busybox:1.36 \
--restart=Never -- nslookup kubernetes.default
ผลที่ดี:
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: kubernetes.default
Address: 10.96.0.1
4. Service Mesh policy (Istio / Linkerd)
ถ้า cluster ใช้ Istio — มี AuthorizationPolicy ที่อาจ block:
kubectl get authorizationpolicy -A
policy แบบ default deny:
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: deny-all
namespace: backend
spec:
{} # empty = deny all
แก้: เพิ่ม policy อนุญาต source
5. Egress NetworkPolicy ที่ frontend
นอกจาก ingress block ที่ destination — egress ของ source อาจ block ด้วย:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-egress
namespace: frontend
spec:
podSelector: {}
policyTypes: [Egress]
egress:
- to:
- podSelector: {} # อนุญาตเฉพาะใน namespace เดียวกัน
ตรวจ + แก้:
kubectl get networkpolicy -n frontend
6. CNI Plugin ไม่รองรับ NetworkPolicy
NetworkPolicy ที่เขียนไม่ทำงาน — เพราะ CNI ไม่ enforce policy
CNI ที่รองรับ:
- Calico ✓
- Cilium ✓
- Weave ✓
- Flannel ✗ (default mode ไม่ enforce)
ตรวจ:
kubectl get pods -n kube-system | grep -E "calico|cilium|weave|flannel"
ถ้าเป็น Flannel — policy ไม่ทำงาน ใช้ Calico chain mode หรือเปลี่ยน CNI
7. mTLS ที่ Service Mesh
Istio strict mTLS — pod ที่ไม่มี sidecar เรียก service ที่บังคับ mTLS ไม่ได้
kubectl get peerauthentication -A
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: backend
spec:
mtls:
mode: STRICT # ← ต้อง mTLS เท่านั้น
แก้: ให้ pod source มี sidecar (istio-injection: enabled) หรือลด mode เป็น PERMISSIVE
8. Resource Quota / LimitRange บล็อก pod ไม่ขึ้น
ไม่ใช่ network issue ตรงๆ — แต่ถ้า pod backend ไม่ start เพราะ ResourceQuota เต็ม:
kubectl get pods -n backend
# ถ้าเห็น Pending — ดู describe
kubectl describe pod <pod-name> -n backend
วิธี Debug ทีละขั้น
Step 1: DNS resolve ได้มั้ย
kubectl exec -it -n frontend webapp -- nslookup api.backend
ถ้าตอบ:
Name: api.backend.svc.cluster.local
Address: 10.96.x.x
→ DNS ok
ถ้าไม่ตอบ:
nslookup: can't resolve 'api.backend'
→ DNS ปัญหา — ดู CoreDNS
Step 2: Service มี endpoint มั้ย
kubectl get endpoints api -n backend
Step 3: TCP connect ได้มั้ย
kubectl exec -it -n frontend webapp -- nc -zv api.backend 8080
ถ้า:
succeeded→ network ผ่าน — ลอง HTTPConnection refused→ service มี endpoint แต่ pod ปฏิเสธtimeout→ NetworkPolicy block หรือ network issue
Step 4: HTTP ตอบมั้ย
kubectl exec -it -n frontend webapp -- curl -v http://api.backend:8080/
ถ้าตอบ — ปัญหาแก้แล้ว ถ้า timeout — กลับไปดู NetworkPolicy
Step 5: ใช้ debug pod
kubectl run -it --rm debug -n frontend \
--image=nicolaka/netshoot \
--restart=Never -- bash
# ใน debug pod
nslookup api.backend
curl -v http://api.backend:8080
mtr api.backend.svc.cluster.local
Tip: ใช้ External Service Pattern
ถ้า service ที่เรียกอยู่ใน namespace อื่นเสมอ — สร้าง alias:
# ใน frontend namespace
apiVersion: v1
kind: Service
metadata:
name: api
namespace: frontend
spec:
type: ExternalName
externalName: api.backend.svc.cluster.local
ทำให้ใน frontend เรียก api ได้เลย (ไม่ต้องเขียน FQDN)
ตรวจ NetworkPolicy ผ่าน tool
Cilium:
cilium connectivity test
Calico:
calicoctl get networkpolicy -A
calicoctl get globalnetworkpolicy
kubectl-trace หรือ netpol-analyzer — analyze policy effect
Cheat Sheet
# 1. ใช้ FQDN
http://service.namespace.svc.cluster.local
# 2. ดู resolv.conf
kubectl exec <pod> -- cat /etc/resolv.conf
# 3. ทดสอบ DNS
kubectl exec <pod> -- nslookup service.namespace
# 4. ทดสอบ TCP
kubectl exec <pod> -- nc -zv service.namespace 8080
# 5. ดู NetworkPolicy
kubectl get networkpolicy -A
# 6. ดู endpoint
kubectl get endpoints service -n namespace
# 7. ดู Service Mesh policy
kubectl get authorizationpolicy -A
kubectl get peerauthentication -A
สรุป
ลำดับสาเหตุที่เจอบ่อย:
- ใช้ short name แทน FQDN (50% ของกรณี)
- NetworkPolicy block (30%)
- CoreDNS / mesh policy (15%)
- Service / endpoint ไม่มี (5%)
แก้: ใช้ service.namespace หรือ FQDN เต็ม + ตรวจ NetworkPolicy ทั้ง ingress (destination) และ egress (source)
อ่านต่อ: