OpenShift Pod重建后权限异常:一次 SCC 变更引发的问题

背景

某个运行了两年多的 OpenShift 应用一直非常稳定。

某次由于 Node OOM,Pod 被驱逐并重新调度到其他节点。原本以为只是一次普通的重启,结果 Pod 无法启动,日志中出现大量文件和目录权限错误。

由于应用镜像、PVC 和 OpenShift 版本均未发生变化,因此问题一开始比较难定位。


故障现象

应用启动时出现类似错误:

1
2
3
Permission denied
Cannot create file
Cannot write to directory

查看 Pod 信息发现:

老 Pod:

1
openshift.io/scc: anyuid

新创建的 Pod:

1
openshift.io/scc: restricted-v2

问题开始有了方向。


OpenShift SCC 机制

OpenShift 中的 SCC(Security Context Constraints)决定了 Pod 运行时的安全策略。

常见的 SCC 包括:

1
2
3
restricted-v2
anyuid
privileged

很多人会认为:

1
openshift.io/scc: anyuid

是 Deployment 或 StatefulSet 的固定配置。

实际上并不是。

SCC 是在 Pod 创建时动态选择的:

1
2
3
4
5
6
7
ServiceAccount
+
Pod Spec

OpenShift Admission

选择符合条件的 SCC

因此:

1
2
3
4
5
删除 Pod

重新创建 Pod

重新计算 SCC

新 Pod 完全有可能获得与旧 Pod 不同的 SCC。


关键发现

检查一个两年前创建且从未重启过的 Pod:

1
2
3
serviceAccountName: default

openshift.io/scc: anyuid

说明系统安装时:

1
2
3
default ServiceAccount

拥有 anyuid 权限

否则 Pod 不可能获得 AnyUID SCC。

进一步验证:

1
2
oc auth can-i use scc/anyuid \
--as system:serviceaccount:<namespace>:default

结果:

1
no

说明当前的 default ServiceAccount 已经失去了使用 AnyUID 的权限。


Root Cause

系统安装时:

1
2
3
default ServiceAccount

允许使用 anyuid

因此创建出来的 Pod 使用:

1
openshift.io/scc: anyuid

后来某个时间点:

1
SCC 或 RBAC 配置发生变化

导致:

1
2
3
default ServiceAccount

无法再使用 anyuid

但是由于旧 Pod 一直没有重建,所以问题始终没有暴露。

直到:

1
2
3
4
5
Node OOM

Pod 被驱逐

Pod 重建

OpenShift 重新选择 SCC。

由于 AnyUID 已不可用:

1
restricted-v2

成为新的 SCC。


为什么 Restricted-v2 会导致启动失败

Restricted-v2 要求容器使用随机非 Root UID。

例如:

1
2
uid=1000700000
gid=0

而很多历史镜像中的目录权限是按照固定 UID 或 Root 用户设计的。

例如:

1
2
3
4
/opt/app
/app
/var/log
/data

当随机 UID 无法访问这些目录时:

1
Permission denied

应用启动失败。


解决方案

方案一:调整 SecurityContext

例如:

1
2
securityContext:
fsGroup: 1000700000

或者根据应用实际情况调整:

1
2
3
4
securityContext:
runAsUser:
runAsGroup:
fsGroup:

使应用兼容 Restricted-v2。

这是推荐方案。


方案二:恢复 AnyUID 权限

执行:

1
2
3
oc adm policy add-scc-to-user anyuid \
-z default \
-n <namespace>

验证:

1
2
oc auth can-i use scc/anyuid \
--as system:serviceaccount:<namespace>:default

返回:

1
yes

之后重新创建 Pod,即可重新获得 AnyUID SCC。


排查过程中学到的经验

1. 长时间运行的 Pod 会隐藏问题

一个运行了几年都没有重建过的 Pod,并不能证明当前配置仍然正确。

很多问题只有在:

  • Pod 重建
  • 节点迁移
  • 集群升级

时才会暴露出来。


2. SCC 是动态计算的

不要认为:

1
openshift.io/scc: anyuid

会永久存在。

每次创建 Pod 时都会重新计算。


3. 尽量不要依赖 Default ServiceAccount

推荐为应用创建专用 ServiceAccount:

1
serviceAccountName: my-app-sa

避免未来权限调整影响整个 Namespace。


4. 优先兼容 Restricted-v2

从 OpenShift 安全模型的发展趋势来看:

1
restricted-v2

已经成为默认推荐方案。

新开发的应用应尽量避免依赖:

1
2
anyuid
privileged

等高权限 SCC。


总结

这次问题表面上看是文件权限异常:

1
Permission denied

实际上根因是:

1
2
3
4
5
6
7
8
9
10
11
历史 Pod 使用 AnyUID

ServiceAccount 权限发生变化

Pod 重建

获得 Restricted-v2

随机 UID 无法访问应用目录

启动失败

对于长期运行的 OpenShift 集群,定期检查 SCC、ServiceAccount 和 SecurityContext 配置,是避免此类问题的有效手段。

Notice: 正常情况下,这里会有一个基于utteranc.es的留言系统,如果看不到,可能要想想办法才能看到。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2012 - 2026 tiaobug.com All Rights Reserved.

鲁ICP备2024124237号-1