Kubernetes Namespace - 叢集資源隔離
Kubernetes 的 Namespace (命名空間) 提供了一種將單一實體叢集 (Physical Cluster) 劃分為多個虛擬叢集 (Virtual Clusters) 的機制。 這就像在電腦硬碟上建立不同的資料夾,不同資料夾 (Namespace) 裡的檔案 (Resources) 可以有相同的名稱而不衝突。
對於多人協作或多環境 (Dev/Stage/Prod) 的專案來說,Namespace 是最基礎且最重要的管理單位。
什麼時候需要 Namespace?
- 多租戶隔離 (Multi-tenancy):
- 一個公司內部的多個團隊 (Team A, Team B) 共用同一個 K8s 叢集。
- 避免 Team A 的
deployment-backend跟 Team B 的deployment-backend撞名。
- 環境隔離:
- 開發 (Dev)、測試 (Stage)、生產 (Prod) 可以在同一個叢集,但分屬不同 Namespace 以方便管理與資源控管。
- 資源配額 (Quota):
- 可以限制每個 Namespace 能使用的 CPU/Memory 總量 (ResourceQuota),避免測試環境吃光生產環境的資源。
深入理解:資源的作用範圍 (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-infoConfigMap),無需驗證即可讀取。
常用操作指令
建立與管理 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
- 同 Namespace: 直接用
db。 - 不同 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
這會觸發以下連鎖反應:
- 該 Namespace 狀態變為
Terminating。 - K8s 開始刪除該 Namespace 下的 所有資源 (Pods, Services, PVCs, ConfigMaps...)。
- 等到所有資源都刪除乾淨後,Namespace 才會真正消失。
Terminating 很久刪不掉?通常是因為某個資源 (如 CRD 或 Metrics Server) 的
finalizer 卡住了,導致刪除流程無法完成。這時候需要手動修復或強制移除 finalizer。總結
- 不要全部塞 default: 生產環境中,至少應區分
dev,stage,prod。 - 資源清理: 刪除 Namespace 是清理環境最快的方法 (例如 CI/CD 測試完後直接刪除整個臨時 Namespace)。
- 隔離層級:
- 名稱隔離: Namespace (預設)
- 資源隔離: ResourceQuota / LimitRange
- 權限隔離: RBAC (RoleBinding)
- 網路隔離: NetworkPolicy