写在前面

Kubernetes 把计算变成了“声明式 API”。对业务来说,这意味着弹性与效率;对安全来说,这意味着:

谁能调用哪些 API、谁能连到哪些 Pod、什么配置允许进入集群——这三道闸若失效,容器逃逸都不必发生,集群也会从内部被合法接管。

实战里最常见的失陷路径,往往不是全新 0day,而是:

  • ServiceAccount 绑了 cluster-admin
  • 默认允许全网互通,一破应用即可横扫;
  • 没有准入策略,特权 Pod、宿主机挂载、特权能力随意进集群。

本文聚焦 K8s 安全的三根支柱:

  1. RBAC(谁能对 API 做什么)
  2. NetworkPolicy(谁能和谁通信)
  3. 准入控制(什么对象能被创建/变更)

面向平台安全、DevSecOps、蓝队与授权红队。给出可落地的模型、反模式、检测点与加固顺序;示例清单用于教学与基线,落地前请按发行版与 CNI 能力验证。


一、先建立 K8s 安全全景

1.1 控制面与数据面

平面关键组件安全含义
控制面API Server、etcd、scheduler、controller-managerAPI 被盗 ≈ 集群被盗
数据面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 建议的加固顺序

  1. 关掉或收紧“人人可进”的匿名/过度匿名访问;
  2. 清理 cluster-admin 绑定;
  3. 上 Pod 安全基线(准入);
  4. 默认拒绝命名空间网络,再放行必要流量;
  5. 审计日志 + 检测规则;
  6. 供应链与运行时(镜像签名、运行时防护)。

本文覆盖其中 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/读文件打到后可盗用。

实战建议:

  1. 每个应用独立 SA,禁止共用 default 高权。
  2. automountServiceAccountToken: false,除非确实要访问 API。
  3. 使用有界、短时令牌(TokenRequest / 投影卷),减少长寿命 Secret 令牌。
  4. CI/CD、Ingress Controller、Operator 的 SA 单独审计,它们常是“隐式集群管理员”。

2.4 典型反模式

反模式 A:给开发组绑 cluster-admin“图省事”
后果:任一开发凭证泄漏 = 集群全失陷。
改法:按命名空间 Role;集群级操作走平台组 + 变更单。

反模式 B:Operator 全开 *
改法:按 CRD 细分;控制面与数据面权限拆开。

反模式 C:认为“只读”就安全
list/watch secretsget 大量资源对攻击者足够做地图与凭据收集。只读也要最小。

反模式 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 创建成功也不会生效——这是最常见的“假安全感”。

落地前验证:

  1. 集群使用的 CNI 是否声明支持 NetworkPolicy;
  2. 建试策略:默认拒绝 + 放行探测,用真流量验证;
  3. 观测网络插件组件健康与策略日志。

3.3 策略模型心智

对选中的 Pod:
  默认:无策略时通常全开(取决于实现)
  有策略后:仅允许规则中声明的流量(同方向)

注意:

  • Ingress 与 Egress 分开;
  • 只写 Ingress 时,Egress 可能仍全开(反之亦然);
  • 命名空间选择器、Pod 选择器、IPBlock 可组合;
  • DNS 放行常被忘记,导致“策略一生效应用全挂”。

3.4 推荐落地模式:默认拒绝 + 逐条放行

命名空间级基线思路:

  1. 给命名空间打标签,例如 net=isolated
  2. 对该命名空间所有 Pod 下发 default-deny ingress/egress
  3. 放行:
    • 命名空间内 DNS(kube-system 中 CoreDNS);
    • 应用所需的南北向(经 Ingress/网关);
    • 明确的后端端口(如 app → db:5432);
    • 可观测性 agent 所需出口(若需要)。
  4. 再建更细的服务级策略。

示例:默认拒绝 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/auditenforce,避免一刀切中断业务。

4.4 策略引擎要拦截的“高危 Pod 特征”

无论用 PSA、Gatekeeper 还是 Kyverno,下列应默认拒绝(例外走豁免清单):

  1. privileged: true
  2. 危险 capabilities(SYS_ADMINNET_ADMINSYS_PTRACE 等)
  3. 宿主机路径挂载(//etc/var/run/docker.sock/var/lib/kubelet 等)
  4. hostNetwork / hostPID / hostIPC
  5. 可写的根文件系统(按应用兼容逐步收紧)
  6. 以 root 运行(runAsNonRoot
  7. 未签名/非允许仓库的镜像
  8. 自动挂载高权 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 标签被改弱(restrictedprivileged);
  • 豁免账号创建特权工作负载。

五、三支柱串联:一张防御图

            创建特权 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、试扫网,验证告警;
  • 与镜像签名、运行时防护对接。

七、运维友好:如何少挨骂

安全变更失败,多半死在“突然全断”。建议:

  1. 先审计模式,后强制
  2. 每个命名空间有应用负责人对标签与端口清单签字;
  3. 提供自助文档:如何声明合法流量、如何申请豁免;
  4. 变更窗口做 NetworkPolicy,先观察 DNS/探针;
  5. 平台组保留紧急“破玻璃”流程(短时提权 + 全程审计)。

安全可控,且业务可发版,策略才能活过一个季度。


八、检查清单(可打印)

RBAC

  • 无业务主体绑 cluster-admin
  • 无通配符 *.*/* 给应用 SA
  • 独立 SA + 最小 verbs
  • 限制 secretspods/execbindescalateimpersonate
  • Audit 覆盖授权变更

NetworkPolicy

  • CNI 已验证策略生效
  • 敏感命名空间 default-deny
  • DNS/探针/Ingress 路径已放行
  • 策略变更受 RBAC 保护并告警
  • hostNetwork 例外受准入控制

准入控制

  • 业务命名空间 PSA 至少 baseline enforce
  • 拒绝 privileged、危险 hostPath、危险 capability
  • 镜像仓库白名单
  • webhook 高可用与配置审计
  • 豁免有期限

九、结语

Kubernetes 安全不是装一个扫描器就结束,而是把集群变成:

  • 手被 RBAC 管住
  • 身体被准入管住
  • 嘴巴和耳朵被 NetworkPolicy 管住

这三件事做好,很多“炫技型集群打穿”会变成:令牌没用、特权 Pod 起不来、横向连不通——攻击者只能困在已失陷的那个业务进程里,等你的运行时检测与响应。

建议你读完本文后立刻做三件极具体的事:

  1. 列出所有绑定到 cluster-admin 的主体,能删则删,不能删则换平台账号并加监控;
  2. 在一个预发命名空间验证 NetworkPolicy 是否真的拦截(而不是只 YAML 成功);
  3. 给生产业务命名空间打上 PSA enforce=baseline,先从非核心应用开始。

三件事落地后,再回头看本文的 90 天路线,你会发现 K8s 安全从“概念正确”变成了“集群上可验证的状态”——而这正是实战与 PPT 的差别。


附录 A:对象与职责速查

支柱关键对象一句话
RBACRole/Binding/SA谁能调用 API
NetworkPolicyNetworkPolicy + CNI谁能与谁通信
准入PSA/Webhook/策略引擎什么配置能进集群

附录 B:高危权限速记

secretspods/execpods/portforwardimpersonatebindescalate*create+任意 SA、改 networkpolicies、改 validatingwebhookconfigurations

更多推荐