Kubernetes Namespace - 叢集資源隔離

Kubernetes 的 Namespace (命名空間) 提供了一種將單一實體叢集 (Physical Cluster) 劃分為多個虛擬叢集 (Virtual Clusters) 的機制。 這就像在電腦硬碟上建立不同的資料夾,不同資料夾 (Namespace) 裡的檔案 (Resources) 可以有相同的名稱而不衝突。

對於多人協作或多環境 (Dev/Stage/Prod) 的專案來說,Namespace 是最基礎且最重要的管理單位。

什麼時候需要 Namespace?

  1. 多租戶隔離 (Multi-tenancy):
    • 一個公司內部的多個團隊 (Team A, Team B) 共用同一個 K8s 叢集。
    • 避免 Team A 的 deployment-backend 跟 Team B 的 deployment-backend 撞名。
  2. 環境隔離:
    • 開發 (Dev)、測試 (Stage)、生產 (Prod) 可以在同一個叢集,但分屬不同 Namespace 以方便管理與資源控管。
  3. 資源配額 (Quota):
    • 可以限制每個 Namespace 能使用的 CPU/Memory 總量 (ResourceQuota),避免測試環境吃光生產環境的資源。
Namespace 主要是「名稱與管理」上的隔離。雖然可以透過 NetworkPolicy 進行網路隔離,但預設情況下,不同 Namespace 的 Pod 是可以互相通訊的 (只要知道對方的 IP 或 Domain Name)。

深入理解:資源的作用範圍 (Scope)

新手常誤以為所有 K8s 資源都在 Namespace 裡,其實不然。資源分為兩類:

1. Namespaced (隸屬於命名空間)

這些資源必須依附在某個 Namespace 下,刪除 Namespace 時它們也會一起消失。

  • Workloads: Pod, ReplicaSet, Deployment, StatefulSet, Job, CronJob
  • Discovery & LoadBalancing: Service, Ingress
  • Config & Storage: ConfigMap, Secret, PersistentVolumeClaim (PVC)
  • Access Control: Role, RoleBinding

你可以用指令查詢所有 Namespaced 資源:

kubectl api-resources --namespaced=true

2. Cluster-wide (叢集全域)

這些資源是全叢集共用的,不屬於任何 Namespace,且名稱必須全叢集唯一。

  • Cluster Architecture: Node, Namespace
  • Storage: PersistentVolume (PV), StorageClass
  • Access Control: ClusterRole, ClusterRoleBinding

你可以用指令查詢所有 Cluster-wide 資源:

kubectl api-resources --namespaced=false

內建 Namespace 介紹

當你建立一個 K8s 叢集時,會有幾個預設的 Namespace:

  • default: 預設的 Namespace。如果你沒指定 -n,所有指令都會作用在這裡。
  • kube-system: K8s 系統核心組件 (API Server, Scheduler, CoreDNS, kube-proxy 等) 所在的地方。強烈建議不要隨意修改這裡的資源
  • kube-node-lease: 用於節點心跳檢測 (Node Heartbeat),一般使用者無須理會。
  • kube-public: 存放全叢集可見的資訊 (如 cluster-info ConfigMap),無需驗證即可讀取。

常用操作指令

建立與管理 Namespace

# 建立一個名為 dev 的 Namespace
kubectl create namespace dev

# 查看所有 Namespace
kubectl get ns

或者使用 YAML 定義 (ns-dev.yaml):

apiVersion: v1
kind: Namespace
metadata:
  name: dev
  labels:
    env: development

並執行:

kubectl apply -f ns-dev.yaml

# 若要刪除 (根據 YAML 設定刪除)
kubectl delete -f ns-dev.yaml

在特定 Namespace 操作資源

方法 A: 加上 -n 參數 (單次有效)

# 在 dev 建立一個 Nginx Pod
kubectl run nginx --image=nginx -n dev

# 查看 dev 下的所有 Pod
kubectl get pods -n dev

方法 B: 在 YAML metadata 指定

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: dev # 指定建立在 dev
spec:
  containers:
    - name: nginx
      image: nginx

切換預設 Context Namespace (推薦工具)

如果你這陣子都要在 dev 做事,每次指令都要打 -n dev 會很累且容易忘記。

原生指令切換:

kubectl config set-context --current --namespace=dev
# 驗證
kubectl config view --minify | grep namespace

推薦工具: kubens (from kubectx)

更快速切換 Namespace 的神級與工具 (支援互動式選單):

# 切換到 dev
kubens dev

# 切換回上一個 namespace
kubens -

跨 Namespace 通訊 (Networking)

預設情況下,K8s 的網路是打通的 (Flat Network)。Namespace 不會 阻止網路流量。

DNS 解析規則 (FQDN)

若 Application A (在 dev) 想呼叫 Application B (在 prod 的 Service 名為 db),必須使用 完整網域名稱 (FQDN)

格式:<Service>.<Namespace>.svc.cluster.local

  1. 同 Namespace: 直接用 db
  2. 不同 Namespace: 必須用 db.prod 或完整寫法 db.prod.svc.cluster.local

如何實作網路隔離?

如果你希望 dev 的 Pod 不能 連線到 prod 的 Pod,必須使用 NetworkPolicy。 這需要 CNI Plugin (如 Calico, Cilium) 的支援。

# 範例:拒絕所有進入 prod namespace 的流量,除非來源 Namespace 有特定標籤
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: protect-prod
  namespace: prod
spec:
  # 選擇目標 Pod:{} 代表選取該 Namespace (prod) 下的「所有」Pod
  podSelector: {}

  # 策略類型:只控制 Ingress (入站/連入流量)
  policyTypes:
    - Ingress

  # 入站白名單規則:只有符合以下條件的來源才允許連線
  # (若沒列在這邊的來源,預設就是 Deny 拒絕)
  ingress:
    - from:
        # 允許來源 1: 帶有標籤 access="true" 的 Namespace (例如管理用的 admin-ns)
        - namespaceSelector:
            matchLabels:
              access: 'true'
        # 允許來源 2: (可視需求增加,例如特定 IP 段)
        # - ipBlock:
        #     cidr: 10.0.0.0/24

刪除 Namespace 與注意事項

警告: 刪除 Namespace 是一個破壞性操作

kubectl delete ns dev

這會觸發以下連鎖反應:

  1. 該 Namespace 狀態變為 Terminating
  2. K8s 開始刪除該 Namespace 下的 所有資源 (Pods, Services, PVCs, ConfigMaps...)。
  3. 等到所有資源都刪除乾淨後,Namespace 才會真正消失。
常見問題: Namespace 卡在 Terminating 很久刪不掉?
通常是因為某個資源 (如 CRD 或 Metrics Server) 的 finalizer 卡住了,導致刪除流程無法完成。這時候需要手動修復或強制移除 finalizer。

總結

  1. 不要全部塞 default: 生產環境中,至少應區分 dev, stage, prod
  2. 資源清理: 刪除 Namespace 是清理環境最快的方法 (例如 CI/CD 測試完後直接刪除整個臨時 Namespace)。
  3. 隔離層級:
    • 名稱隔離: Namespace (預設)
    • 資源隔離: ResourceQuota / LimitRange
    • 權限隔離: RBAC (RoleBinding)
    • 網路隔離: NetworkPolicy