K8s · 網路與服務 · 第 19 課 · · 8min read

K8s DNS 與 Namespace:用名字找服務,跨 Namespace 怎麼連?

叢集內不用記 IP,直接用名字 mysql-svc 連得到。換個 namespace 就要寫 mysql-svc.production。這篇用 nslookup 看 K8s 內部 DNS 怎麼運作。

#Kubernetes #DNS #Namespace #CoreDNS
章節目錄 · 11

為什麼要學 DNS?

Service 篇我們說「程式裡寫 mysql-svc:3306 就能連到 MySQL」,但到底是誰在做這件事? mysql-svc 又不是 IP,K8s 怎麼解析的?

答案是 CoreDNS — K8s 內建的 DNS 服務。

這篇要回答兩個問題:

  • 為什麼用名字而不是 IP?

  • 跨 namespace 連線怎麼寫?
  • 為什麼不直接用 ClusterIP 的 IP?

    技術上沒人擋你。kubectl get svc 看到 IP 是 10.43.0.150,你寫死在程式裡也能跑。

    • ClusterIP 雖然比 Pod IP 穩,Service 重建後會變(你刪一次 mysql-svc 重建,新 IP 就變了)
    • 一個叢集裡 30 個微服務 = 30 個 ClusterIP,沒人記得起來
    • 換 namespace、換叢集、跨環境部署,IP 全變
    就像手機通訊錄。你不會背朋友的手機號碼,你存名字。

    K8s 的「通訊錄」就是 CoreDNS

    CoreDNS 是什麼?

    K8s 叢集裡內建的 DNS 服務,跑在 kube-system namespace。

    $ kubectl get pods -n kube-system | grep coredns
    coredns-77ccd57875-abc12   1/1     Running

    它做的事很單純:

    每建一個 Service,CoreDNS 自動註冊一筆 DNS 記錄。

    你建一個叫 nginx-svc 的 Service → CoreDNS 記住「nginx-svc 對應 10.43.0.150」。任何 Pod 查 nginx-svc,CoreDNS 就回那個 IP。

    Pod 怎麼知道要找 CoreDNS? K8s 在每個 Pod 啟動時自動寫好 /etc/resolv.conf

    $ kubectl exec -it <pod> -- cat /etc/resolv.conf
    search default.svc.cluster.local svc.cluster.local cluster.local
    nameserver 10.43.0.10    # ← CoreDNS 的 ClusterIP

    你完全不用設定,curl / wget / nslookup 都會自動走 CoreDNS。

    DNS 名字的三種寫法

    寫法什麼時候用
    nginx-svc同一個 namespace 內(最常用
    nginx-svc.dev跨 namespace
    nginx-svc.dev.svc.cluster.local完整 FQDN
    完整格式拆解:
    nginx-svc . dev . svc . cluster.local
       ↑       ↑    ↑      ↑
     Service  ns  固定   叢集網域

    /etc/resolv.conf 裡的 search 設定會幫你補後綴。所以同 namespace 用短名,K8s 自動補上 .default.svc.cluster.local;跨 namespace 至少要寫到 namespace。

    Namespace 是什麼?

    Namespace = 叢集裡的「資料夾」,用來分類 / 隔離資源。

    最常見用途:隔離環境

    ┌──── default ────┐    ┌──── dev ────┐    ┌──── prod ────┐
    │ nginx-svc       │    │ nginx-svc   │    │ nginx-svc    │
    │ (你的測試)       │    │ (1.26)      │    │ (1.27)       │
    └────────────────┘    └─────────────┘    └──────────────┘

    三個 namespace 都有 nginx-svc互不衝突。如果都擠在 default,K8s 會擋你 — 同 namespace 不允許同名 Service。

    K8s 預設四個 namespace:

    Namespace用途
    default你沒指定就在這
    kube-systemK8s 系統元件(CoreDNS、kube-proxy)
    kube-public公開資源(很少用)
    kube-node-lease節點心跳(不用管)
    ⚠️ 注意:Namespace 是邏輯隔離不是網路隔離。default 的 Pod 預設可以用 nginx-svc.dev.svc.cluster.local 連到 dev 的服務。要做網路隔離得用 NetworkPolicy

    用 nslookup 看穿 CoreDNS

    開一個臨時 busybox Pod 來查:

    $ kubectl run dns-test --image=busybox:1.36 --rm -it --restart=Never -- sh
    

    / # nslookup nginx-svc
    Server: 10.43.0.10
    Address: 10.43.0.10:53

    Name: nginx-svc.default.svc.cluster.local
    Address: 10.43.0.150

    兩個重點:

    • Server: 10.43.0.10 → 那是 CoreDNS 的 ClusterIP
    • 你問 nginx-svc,CoreDNS 回的是完整 FQDN nginx-svc.default.svc.cluster.local 對應 10.43.0.150
    直接 wget 試試:

    / # wget -qO- http://nginx-svc
    <h1>Welcome to nginx!</h1>
    

    # 完整 FQDN 也行
    / # wget -qO- http://nginx-svc.default.svc.cluster.local
    <h1>Welcome to nginx!</h1>

    兩個寫法指向同一個 Service。

    跨 Namespace 實作

    # 1. 建 dev namespace
    $ kubectl create namespace dev
    

    # 2. 在 dev 部署 nginx
    $ kubectl create deployment nginx-dev --image=nginx:1.27 -n dev
    $ kubectl expose deployment nginx-dev --port=80 -n dev

    # 3. 從 default 跨 namespace 連線
    $ kubectl run cross-test --image=busybox:1.36 --rm -it --restart=Never \
    -- wget -qO- http://nginx-dev.dev.svc.cluster.local
    <h1>Welcome to nginx!</h1>

    關鍵:busybox 在 default,要連 dev 的服務,必須帶上 namespacenginx-dev.dev(或完整 FQDN)。

    kubectl 操作 Namespace

    # 看所有 namespace
    $ kubectl get namespaces
    

    # 看特定 namespace 的所有資源
    $ kubectl get all -n dev

    # 看所有 namespace 的 Pod
    $ kubectl get pods -A

    常見坑:跑 kubectl 忘記加 -n dev,資源全跑到 default 去。
    排錯kubectl get pods -A | grep ,看資源到底跑去哪了。

    對照 Docker

    DockerKubernetes
    Compose 服務名(mysqlService name(mysql-svc
    不同 Compose project = 不同 network不同 namespace
    內建 DNS(compose 版)CoreDNS(叢集版)
    Docker Compose 也有用名字找服務的能力,但只在同一個 docker network 內。K8s 的 CoreDNS 是叢集級的,所有 namespace 共用同一套 DNS 解析機制。

    重點整理

    • 用名字不用 IP — Service 重建 IP 會變、人腦記不住
    • CoreDNS 跑在 kube-system,每建一個 Service 自動註冊 DNS
    • 三種寫法:name / name.ns / name.ns.svc.cluster.local
    • 同 ns 用短名,跨 ns 至少帶上 namespace
    • Namespace 是邏輯隔離,不是網路隔離

    下一步

    到目前為止學的都是「我要 N 個 Pod」。但有些情境是「每台 Node 都要一個」(日誌收集 agent、監控 agent),有些是「每天凌晨備份一次」(定時任務)。

    這就要用 DaemonSet 與 CronJob