【架构实战】Kubernetes安全加固实战:从RBAC到Pod Security Standards的完整防护体系
把应用跑进Kubernetes只是第一步。一旦上生产,安全问题立刻浮出水面:谁有权限访问集群?Pod能随便跑特权容器吗?容器逃逸了怎么办?这篇把Kubernetes的安全体系从认证、授权、准入控制到运行时防护拆解一遍,给你一套生产可用的防护方案。
一、K8s安全的三层模型
Kubernetes的安全模型可以抽象为三个关卡:
- 认证(Authentication):你是谁?(验证身份)
- 授权(Authorization):你能干什么?(验证权限)
- 准入控制(Admission Control):你提交的请求合规吗?(验证请求内容)
三层关卡串在一起,每一层都能拦截非法请求。理解了这个模型,安全问题就是"在哪一层加强防护"的选择题。
二、认证:谁有资格进集群
Kubernetes支持多种认证方式,生产环境通常组合使用:
2.1 客户端证书认证
最常用的方式。每个用户/服务账户绑定一个客户端证书,API Server通过证书CN(Common Name)识别身份。kubeconfig文件里的client-certificate就是这东西。
注意:证书一旦签发,权限就跟着证书走。吊销权限需要重新签发证书,管理成本高。建议用短期证书(如24小时有效期)+ 自动续期工具(如cert-manager)。
2.2 Service Account Token
Pod访问API Server默认用ServiceAccount的JWT Token。Token挂载在/var/run/secrets/kubernetes.io/serviceaccount/token。Kubernetes会自动验证Token签名和过期时间。
增强做法:
- 开启
BoundServiceAccountTokenVolume(Kubernetes 1.20+),Token会定期轮换; - 用
ServiceAccountTokenPodNodeInfo绑定Token到Pod所在节点,防Token被盗用后跨节点使用。
2.3 OIDC集成
企业环境常用OIDC(如Keycloak、Dex、Azure AD)对接现有身份系统。用户登录后拿到OIDC Token,API Server验证Token并映射到Kubernetes用户。
配置示例:
--oidc-issuer-url=https://keycloak.example.com/auth/realms/myrealm--oidc-client-id=kubernetes--oidc-username-claim=email--oidc-groups-claim=groups这样就能用公司SSO登录kubectl,权限按OIDC里的group自动映射。
三、授权:RBAC到底怎么配
认证通过后,进入授权阶段。Kubernetes默认用RBAC(Role-Based Access Control)。
3.1 RBAC的四要素
- Role/ClusterRole:定义"能操作哪些资源"(规则集合)
- RoleBinding/ClusterRoleBinding:绑定Role到User/Group/ServiceAccount
Role是namespace级别,ClusterRole是集群级别。绑定也分namespace级(RoleBinding)和集群级(ClusterRoleBinding)。
3.2 最小权限原则
新手最容易犯的错是绑定cluster-admin给普通用户。正确做法是:
- 按namespace隔离:不同团队/环境用不同namespace;
- 定义精细Role:只授权必要的操作,如只读权限:
apiVersion:rbac.authorization.k8s.io/v1kind:Rolemetadata:name:pod-readernamespace:devrules:-apiGroups:[""]resources:["pods","pods/log"]verbs:["get","list","watch"]- 用Group而非User绑定:人员离职/调岗时改Group成员即可,无需改RoleBinding。
3.3 常用Role模板
| 场景 | 推荐Role |
|---|---|
| 开发者查看日志 | pod-reader(自定义,只读pod/log) |
| CI/CD部署应用 | deployer(自定义,可create/update deployment) |
| 运维管理namespace | admin(内置,namespace级完全控制) |
| 集群只读审计 | view(内置,集群级只读) |
四、准入控制:请求合规性校验
授权通过后,请求还要过准入控制器的审查。这里可以拦截非法的Pod创建请求、注入sidecar、强制添加标签等。
4.1 准入控制器的类型
- ValidatingAdmissionWebhook:只校验,不修改对象(如禁止privileged容器)
- MutatingAdmissionWebhook:可以修改对象(如自动注入istio-proxy容器)
两者配合,先Mutating(修改),再Validating(校验)。
4.2 生产必开的准入控制器
- NamespaceLifecycle:防止在已删除的namespace创建资源
- LimitRanger:限制Pod资源request/limit,防止资源耗尽
- ResourceQuota:namespace资源配额限制
- PodSecurityPolicy(已废弃,用Pod Security Standards替代)
- NodeRestriction:限制kubelet只能修改自己节点上的Pod
4.3 自定义Webhook实战
比如禁止在default namespace部署应用:
# 准入webhook示例(Python Flask)fromflaskimportFlask,request,jsonify app=Flask(__name__)@app.route('/validate',methods=['POST'])defvalidate():req=request.json namespace=req['request']['namespace']ifnamespace=='default':returnjsonify({"response":{"allowed":False,"status":{"message":"禁止在default namespace部署应用"}}})returnjsonify({"response":{"allowed":True}})部署为ValidatingAdmissionWebhook后,所有在default namespace创建Pod的请求都会被拦截。
五、Pod Security Standards:容器运行时防护
Kubernetes 1.25废弃了PodSecurityPolicy(PSP),引入Pod Security Standards(PSS),用namespace标签声明安全级别:
5.1 三个安全级别
| 级别 | 标签值 | 限制强度 | 适用场景 |
|---|---|---|---|
| Privileged | enforce: privileged | 无限制 | 系统组件、infra Pod |
| Baseline | enforce: baseline | 禁止明显危险配置 | 一般应用 |
| Restricted | enforce: restricted | 严格限制 | 安全敏感应用 |
5.2 Baseline级别禁止的操作
- 特权容器(
privileged: true) - 挂载宿主机路径(
hostPath) - 使用宿主机网络/IPC/PID命名空间
- 添加危险capabilities(如SYS_ADMIN)
5.3 Restricted级别额外要求
- 必须以非root用户运行(
runAsNonRoot: true) - 只读根文件系统(
readOnlyRootFilesystem: true) - 禁止特权升级(
allowPrivilegeEscalation: false) - Seccomp profile必填
5.4 实施方式
在namespace打标签:
kubectl label namespace myapp\pod-security.kubernetes.io/enforce=restricted\pod-security.kubernetes.io/enforce-version=latest此后该namespace所有Pod必须符合restricted级别要求,否则创建失败。
六、运行时安全:容器逃逸后怎么办
假设攻击者已经进入容器内部,如何限制其破坏范围?
6.1 只读根文件系统
readOnlyRootFilesystem: true防止容器内被写入恶意文件。
6.2 限制capabilities
默认容器拥有少量capabilities(如NET_BIND_SERVICE)。去掉所有不必要的:
securityContext:capabilities:drop:["ALL"]add:["NET_BIND_SERVICE"]# 只保留必要能力6.3 Seccomp & AppArmor
- Seccomp:限制容器能调用的系统调用(如禁止
ptrace、mount) - AppArmor:限制容器能访问的文件路径和权限
Kubernetes 1.25+默认启用Seccomp,建议显式配置:
securityContext:seccompProfile:type:RuntimeDefault# 使用容器运行时默认profile6.4 网络隔离
用NetworkPolicy限制Pod间通信,配合Cilium的策略引擎做更细粒度的控制(如只允许访问特定Service的特定端口)。
七、审计日志:谁干了什么
开启审计日志,所有对API Server的请求都会记录:
# kube-apiserver启动参数--audit-log-path=/var/log/kubernetes/audit.log--audit-log-maxage=30--audit-log-maxbackup=10--audit-policy-file=/etc/kubernetes/audit-policy.yaml审计策略示例:
apiVersion:audit.k8s.io/v1kind:Policyrules:-level:RequestResponseresources:-group:""resources:["pods","secrets"]verbs:["create","update","delete"]-level:Metadataresources:-group:""resources:["pods"]verbs:["get","list"]定期审计日志可以发现异常行为(如半夜有人批量删除Pod)。
八、安全检查清单
| 检查项 | 推荐配置 |
|---|---|
| 匿名访问 | --anonymous-auth=false |
| RBAC模式 | --authorization-mode=RBAC |
| 客户端证书 | 短期证书 + 自动轮换 |
| ServiceAccount Token | 启用BoundServiceAccountTokenVolume |
| namespace隔离 | 不同团队/环境用不同namespace |
| Pod Security | 至少enforce=baseline |
| NetworkPolicy | 配置namespace隔离策略 |
| 审计日志 | 记录敏感操作(create/delete/update) |
| 容器镜像 | 只允许可信镜像仓库 |
| 节点访问 | 禁用SSH,用kubectl exec代替 |
九、小结
Kubernetes安全是个系统工程,没有一招鲜的银弹。核心思路:
- 认证做牢:OIDC集成企业SSO,ServiceAccount Token绑定到Pod;
- RBAC做细:按namespace隔离,最小权限原则;
- 准入做硬:Webhook拦截非法请求,强制安全标准;
- 运行时做绝:只读文件系统、Seccomp、NetworkPolicy多管齐下;
- 审计做全:记录所有敏感操作,定期回溯。
记住:安全没有终点,只有持续的加固和监控。定期审计、及时升级、关注CVE,才能在攻防博弈中立于不败之地。
下一篇预告:Kubernetes故障排查全景图——从Pod起不来到集群雪崩的诊断手册。