某个运行了两年多的 OpenShift 应用一直非常稳定。某次由于 Node OOM,Pod 被驱逐并重新调度到其他节点。原本以为只是一次普通的重启,结果 Pod 无法启动,日志中出现大量文件和目录权限错误。
由于应用镜像、PVC 和 OpenShift 版本均未发生变化,问题一开始比较难定位。
故障现象
应用启动时出现类似错误:
1 | Permission denied |
查看 Pod 信息发现:
老 Pod:
1 | openshift.io/scc: anyuid |
新创建的 Pod:
1 | openshift.io/scc: restricted-v2 |
问题开始有了方向。
OpenShift SCC 机制
OpenShift 中的 SCC(Security Context Constraints)决定了 Pod 运行时的安全策略。
常见的 SCC 包括:
1 | restricted-v2 |
很多人会认为:
1 | openshift.io/scc: anyuid |
是 Deployment 或 StatefulSet 的固定配置。实际上并不是。
SCC 是在 Pod 创建时动态选择的:
1 | ServiceAccount + Pod Spec |
因此:
1 | 删除 Pod → 重新创建 Pod → 重新计算 SCC |
新 Pod 完全有可能获得与旧 Pod 不同的 SCC。
关键发现
检查一个两年前创建且从未重启过的 Pod:
1 | serviceAccountName: default |
说明系统安装时,default ServiceAccount 拥有 anyuid 权限,否则 Pod 不可能获得 AnyUID SCC。
进一步验证:
1 | oc auth can-i use scc/anyuid \ |
结果:
1 | no |
说明当前的 default ServiceAccount 已经失去了使用 AnyUID 的权限。
Root Cause
系统安装时,default ServiceAccount 允许使用 anyuid,因此创建出来的 Pod 使用 openshift.io/scc: anyuid。
后来某个时间点,SCC 或 RBAC 配置发生变化,导致 default ServiceAccount 无法再使用 anyuid。但由于旧 Pod 一直没有重建,问题始终没有暴露。
直到 Node OOM → Pod 被驱逐 → Pod 重建,OpenShift 重新选择 SCC。由于 AnyUID 已不可用,restricted-v2 成为新的 SCC。
为什么 Restricted-v2 会导致启动失败
Restricted-v2 要求容器使用随机非 Root UID,例如:
1 | uid=1000700000 |
而很多历史镜像中的目录权限是按照固定 UID 或 Root 用户设计的,例如 /opt/app、/app、/var/log、/data。当随机 UID 无法访问这些目录时,就会出现 Permission denied,应用启动失败。
解决方案
方案一:调整 SecurityContext(推荐)
1 | securityContext: |
或者根据应用实际情况调整 runAsUser、runAsGroup、fsGroup,使应用兼容 Restricted-v2。
方案二:恢复 AnyUID 权限
1 | oc adm policy add-scc-to-user anyuid \ |
验证:
1 | oc auth can-i use scc/anyuid \ |
返回 yes 后,重新创建 Pod 即可重新获得 AnyUID SCC。
排查过程中学到的经验
1. 长时间运行的 Pod 会隐藏问题
一个运行了几年都没有重建过的 Pod,并不能证明当前配置仍然正确。很多问题只有在 Pod 重建、节点迁移、集群升级时才会暴露。
2. SCC 是动态计算的
不要认为 openshift.io/scc: anyuid 会永久存在。每次创建 Pod 时都会重新计算。
3. 尽量不要依赖 Default ServiceAccount
推荐为应用创建专用 ServiceAccount(serviceAccountName: my-app-sa),避免未来权限调整影响整个 Namespace。
4. 优先兼容 Restricted-v2
从 OpenShift 安全模型的发展趋势来看,restricted-v2 已成为默认推荐方案。新开发的应用应尽量避免依赖 anyuid、privileged 等高权限 SCC。
总结
这次问题表面上看是文件权限异常(Permission denied),实际上根因是:
1 | 历史 Pod 使用 AnyUID |
对于长期运行的 OpenShift 集群,定期检查 SCC、ServiceAccount 和 SecurityContext 配置,是避免此类问题的有效手段。