← กลับ
KubernetesNetworkingTroubleshootingNamespace

Kubernetes Network วิ่งข้าม Namespace ไม่ได้ เกิดจากอะไร

service ใน namespace A เรียก service ใน namespace B ไม่ได้ — สาเหตุที่เป็นไปได้ตั้งแต่ DNS, NetworkPolicy, RBAC, mesh policy

2026-02-28อ่าน 6 นาทีใหม่

อาการ

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 ลองต่อท้าย
    • apiapi.frontend.svc.cluster.local (ลองอันแรก)
    • apiapi.svc.cluster.local (ลองถัดไป)
    • apiapi.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 ผ่าน — ลอง HTTP
  • Connection 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

สรุป

ลำดับสาเหตุที่เจอบ่อย:

  1. ใช้ short name แทน FQDN (50% ของกรณี)
  2. NetworkPolicy block (30%)
  3. CoreDNS / mesh policy (15%)
  4. Service / endpoint ไม่มี (5%)

แก้: ใช้ service.namespace หรือ FQDN เต็ม + ตรวจ NetworkPolicy ทั้ง ingress (destination) และ egress (source)

อ่านต่อ:

← ดูบทความอื่น