多租户集群管理:命名空间隔离与资源配额
深入理解 Kubernetes 多租户架构,学习命名空间隔离、ResourceQuota、LimitRange 以及集群联邦管理。
概述
多租户是生产级 Kubernetes 集群的核心需求,通过命名空间隔离和资源配额实现安全的资源共享。本文将深入探讨:
学习目标:
- 理解多租户架构设计
- 掌握命名空间隔离与配额管理
- 学会使用 LimitRange 控制容器资源
- 了解集群联邦与多集群管理
- 实现租户成本监控与优化
多租户架构概述
为什么要多租户?
┌─────────────────────────────────────────────────────────────────┐
│ 多租户优势 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 资源利用率 vs 隔离性 │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 单租户模式 │ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │
│ │ │Team A │ │Team B │ │Team C │ │ │
│ │ │Cluster │ │Cluster │ │Cluster │ │ │
│ │ └────────┘ └────────┘ └────────┘ │ │
│ │ 隔离好,但资源浪费严重 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 多租户模式 │ │
│ │ ┌────────────────────────────────────────────────┐ │ │
│ │ │ Shared Cluster │ │ │
│ │ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │
│ │ │ │Team A │ │Team B │ │Team C │ │ │ │
│ │ │ │ NS │ │ NS │ │ NS │ │ │ │
│ │ │ └────────┘ └────────┘ └────────┘ │ │ │
│ │ └────────────────────────────────────────────────┘ │ │
│ │ 资源利用率高,需要合理的隔离策略 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 多租户类型: │
│ ✓ 软多租户(团队隔离,信任内部) │
│ ✓ 硬多租户(完全隔离,无信任) │
│ │
└─────────────────────────────────────────────────────────────────┘
多租户隔离层次
┌─────────────────────────────────────────────────────────────────┐
│ 多租户隔离层次 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 网络隔离 │ │
│ │ NetworkPolicy / 节点拓扑 / 负载均衡器 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 资源隔离 │ │
│ │ ResourceQuota / LimitRange / 优先级调度 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 身份隔离 │ │
│ │ RBAC / ServiceAccount / 审计日志 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ 存储隔离 │ │
│ │ StorageClass / PVC 配额 / 存储类隔离 │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
命名空间管理
创建命名空间
# team-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: team-a
labels:
team: a
environment: production
# Pod Security Standards
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restricted
---
# team-b.yaml
apiVersion: v1
kind: Namespace
metadata:
name: team-b
labels:
team: b
environment: production
---
# staging namespace
apiVersion: v1
kind: Namespace
metadata:
name: staging
labels:
environment: staging
命名空间配额
# resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
# 计算资源
requests.cpu: "10"
requests.memory: "20Gi"
limits.cpu: "20"
limits.memory: "40Gi"
# 存储配额
persistentvolumeclaims: "50"
requests.storage: "100Gi"
# 对象数量
pods: "100"
replicationcontrollers: "20"
services: "20"
secrets: "50"
configmaps: "50"
# 负载均衡器
services.loadbalancers: "2"
services.nodeports: "10"
---
# scopes 配额
apiVersion: v1
kind: ResourceQuota
metadata:
name: best-effort-quota
namespace: team-a
spec:
scopes:
- BestEffort
hard:
pods: "50"
LimitRange
# limitrange.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: team-a-limits
namespace: team-a
spec:
limits:
# 容器级别限制
- type: Container
default:
cpu: "200m"
memory: "256Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
max:
cpu: "4"
memory: "8Gi"
min:
cpu: "50m"
memory: "64Mi"
# 限制 requests/limits 比例
maxLimitRequestRatio:
cpu: 4
memory: 4
# Pod 级别限制
- type: Pod
max:
cpu: "8"
memory: "16Gi"
# PVC 级别限制
- type: PersistentVolumeClaim
min:
storage: "1Gi"
max:
storage: "100Gi"
完整配额配置
# team-quota.yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: team-a
---
# ResourceQuota
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-a-quota
namespace: team-a
spec:
hard:
requests.cpu: "10"
requests.memory: "20Gi"
limits.cpu: "20"
limits.memory: "40Gi"
pods: "100"
persistentvolumeclaims: "20"
services.loadbalancers: "1"
services.nodeports: "5"
---
# LimitRange
apiVersion: v1
kind: LimitRange
metadata:
name: team-a-limits
namespace: team-a
spec:
limits:
- type: Container
default:
cpu: "200m"
memory: "256Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
max:
cpu: "4"
memory: "8Gi"
min:
cpu: "50m"
memory: "64Mi"
---
# NetworkPolicy(默认隔离)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny
namespace: team-a
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
租户配额设计
配额计算公式
┌─────────────────────────────────────────────────────────────────┐
│ 资源配额计算 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 步骤1:确定团队需求 │
│ │
│ 典型应用配置: │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Frontend Pod │ │
│ │ requests: 100m CPU, 128Mi memory │ │
│ │ limits: 500m CPU, 512Mi memory │ │
│ │ │ │
│ │ Backend Pod │ │
│ │ requests: 250m CPU, 256Mi memory │ │
│ │ limits: 1000m CPU, 1Gi memory │ │
│ │ │ │
│ │ Worker Pod │ │
│ │ requests: 100m CPU, 128Mi memory │ │
│ │ limits: 500m CPU, 512Mi memory │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ 步骤2:计算副本数需求 │
│ │
│ Frontend: 3 副本 │
│ Backend: 5 副本 │
│ Worker: 10 副本 │
│ │
│ 步骤3:汇总 │
│ │
│ CPU requests: (100m + 250m + 100m) × 副本数 │
│ Memory requests: (128Mi + 256Mi + 128Mi) × 副本数 │
│ │
└─────────────────────────────────────────────────────────────────┘
配额模板
# quota-template.yaml
# 用于快速创建团队配额
apiVersion: v1
kind: Namespace
metadata:
name: ${TEAM_NAME}
labels:
team: ${TEAM_NAME}
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: ${TEAM_NAME}-quota
namespace: ${TEAM_NAME}
spec:
hard:
requests.cpu: "${CPU_LIMIT}"
requests.memory: "${MEMORY_LIMIT}"
limits.cpu: "${CPU_LIMIT_MAX}"
limits.memory: "${MEMORY_LIMIT_MAX}"
pods: "${POD_LIMIT}"
---
apiVersion: v1
kind: LimitRange
metadata:
name: ${TEAM_NAME}-limits
namespace: ${TEAM_NAME}
spec:
limits:
- type: Container
default:
cpu: "200m"
memory: "256Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
max:
cpu: "4"
memory: "8Gi"
配额使用监控
# 查看命名空间资源使用
kubectl describe namespace team-a
# 查看具体配额
kubectl get resourcequota -n team-a -o yaml
# 查看 LimitRange
kubectl get limitrange -n team-a -o yaml
# 使用 kubectl-topology 或 prometheus 查询配额使用
kubectl top pod -n team-a
优先级调度
PriorityClass
# priority-classes.yaml
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: production-high
value: 1000
globalDefault: false
description: "Production workloads with high priority"
preemptionPolicy: PreemptLowerPriority
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: production-normal
value: 500
globalDefault: true
description: "Normal production workloads"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: development
value: 100
description: "Development and test workloads"
---
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: batch
value: 50
description: "Batch processing workloads"
preemptionPolicy: Never
使用优先级
# production-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: production-app
spec:
replicas: 3
template:
spec:
priorityClassName: production-normal
containers:
- name: app
image: myapp:1.0
---
# batch-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: data-processing
spec:
ttlSecondsAfterFinished: 3600
template:
spec:
priorityClassName: batch
containers:
- name: processor
image: processor:1.0
restartPolicy: OnFailure
集群联邦
何时需要多集群
┌─────────────────────────────────────────────────────────────────┐
│ 多集群场景 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 场景1:地理分布 │
│ - 降低延迟 │
│ - 满足数据主权要求 │
│ - 灾难恢复 │
│ │
│ 场景2:环境隔离 │
│ - 开发/测试/生产 │
│ - 多租户隔离 │
│ │
│ 场景3:容量扩展 │
│ - 突发流量 │
│ - 资源超卖 │
│ │
│ 场景4:混合云 │
│ - AWS/GCP/Azure 混合 │
│ - 边缘计算 │
│ │
└─────────────────────────────────────────────────────────────────┘
Federation v2 架构
┌─────────────────────────────────────────────────────────────────┐
│ Federation 架构 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Federation Control Plane │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Types │ │ Core │ │ DNS │ │Policy │ │ │
│ │ │ Controller│ │Plugins │ │Controller│ │ Controller│ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │ │ │
│ └──────────────┼──────────────┘ │
│ │ │
│ ┌───────────────┼───────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Cluster │ │ Cluster │ │ Cluster │ │
│ │ us-west │ │ us-east │ │ eu-west │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
多集群管理工具
┌─────────────────────────────────────────────────────────────────┐
│ 多集群管理方案 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌────────────────┐ │
│ │ Kubernetes │ │ Rancher │ │ Anthos │ │
│ │ Federation │ │ │ │ (GKE) │ │
│ │ │ │ │ │ │ │
│ │ K8s 原生 │ │ 多集群管理 │ │ 企业级方案 │ │
│ │ 跨集群调度 │ │ 统一 UI │ │ Anthos config │ │
│ │ │ │ RBAC 统一 │ │ management │ │
│ └────────────────┘ └────────────────┘ └────────────────┘ │
│ │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ OpenShift │ │ Tanzu │ │
│ │ │ │ │ │
│ │ Red Hat 方案 │ │ VMware 方案 │ │
│ └────────────────┘ └────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
跨集群服务发现
# 跨集群 Federation 资源配置
apiVersion: core.federation.k8s.io/v1beta1
kind: FederatedService
metadata:
name: myapp
namespace: production
spec:
template:
spec:
selector:
app: myapp
ports:
- name: http
port: 80
targetPort: 8080
placement:
clusters:
- name: us-west-cluster
- name: us-east-cluster
- name: eu-west-cluster
成本管理
资源成本模型
# namespace-cost-budget.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: team-cost-budget
namespace: team-a
spec:
hard:
# 基于成本的配额(使用注释扩展)
pods: "50"
---
# 注释方式记录配额
metadata:
annotations:
cost.budget/month: "1000" # 月预算(美元)
cost.cpu/hour: "0.05" # CPU 每小时成本
cost.memory/hour: "0.01" # 内存每小时成本
成本监控
# kubecost 或 OpenCost 配置
apiVersion: v1
kind: ConfigMap
metadata:
name: kubecost-config
namespace: kubecost
data:
prometheus-config.json: |
{
"prometheus": {
"server": "http://prometheus-server:9090"
}
}
---
# 部署 OpenCost
kubectl apply -f https://raw.githubusercontent.com/opencost/opencost/develop/kubernetes/opencost.yaml
# 访问成本 Dashboard
kubectl port-forward -n opencost svc/opencost 9090:9090
成本优化建议
┌─────────────────────────────────────────────────────────────────┐
│ 成本优化策略 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. Right-sizing(合理规格) │
│ - 分析实际资源使用 │
│ - 调整 requests/limits │
│ - 使用 VPA 自动调整 │
│ │
│ 2. 抢占式实例(Spot/Preemptible) │
│ - 运行批处理任务 │
│ - 设置合适的优先级 │
│ │
│ 3. 资源预留 │
│ - 合理规划预留实例 │
│ - 混合实例类型 │
│ │
│ 4. 存储优化 │
│ - 使用适当存储类 │
│ - 清理废弃 PVC │
│ - 定期归档数据 │
│ │
│ 5. 网络优化 │
│ - 减少跨可用区流量 │
│ - 使用内网负载均衡 │
│ │
└─────────────────────────────────────────────────────────────────┘
常见问题与避坑指南
Q1:配额不足导致 Pod 无法创建?
# 排查步骤
# 1. 查看命名空间配额
kubectl describe resourcequota -n team-a
# 2. 查看 LimitRange
kubectl describe limitrange -n team-a
# 3. 查看 Pod 状态
kubectl describe pod <pod-name> -n team-a
# 4. 检查事件
kubectl get events -n team-a --sort-by='.lastTimestamp'
# 解决方案
# - 申请增加配额
# - 清理未使用的资源
# - 优化资源使用
Q2:如何避免命名空间资源耗尽?
# 1. 设置 ResourceQuota
kubectl apply -f resource-quota.yaml
# 2. 设置 LimitRange
kubectl apply -f limitrange.yaml
# 3. 使用 VPA 自动调整资源
# kubectl autovpa --namespace=team-a
# 4. 监控配额使用
kubectl get resourcequota -o wide -n team-a
Q3:多集群如何统一管理?
# 使用 Rancher
# 1. 安装 Rancher
helm install rancher rancher-latest/rancher \
--namespace cattle-system \
--set hostname=rancher.example.com
# 2. 注册集群
# Rancher UI → Add Cluster → 导入或创建
# 使用 ArgoCD Fleet
# 1. 安装 Fleet
helm install fleet rancher/fleet -n fleet-system
# 2. 创建 GitRepo
kubectl apply -f gitrepo.yaml
Q4:如何实现跨集群流量调度?
# 使用服务网格(Istio)
# 1. 在多个集群安装 Istio
# 2. 配置 Multi-Cluster Mesh
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: myapp-global
spec:
host: myapp.global
trafficPolicy:
localityLbSetting:
enabled: true
failover:
- from: us-west
to: us-east
- from: us-east
to: eu-west
总结
┌─────────────────────────────────────────────────────────────────┐
│ 核心要点回顾 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 多租户隔离 │
│ ├── 命名空间是隔离边界 │
│ ├── ResourceQuota 控制总量 │
│ └── LimitRange 控制单个 Pod/容器 │
│ │
│ 资源配额 │
│ ├── CPU/内存 requests 和 limits │
│ ├── 存储和对象数量配额 │
│ └── 优先级调度 │
│ │
│ 多集群管理 │
│ ├── 联邦用于跨集群管理 │
│ ├── 工具:Rancher, Anthos, OpenShift │
│ └── 服务网格跨集群流量 │
│ │
│ 成本管理 │
│ ├── 监控资源使用 │
│ ├── 合理调整规格 │
│ └── 使用抢占式实例 │
│ │
└─────────────────────────────────────────────────────────────────┘
思考题
- 如何设计一个支持多租户的资源配额模型?
- 软多租户和硬多租户各有什么优缺点?
- 如何在多集群环境中实现统一的身份认证和授权?
引用与参考
下篇预告
下一篇文章我们将探讨 性能调优与故障排查,包括:
- 资源分析与性能剖析
- 日志调试与事件排查
- 网络问题诊断
- 常见故障案例
敬请期待!