集群安全不是只在网络层
很多团队一讲 K8s 安全,第一反应是「网络防火墙」。但在 Kubernetes 里,真正的风险点更多在权限和配置层:谁能在生产命名空间里改 Deployment?能不能把容器跑成 root?镜像里有没有藏后门?这些都不是防火墙能拦的。
所以 K8s 安全是分层的:身份与权限(RBAC)→ 准入拦截(准入控制)→ 镜像与运行时 → 网络策略 → 密钥管理。每一层拦一类风险,缺一不可。这一篇就按这个层次走一遍,最后给一套能直接抄走的最小基线。
网络防的是「外面的人」;RBAC 和准入控制防的是「里面的误操作和越权」。
- RBAC用角色绑定控制谁能对什么资源做什么操作。
- 准入控制资源进集群之前,按规则拦截不合规的配置。
- 最小权限默认不给权限,按需按需授予。
- 多集群按环境或业务拆分集群,爆炸半径隔离。
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 跑,前面准入控制已经能拦掉这一项,双保险。
多集群:从一个到多个
当业务大了之后,把所有东西塞进一个集群会越来越危险:一个配置错误可能同时打到所有业务。多集群治理的核心思路就是分区隔离——按环境(测试/预发/生产)或按业务线拆成多个集群,爆炸半径被天然隔小。
典型的多集群拆分:
- cluster-test 测试环境,随便折腾
- cluster-staging 预发,贴近生产配置
- cluster-prod-1 生产业务 A
- cluster-prod-2 生产业务 B(独立故障域)
多集群带来的新问题是配置和访问怎么统一管。一般做法是:每个集群一份 kubeconfig,用一个中央工具(如前面讲的 GitOps 方案)统一下发声明;人访问不同集群切不同 context。别为了省事给所有人 prod-1 的管理员权限,那就等于没拆。
密钥与配置管理
集群里总有一堆敏感信息:数据库密码、API 密钥、证书。这些东西最忌讳直接写进镜像或 Git 仓库。K8s 自己有 Secret 对象,但它只是 base64 编码、不是加密——真正生产做法是接外部密钥管理系统(云厂商的 KMS、或 sealed-secrets),让 Secret 密文落盘、运行时才解密注入。
另一条铁律:密钥要能轮换、要最小暴露。哪个服务用哪个密钥、多久没换了,心里要有数。定期轮换一次,发现泄露时才不会手忙脚乱。配合前面讲的准入控制,可以拦掉「把密码明文写进 Deployment env」这种最常见的失误。
一套最小安全基线
如果你现在的集群还没系统做过安全,按这个顺序落地:
第一步:盘点权限
- 找出所有 cluster-admin 绑定,砍掉不必要的
- 按岗位拆只读/可发布/管理员三档 Role
第二步:接准入控制
- 先开三条最基本的:禁特权容器、禁 root、必须设资源限制
第三步:CI 加镜像扫描
- 高危漏洞直接阻断发布
第四步:密钥出仓库
- 密码一律走外部密钥系统,不进 Git 不进镜像
第五步:按环境拆集群
- 至少把测试和生产分开,爆炸半径先隔小
安全这件事,没有「做完了」的一天,但把上面这五条先做到位,已经能挡住绝大多数常见事故。剩下的就靠定期演练(参考前面讲的混沌工程)和持续扫描慢慢收紧。记住一个原则:默认不信任,最小权限,出问题能立刻发现、立刻回滚——这比追任何最新的安全工具体系都重要。