16.9.5 多租户与命名空间治理

在生产环境中,多租户治理以命名空间为隔离边界,需统一命名规范(如 业务线-环境-团队),并建立生命周期流程(申请、审批、创建、变更、回收)。通过命名空间级配额(ResourceQuota)与默认 LimitRange 限制资源滥用,结合 PriorityClass 保证关键业务调度优先级。跨团队共享能力采用共享命名空间或专用平台命名空间,辅以标签实现可识别、可计量、可审计。

文章图片

1. 命名空间与资源基线模板(示例)#

命名规范:<业务线>-<环境>-<团队>
示例:pay-prod-teamA

创建命名空间、默认配额与 LimitRange(可直接执行):

# 1) 创建命名空间
kubectl create namespace pay-prod-teama

# 2) 设置资源配额(CPU/内存/对象数量)
cat > /tmp/quota.yaml <<'EOF'
apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota-pay-prod-teama
  namespace: pay-prod-teama
spec:
  hard:
    requests.cpu: "20"
    requests.memory: "40Gi"
    limits.cpu: "40"
    limits.memory: "80Gi"
    pods: "200"
    services: "50"
    configmaps: "200"
    secrets: "200"
EOF
kubectl apply -f /tmp/quota.yaml

# 3) 设置默认 LimitRange
cat > /tmp/limit.yaml <<'EOF'
apiVersion: v1
kind: LimitRange
metadata:
  name: limit-pay-prod-teama
  namespace: pay-prod-teama
spec:
  limits:
  - type: Container
    defaultRequest:
      cpu: "200m"
      memory: "256Mi"
    default:
      cpu: "500m"
      memory: "512Mi"
EOF
kubectl apply -f /tmp/limit.yaml

# 4) 预期效果检查
kubectl describe quota quota-pay-prod-teama -n pay-prod-teama
kubectl describe limitrange limit-pay-prod-teama -n pay-prod-teama

常见排错:

# 配额不足导致 Pod Pending
kubectl get pod -n pay-prod-teama
kubectl describe pod <pod-name> -n pay-prod-teama | sed -n '/Events/,$p'

# 查看当前配额使用情况
kubectl describe quota -n pay-prod-teama

2. RBAC 最小权限与 ServiceAccount(示例)#

为开发团队创建只读角色与绑定:

# 创建 ServiceAccount
kubectl create sa dev-readonly -n pay-prod-teama

# 创建 Role:只读
cat > /tmp/role-readonly.yaml <<'EOF'
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: readonly
  namespace: pay-prod-teama
rules:
- apiGroups: ["", "apps", "batch"]
  resources: ["pods", "deployments", "services", "jobs", "configmaps"]
  verbs: ["get", "list", "watch"]
EOF
kubectl apply -f /tmp/role-readonly.yaml

# 绑定 Role
cat > /tmp/rolebinding-readonly.yaml <<'EOF'
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: bind-readonly
  namespace: pay-prod-teama
subjects:
- kind: ServiceAccount
  name: dev-readonly
  namespace: pay-prod-teama
roleRef:
  kind: Role
  name: readonly
  apiGroup: rbac.authorization.k8s.io
EOF
kubectl apply -f /tmp/rolebinding-readonly.yaml

# 验证权限
kubectl auth can-i list pods --as=system:serviceaccount:pay-prod-teama:dev-readonly -n pay-prod-teama

常见排错:

# 权限不足时查看审计/事件
kubectl describe rolebinding bind-readonly -n pay-prod-teama
kubectl auth can-i create pods --as=system:serviceaccount:pay-prod-teama:dev-readonly -n pay-prod-teama

3. 网络隔离与白名单(NetworkPolicy)#

默认拒绝跨命名空间访问,只放行指定服务:

cat > /tmp/np-deny-all.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: pay-prod-teama
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
EOF
kubectl apply -f /tmp/np-deny-all.yaml

cat > /tmp/np-allow-from-gateway.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-gateway
  namespace: pay-prod-teama
spec:
  podSelector:
    matchLabels:
      app: pay-api
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: gateway-prod
    ports:
    - protocol: TCP
      port: 8080
EOF
kubectl apply -f /tmp/np-allow-from-gateway.yaml

排错建议:

# 确认命名空间标签存在
kubectl label namespace gateway-prod name=gateway-prod --overwrite

# 验证流量(需要具备网络工具的测试 Pod)
kubectl run test --image=busybox:1.36 -n gateway-prod -- sleep 3600
kubectl exec -n gateway-prod test -- wget -qO- http://pay-api.pay-prod-teama:8080/health

4. 准入控制示例(Kyverno:命名规范与镜像来源)#

限制镜像只能来自内部仓库:

# 安装(示例使用官方 Helm)
helm repo add kyverno https://kyverno.github.io/kyverno/
helm install kyverno kyverno/kyverno -n kyverno --create-namespace

cat > /tmp/kyverno-policy.yaml <<'EOF'
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: enforce-image-registry
spec:
  validationFailureAction: Enforce
  rules:
  - name: validate-registry
    match:
      resources:
        kinds:
        - Pod
    validate:
      message: "镜像必须来自 registry.internal.local"
      pattern:
        spec:
          containers:
          - image: "registry.internal.local/*"
EOF
kubectl apply -f /tmp/kyverno-policy.yaml

排错建议:

# 查看策略生效情况
kubectl get cpol
kubectl describe cpol enforce-image-registry

5. 成本与容量治理命令#

查看命名空间资源使用与请求:

kubectl top pods -n pay-prod-teama
kubectl get quota -n pay-prod-teama -o yaml

对非生产环境设置更严格上限示例:

kubectl patch quota quota-pay-prod-teama -n pay-prod-teama --type='merge' -p '
{"spec":{"hard":{"limits.cpu":"20","limits.memory":"40Gi"}}}'

6. 排错清单(快速定位)#

  • Pod Pending:检查 ResourceQuota/LimitRange 与节点可用资源
  • 无法访问服务:检查 NetworkPolicy 与命名空间标签
  • 权限被拒:检查 RBAC 绑定与 ServiceAccount
  • 准入失败:检查 Kyverno/OPA 策略与镜像来源

7. 实战练习#

  1. 新建命名空间 order-test-teamB 并设置配额:CPU 5、内存 10Gi、Pods 50
  2. order-api 设置网络白名单,仅允许 gateway-test 命名空间访问 8080
  3. 创建只读 RBAC,并验证 list pods 权限
  4. 部署一个不符合镜像规则的 Pod,观察准入失败原因并修正