昨天幫 todo-api、todo-frontend、MySQL 都加上了 Resource Request 和 Limit,今天要學 Namespace,看看怎麼用它隔離不同環境的資源。
目前所有資源都在 default Namespace 裡:todo-api、todo-frontend、mysql,全部混在一起。
這在單人開發的時候沒問題,但實際工作場景通常需要:
Namespace 提供了一個邏輯上的隔離層,讓同一個 Cluster 可以跑多套環境或服務,互不干擾。
Namespace 是 K8s 資源的邏輯分組,同一個 Namespace 裡的資源名稱必須唯一,但不同 Namespace 可以有同名的資源。
K8s 預設有幾個 Namespace:
kubectl get namespaces
NAME STATUS AGE
default Active 10d ← 沒有指定 Namespace 的資源都在這裡
kube-node-lease Active 10d ← Node 心跳資訊
kube-public Active 10d ← 公開讀取的資源
kube-system Active 10d ← K8s 系統元件
哪些資源有 Namespace 隔離,哪些沒有:
Namespace 只隔離邏輯資源(部署的應用)。Node 是實體機器、PV 是實體儲存空間,這類叢集基礎設施是所有 Namespace 共用的,無法隔離。
Namespace 只是一個邏輯邊界,怎麼切都可以,實際上沒有唯一標準答案。常見的做法有三種:
1. 按環境分(本篇示範這個)
dev / staging / production
每個環境自帶完整的前端、後端、資料庫。最直觀,適合小型專案或剛開始導入 K8s 的團隊。
2. 按功能層分
frontend / backend / database
每層各自一個 Namespace,方便用 NetworkPolicy 限制存取(例如只允許 backend 連 database,frontend 不能直連 DB)。適合單一產品、職責邊界清楚的團隊。
3. 按服務分(微服務常見)
app-order / app-user / infra
每個業務服務自己的 Namespace,包含自己的 API 和 DB;infra 放 Ingress、監控等公用元件。一個 team 只管一個 Namespace,最小權限原則好執行。
實務上也常混用,例如先按環境分,再在各環境裡按功能或服務細分。(下面會用「按環境」示範,比較容易理解 Namespace 隔離的概念 !)
同一個 Namespace 內,Service 直接用名稱連線:
http://todo-api-service:80
跨 Namespace 則需要用完整的 DNS 名稱:
http://todo-api-service.production.svc.cluster.local:80
格式是:<service名稱>.<namespace名稱>.svc.cluster.local
今天目標:建立 dev Namespace,把 Todo App 的所有資源部署到 dev Namespace,設定 ResourceQuota 限制資源上限,並將預設 Namespace 切換到 dev。
kubectl create namespace dev
或是用 YAML:
apiVersion: v1
kind: Namespace
metadata:
name: dev
確認建立成功:
kubectl get namespaces

方式一:在 YAML 的 metadata 裡指定
apiVersion: apps/v1
kind: Deployment
metadata:
name: todo-api
namespace: dev # 指定 Namespace
spec:
...
方式二:用 kubectl 指令時加 -n 參數
kubectl apply -f todo-api-deployment.yaml -n dev
todo-api-configmap.yaml 的內容如下,DATABASE_URL 已移到 Secret,ConfigMap 只放非敏感設定:
apiVersion: v1
kind: ConfigMap
metadata:
name: todo-api-config
namespace: dev
data:
APP_ENV: "development"
LOG_LEVEL: "info"
kubectl apply -f todo-api-configmap.yaml
DATABASE_URL 放在這裡:kubectl create secret generic todo-api-secret \
--from-literal=DATABASE_URL=mysql+pymysql://user:password@mysql-service:3306/tododb \
-n dev
kubectl create secret generic mysql-secret \
--from-literal=MYSQL_ROOT_PASSWORD=rootpassword \
--from-literal=MYSQL_PASSWORD=password \
-n dev
kubectl apply -f mysql-statefulset.yaml -n dev
kubectl apply -f mysql-service.yaml -n dev
kubectl get pod mysql-0 -n dev -w
看到 Running 後按 Ctrl+C 繼續下一步。
kubectl apply -f todo-api-deployment.yaml -n dev
kubectl apply -f todo-api-service.yaml -n dev
kubectl apply -f todo-frontend-deployment.yaml -n dev
kubectl apply -f todo-frontend-service.yaml -n dev
kubectl get pods -n dev

# 看 dev Namespace 的所有 Pod
kubectl get pods -n dev
# 看所有 Namespace 的 Pod
kubectl get pods --all-namespaces
# 或
kubectl get pods -A
每次下指令都要加 -n dev 很麻煩,可以設定預設的 Namespace:
kubectl config set-context --current --namespace=dev
之後的指令就不需要加 -n dev 了。確認目前的設定:
kubectl config view --minify | grep namespace
設定完之後,後續所有指令預設都在 dev Namespace 執行。
Namespace 可以設定資源配額,限制這個 Namespace 最多能用多少資源。在 /Todo-app/k8s 目錄下,建立 dev-quota.yaml:
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: dev
spec:
hard:
requests.cpu: "2" # 所有 Pod 的 CPU request 總和不超過 2 顆
requests.memory: "2Gi" # 所有 Pod 的 Memory request 總和不超過 2Gi
limits.cpu: "4"
limits.memory: "4Gi"
pods: "20" # 最多 20 個 Pod
kubectl apply -f dev-quota.yaml
注意:設定 ResourceQuota 之後,Namespace 內所有 Pod 都必須明確指定
requests和limits,否則會被拒絕建立。請確認你的 Deployment YAML 都有設定,格式如下:resources: requests: cpu: "100m" memory: "128Mi" limits: cpu: "200m" memory: "256Mi"
確認配額使用狀況:
kubectl describe resourcequota dev-quota -n dev
Name: dev-quota
Namespace: dev
Resource Used Hard
-------- ---- ----
limits.cpu 500m 4
limits.memory 256Mi 4Gi
pods 4 20
requests.cpu 100m 2
requests.memory 128Mi 2Gi
今天學了 Namespace,把資源做邏輯隔離:
從現在開始,後續所有操作都在 dev Namespace 進行,請確認預設 Namespace 已設定為 dev:
kubectl config view --minify | grep namespace
#應該看到 namespace: dev
明天會學 HPA,讓 K8s 根據負載自動調整 Pod 數量,不需要人工盯著手動 scale !