Kubernetes 安全实战:RBAC、NetworkPolicy、准入控制
文章目录
写在前面
Kubernetes 把计算变成了“声明式 API”。对业务来说,这意味着弹性与效率;对安全来说,这意味着:
谁能调用哪些 API、谁能连到哪些 Pod、什么配置允许进入集群——这三道闸若失效,容器逃逸都不必发生,集群也会从内部被合法接管。
实战里最常见的失陷路径,往往不是全新 0day,而是:
- ServiceAccount 绑了
cluster-admin; - 默认允许全网互通,一破应用即可横扫;
- 没有准入策略,特权 Pod、宿主机挂载、特权能力随意进集群。
本文聚焦 K8s 安全的三根支柱:
- RBAC(谁能对 API 做什么)
- NetworkPolicy(谁能和谁通信)
- 准入控制(什么对象能被创建/变更)
面向平台安全、DevSecOps、蓝队与授权红队。给出可落地的模型、反模式、检测点与加固顺序;示例清单用于教学与基线,落地前请按发行版与 CNI 能力验证。
一、先建立 K8s 安全全景
1.1 控制面与数据面
| 平面 | 关键组件 | 安全含义 |
|---|---|---|
| 控制面 | API Server、etcd、scheduler、controller-manager | API 被盗 ≈ 集群被盗 |
| 数据面 | kubelet、kube-proxy、容器运行时、CNI | 节点失陷、网络绕过、逃逸 |
| 扩展面 | Ingress、Operator、Webhook、CI 插件 | 额外信任锚,常被忽略 |
三支柱大致对应:
RBAC → 控制“调用 API 的手”
准入控制 → 控制“什么样的意图能写入集群”
NetworkPolicy → 控制“工作负载之间的嘴与耳朵”
缺一不可:只有 RBAC,恶意 Pod 仍可扫内网;只有网络策略,攻击者仍可创建特权 Pod;只有准入,已泄露的高权账号仍可改策略。
1.2 身份从哪里来
- 用户:证书、OIDC、云身份——通常不存为 K8s 对象。
- ServiceAccount(SA):给 Pod 内进程用的身份;默认会挂载令牌。
- Group:认证层映射,RBAC 可按组授权。
- Node:节点身份,涉及 kubelet 与节点授权。
实战原则:人用短寿命身份 + 强认证;工作负载用最小 SA;禁止业务 Pod 共用默认 SA 的过量权限。
1.3 建议的加固顺序
- 关掉或收紧“人人可进”的匿名/过度匿名访问;
- 清理
cluster-admin绑定; - 上 Pod 安全基线(准入);
- 默认拒绝命名空间网络,再放行必要流量;
- 审计日志 + 检测规则;
- 供应链与运行时(镜像签名、运行时防护)。
本文覆盖其中 2~5 的主干。
二、RBAC 实战
2.1 核心对象
| 对象 | 作用域 | 说明 |
|---|---|---|
| Role | 命名空间 | 定义对资源的 verbs |
| RoleBinding | 命名空间 | 把 Role 绑到用户/组/SA |
| ClusterRole | 集群 | 可跨命名空间或管集群级资源 |
| ClusterRoleBinding | 集群 | 把 ClusterRole 绑到主体 |
关键理解:
- 权限来自 Role/ClusterRole 的 rules;
- Binding 只负责“给谁”;
- 授权是累加的,没有“拒绝优先”的经典 ACL(需靠不授予 + 准入/策略引擎补充)。
2.2 Rule 里真正危险的字段
rules:
- apiGroups: [""]
resources: ["pods", "secrets"]
verbs: ["get", "list", "watch", "create", "delete", "patch", "update"]
高危组合示例:
| 权限 | 风险 |
|---|---|
secrets 的 get/list | 凭证盗窃 |
pods/exec | 进容器执行 |
pods/portforward | 隧道绕过边界 |
create on pods + 任意 SA | 提权跳板 |
escalate / bind | 自我赋权 |
impersonate | 冒充他人 |
* on *.* | 等于管理员 |
create on clusterrolebindings | 直通提权 |
授权评审时不要只看角色名,要看 resources × verbs。
2.3 ServiceAccount:最容易被忽略的身份
默认行为(随版本与配置变化,需以集群为准):
- Pod 不指定 SA 时用
default; - 令牌可能自动挂载进 Pod,被应用层 SSRF/读文件打到后可盗用。
实战建议:
- 每个应用独立 SA,禁止共用
default高权。 automountServiceAccountToken: false,除非确实要访问 API。- 使用有界、短时令牌(TokenRequest / 投影卷),减少长寿命 Secret 令牌。
- CI/CD、Ingress Controller、Operator 的 SA 单独审计,它们常是“隐式集群管理员”。
2.4 典型反模式
反模式 A:给开发组绑 cluster-admin“图省事”
后果:任一开发凭证泄漏 = 集群全失陷。
改法:按命名空间 Role;集群级操作走平台组 + 变更单。
反模式 B:Operator 全开 *
改法:按 CRD 细分;控制面与数据面权限拆开。
反模式 C:认为“只读”就安全
list/watch secrets、get 大量资源对攻击者足够做地图与凭据收集。只读也要最小。
反模式 D:RoleBinding 绑到 system:authenticated
等于给所有通过认证的人开门。极少场景需要,必须极严审查。
2.5 授权自查命令(只读)
# 某 SA 能否做某动作
kubectl auth can-i create pods --as=system:serviceaccount:prod:app-sa -n prod
# 查看绑定
kubectl get clusterrolebinding,rolebinding -A
# 谁拥有 cluster-admin
kubectl get clusterrolebinding -o wide | grep -i cluster-admin
# 解析某主体有效权限(可用 kubectl-who-can 等插件辅助)
kubectl describe clusterrolebinding <name>
把 can-i --list 纳入发版前检查,对高权 SA 做月度回顾。
2.6 RBAC 与攻击链(防御视角)
常见链:
应用 RCE
→ 读 /var/run/secrets/.../token
→ 调 API list secrets / create privileged pod
→ 节点逃逸或云元数据
断链:
- 令牌不自动挂载;
- SA 不能 create privileged pod(交给准入拒绝);
- SA 不能 list 全集群 secrets;
- 网络策略禁止随意访问 API Server(仍要保留必要 DNS/平台通道,需精细设计)。
2.7 RBAC 检测点
- 新增 ClusterRoleBinding 指向
cluster-admin或含escalate|bind|impersonate; - 短时间大量
get/list secrets; - 来自业务命名空间 SA 的
pods/exec; - 非变更窗口创建绑定。
开启 API Audit 日志 并转发到 SIEM,否则 RBAC 再漂亮也不可审计。
三、NetworkPolicy 实战
3.1 它解决什么问题
默认情况下,很多集群里 Pod 扁平互通。一个被控前端 Pod 可以直接连:
- 同命名空间其它服务;
- 其它命名空间数据库;
- 节点元数据/内网;
- 有时甚至摸到管控组件(视网络模型)。
NetworkPolicy 用标签选择器定义 Ingress/Egress 允许规则,把东西向流量收成“白名单”。
3.2 前置条件(必须写进方案)
NetworkPolicy 不是 API Server 内置强制执行的数据面,而依赖 CNI 插件支持(Calico、Cilium、Antrea、Kube-router 等)。
若 CNI 不支持或未启用策略,YAML 创建成功也不会生效——这是最常见的“假安全感”。
落地前验证:
- 集群使用的 CNI 是否声明支持 NetworkPolicy;
- 建试策略:默认拒绝 + 放行探测,用真流量验证;
- 观测网络插件组件健康与策略日志。
3.3 策略模型心智
对选中的 Pod:
默认:无策略时通常全开(取决于实现)
有策略后:仅允许规则中声明的流量(同方向)
注意:
- Ingress 与 Egress 分开;
- 只写 Ingress 时,Egress 可能仍全开(反之亦然);
- 命名空间选择器、Pod 选择器、IPBlock 可组合;
- DNS 放行常被忘记,导致“策略一生效应用全挂”。
3.4 推荐落地模式:默认拒绝 + 逐条放行
命名空间级基线思路:
- 给命名空间打标签,例如
net=isolated。 - 对该命名空间所有 Pod 下发 default-deny ingress/egress。
- 放行:
- 命名空间内 DNS(kube-system 中 CoreDNS);
- 应用所需的南北向(经 Ingress/网关);
- 明确的后端端口(如 app → db:5432);
- 可观测性 agent 所需出口(若需要)。
- 再建更细的服务级策略。
示例:默认拒绝 Ingress(教学示意)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-ingress
namespace: prod
spec:
podSelector: {}
policyTypes: ["Ingress"]
示例:仅允许前端标签访问后端 8080(示意)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-allow-frontend
namespace: prod
spec:
podSelector:
matchLabels:
app: backend
policyTypes: ["Ingress"]
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
生产环境请按真实端口、命名空间选择器与 DNS 规则补全,并做回归测试。
3.5 Egress 的战略价值
只控 Ingress 时,被控 Pod 仍可:
- 扫网、连 Redis/内网;
- 访问云元数据(若网络可达);
- 回连攻击者 C2。
Egress 白名单能显著提高攻击成本,但也最容易误伤(外呼 API、更新、遥测)。建议:
- 敏感命名空间(数据层、密钥相关)先做强 Egress;
- 使用命名的外部端点清单或 Egress Gateway;
- Cilium/服务网格等可提供 L7/DNS 级更细控制。
3.6 典型坑
| 坑 | 说明 |
|---|---|
| 策略未生效 | CNI 不支持或未安装策略控制器 |
| DNS 忘放行 | 应用表现为偶发失败 |
| 只标 Pod 不标流量路径 | Ingress Controller、服务网格旁路未考虑 |
| 健康检查被挡 | 探针源不在允许列表 |
| 以为能替防火墙 | 节点级、hostNetwork、部分 CNI 旁路仍需别的控制 |
| 标签随意改 | 选择器失效导致全断或全开 |
3.7 NetworkPolicy 与 RBAC/准入的配合
- 准入强制:敏感命名空间必须存在 default-deny(可用策略引擎检查)。
- RBAC:谁能改 NetworkPolicy 本身要严控——改策略等于改防火墙。
- 审计:对 NetworkPolicy 的 create/update/delete 做高优先级告警。
3.8 检测点
- 无策略的命名空间突然出现高东西向连接(需网络可观测);
- 被控 Pod 对大量集群 IP 端口扫描;
- 策略被删除或改为空选择器“形同虚设”;
- hostNetwork Pod 绕过策略(需准入禁止)。
四、准入控制实战
4.1 准入控制在流水线中的位置
请求进入 API Server 后的简化顺序:
认证 → 授权(RBAC) → 变更准入(Mutating) → 对象校验 → 验证准入(Validating) → 写入 etcd
因此:
- RBAC 说“你能不能提交”;
- 准入说“你提交的内容合不合法”。
攻击者有建 Pod 权限不等于能建特权 Pod——若验证准入拒绝。
4.2 内置与常用机制
| 机制 | 类型 | 用途 |
|---|---|---|
| 限制范围 LimitRange / 资源配额 | 资源治理 | 防资源滥用 |
| Pod Security Admission(PSA) | 验证 | 替代旧 PSP 的命名空间级 Pod 安全 |
| Mutating Admission Webhook | 变更 | 注入 sidecar、默认标签 |
| Validating Admission Webhook | 验证 | 拒绝危险配置 |
| OPA Gatekeeper / Kyverno / 等 | 策略即代码 | 企业级规则库 |
| ImagePolicy(若启用) | 验证 | 镜像来源 |
4.3 Pod Security Admission:应作为底线
PSA 常用三级(概念):
| 级别 | 含义 |
|---|---|
| privileged | 几乎无限制(仅特殊命名空间) |
| baseline | 防已知特权升级 |
| restricted | 强硬化(非 root、限制能力等) |
实践建议:
kube-system等系统命名空间单独评估;- 业务命名空间默认
baseline,高敏restricted; - 用命名空间标签启用,例如(以官方文档字段为准):
# 示意:请按当前版本官方文档书写
apiVersion: v1
kind: Namespace
metadata:
name: prod
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
先 warn/audit 再 enforce,避免一刀切中断业务。
4.4 策略引擎要拦截的“高危 Pod 特征”
无论用 PSA、Gatekeeper 还是 Kyverno,下列应默认拒绝(例外走豁免清单):
privileged: true- 危险 capabilities(
SYS_ADMIN、NET_ADMIN、SYS_PTRACE等) - 宿主机路径挂载(
/、/etc、/var/run/docker.sock、/var/lib/kubelet等) hostNetwork/hostPID/hostIPC- 可写的根文件系统(按应用兼容逐步收紧)
- 以 root 运行(
runAsNonRoot) - 未签名/非允许仓库的镜像
- 自动挂载高权 SA 令牌的组合
豁免必须:有工单、有期限、有负责人、有替代方案。
4.5 Mutating Webhook 的双刃剑
变更准入可自动注入安全配置(只读根、seccomp),也可被攻击者利用——若 webhook 被劫持或配置了恶意 URL。
加固:
- webhook 配置的 RBAC 极严;
- TLS 与合法 CA;
failurePolicy明确(Fail 关闭 vs Ignore 放行的风险权衡);- 监控 webhook 可用性,防“打挂 webhook + Ignore = 策略失效”。
4.6 准入与供应链
把镜像策略放进准入:
- 仅允许企业仓库;
- 要求签名与漏洞扫描门禁标签;
- 拒绝
latest或不可变标签策略。
这样 RBAC 即使给了 create pods,也拖不进任意公共恶意镜像。
4.7 检测点
- 短时间大量准入拒绝(可能在试探策略边界);
- webhook 配置变更;
- 命名空间 PSA 标签被改弱(
restricted→privileged); - 豁免账号创建特权工作负载。
五、三支柱串联:一张防御图
创建特权 Pod 请求
│
▼
RBAC 放行? ──否──► 拒绝(审计)
│是
▼
变更准入注入默认安全配置
│
▼
验证准入 / PSA / 策略引擎 ──否──► 拒绝
│是
▼
Pod 落地
│
▼
NetworkPolicy:仅允许必要东西向
│
▼
运行时检测:异常进程/逃逸行为
攻击者要成功,需要权限、策略漏洞、网络空档同时对齐——这正是纵深防御要的效果。
5.1 合成攻击与断点(教学)
故事:业务 SA 可创建 Pod;无 PSA;无 NetworkPolicy。
攻击者:盗令牌 → 建 privileged Pod → 挂载宿主机 → 逃逸 → 平扫集群网络。
断点对照:
| 控制 | 效果 |
|---|---|
| RBAC 禁止该 SA create pods | 链断于 API |
| 准入拒绝 privileged/hostPath | 链断于落地 |
| NetworkPolicy 禁东西向与元数据 | 减损横向 |
| 令牌不挂载 + 短时令牌 | 提高盗用成本 |
六、30/60/90 天落地路线
前 30 天:可见与止血
- 导出所有 ClusterRoleBinding,清理明显过度授权;
- 开启 API Audit,转发安全相关 verb;
- 确认 CNI 是否支持 NetworkPolicy;
- 选 1~2 个非核心命名空间试 PSA
warn; - 禁止新创建:privileged、docker.sock 挂载(策略引擎或手工门禁)。
30~60 天:结构化
- 业务命名空间 default-deny 网络 + DNS/必要放行;
- SA 一应用一账户,去掉无用 automount;
- PSA 从 warn 到 enforce(baseline);
- 建立豁免流程;
- CI 集成
kubectl auth can-i与策略 dry-run。
60~90 天:运营化
- restricted 向高敏命名空间推进;
- Egress 控制与外部端点清单;
- webhook/策略规则版本化与仓库托管;
- 红蓝演练:盗 SA、试建特权 Pod、试扫网,验证告警;
- 与镜像签名、运行时防护对接。
七、运维友好:如何少挨骂
安全变更失败,多半死在“突然全断”。建议:
- 先审计模式,后强制;
- 每个命名空间有应用负责人对标签与端口清单签字;
- 提供自助文档:如何声明合法流量、如何申请豁免;
- 变更窗口做 NetworkPolicy,先观察 DNS/探针;
- 平台组保留紧急“破玻璃”流程(短时提权 + 全程审计)。
安全可控,且业务可发版,策略才能活过一个季度。
八、检查清单(可打印)
RBAC
- 无业务主体绑
cluster-admin - 无通配符
*.*/*给应用 SA - 独立 SA + 最小 verbs
- 限制
secrets、pods/exec、bind、escalate、impersonate - Audit 覆盖授权变更
NetworkPolicy
- CNI 已验证策略生效
- 敏感命名空间 default-deny
- DNS/探针/Ingress 路径已放行
- 策略变更受 RBAC 保护并告警
- hostNetwork 例外受准入控制
准入控制
- 业务命名空间 PSA 至少 baseline enforce
- 拒绝 privileged、危险 hostPath、危险 capability
- 镜像仓库白名单
- webhook 高可用与配置审计
- 豁免有期限
九、结语
Kubernetes 安全不是装一个扫描器就结束,而是把集群变成:
- 手被 RBAC 管住;
- 身体被准入管住;
- 嘴巴和耳朵被 NetworkPolicy 管住。
这三件事做好,很多“炫技型集群打穿”会变成:令牌没用、特权 Pod 起不来、横向连不通——攻击者只能困在已失陷的那个业务进程里,等你的运行时检测与响应。
建议你读完本文后立刻做三件极具体的事:
- 列出所有绑定到
cluster-admin的主体,能删则删,不能删则换平台账号并加监控; - 在一个预发命名空间验证 NetworkPolicy 是否真的拦截(而不是只 YAML 成功);
- 给生产业务命名空间打上 PSA
enforce=baseline,先从非核心应用开始。
三件事落地后,再回头看本文的 90 天路线,你会发现 K8s 安全从“概念正确”变成了“集群上可验证的状态”——而这正是实战与 PPT 的差别。
附录 A:对象与职责速查
| 支柱 | 关键对象 | 一句话 |
|---|---|---|
| RBAC | Role/Binding/SA | 谁能调用 API |
| NetworkPolicy | NetworkPolicy + CNI | 谁能与谁通信 |
| 准入 | PSA/Webhook/策略引擎 | 什么配置能进集群 |
附录 B:高危权限速记
secrets、pods/exec、pods/portforward、impersonate、bind、escalate、*、create+任意 SA、改 networkpolicies、改 validatingwebhookconfigurations。
更多推荐
所有评论(0)