3、Kubernetes安全架构:RBAC、网络策略、Pod安全策略
聊到Kubernetes安全,很多人第一反应就是「搞个网络隔离」。其实不然。我个人的经验是,K8s的安全架构更像一个层层递进的防御体系。你想想看,从谁可以操作集群,到Pod之间能不能通信,再到Pod本身能不能干危险的事——这三层缺一不可。
今天我们就来拆解这三个核心组件:RBAC、网络策略、Pod安全策略。嗯,它们各自解决什么问题,又该怎么配合使用。
3.1 RBAC:谁可以做什么
RBAC,全称是Role-Based Access Control。说白了,就是「什么人能对什么资源做什么操作」。我在项目中遇到过不少团队,上来就给所有人cluster-admin权限。结果呢?一个实习生误删了namespace,整个dev环境崩了。
RBAC的核心概念其实就四个:
- Subject:谁在操作?可以是User、Group、ServiceAccount。
- Resource:操作什么?Pod、Service、Deployment、Node等。
- Verb:做什么?get、list、create、update、delete等。
- Role / ClusterRole:把资源和动词打包成一个角色。
这里有个关键区别:Role是namespace级别的,ClusterRole是集群级别的。你想想看,如果你要授权一个用户只能看default命名空间的Pod,那就用Role。如果你要授权他看所有命名空间的Pod,那就得用ClusterRole。
核心原则:最小权限原则
只给每个主体恰好够用的权限。多一分都是风险。
来看一个实际例子。假设我们有个CI/CD系统,它需要一个ServiceAccount来部署应用:
apiVersion: v1
kind: ServiceAccount
metadata:
name: cicd-bot
namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: deployer
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "create", "update", "patch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: cicd-bot-binding
namespace: production
subjects:
- kind: ServiceAccount
name: cicd-bot
namespace: production
roleRef:
kind: Role
name: deployer
apiGroup: rbac.authorization.k8s.io
你看,这个ServiceAccount只能操作production命名空间的Deployment和Pod。它不能删Service,不能动Node,更不能看其他命名空间的东西。我曾经见过一个CI系统因为权限过大,误操作把生产环境的Ingress给删了——嗯,那天的故障复盘会,气氛很凝重。
我的习惯:每次创建RoleBinding或ClusterRoleBinding之后,先用kubectl auth can-i验证一下权限。比如:kubectl auth can-i --as=system:serviceaccount:production:cicd-bot create deployments。确认没问题再上线。
3.2 网络策略:Pod之间的防火墙
默认情况下,K8s集群里的所有Pod都可以互相通信。这听起来很方便,但你想过没有——如果攻击者攻破了一个Web Pod,他就能直接访问数据库Pod。这太危险了。
网络策略(NetworkPolicy)就是来解决这个问题的。它本质上是一个Pod级别的防火墙规则。你可以控制:
- 入站规则(Ingress):哪些来源可以访问这个Pod
- 出站规则(Egress):这个Pod可以访问哪些目标
这里要注意,网络策略需要CNI插件的支持。不是所有K8s集群都默认支持。我常用的Calico、Cilium都支持,但Flannel默认不支持。嗯,选CNI的时候要留意这一点。
来看一个典型的三层架构隔离策略:
# 允许前端访问后端
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
---
# 只允许后端访问数据库
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-to-database
namespace: production
spec:
podSelector:
matchLabels:
app: database
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: backend
ports:
- protocol: TCP
port: 5432
这个配置意味着:
- 前端Pod只能访问后端Pod的8080端口
- 后端Pod只能访问数据库Pod的5432端口
- 数据库Pod不接受来自其他任何Pod的流量
我曾经踩过的坑:网络策略默认是「白名单」机制。也就是说,你一旦创建了任何一条NetworkPolicy,所有未显式允许的流量都会被拒绝。我曾经在迁移环境时,忘了给监控系统加白名单,结果Prometheus抓不到指标,告警全哑了。排查了整整两个小时才发现是网络策略的问题。
我个人建议,在实施网络策略时,先以「审计模式」运行一段时间。也就是先创建策略但不启用,观察流量模式,确认无误后再正式生效。很多CNI插件都支持这种模式。
3.3 Pod安全策略:限制Pod的行为
RBAC管的是人,网络策略管的是流量。那Pod本身呢?一个Pod能不能以root用户运行?能不能挂载宿主机目录?能不能使用hostNetwork?这些就是Pod安全策略(Pod Security Policy,简称PSP)要管的事。
不过,K8s在1.21版本之后弃用了PSP,转而推荐使用Pod Security Admission(PSA)。嗯,这里要注意,如果你还在用旧版PSP,建议尽快迁移。
PSA定义了三个安全等级:
| 等级 | 说明 | 典型限制 |
|---|---|---|
| Privileged | 无限制,完全信任 | 无限制 |
| Baseline | 最小限制,防止已知特权升级 | 禁止hostNetwork、禁止privileged容器、禁止hostPID等 |
| Restricted | 严格限制,遵循Pod安全最佳实践 | 禁止所有特权、必须以非root运行、必须使用只读根文件系统等 |
实际使用中,我一般这样分配:
- 系统组件(如kube-proxy、CNI插件)用Privileged
- 普通业务应用用Restricted
- 需要特殊权限的中间件(如某些日志采集器)用Baseline
来看一个Restricted级别的配置示例:
apiVersion: v1
kind: Namespace
metadata:
name: secure-app
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
---
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
namespace: secure-app
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: nginx:latest
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
ports:
- containerPort: 80
你看,这个Pod明确要求:不能以root运行、不能提权、不能有额外能力、根文件系统只读。嗯,这基本堵死了大部分容器逃逸的路径。
我的建议:先在namespace级别设置warn和audit模式,观察一段时间。确认没有误伤后再启用enforce模式。我曾经在一个大版本升级时直接启用了Restricted策略,结果有十几个旧Pod启动失败——因为它们都用了root用户。那天的回滚操作,我到现在还记得。
3.4 三者如何协同
这三个组件不是孤立的。它们构成了一个纵深防御体系:
- RBAC:控制谁可以操作集群资源。这是第一道门。
- 网络策略:控制Pod之间的流量。这是第二道墙。
- Pod安全策略:控制Pod本身的行为。这是最后一道锁。
举个例子。假设攻击者通过Web漏洞拿到了一个Pod的shell:
- 如果RBAC配置得当,这个Pod的ServiceAccount权限很小,攻击者无法操作集群资源。
- 如果网络策略配置得当,攻击者无法从这个Pod横向移动到数据库Pod。
- 如果Pod安全策略配置得当,攻击者无法提权、无法挂载宿主机目录、无法逃逸。
三层防护,一层比一层深入。你想想看,就算某一层被突破了,还有后面的层兜底。这就是纵深防御的精髓。
总结一句话:RBAC管人,网络策略管网,Pod安全策略管Pod本身。三者缺一不可,配合使用才能构建真正安全的K8s集群。
好了,这一章的内容就到这里。下一章我们会聊聊容器镜像安全——嗯,那个环节也经常出问题。到时候再细说。