4. 高风险变更场景识别
在多租户隔离集群中,并非所有 Kubernetes 资源变更都会带来同等风险。部分变更类型会直接突破租户边界、削弱节点安全或导致资源争抢,必须被准入策略严格拦截或审计。本章系统识别五类高风险变更场景,并给出每类场景的检测要点与策略示例。
4.1 五类高风险变更总览
| 风险类别 | Kubernetes 资源字段 | 影响范围 | Argo CD 检测方式 |
|---|---|---|---|
| 特权容器 | securityContext.privileged |
节点级逃逸 | 准入策略检查 spec.containers[*].securityContext.privileged |
| HostPath 挂载 | volumes.hostPath |
节点文件系统暴露 | 拒绝所有 hostPath 卷类型 |
| NodePort 暴露 | spec.ports[*].nodePort |
集群网络边界突破 | 拦截 Service 类型为 NodePort 或显式设置 nodePort 字段 |
| 资源配额超限 | resources.requests / limits |
租户资源抢占 | 校验总和是否超过 Namespace 的 ResourceQuota |
| 镜像来源不可信 | spec.containers[*].image |
供应链攻击 | 正则匹配允许的镜像仓库域名列表 |
4.2 特权容器:节点逃逸的直通车
当容器以 privileged: true 运行时,它拥有宿主机内核的全部能力,可以加载内核模块、挂载宿主机设备、访问 /proc 和 /sys 敏感路径。在多租户集群中,任何一个租户获得特权容器权限,即可控制整个节点。
privileged: true 就足够。实际上,capabilities.add: ["SYS_ADMIN"] 或 securityContext.capabilities.add: ["ALL"] 也能达到类似效果。策略必须同时检查 privileged 字段和 capabilities 列表。
策略检测示例(Kyverno):
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged-containers
spec:
validationFailureAction: Enforce
rules:
- name: check-privileged
match:
any:
- resources:
kinds:
- Pod
validate:
message: "特权容器在多租户集群中禁止使用。"
pattern:
spec:
containers:
- securityContext:
privileged: "false"
- name: check-capabilities
match:
any:
- resources:
kinds:
- Pod
validate:
message: "禁止添加 ALL 或 SYS_ADMIN 等危险 Capability。"
pattern:
spec:
containers:
- securityContext:
capabilities:
add:
- "!ALL"
- "!SYS_ADMIN"
4.3 HostPath 挂载:宿主机文件系统的后门
hostPath 卷允许容器直接访问宿主机文件系统。攻击者可以通过挂载 /var/lib/kubelet 获取集群凭证,或挂载 / 修改宿主机配置。在多租户场景下,任何 hostPath 挂载都应被拒绝,除非有明确的节点级运维需求且通过特殊标签豁免。
策略检测要点:
- 检查
spec.volumes[*].hostPath是否存在 - 检查
spec.containers[*].volumeMounts中挂载的路径是否来自 hostPath 卷 - 对于需要 hostPath 的 DaemonSet(如日志采集),使用 Namespace 标签豁免
4.4 NodePort 暴露:集群网络边界的突破
NodePort 类型的 Service 会在每个节点上打开一个宿主机端口(30000-32767),直接暴露服务到集群外部。在多租户集群中,这会导致:
- 租户服务绕过集群入口网关(Ingress/Gateway API)
- 无法统一管理 TLS 终止和访问控制
- 端口冲突风险(不同租户可能申请相同 NodePort)
4.5 资源配额超限:租户间的无声战争
即使每个 Namespace 都配置了 ResourceQuota,Argo CD 同步的变更仍可能超出配额。例如,一个 Deployment 的 replicas: 10 且每个 Pod 请求 2 核 CPU,但 Namespace 的配额只有 10 核。这种变更在 Apply 时会被 API Server 拒绝,导致同步失败。
策略检测方式:
- 在准入策略中计算当前 Namespace 已使用资源 + 新变更请求资源
- 与
ResourceQuota的hard字段对比 - 超出时生成警告或直接拒绝变更
注意: 由于准入策略无法实时查询集群当前资源使用量,更实用的做法是在 CI/CD 流水线中预检,或在 Argo CD 的 PreSync hook 中执行资源校验。
4.6 镜像来源不可信:供应链攻击的入口
允许从任意镜像仓库拉取镜像,等于将集群安全交给外部第三方。攻击者可以上传恶意镜像到公共仓库(如 Docker Hub 的未验证用户仓库),或利用镜像名称混淆(例如 gcr.io/google-containers/pause:latest 与 gcr.io/google_containers/pause:latest)。
策略检测规则:
| 规则类型 | 示例 | 说明 |
|---|---|---|
| 白名单域名 | registry.k8s.io/*, docker.io/your-org/* |
只允许企业私有仓库或可信公共仓库 |
| 禁止 latest 标签 | image: !*:latest |
强制使用语义化版本标签 |
| 镜像签名验证 | Cosign 验证 + 准入策略 | 要求镜像必须携带有效签名 |
# Kyverno 策略:只允许来自私有仓库的镜像
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
spec:
validationFailureAction: Enforce
rules:
- name: validate-registry
match:
any:
- resources:
kinds:
- Pod
validate:
message: "镜像必须来自 registry.example.com。"
pattern:
spec:
containers:
- image: "registry.example.com/*"
4.7 高风险变更场景关系图
下图展示了五类高风险变更在 Kubernetes 集群中的影响层级,从容器内部到节点、网络、资源、供应链,逐层递进。
4.8 策略优先级矩阵
根据风险等级和拦截难度,建议按以下优先级实施准入策略:
| 优先级 | 风险场景 | 拦截策略 | 豁免条件 |
|---|---|---|---|
| P0 | 特权容器 | 强制拒绝 | 仅系统 Namespace(kube-system) |
| P0 | HostPath 挂载 | 强制拒绝 | DaemonSet 且标签 app.kubernetes.io/component: node-agent |
| P1 | 镜像来源不可信 | 强制拒绝 | 白名单内的镜像仓库 |
| P1 | NodePort 暴露 | 强制拒绝 | 已审批的 Service 通过 Annotation 豁免 |
| P2 | 资源配额超限 | 审计告警 | 紧急变更可通过 Argo CD 的 syncPolicy 跳过 |
validationFailureAction: Enforce 直接拒绝变更;P2 级别设置 Audit 模式,记录事件但不阻断。