在前面 18 天的實作中,如果我們沒有特別指定,所有的資源(Pod、Deployment、Service、PVC 等)都會被丟進預設的 default 命名空間。
當公司內部有多個團隊共用同一個 Kubernetes 集群時,這會引發嚴重的維運災難:
db-service,B 專案的資料庫也想叫 db-service,在同一空間內會直接覆蓋衝突。為了解決這些問題,Kubernetes 提供了 Namespace 與 ResourceQuota 機制。
Namespace 是 Kubernetes 在同一個實體集群內部劃分出的**「虛擬工作區(Virtual Cluster)」**:
dev 和 prod 空間可以同時存在名為 web-app 的 Deployment)。default:預設的工作空間。kube-system:Kubernetes 核心系統元件(如 API Server、CoreDNS 等)運行的空間。kube-public:所有使用者均可讀取的公共空間。kube-node-lease:用於節點心跳檢測(Heartbeat)的租約空間。劃分了 Namespace 之後,我們需要給這個虛擬空間設定**「算力上限」**,這就是 ResourceQuota:
建立 dev-namespace.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: development
套用配置:
kubectl apply -f dev-namespace.yaml
也可以直接使用快速指令建立:kubectl create namespace development。
我們設定這個環境:
建立 dev-quota.yaml:
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-resource-quota
namespace: development # 明確指定套用的 Namespace
spec:
hard:
pods: "2"
requests.cpu: "1"
requests.memory: "1Gi"
limits.cpu: "2"
limits.memory: "2Gi"
套用配置並檢查配額使用狀況:
kubectl apply -f dev-quota.yaml
# 查看該 Namespace 的配額現況
kubectl get resourcequota -n development
重要規則:當 Namespace 啟用了 CPU/Memory 配額限制後,該空間內的任何 Pod 建立時,**必須明確宣告
resources.requests與resources.limits**,否則會直接被 API Server 拒絕!
建立 dev-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: app-pod-1
namespace: development
spec:
containers:
- name: nginx
image: nginx:1.25
resources:
requests:
cpu: "200m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
套用配置並建立第 1 個 Pod:
kubectl apply -f dev-pod.yaml
建立第 2 個 Pod(將名稱改為 app-pod-2 後再次 apply):
kubectl run app-pod-2 --image=nginx:1.25 -n development \
--requests='cpu=200m,memory=256Mi' \
--limits='cpu=500m,memory=512Mi'
檢查當前配額使用率:
kubectl describe resourcequota dev-resource-quota -n development
你會看到 pods 的使用量已經達到 2/2(100% 滿載)。
現在我們嘗試建立第 3 個 Pod,測試 Kubernetes 是否會阻擋:
kubectl run app-pod-3 --image=nginx:1.25 -n development \
--requests='cpu=200m,memory=256Mi' \
--limits='cpu=500m,memory=512Mi'
預期錯誤訊息:
Error from server (Forbidden): pods "app-pod-3" is forbidden: exceeded quota: dev-resource-quota, requested: pods=1, used: pods=2, limited: pods=2
API Server 在第一道防線就直接拒絕了這個請求! 這確保了該團隊永遠不會無節制地超量佔用集群資源。
如果不想每次下指令都要加上 -n development,可以透過切換 context 預設命名空間:
kubectl config set-context --current --namespace=development
切換後,執行 kubectl get pods 就會自動查詢 development 空間中的資源。
今天我們搞懂了如何為團隊建立安全隔離的虛擬空間:
目前為止,我們部署一套應用程式往往需要寫 3 到 5 個 YAML 檔(Deployment, Service, PVC, Secret...)。如果要把整套架構複製給別人,或是要部署像 WordPress 這樣複雜的開源專案,一個個 YAML 改參數會非常痛苦。
明天 Day 20,我們將學習 Kubernetes 的套件包裝神器:「K8s 包裝神器:Helm Chart 概念與 Helm Repo 操作」!