多租户 Kubernetes Namespace 隔离加 RBAC 权限配置和资源配额设置详解
说实话,刚开始接触 Kubernetes 的时候,我也觉得多租户这事挺玄乎的。说白了,就是”一群人共用一套集群,但各玩各的,互不干扰”。这就好比你住在一个大公寓楼里,每间房都有自己独立的门锁、水电表,邻居不会随便闯进来翻你东西。今天咱们就把这个事儿掰开揉碎了讲清楚。
为什么需要多租户隔离
先讲个真实故事。有一家创业公司,有前端团队、后端团队、数据团队,三个组共用一台 Kubernetes 集群。结果有一天,前端同学误操作,删除了属于后端同学的 Deployment。后端同学当时就炸了,直接冲到了前端工位。后来运维同学想了个办法:把三个团队分到不同的 Namespace 里,再配合 RBAC 权限控制,事情就解决了。
这就是多租户的核心痛点——资源隔离 + 权限隔离。
Namespace 在 Kubernetes 里就是个逻辑隔离的”虚拟集群”,不同 Namespace 之间默认是看不到对方的资源的。但这只是第一步,光有 Namespace 还不够,你得确保每个团队只能操作自己的 Namespace,不能越界。这就是 RBAC 要干的事。
Namespace 隔离:先建好房间
Namespace 本身就是一个简单的隔离机制。我们先来创建一个多租户的场景:
# namespaces.yaml
apiVersion: v1
kind: Namespace
metadata:
name: frontend-team
labels:
team: frontend
env: prod
---
apiVersion: v1
kind: Namespace
metadata:
name: backend-team
labels:
team: backend
env: prod
---
apiVersion: v1
kind: Namespace
metadata:
name: data-team
labels:
team: data
env: prod
应用这个配置很简单:
kubectl apply -f namespaces.yaml
这时候三个 Namespace 就建好了。你可以验证一下:
kubectl get namespaces
输出大概是这样的:
NAME STATUS AGE
frontend-team Active 1m
backend-team Active 1m
data-team Active 1m
default Active 30d
kube-system Active 30d
注意看,kube-system 是 Kubernetes 系统自己用的,千万别碰它。default 是默认 Namespace,所有没有明确指定 Namespace 的资源都会跑到这里。
现在的问题是:光有 Namespace 还不够,因为 Kubernetes 默认有个 cluster-admin 角色,拥有整个集群的权限。如果一个团队的人拿到了 kubeconfig 里的 admin 权限,他照样可以跨 Namespace 乱操作。所以必须上 RBAC。
RBAC 权限配置:锁好各家的门
RBAC 的全称是 Role-Based Access Control(基于角色的访问控制)。它的基本思路是:先定义角色(Role),再决定谁有这个角色(RoleBinding)。
第一层:在各自 Namespace 里创建 Role
我们先给前端团队定义一个 Role,让他们能管理自己的 Deployment、Pod、Service,但不能删 Namespace,也不能碰其他团队的东西:
# roles/frontend-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: frontend-team
name: frontend-developer
rules:
# 可以管理 Pod
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/exec"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
# 可以管理 Deployment
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
# 可以管理 Service
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
# 可以管理 ConfigMap 和 Secret
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
# 可以管理 Ingress
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
# 可以管理 PersistentVolumeClaim
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
后端团队的角色类似,但可以额外给他们一些数据库相关的权限:
# roles/backend-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: backend-team
name: backend-developer
rules:
- apiGroups: [""]
resources: ["pods", "pods/log", "pods/exec"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
- apiGroups: ["apps"]
resources: ["deployments", "replicasets", "statefulsets"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
# 后端团队可以管理 CronJob(定时任务)
- apiGroups: ["batch"]
resources: ["cronjobs", "jobs"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "create", "update", "delete", "patch"]
数据团队的角色,可以给他们更多敏感操作:
# roles/data-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: data-team
name: data-engineer
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "create", "update", "delete"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["get", "list", "create", "update", "delete"]
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list", "create", "update", "delete"]
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "create", "update", "delete"]
# 数据团队可以操作 CronJob
- apiGroups: ["batch"]
resources: ["cronjobs", "jobs"]
verbs: ["get", "list", "create", "update", "delete"]
第二层:把角色绑定到人
Role 定义好了,但光有角色没人用也是白搭。我们需要用 RoleBinding 把角色绑定到具体的用户或用户组上。
先假设前端团队有两个同学:张三和李四,他们的 Kubernetes 用户身份分别是 zhangsan 和 lisi。
# rolebindings/frontend-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: frontend-developer-binding
namespace: frontend-team
subjects:
- kind: User
name: zhangsan
apiGroup: rbac.authorization.k8s.io
- kind: User
name: lisi
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: frontend-developer
apiGroup: rbac.authorization.k8s.io
后端团队绑定:
# rolebindings/backend-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: backend-developer-binding
namespace: backend-team
subjects:
- kind: User
name: wangwu
apiGroup: rbac.authorization.k8s.io
- kind: User
name: zhaoliu
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: backend-developer
apiGroup: rbac.authorization.k8s.io
数据团队绑定:
# rolebindings/data-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: data-engineer-binding
namespace: data-team
subjects:
- kind: User
name: qianqi
apiGroup: rbac.authorization.k8s.io
- kind: User
name: sunba
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: data-engineer
apiGroup: rbac.authorization.k8s.io
第三层:创建用户和 kubeconfig
RBAC 里提到的 zhangsan、lisi 这些用户,需要在 Kubernetes 的认证体系里真实存在。通常有两种方式:
方式一:用 X.509 证书认证(推荐生产环境使用)
# 生成 zhangsan 的私钥
openssl genrsa -out zhangsan.key 2048
# 生成 CSR(证书签名请求)
openssl req -new -key zhangsan.key -out zhangsan.csr \
-subj "/CN=zhangsan/O=frontend-team"
# 用 CA 签名生成证书
openssl x509 -req -in zhangsan.csr \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-out zhangsan.crt \
-days 365
# 把证书信息写入 kubeconfig
kubectl config set-credentials zhangsan \
--client-certificate=zhangsan.crt \
--client-key=zhangsan.key
kubectl config set-context zhangsan-context \
--cluster=kubernetes \
--user=zhangsan
kubectl config use-context zhangsan-context
方式二:用 ServiceAccount(适合应用之间调用,不适合人工使用)
# serviceaccounts/frontend-sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: frontend-sa
namespace: frontend-team
第四层:用 kubeconfig 限制用户的默认 Namespace
这个细节很多人会忽略。即使绑定了 Role,如果用户的 kubeconfig 没有设置默认 Namespace,他可能会不小心操作到错误的位置。
给 zhangsan 设置默认的 context,让他一登录就在 frontend-team Namespace 里:
kubectl config set-context zhangsan-context \
--cluster=kubernetes \
--user=zhangsan \
--namespace=frontend-team
这样 zhangsan 登录后,所有操作默认都在 frontend-team Namespace 下,想操作别的 Namespace 得显式指定。
验证 RBAC 权限
现在 zhangsan 用他的 kubeconfig 登录,执行以下命令测试:
# 切换到 zhangsan 的上下文
kubectl config use-context zhangsan-context
# 查看当前 Namespace(应该是 frontend-team)
kubectl config view --minify --output 'jsonpath={..namespace}'
# 在 frontend-team 里创建 Deployment(应该成功)
kubectl run nginx --image=nginx:1.21
# 尝试查看 backend-team 的 Pod(应该被拒绝)
kubectl get pods -n backend-team
# 输出应该是:
# Error from server (Forbidden): pods is forbidden: User "zhangsan" cannot list resource "pods" in API group "" in the namespace "backend-team"
这个报错信息非常关键——它明确告诉用户:你没有权限做这件事。这就是 RBAC 在起作用。
资源配额:别让人”吃饱了撑的”
RBAC 解决了”谁能做什么”的问题,但还没解决”能做多少”的问题。想象一下,前端团队的一个同学写了个循环,疯狂创建 Pod,把集群资源占满了,其他团队怎么办?
这时候就需要 ResourceQuota 和 LimitRange。
ResourceQuota:给 Namespace 设个总预算
ResourceQuota 控制的是一个 Namespace 内所有资源的总量上限:
# quotas/frontend-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: frontend-quota
namespace: frontend-team
spec:
hard:
# CPU 总量限制
requests.cpu: "4"
limits.cpu: "8"
# 内存总量限制
requests.memory: 8Gi
limits.memory: 16Gi
# Pod 数量限制
pods: "20"
# Service 数量限制
services: "10"
# ConfigMap 数量限制
configmaps: "20"
# Secret 数量限制
secrets: "20"
# PersistentVolumeClaim 总量限制
persistentvolumeclaims: "5"
# ReplicationController 数量限制
replicationcontrollers: "10"
# quotas/backend-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: backend-quota
namespace: backend-team
spec:
hard:
requests.cpu: "8"
limits.cpu: "16"
requests.memory: 16Gi
limits.memory: 32Gi
pods: "50"
services: "10"
configmaps: "30"
secrets: "30"
persistentvolumeclaims: "10"
# 后端团队额外限制 StatefulSet 数量
count/statefulsets.apps: "5"
# quotas/data-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: data-quota
namespace: data-team
spec:
hard:
requests.cpu: "16"
limits.cpu: "32"
requests.memory: 64Gi
limits.memory: 128Gi
pods: "30"
services: "10"
configmaps: "20"
secrets: "20"
persistentvolumeclaims: "20"
应用配额配置:
kubectl apply -f quotas/frontend-quota.yaml
kubectl apply -f quotas/backend-quota.yaml
kubectl apply -f quotas/data-quota.yaml
验证配额是否生效:
kubectl describe quota -n frontend-team
输出示例:
Name: frontend-quota
Namespace: frontend-team
Resource Used Hard
-------- ---- ----
pods 3 20
requests.cpu 2 4
requests.memory 4Gi 8Gi
limits.cpu 4 8
limits.memory 8Gi 16Gi
services 1 10
configmaps 2 20
secrets 1 20
persistentvolumeclaims 0 5
LimitRange:给单个资源设个上限
ResourceQuota 限制的是总量,LimitRange 限制的是单个资源对象的上下限。比如你不想让前端团队随便起一个 16C 的 Pod,就可以用 LimitRange:
# limits/frontend-limits.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: frontend-limits
namespace: frontend-team
spec:
limits:
# 默认限制:如果不指定 resource request/limit,自动填充
- default:
cpu: "2"
memory: 2Gi
defaultRequest:
cpu: "500m"
memory: 512Mi
type: Container
# 单个容器最大不能超过 4C/8Gi
- max:
cpu: "4"
memory: 8Gi
type: Container
# 单个容器最小不能低于 100m/128Mi
- min:
cpu: "100m"
memory: 128Mi
type: Container
# Pod 级别的限制
- max:
cpu: "8"
memory: 16Gi
type: Pod
# limits/backend-limits.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: backend-limits
namespace: backend-team
spec:
limits:
- default:
cpu: "2"
memory: 4Gi
defaultRequest:
cpu: "500m"
memory: 1Gi
type: Container
- max:
cpu: "8"
memory: 16Gi
type: Container
- min:
cpu: "100m"
memory: 256Mi
type: Container
- max:
cpu: "16"
memory: 32Gi
type: Pod
# limits/data-limits.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: data-limits
namespace: data-team
spec:
limits:
- default:
cpu: "4"
memory: 8Gi
defaultRequest:
cpu: "1"
memory: 2Gi
type: Container
- max:
cpu: "16"
memory: 32Gi
type: Container
- min:
cpu: "200m"
memory: 512Mi
type: Container
- max:
cpu: "32"
memory: 64Gi
type: Pod
应用 LimitRange:
kubectl apply -f limits/frontend-limits.yaml
kubectl apply -f limits/backend-limits.yaml
kubectl apply -f limits/data-limits.yaml
验证 LimitRange:
kubectl describe limitrange -n frontend-team
输出:
Name: frontend-limits
Namespace: frontend-team
Type Resource Min Max Default Request Default Limit
------ -------- --- --- ------------- -----------
Container cpu 100m 4 500m 2
Container memory 128Mi 8Gi 512Mi 2Gi
Pod cpu - 8 - -
Pod memory - 16Gi - -
实际测试:配额超限会发生什么
现在我们来测试一下,如果前端团队试图超出配额会怎样。
先看看当前配额使用情况:
kubectl quota -n frontend-team
输出:
Name: frontend-quota
Resource Used Hard
-------- ---- ----
pods 3 20
requests.cpu 2 4
requests.memory 4Gi 8Gi
现在 zhangsan 试图创建一个需求超过配额限制的 Pod:
# 尝试创建一个需要 5 核 CPU 的 Pod(超过了 Namespace 的 CPU 上限 4 核)
kubectl run heavy-pod --image=nginx:1.21 --requests=cpu=5
# 输出:
# Error from server (Forbidden): pods "heavy-pod" is forbidden:
# failed quota: frontend-quota: must specify requests.cpu,limits.cpu,requests.memory,limits.memory
# ...
或者更直接地,尝试创建超配额的 Deployment:
# 先看看当前 CPU 使用量是 2,上限是 4
# 尝试创建一个需要 3 核 CPU 的 Pod,总需求变成 5,超过上限
kubectl run extra-pod --image=nginx:1.21 --requests=cpu=3
# 输出:
# Error from server (Forbidden): pods "extra-pod" is forbidden:
# failed quota: frontend-quota: must specify requests.cpu,limits.cpu,requests.memory,limits.memory
# cannot exceed remaining quota: pods remaining 17, used 3 and requested 1
如果是 LimitRange 的限制,创建单个容器超过 Max 限制也会失败:
# 尝试创建一个需要 10C CPU 的容器(超过了 LimitRange 的 max 4C)
kubectl run big-pod --image=nginx:1.21 --requests=cpu=10
# 输出:
# Error from server (Forbidden): pods "big-pod" is forbidden:
# failed limit: must not request more than 4 core(s) cpu,
# but was requested 10 core(s)
这些错误信息清晰地告诉用户:你越界了。
NetworkPolicy:网络层面的隔离
资源隔离和权限隔离都有了,但还有一个容易被忽视的问题:网络隔离。即使两个团队在同一个 Namespace 里都没问题,但如果他们在不同的 Namespace,默认情况下 Kubernetes 并不限制他们之间的网络通信。
比如前端团队的 Pod 能不能 ping 通后端团队的 Pod?默认是可以的。这就需要 NetworkPolicy 来限制。
先确保你的集群装了支持 NetworkPolicy 的 CNI 插件(比如 Calico、 Cilium、Flannel with policy 等)。可以用这个命令检查:
kubectl get pods -n kube-system | grep -E 'calico|cilium|flannel'
如果没看到,需要先安装。以 Calico 为例:
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml
然后给每个 Namespace 创建 NetworkPolicy:
# networkpolicies/frontend-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-network-policy
namespace: frontend-team
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
# 入站规则:只允许来自本 Namespace 和后端团队 Namespace 的流量
ingress:
- from:
- namespaceSelector:
matchLabels:
team: frontend
- namespaceSelector:
matchLabels:
team: backend
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
# 出站规则:只允许访问 DNS 和后端团队
egress:
- to:
- namespaceSelector:
matchLabels:
team: backend
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
# 允许 DNS 解析
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# networkpolicies/backend-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-network-policy
namespace: backend-team
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
team: frontend
- namespaceSelector:
matchLabels:
team: data
ports:
- protocol: TCP
port: 8080
- protocol: TCP
port: 3000
egress:
- to:
- namespaceSelector:
matchLabels:
team: data
ports:
- protocol: TCP
port: 5432
- protocol: TCP
port: 6379
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
# networkpolicies/data-netpol.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: data-network-policy
namespace: data-team
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
team: backend
ports:
- protocol: TCP
port: 5432
- protocol: TCP
port: 6379
egress:
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
应用 NetworkPolicy:
kubectl apply -f networkpolicies/
验证 NetworkPolicy:
kubectl get networkpolicy -A
输出:
NAME POD-SELECTOR AGE
frontend-network-policy <none> 1m
backend-network-policy <none> 1m
data-network-policy <none> 1m
完整的部署脚本
光有 YAML 文件还不够,我整理了一个完整的部署脚本,方便你一键配置:
#!/bin/bash
# deploy-multitenant.sh - 多租户 Kubernetes 环境一键部署脚本
set -euo pipefail
echo "🚀 开始部署多租户 Kubernetes 环境..."
# 1. 创建 Namespace
echo "📦 创建 Namespace..."
kubectl apply -f namespaces.yaml
echo "✅ Namespace 创建完成"
# 2. 创建 Role
echo "🔐 创建 RBAC Roles..."
kubectl apply -f roles/
echo "✅ Roles 创建完成"
# 3. 创建 RoleBinding
echo "🔗 创建 RoleBindings..."
kubectl apply -f rolebindings/
echo "✅ RoleBindings 创建完成"
# 4. 创建 ResourceQuota
echo "📊 创建 ResourceQuota..."
kubectl apply -f quotas/
echo "✅ ResourceQuota 创建完成"
# 5. 创建 LimitRange
echo "📏 创建 LimitRange..."
kubectl apply -f limits/
echo "✅ LimitRange 创建完成"
# 6. 创建 NetworkPolicy(需要先确认 CNI 支持)
echo "🌐 创建 NetworkPolicy..."
kubectl apply -f networkpolicies/
echo "✅ NetworkPolicy 创建完成"
echo ""
echo "🎉 多租户环境部署完成!"
echo ""
echo "📋 各 Namespace 配额情况:"
for ns in frontend-team backend-team data-team; do
echo ""
echo "── Namespace: $ns ──"
kubectl describe quota -n $ns 2>/dev/null || echo " 无 quota 配置"
echo ""
kubectl describe limitrange -n $ns 2>/dev/null || echo " 无 limitrange 配置"
done
PodSecurityStandards:防止特权容器逃逸
还有一个容易被忽视的安全问题——特权容器。即使 RBAC 和 NetworkPolicy 都配好了,如果一个团队在一个 Namespace 里创建了一个 privileged: true 的 Pod,理论上他们可以挂载宿主机的文件系统,从而逃逸到宿主机,进而访问其他 Namespace 的资源。
所以需要启用 PodSecurityStandards(或者更早版本的 PodSecurityPolicy)。在 Kubernetes 1.25+ 中,PodSecurityPolicy 已经被移除,推荐使用 PodSecurity Admission 控制器。
# pod-security-admissions.yaml
# 给每个 Namespace 打上 PodSecurity 标签,限制容器权限级别
apiVersion: v1
kind: Namespace
metadata:
name: frontend-team
labels:
team: frontend
env: prod
# 限制为 restricted 级别(最严格)
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
---
apiVersion: v1
kind: Namespace
metadata:
name: backend-team
labels:
team: backend
env: prod
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
---
apiVersion: v1
kind: Namespace
metadata:
name: data-team
labels:
team: data
env: prod
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
restricted 级别意味着:
- 不能使用
privileged容器 - 不能挂载主机路径
- 不能以 root 用户运行(除非特别配置)
- 不能使用 hostNetwork、hostPID、hostIPC
如果你想更宽松一点,可以用 baseline 级别,它只禁止明显的危险操作,但不强制要求非 root 运行。
总结:一张图看清全局
把这个多租户架构画出来,大概是这样:
┌─────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌───────────┐│
│ │ frontend-team │ │ backend-team │ │ data-team ││
│ │ Namespace │ │ Namespace │ │ Namespace ││
│ │ │ │ │ │ ││
│ │ Role: │ │ Role: │ │ Role: ││
│ │ developer │ │ developer │ │ engineer ││
│ │ │ │ │ │ ││
│ │ Quota: │ │ Quota: │ │ Quota: ││
│ │ 4C/8Gi │ │ 8C/16Gi │ │ 16C/64Gi ││
│ │ │ │ │ │ ││
│ │ Network: │ │ Network: │ │ Network: ││
│ │ ↔ frontend │ │ ↔ backend │ │ ↔ data ││
│ │ ↔ backend │ │ ↔ frontend │ │ ↔ backend││
│ │ ✗ data │ │ ✗ frontend │ │ ✗ frontend│
│ └────────┬────────┘ └────────┬────────┘ └────┬────┘│
│ │ │ │ │
│ └────────────────────┼─────────────────┘ │
│ │ │
│ ┌───────────┴───────────┐ │
│ │ RBAC + PSA + CNI │ │
│ │ NetworkPolicy │ │
│ │ ResourceQuota │ │
│ │ LimitRange │ │
│ └───────────────────────┘ │
└─────────────────────────────────────────────────────────┘
核心要点就六个字:分Namespace、绑Role、限资源。
- Namespace 负责把资源隔离在不同的逻辑空间里
- RBAC 负责把不同的人分配到不同的 Namespace,并限制他们的操作范围
- ResourceQuota + LimitRange 负责防止任何团队把集群资源撑爆
- NetworkPolicy 负责在网络层面阻断跨 Namespace 的非法访问
- PodSecurityStandards 负责防止特权容器逃逸
这几个层面叠加起来,才能真正实现一个安全、可控的多租户 Kubernetes 环境。
记住,安全不是做到”看起来没问题”就够了,而是要做到”哪怕有人恶意操作,也翻不出天来”。多租户集群就是这样,每一个防线都是为了应对最坏的情况。