想象一下,你是一家初创公司的技术负责人,团队里有前端、后端、运维,还有几个外包同学。大家共用一套Kubernetes集群,结果某天前端同学误删了后端的数据库Deployment,运维同学抱怨资源被挤爆,外包同学连测试环境都进不去。这就是典型的“多租户混乱现场”。
别慌,这篇指南手把手带你从零搭建一个安全、高效、协作顺畅的多租户Kubernetes集群。我们不只讲理论,更用真实代码和配置说话,保证你看完就能落地。
一、为什么多租户隔离如此关键?
多租户场景下,不同团队或项目共享同一套基础设施。没有隔离,轻则资源争抢、性能下降,重则数据泄露、服务中断。Kubernetes原生提供了Namespace、RBAC、NetworkPolicy、ResourceQuota等多层隔离机制,但如何组合使用,才是拉开差距的地方。
我们的目标:
- 安全性:防止越权访问和恶意操作
- 公平性:合理分配资源,避免个别团队独占
- 协作性:团队间互不干扰,又能高效配合
- 可审计性:所有操作留痕,便于追溯
二、Namespace:多租户的第一道防线
Namespace是Kubernetes中最基础的隔离单元。每个租户对应一个Namespace,就像公寓楼里的不同房间。
创建租户Namespace
# namespace-frontend.yaml
apiVersion: v1
kind: Namespace
metadata:
name: frontend-team
labels:
team: frontend
environment: production
owner: zhangsan@example.com
annotations:
description: "前端团队生产环境"
cost-center: "marketing-001"
# namespace-backend.yaml
apiVersion: v1
kind: Namespace
metadata:
name: backend-team
labels:
team: backend
environment: production
owner: lisi@example.com
创建命令:
kubectl apply -f namespace-frontend.yaml
kubectl apply -f namespace-backend.yaml
Namespace最佳实践
- 命名规范:使用小写字母、数字和连字符,如
team-alpha、project-beta - 标签体系:打上团队、环境、成本中心等标签,便于筛选和管理
- 注解信息:记录负责人、描述、成本中心,方便追溯
- 避免default:不要在生产环境使用default Namespace
三、RBAC:细粒度的权限控制
RBAC(Role-Based Access Control)是Kubernetes的核心安全机制。通过Role和ClusterRole定义权限,再通过RoleBinding和ClusterRoleBinding将权限绑定给用户或服务账号。
定义前端团队角色
# role-frontend.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: frontend-developer
namespace: frontend-team
rules:
# 允许管理Deployment、Service、ConfigMap、Secret
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# 允许查看Pod日志和事件
- apiGroups: [""]
resources: ["pods", "pods/log", "events"]
verbs: ["get", "list", "watch"]
# 禁止删除命名空间
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["delete"]
nonResourceURLs: []
resourceNames: []
# role-binding-frontend.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: frontend-developer-binding
namespace: frontend-team
subjects:
- kind: Group
name: frontend-team
apiGroup: rbac.authorization.k8s.io
- kind: User
name: zhangsan
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: frontend-developer
apiGroup: rbac.authorization.k8s.io
定义后端团队角色(更严格)
# role-backend.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: backend-developer
namespace: backend-team
rules:
# 允许管理所有资源,但禁止删除命名空间
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# 特别限制:禁止操作persistentvolumeclaims
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["delete"]
创建服务账号(用于CI/CD)
# sa-frontend-cicd.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: frontend-cicd
namespace: frontend-team
annotations:
description: "前端团队CI/CD服务账号"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: frontend-cicd-role
namespace: frontend-team
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: frontend-cicd-binding
namespace: frontend-team
subjects:
- kind: ServiceAccount
name: frontend-cicd
namespace: frontend-team
roleRef:
kind: Role
name: frontend-cicd-role
apiGroup: rbac.authorization.k8s.io
RBAC最佳实践
- 最小权限原则:只授予完成任务所需的最小权限
- 使用ServiceAccount:自动化流程使用服务账号,避免使用用户账号
- 定期审计:使用
kubectl auth can-i检查权限,定期审查Role和RoleBinding - 避免cluster-admin:不要随意授予集群管理员权限
- 使用Namespace-scoped Role:除非必要,不要使用ClusterRole
四、NetworkPolicy:网络隔离
即使在不同Namespace,默认情况下Pod之间可以互相通信。NetworkPolicy允许你定义“谁可以和谁通信”。
前端团队网络策略
# network-policy-frontend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: frontend-policy
namespace: frontend-team
spec:
podSelector:
matchLabels:
app: frontend
policyTypes:
- Ingress
- Egress
ingress:
# 只允许从ingress-controller命名空间的流量进入
- from:
- namespaceSelector:
matchLabels:
name: ingress-controller
ports:
- protocol: TCP
port: 80
- protocol: TCP
port: 443
egress:
# 允许访问后端团队的API服务
- to:
- namespaceSelector:
matchLabels:
team: backend
podSelector:
matchLabels:
app: backend-api
ports:
- protocol: TCP
port: 8080
# 允许访问DNS
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
后端团队网络策略(更严格)
# network-policy-backend.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
namespace: backend-team
spec:
podSelector:
matchLabels:
app: backend-api
policyTypes:
- Ingress
- Egress
ingress:
# 只允许前端团队访问
- from:
- namespaceSelector:
matchLabels:
team: frontend
podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
# 允许监控系统访问(用于健康检查)
- from:
- namespaceSelector:
matchLabels:
name: monitoring
ports:
- protocol: TCP
port: 9090
egress:
# 只允许访问数据库和缓存
- to:
- namespaceSelector:
matchLabels:
team: data
podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
team: data
podSelector:
matchLabels:
app: redis
ports:
- protocol: TCP
port: 6379
# 允许访问DNS
- to:
- namespaceSelector: {}
ports:
- protocol: UDP
port: 53
- protocol: TCP
port: 53
数据库团队网络策略
# network-policy-data.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: data-policy
namespace: data-team
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
- Egress
ingress:
# 只允许后端团队访问
- from:
- namespaceSelector:
matchLabels:
team: backend
podSelector:
matchLabels:
app: backend-api
ports:
- protocol: TCP
port: 5432
egress:
# 禁止任何出站连接(数据库不需要外联)
# 不定义egress规则,默认拒绝所有出站
NetworkPolicy最佳实践
- 默认拒绝:先创建默认拒绝所有流量的策略,再逐步放开
- 白名单机制:明确允许需要的流量,其他全部拒绝
- 标签匹配:使用标签选择器,便于管理
- 测试验证:使用
kubectl exec和nc测试连通性 - CNI兼容:确保你的CNI插件支持NetworkPolicy(如Calico、 Cilium)
五、ResourceQuota和LimitRange:资源管控
资源配额限制Namespace级别的资源使用, LimitRange限制单个Pod或容器的资源限制。
前端团队资源配额
# resource-quota-frontend.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: frontend-quota
namespace: frontend-team
spec:
hard:
# CPU和内存限制
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
# 资源数量限制
pods: "20"
services: "10"
configmaps: "20"
secrets: "20"
persistentvolumeclaims: "5"
replicationcontrollers: "10"
# 存储限制
requests.storage: "100Gi"
persistentvolumeclaims: "5"
后端团队资源配额(更严格)
# resource-quota-backend.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: backend-quota
namespace: backend-team
spec:
hard:
requests.cpu: "8"
requests.memory: 16Gi
limits.cpu: "16"
limits.memory: 32Gi
pods: "30"
services: "15"
configmaps: "30"
secrets: "30"
persistentvolumeclaims: "10"
requests.storage: "500Gi"
LimitRange:默认容器资源限制
# limit-range-frontend.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: frontend-limits
namespace: frontend-team
spec:
limits:
# 默认容器限制
- default:
cpu: "500m"
memory: 512Mi
defaultRequest:
cpu: "200m"
memory: 256Mi
type: Container
# 最大限制
- max:
cpu: "2"
memory: 4Gi
type: Container
# Pod级别限制
- max:
cpu: "4"
memory: 8Gi
type: Pod
# PVC限制
- max:
storage: 50Gi
type: PersistentVolumeClaim
资源配额最佳实践
- 根据团队规模分配:大型团队获得更多资源
- 监控使用率:定期查看配额使用情况,及时调整
- 设置默认限制:通过LimitRange设置默认资源请求和限制
- 预留资源:为关键服务预留资源,避免被挤占
- 使用PriorityClass:为重要服务设置更高优先级
六、多团队协作最佳实践
案例:完整的团队协作场景
假设我们有三个团队:
- 前端团队:负责Web应用
- 后端团队:负责API服务
- 数据团队:负责数据库和缓存
Step 1:创建Namespace和标签
# 创建命名空间
kubectl create namespace frontend-team
kubectl create namespace backend-team
kubectl create namespace data-team
# 添加标签
kubectl label namespace frontend-team team=frontend environment=production
kubectl label namespace backend-team team=backend environment=production
kubectl label namespace data-team team=data environment=production
Step 2:创建RBAC角色和绑定
为每个团队创建不同的角色:
# role-frontend-admin.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: frontend-admin
namespace: frontend-team
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: frontend-admin-binding
namespace: frontend-team
subjects:
- kind: Group
name: frontend-team
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: frontend-admin
apiGroup: rbac.authorization.k8s.io
类似地为后端和数据团队创建角色。
Step 3:配置网络策略
确保团队间按需要通信,其他流量被拒绝。
Step 4:设置资源配额
根据团队需求分配资源。
Step 5:创建CI/CD服务账号
# sa-frontend-cicd.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: cicd-frontend
namespace: frontend-team
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: cicd-frontend-role
namespace: frontend-team
rules:
- apiGroups: ["apps"]
resources: ["deployments", "replicasets"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services", "configmaps", "secrets"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cicd-frontend-binding
namespace: frontend-team
subjects:
- kind: ServiceAccount
name: cicd-frontend
namespace: frontend-team
roleRef:
kind: Role
name: cicd-frontend-role
apiGroup: rbac.authorization.k8s.io
Step 6:验证和测试
# 测试前端团队权限
kubectl auth can-i create deployments --namespace=frontend-team --as=zhangsan
kubectl auth can-i delete pods --namespace=backend-team --as=zhangsan
# 测试网络连通性
kubectl exec -n frontend-team pod-frontend-xxx -- nc -zv backend-team 8080
kubectl exec -n frontend-team pod-frontend-xxx -- nc -zv data-team 5432
七、监控和审计
启用审计日志
# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# 记录所有请求
- level: RequestResponse
# 不记录某些资源
- level: None
resources:
- group: ""
resources: ["events"]
# 记录特定命名空间的删除操作
- level: Request
resources:
- group: ""
resources: ["pods", "services"]
verbs: ["delete", "deletecollection"]
namespaces: ["frontend-team", "backend-team", "data-team"]
使用Prometheus监控资源使用
”`yaml
prometheus-configmap.yaml
apiVersion: v1 kind: ConfigMap metadata: name: prometheus-config namespace: monitoring data: prometheus.yml: |
global:
scrape