集群安全不是只在网络层

很多团队一讲 K8s 安全,第一反应是「网络防火墙」。但在 Kubernetes 里,真正的风险点更多在权限和配置层:谁能在生产命名空间里改 Deployment?能不能把容器跑成 root?镜像里有没有藏后门?这些都不是防火墙能拦的。

所以 K8s 安全是分层的:身份与权限(RBAC)→ 准入拦截(准入控制)→ 镜像与运行时 → 网络策略 → 密钥管理。每一层拦一类风险,缺一不可。这一篇就按这个层次走一遍,最后给一套能直接抄走的最小基线。

网络防的是「外面的人」;RBAC 和准入控制防的是「里面的误操作和越权」。
本文核心知识点
  • RBAC用角色绑定控制谁能对什么资源做什么操作。
  • 准入控制资源进集群之前,按规则拦截不合规的配置。
  • 最小权限默认不给权限,按需按需授予。
  • 多集群按环境或业务拆分集群,爆炸半径隔离。
Kubernetes 安全与多集群治理配图:中央发光盾牌包围的控制台建筑、周围多个节点方块与门禁钥匙孔图标的蓝色扁平科技插画
安全是一层一层叠上去的,最外面那道防火墙只是其中一层。

RBAC:谁能对什么做什么

Kubernetes 的权限模型叫 RBAC(基于角色的访问控制)。核心是两个对象:Role(角色,定义「能做什么」)和 RoleBinding(绑定,把角色授给某个人或某个账号)。写一份最小的只读角色:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: prod
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get","list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: bind-pod-reader
  namespace: prod
subjects:
- kind: User
  name: zhangsan
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

这个例子里,zhangsan 在 prod 命名空间只能看 Pod,不能改、不能删。新手最常犯的错,是直接给 cluster-admin——那等于把整个集群的钥匙交出去。正确做法是按「岗位」拆角色:开发只读、运维可改 Deployment、DBA 只管数据库相关资源,互相不越界。

准入控制:资源进集群之前拦截

就算 RBAC 收紧了,还有一种情况:有权限的人提交了一份「合规但不安全」的配置——比如允许容器以 root 运行、没设资源限制。准入控制(Admission Controller)就是在资源写进 etcd 之前,多一道检查门,不合规直接拒绝:

# 一个典型的准入规则要点:
- 禁止 privileged 特权容器
- 必须设 resources.requests / limits
- 禁止以 root 用户运行(runAsNonRoot: true)
- 只允许从内部镜像仓库拉镜像
- 禁止挂载宿主机目录

实践上一般用 OPA Gatekeeper 或 Kyverno 这类策略引擎,把这些规则写成声明文件统一下发。它的价值在于:安全策略从「靠人记得」变成「集群自动检查」。新人提交了一个忘了设资源限制的 Deployment,不是上线后才被骂,而是提交的那一刻就被拒了。

镜像与运行时安全

权限和准入管住了「谁能提交什么」,但还有一个环节:跑起来的镜像本身安不安全。镜像里如果带了已知漏洞的依赖、或者有人偷偷塞了后门,前面那两层都查不出来。

最基础的三件事:第一,镜像扫描——CI 流水线里加一步,镜像构建完自动扫一遍已知漏洞,高危就阻断发布。第二,用官方基础镜像、别用随手拉的野镜像,别为了省事从陌生仓库拉个带漏洞的镜像当底座。第三,容器不要以 root 跑,前面准入控制已经能拦掉这一项,双保险。