SOP — 普通用户 Lustre 写入被拒(服务端身份解析缺失)¶
- 主题目录:
fix-lustre-write-perm/ - 执行日期:2026-10-06
- 类型:C 类变更(服务端账户条目补齐)
- 关联:
docs/HANDOFF.md§3.1 #13(本变更结案项);巡检报告reports/inspect-20261006-012305.md
1. 背景¶
EDA 仿真需把中间文件落到 Lustre(/mnt/lustre/scratch/tmp),但普通用户 rain01 真实写入报
Permission denied,root 正常,阻塞仿真落盘。该问题由巡检发现并经手工复现确认,
列为 HANDOFF §3.1 #13。
排查中排除了多个常见怀疑点:目录权限(scratch/tmp 已是 drwxrwxrwt 1777)、SELinux
(Disabled/Permissive)、挂载状态(.18/.20/.28 均 state=FULL)。真正原因在服务端。
根因(有日志证据):客户端用户来自集中身份源(SSSD + LDAP),而服务端 .21/.22 未接入该身份源,
本地解析不到客户端 UID,导致 MDS 的身份解析程序 l_getidentity 失败、拒绝一切非 root 请求:
(MDS .21,journalctl,时间戳与本轮写入测试完全对应)
l_getidentity[108071]: no such user 2001
l_getidentity[108071]: get identity for uid 2001 ... rc = -1
root 不受影响,是因为 mdt.*.root_squash = 0:0——root 身份不走该解析路径。
2. 目标¶
| 项 | 可验证状态 |
|---|---|
| 验收 | .18 / .20 / .28 三台以 rain01 真实写入 /mnt/lustre/scratch/tmp 成功 |
| 回归 | 复跑仍成功(幂等);root 写入不受影响 |
| 旁证 | MDS .21 近 10 分钟 l_getidentity 日志条数为 0 |
| 边界 | 不改变任何 Lustre 配置、目录权限与调优参数 |
3. 前置条件¶
- root 免密 SSH 可达
.21(MGS+MDT)、.22(OSS) - UID/GID 事实(客户端经 LDAP 解析,
ldap_id_mapping = false,故必须严格一致):rain01= uid 2001、主组design= gid 2000 - 服务端
uid 2001/gid 2000均空闲(已实测确认) - 远程备份落点:
/var/backups/lustre-ins/
4. 影响范围¶
| 主机 | 组件 | 变更内容 | 停服 | 窗口 |
|---|---|---|---|---|
192.168.31.21 |
MGS + MDT | /etc/{passwd,group,shadow,gshadow} 各新增 1 组 + 1 用户 |
否 | 任意 |
192.168.31.22 |
OSS | 同上 | 否 | 任意 |
- 不重启
lnet/ 不重挂载 / 不重启 Lustre 服务;不影响在跑作业 - 不改目录属主与权限(
scratch/tmp维持 1777)
5. 分步操作¶
步骤 0:判据——必须真实写入,不要用 test -w¶
test -w(及部分工具的预检)在 Lustre/llite 上会对不可写目录误报「可写」,本问题即被它掩盖过一次。
判据一律为「以目标用户真实创建文件」。
# 在客户端执行;预期输出 Permission denied 才是复现
su -s /bin/bash rain01 -c 'touch /mnt/lustre/scratch/tmp/.probe && rm -f /mnt/lustre/scratch/tmp/.probe'
失败判断:若此处成功,说明现象已变,先回到步骤 1 重新取证,不要套用本 SOP。
步骤 1:定位根因(客户端现场 + 服务端日志)¶
先在客户端确认「不是权限位、不是 SELinux」:
findmnt -n -o SOURCE,TARGET,FSTYPE --target /mnt/lustre
# 预期 192.168.31.21@tcp:/edafs /mnt/lustre lustre
stat -c '%A %U:%G %n' /mnt/lustre /mnt/lustre/scratch /mnt/lustre/scratch/tmp
# 预期 /mnt/lustre/scratch/tmp 为 drwxrwxrwt root:root(1777,任何用户可写)
getenforce
# 预期 Disabled 或 Permissive
再在 MDS 上取身份解析日志(关键判据):
journalctl --since '-10min' | grep -iE 'l_getidentity|no such user'
# 命中 "no such user <uid>" 即根因确认
lctl get_param -n mdt.*.identity_upcall
# 预期 /usr/sbin/l_getidentity
lctl get_param -n mdt.*.root_squash
# 预期 0:0(说明 root 为何不受影响)
getent passwd 2001
# 修复前为空 —— 这是被拒的直接原因
坑:不要被「ACL 显示 other::rwx 却仍被拒」误导去改目录权限。Lustre 的权限判定发生在 MDS 侧,
身份解析失败时任何权限位都不生效,改目录权限是无效动作。
实现体:无(本变更为一次性手工变更,未产出脚本)。
步骤 2:备份并补齐服务端账户条目(在 .21、.22 各执行一次)¶
先备份四个账户文件(必须,回滚依赖它),再以幂等方式新增组与用户。
TS=$(date +%Y%m%d-%H%M%S)
mkdir -p /var/backups/lustre-ins
for f in passwd group shadow gshadow; do
cp -a "/etc/$f" "/var/backups/lustre-ins/$f.bak.$TS"
done
getent group design >/dev/null 2>&1 || groupadd -g 2000 design
getent passwd rain01 >/dev/null 2>&1 || \
useradd -u 2001 -g 2000 -M -s /sbin/nologin -c "EDA user (mirror of client LDAP)" rain01
getent passwd 2001
getent group 2000
预期:rain01:x:2001:2000:...:/home/rain01:/sbin/nologin 与 design:x:2000:。
坑与注意:
-M不在服务端建家目录,-s /sbin/nologin防止服务端出现可登录账户;两者都不影响 Lustre 权限判定 (MDS 只做 NSS 数字 UID/GID 解析,不看 shell 与家目录)- UID/GID 必须与客户端逐位一致(2001/2000)。客户端
ldap_id_mapping = false, 若服务端用 SSSD 自动映射会得到另一套 UID,仍然失败 - 命令以
getent ... ||前置判空,重复执行零变更(幂等)
步骤 3(可选,长期方案):服务端接入同一 LDAP¶
本地条目与 LDAP 属双轨:后续新增 EDA 用户仍需在服务端同步一次。长期正解是让服务端接入同一身份源:
# 示意:需先解决装包(跨境仓库约 2 KB/s,可从既有客户端拷 /var/cache/dnf 与 repo 文件)
dnf install -y sssd sssd-ldap
# 复制客户端同款配置(含域 rainchen / ldap_uri / ldap_schema=rfc2307 / ldap_id_mapping=false)
install -m 600 /path/to/sssd.conf /etc/sssd/sssd.conf
systemctl enable --now sssd
getent passwd rain01 # 预期返回 uid 2001 即接入成功
本轮未采用该方案(需在服务端装包并引入对 LDAP 的运行时依赖),记为待办。
6. 验证¶
# 在 .18 / .20 / .28 三台分别执行;两次都应输出 OK(第二次即幂等回归)
su -s /bin/bash rain01 -c 'f=/mnt/lustre/scratch/tmp/.verify_$$; touch $f && { echo OK; rm -f $f; } || echo FAIL'
预期:三台均 OK。
# MDS 侧旁证
journalctl --since '-10min' | grep -c l_getidentity # 预期 0
getent passwd 2001 # 预期返回 rain01 行
| 验证项 | 结果(2026-10-06) |
|---|---|
.18 / .20 / .28 真实写入 scratch/tmp |
三台 OK |
| 复跑(幂等回归) | 三台 OK |
MDS l_getidentity 报错(近 10 min) |
0 条 |
getent passwd 2001(服务端) |
返回 rain01 |
root 写入 |
不受影响(全程正常) |
说明:/mnt/lustre/scratch(755 root:root)对 rain01 仍拒绝写入,这是正常的 POSIX 语义,
不是缺陷;如有业务需求让 design 组在 scratch/ 下写,应单独调整目录属组或加 ACL。
7. 回滚¶
备份位置:192.168.31.21:/var/backups/lustre-ins/、192.168.31.22:/var/backups/lustre-ins/
(文件名 passwd.bak.20261006-052523 等)。台账见本目录 backup/README.md。
# 回滚触发条件(任一即回滚):
# ① 三台任一写入验证不通过;② MDS 出现新的身份解析报错;③ 影响在跑作业
TS=20261006-052523
for f in passwd group shadow gshadow; do
cp -a "/var/backups/lustre-ins/$f.bak.$TS" "/etc/$f"
done
getent passwd 2001 || echo "回滚完成:uid 2001 已不可解析"
回滚后验证:getent passwd 2001 返回空、客户端写入回到 Permission denied 状态即回滚成功。
回滚不影响正在运行的 Lustre(无需重挂载)。
8. 风险说明¶
| 风险 | 等级 | 缓解 |
|---|---|---|
| 本地条目与 LDAP 双轨漂移(新增用户需手工同步) | 中 | 记待办:服务端接入 SSSD;或纳入服务端初始化流程 |
useradd 误占 uid/gid(若与未来 LDAP 用户冲突) |
低 | 已实测 2001/2000 空闲;创建前均做 getent 判空 |
| 服务端新增账户带来登录面 | 低 | -M -s /sbin/nologin,无家目录、不可登录 |
| 备份文件散落 | 低 | 统一落 /var/backups/lustre-ins/,已登记台账 |
未做且不应做的动作:未修改目录权限、未改 mdt.*.identity_upcall、未改 nodemap、未重挂载。
附录:交付物与证据¶
- 本目录:
SOP.md、backup/README.md - 排障场景沉淀:
docs/troubleshoot.md→ 「普通用户写入 Permission denied」 - 巡检报告:
reports/inspect-20261006-012305.md
来源:
/home/rain/Documents/lustre_ins/fix-lustre-write-perm/SOP.md| 最后更新:2026-10-06 05:26(由build/sync.py同步,请勿在站点侧修改)