4. Namespace 隔离机制:Kubernetes Namespace 的作用、资源配额(ResourceQuota)、限制范围(LimitRange)、默认 ServiceAccount 隔离
在多租户集群中,Namespace 是 Kubernetes 实现软隔离的第一道防线。它并非安全边界(如网络策略或节点隔离),而是逻辑分组与资源管理的边界。本章深入剖析 Namespace 的隔离能力、资源配额(ResourceQuota)、限制范围(LimitRange)以及默认 ServiceAccount 的隔离策略,帮助你在控制平面层面构建稳固的租户资源模型。
4.1 Namespace 的核心作用与隔离边界
Namespace 将集群内的对象划分为互不干扰的虚拟空间。每个 Namespace 拥有独立的资源视图,但底层共享同一个物理集群。其核心作用包括:
- 资源分组:将属于同一租户或项目的 Pod、Service、ConfigMap 等资源归入同一 Namespace,避免命名冲突。
- 资源配额:通过 ResourceQuota 限制租户可消耗的 CPU、内存、存储等总量。
- 默认限制:通过 LimitRange 为未显式设置资源请求/限制的 Pod 或容器注入默认值。
- 访问控制:结合 RBAC,为不同 Namespace 内的 ServiceAccount 授予不同权限。
- 网络策略:配合 NetworkPolicy 实现 Namespace 级别的网络隔离(本章不展开,后续章节详述)。
4.2 资源配额(ResourceQuota)
ResourceQuota 是控制平面资源模型的核心组件,它定义了 Namespace 级别的资源消耗上限。当租户尝试创建超过配额的资源时,API Server 会直接拒绝请求。
4.2.1 配额类型与配置示例
| 资源类型 | 作用范围 | 示例 |
|---|---|---|
| 计算资源 | Pod 的 CPU/内存请求与限制 | requests.cpu: "10", limits.memory: "20Gi" |
| 存储资源 | PersistentVolumeClaim 的存储总量 | requests.storage: "100Gi" |
| 对象数量 | Namespace 内各类对象的计数 | count/deployments.apps: "10", count/services: "20" |
| 扩展资源 | GPU、FPGA 等自定义资源 | requests.nvidia.com/gpu: "4" |
以下是一个典型的 ResourceQuota 配置,适用于一个中等规模的租户 Namespace:
apiVersion: v1
kind: ResourceQuota
metadata:
name: tenant-quota
namespace: tenant-a
spec:
hard:
requests.cpu: "8"
requests.memory: "16Gi"
limits.cpu: "16"
limits.memory: "32Gi"
requests.storage: "50Gi"
persistentvolumeclaims: "10"
count/deployments.apps: "15"
count/services: "20"
count/secrets: "30"
count/configmaps: "30"
limits.cpu 而未设置 requests.cpu,Pod 可能因未设置请求值而被调度到资源不足的节点。建议始终同时设置 requests 和 limits 的配额,或配合 LimitRange 强制默认值。
4.3 限制范围(LimitRange)
LimitRange 解决了“未显式设置资源约束”的问题。它会在 Pod 或容器创建时,自动注入默认的资源请求/限制,或强制最小/最大值。这对于防止租户创建“无限资源”的 Pod 至关重要。
4.3.1 LimitRange 的三种策略
- 默认值(Default):当 Pod 未设置 requests 或 limits 时,自动注入默认值。
- 最小/最大值(Min/Max):强制 Pod 的资源请求/限制必须在指定范围内,超出则拒绝。
- 比例限制(MaxLimitRequestRatio):限制 limits 与 requests 的比例,防止过度超卖。
示例:为租户 Namespace 设置默认的 CPU 和内存限制:
apiVersion: v1
kind: LimitRange
metadata:
name: tenant-limits
namespace: tenant-a
spec:
limits:
- max:
cpu: "2"
memory: "4Gi"
min:
cpu: "100m"
memory: "128Mi"
default:
cpu: "500m"
memory: "1Gi"
defaultRequest:
cpu: "200m"
memory: "512Mi"
type: Container
4.4 默认 ServiceAccount 隔离
每个 Namespace 创建时,Kubernetes 会自动生成一个名为 default 的 ServiceAccount。如果 Pod 未显式指定 serviceAccountName,则会自动挂载该 default ServiceAccount 的 。在多租户场景下,这可能导致严重的安全风险:
- 权限泄露:default ServiceAccount 通常绑定有集群级别的角色(如
view或edit),租户 Pod 可能意外获得访问其他 Namespace 资源的权限。 - 滥用:如果 default ServiceAccount 的 被泄露,攻击者可能利用它进行横向移动。
4.4.1 隔离策略
| 策略 | 操作 | 效果 |
|---|---|---|
| 禁用自动挂载 | 在 Pod 或 Namespace 级别设置 automountServiceAccountToken: false |
Pod 不自动挂载任何 ServiceAccount |
| 最小权限绑定 | 为 default ServiceAccount 绑定一个空角色或仅限本 Namespace 的只读角色 | 即使挂载 ,也无法访问其他 Namespace |
| 专用 ServiceAccount | 为每个应用创建独立的 ServiceAccount,并绑定最小权限 | 实现细粒度权限控制,避免共享 default 账号 |
| 自动轮换 | 启用 Bound Service Account Volume(Kubernetes 1.21+) | 具有时间限制,降低泄露风险 |
以下是一个 Namespace 级别的配置,禁用 default ServiceAccount 的自动挂载:
apiVersion: v1
kind: Namespace
metadata:
name: tenant-a
annotations:
# 禁用该 Namespace 下所有 Pod 的默认 挂载
serviceaccounts.kubernetes.io/default-automount-service-account-: "false"
automountServiceAccountToken 策略,并禁止使用 default ServiceAccount 运行生产工作负载。
4.5 综合隔离架构图
下图展示了 Namespace 隔离机制中 ResourceQuota、LimitRange 和 ServiceAccount 的协同工作流程:
4.6 实战建议与避坑指南
- 配额硬限制:ResourceQuota 是硬限制,一旦达到上限,后续创建请求会被立即拒绝。建议为每个租户预留 20% 的缓冲配额,避免因突发流量导致 Pod 创建失败。
- LimitRange 与 ResourceQuota 的冲突:如果 LimitRange 设置的默认值超过了 ResourceQuota 的剩余容量,Pod 创建会失败。建议先设置 LimitRange,再设置 ResourceQuota,并确保默认值在配额范围内。
- 默认 ServiceAccount 清理:对于生产租户 Namespace,建议删除或禁用 default ServiceAccount 的权限绑定,并创建专用的 ServiceAccount 用于工作负载。
- 监控与告警:使用
kubectl describe resourcequota -n tenant-a查看当前使用量,并配置 Prometheus 告警规则,当配额使用率超过 80% 时触发通知。