【K8s】集群安全机制(三):准入控制

前两篇已经把认证和授权讲清楚了:

认证解决"你是谁",授权解决"你能干什么"。这篇要讲的是最后一道关卡------你这样做,合不合理?


目录

  • 一、什么是准入控制

  • 二、两大核心机制:Mutating & Validating

  • 三、准入控制完整流程

  • 四、常见准入控制器解析

  • 五、实战配置示例

  • 六、插件管理操作

  • 七、踩坑经验总结

  • 八、总结


一、什么是准入控制

先说一个很多人的误区:

"通过了 RBAC 就能操作资源"

实际上不对。请求进入 API Server 的完整路径是这样的:

复制代码
请求 → 认证 → 授权 → 准入控制 → 写入 etcd

准入控制是最后一道拦截层,处理的是"合法但不合理"的场景。


两类插件

准入控制器本质上是一组插件,分为两类:

类型 作用
功能增强型 为请求补充默认值、注入字段
规则校验型 检查请求是否符合规则,不合规直接拒绝

重要:读取请求不经过准入控制

getlistwatch 这些操作会绕过准入控制层,只有变更类操作(创建、修改、删除)才会被拦截。


二、两大核心机制


2.1 Mutating(变更型)

可以修改请求内容

常见用途:自动补充资源限制(CPU / Memory)、自动注入 sidecar、自动挂载 ServiceAccount、添加默认 label / annotation。


2.2 Validating(验证型)

只做判断,不能修改,要么放行,要么拒绝。

常见用途:超出配额拒绝、namespace 不存在拒绝、安全策略不合规拒绝。


有些控制器两者兼具

比如 LimitRanger:先补默认值(Mutating),再校验是否超限(Validating)。


三、准入控制完整流程

执行顺序固定:

复制代码
Mutating 阶段 → Validating 阶段 → 写入 etcd

有几点需要注意:

① 任何一个控制器拒绝,整个请求立即失败

不会继续走后续步骤,直接返回错误给调用方。

② Validating 看到的是"改完之后"的资源

因为 Mutating 先跑,所以验证阶段拿到的已经是补完默认值的资源。

③ 部分控制器有副作用

有些控制器在处理过程中会创建资源(比如更新配额)。如果后续被其他控制器拒绝,这些副作用不会自动回滚,需要配套的清理机制。这是生产环境中比较容易踩坑的地方。


四、常见准入控制器解析


4.1 LimitRanger

类型:Mutating + Validating

两件事:检查资源请求是否在 LimitRange 约束范围内;为没有设置资源限制的 Pod 自动补默认值。

比如你创建了一个 Pod,没写 resources.limits,LimitRanger 会自动帮你填上,不会报错也不会让容器无限制跑。


4.2 ResourceQuota

类型:Validating

控制 namespace 级别的资源总量上限。如果创建请求会导致超配额,直接拒绝。

复制代码
创建 Pod → 校验 namespace 已用量 + 新增用量 > 配额 → 拒绝

这是防止某个 namespace "撑爆集群"的核心手段。


4.3 NamespaceLifecycle

类型:Validating

三个职责:禁止在正在删除中的 namespace 里创建新资源;禁止操作不存在的 namespace;禁止删除系统保留 namespace(defaultkube-systemkube-public)。

这个一般不会主动关,关了容易出问题。


4.4 NamespaceExists

类型:Validating

确保请求中引用的 namespace 已经存在(注意:它不检查 Namespace 资源对象本身)。


4.5 ServiceAccount

类型:Mutating + Validating

主要做两件事:如果 Pod 没指定 SA,自动挂载 default ServiceAccount;确保指定的 SA 存在。

前文提过每个 namespace 都有一个 default SA,就是这个控制器自动创建的。


五、实战配置示例


场景 1:限制单个容器资源范围

复制代码
apiVersion: v1
kind: LimitRange
metadata:
  name: resource-limit
  namespace: dev
spec:
  limits:
  - type: Container
    default:
      cpu: 200m
      memory: 256Mi
    defaultRequest:
      cpu: 100m
      memory: 128Mi
    max:
      cpu: "1"
      memory: 1Gi

效果:没写资源限制的容器自动补 100m CPU / 128Mi 内存;超过 1核 / 1G 的请求直接拒绝创建。


场景 2:限制 namespace 资源总量

复制代码
apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: dev
spec:
  hard:
    pods: "20"
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"

超配额时会看到这类报错:

复制代码
Error from server (Forbidden): exceeded quota: dev-quota

