多租户集群管理:命名空间隔离与资源配额

深入理解 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                         │
│  └── 服务网格跨集群流量                                         │
│                                                                 │
│  成本管理                                                       │
│  ├── 监控资源使用                                               │
│  ├── 合理调整规格                                              │
│  └── 使用抢占式实例                                             │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

思考题

  1. 如何设计一个支持多租户的资源配额模型?
  2. 软多租户和硬多租户各有什么优缺点?
  3. 如何在多集群环境中实现统一的身份认证和授权?

引用与参考

  1. Creating a Multi-Tenant Cluster
  2. Resource Quotas
  3. Limit Ranges
  4. Rancher Documentation

下篇预告

下一篇文章我们将探讨 性能调优与故障排查,包括:

  • 资源分析与性能剖析
  • 日志调试与事件排查
  • 网络问题诊断
  • 常见故障案例

敬请期待!