公司刚上容器,开发小李兴冲冲地把新项目打包扔进 Kubernetes,结果第二天数据库被删了。一查日志,是他同事临时调试时手滑执行了 rm -rf,而这个操作本不该被允许。这事儿说到底,就是容器权限没管住。
容器不是沙盒,别以为它天生安全
很多人觉得,容器隔离了环境,就等于安全了。其实不然。默认情况下,一个容器里的进程可能拥有 root 权限,能干的事儿一点不少。比如挂载主机目录、修改网络配置,甚至穿透到宿主机执行命令。一旦某个容器被攻破,攻击者就能顺藤摸瓜,拿下整台机器。
从 Docker 到 Kubernetes,权限控制层层加码
在单机 Docker 环境里,可以通过 --user 参数指定运行用户,避免以 root 身份启动。比如:
docker run -d --user 1001:1001 -v /data:/app/data myapp:latest
这样即使容器被入侵,攻击者也只能以普通用户身份操作,限制了破坏范围。
到了 Kubernetes,权限管理更系统化。RBAC(基于角色的访问控制)是核心机制。你可以定义谁(User 或 ServiceAccount)能对哪些资源(Pod、Deployment 等)执行什么操作(get、list、create、delete)。
比如,给测试环境的 CI 机器人分配一个只读角色:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: test
name: ci-reader
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list"]
别忽略 Pod 安全策略
除了用户权限,Pod 本身的运行方式也得约束。Kubernetes 提供 PodSecurityPolicy(已弃用,推荐用 Gatekeeper 或 OPA)来限制容器是否能以特权模式运行、能不能挂载主机路径、能不能开启 CAP_SYS_ADMIN 这类危险能力。
例如,禁止所有 Pod 以特权模式启动:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false
allowedCapabilities: []
hostNetwork: false
hostIPC: false
hostPID: false
实际场景:运维和开发的权限怎么分
开发团队要能部署自己的服务,但不能碰别人的。运维可以查看所有日志,但不能随便删生产 Pod。这就需要精细化授权。
在命名空间级别划分是最常见的做法。每个团队有自己的命名空间,通过 RoleBinding 绑定对应权限。比如开发组只能管理 dev-team 命名空间下的 Deployment 和 ConfigMap,连 secrets 都看不到。
再配合网络策略(NetworkPolicy),限制容器间互访。比如前端服务只能访问后端 API,不能直连数据库容器。这样一来,即使某个服务被黑,横向移动也难得多。
别等出事才想起权限
很多团队一开始图省事,直接给所有人 cluster-admin 权限,说是“先跑起来再说”。结果时间一长,权限越堆越乱,谁也搞不清谁有啥权限。直到某天误操作引发故障,才意识到问题严重性。
从第一天就开始做权限划分,哪怕只是简单分个读写角色,也能避免后期大改。工具可以选原生 RBAC,也可以用外部方案如 Hashicorp Vault 做动态凭据管理。关键是形成习惯:谁要用权限,先申请,再审批,最小化授予。