场景 3:安全策略(Pod Security)

高版本 K8s 推荐直接用 PodSecurity 准入控制器,通过 namespace label 控制安全级别:

复制代码
kubectl label namespace dev \
  pod-security.kubernetes.io/enforce=restricted

效果:该 namespace 内禁止特权容器、禁止 root 用户运行、强制只读根文件系统。


六、插件管理操作


查看支持的插件

复制代码
kube-apiserver -h | grep enable-admission-plugins

查看当前启用的插件

复制代码
ps -ef | grep kube-apiserver | grep admission

启用插件

复制代码
kube-apiserver \
  --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ResourceQuota

禁用插件

复制代码
kube-apiserver \
  --disable-admission-plugins=PodNodeSelector

K8s 1.35 默认启用插件列表

复制代码
CertificateApproval, CertificateSigning, CertificateSubjectRestriction,
DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds,
LimitRanger, MutatingAdmissionWebhook, NamespaceLifecycle,
PersistentVolumeClaimResize, PodSecurity, Priority, ResourceQuota,
RuntimeClass, ServiceAccount, StorageObjectInUseProtection,
TaintNodesByCondition, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook

一般不建议随意禁用默认启用的插件,尤其是 NamespaceLifecycleResourceQuotaServiceAccount


七、踩坑经验总结


1)准入控制不等于权限控制

两者经常被混淆,区别如下:

机制 解决的问题
RBAC 有没有权限做这件事
准入控制 这件事做得对不对

用户有权限创建 Pod,不等于这个 Pod 可以被成功创建。


2)LimitRange 和 ResourceQuota 要配套用

只配 ResourceQuota,不配 LimitRange:Pod 没写资源请求,配额计算为 0,直接绕过了配额限制。两个一起配,才能真正控住。


3)Webhook 型控制器风险大

MutatingAdmissionWebhook / ValidatingAdmissionWebhook 虽然灵活,但 Webhook 服务挂了会导致所有请求卡住,配置错误会让集群资源全部无法创建。

建议:设置合理的 failurePolicyIgnoreFail);Webhook 服务本身要保证高可用。


4)副作用问题

某些控制器会在处理中创建资源(比如自动创建 SA、更新配额计数)。如果后续阶段拒绝了请求,这些副作用不会自动回滚。这类场景要特别注意清理逻辑,否则时间长了会产生"脏数据"。


5)调试失败请求看这两个地方

复制代码
# 看事件
kubectl get events -n dev

# 看详细原因
kubectl describe pod <pod-name> -n dev

八、总结

这篇核心就一句话:

准入控制 = 请求写入 etcd 前的最后一道规则校验

核心要点回顾:不拦截读取请求(get/list/watch 直接绕过);两阶段执行,Mutating 先改,Validating 再验;任意阶段拒绝则整个请求失败;部分控制器有副作用,需要关注清理;LimitRanger 和 ResourceQuota 要配套使用。

三道关卡串起来:

阶段 解决的问题
认证 你是谁
授权 你能干什么
准入控制 你这样做合不合理

RBAC 控制边界,准入控制把守细节。

相关推荐
闪电悠米13 分钟前
黑马点评-秒杀优化-04_lua_and_db_fallback
服务器·开发语言·网络·数据库·缓存·junit·lua
Yang961140 分钟前
风场光伏光缆分缆测损,DM-40A 光通信综合测试仪高效运维
网络·能源
努力搬砖的咸鱼43 分钟前
容器编排底层原理:Kubernetes 网络模型与 CNI 插件
网络·微服务·云原生·容器·架构·kubernetes
ylscode44 分钟前
Chrome桌面安全更新修复数百个漏洞
网络·windows·安全·安全威胁分析
Plastic garden44 分钟前
K8s介绍(2)POD架构
云原生·容器·kubernetes
.小小陈.1 小时前
从零构建可用 TCP 服务:从基础 Socket 到自定义协议与序列化
服务器·网络·tcp/ip
humors2211 小时前
六位数字密码表示
安全·网络安全·密码学
下北沢美食家1 小时前
WebSocket入门
网络·websocket·网络协议
zh路西法1 小时前
【rosbridge-websocket】跨网络的ROS1与ROS2通讯法(上)
linux·网络·c++·python·websocket·网络协议
梁辰兴1 小时前
计算机网络基础:电子邮件的信息格式
网络·计算机网络·电子邮件·计算机网络基础·梁辰兴·信息格式